Generování vnitřní reprezentace programu Miroslav Beneš Dušan Kolář Možnosti překladu Interpretace Okamžité provádění programu Překlad do instrukcí procesoru Závislost na konkrétním typu procesoru Překlad do vnitřní reprezentace Následuje interpretace nebo překlad do instrukcí procesoru Vnitřní reprezentace programu 2 Výhody překladu do vnitřní reprezentace Strukturalizace překladače Mnohem jednodušší přenos na více typů procesorů Možnost optimalizace na úrovni vnitřní reprezentace strojově nezávislé metody Formáty vnitřní reprezentace programu Grafová reprezentace Zásobníkový kód Tříadresový kód Vnitřní reprezentace programu 3 Vnitřní reprezentace programu 4 1
Grafová reprezentace Abstraktní syntaktický strom (AST) a:=b*(-c)+b*(-c) a b assign * + uminus b * uminus Uzly - operátory Listy - operandy Grafová reprezentace DAG (Directed Acyclic Graph) a assign b + * uminus a:=b*(-c)+b*(-c) Společné podvýrazy jako sdílené uzly Používá se pro optimalizaci c c Vnitřní reprezentace programu 5 c Vnitřní reprezentace programu 6 Příklad var n, f: Integer; begin read n; f:=1; while n>1 do begin f:=f*n; n:=n-1 end; write f, \n end. Grafová reprezentace read := n f 1 > n seq while 1 write seq f \n := := f * f n n - n 1 Vnitřní reprezentace programu 7 Vnitřní reprezentace programu 8 2
Zásobníkový kód Postfixová notace a b c uminus * b c uminus * + assign výsledek průchodu AST nebo DAG typu postorder uzel následuje bezprostředně za svými následníky žádný formální rozdíl mezi operandy a operátory Zásobníkový kód Virtuální zásobníkový procesor load b (b) vrchol zás. vpravo load c (b) (c) inv (b) (-c) mul (b*-c) load b (b*-c) (b) load c (b*-c) (b) (c) inv (b*-c) (b) (-c) mul (b*-c) (b*-c) add (b*-c+b*-c) store a Vnitřní reprezentace programu 9 Vnitřní reprezentace programu 10 Zásobníkový kód Virtuální zásobníkový procesor virtuální počítač s pamětí a zásobníkem P-kód (Wirth) přenositelný mezikód pro Pascal specializované procesory Java Virtual Machine MSIL Microsoft Intermediate Language (.NET C#, C++, VB, ) Příklad - JVM public class Priklad { public static void main(string[] args) { int x = 1; System.out.println(x + 2); Vnitřní reprezentace programu 11 Vnitřní reprezentace programu 12 3
Příklad - JVM 0: iconst_1 1: istore_1 2: getstatic #2; //java/lang/system.out 5: iload_1 6: iconst_2 7: iadd 8: invokevirtual #3; //java/io/printstream.println 11: return Příklad - MSIL using System; public class Priklad { public static void Main(string[] args) { int x = 1; Console.WriteLine(x + 2); Vnitřní reprezentace programu 13 Vnitřní reprezentace programu 14 Příklad - MSIL.method public static void Main(string[] args) {.entrypoint.maxstack 2.locals init (int32 V_0) ldc.i4.1 stloc.0 ldloc.0 ldc.i4.2 add call void System.Console::WriteLine(int32) ret Tříadresový kód x := y op z x - (dočasná) proměnná y, z - (dočasné) proměnné, konstanty Operandy nemohou být výrazy rozklad na primitivní výrazy s dočasnými proměnnými Explicitní odkazy na operandy možnost přesouvání příkazů při optimalizaci Vnitřní reprezentace programu 15 Vnitřní reprezentace programu 16 4
Příklad 1 a:=b*(-c)+b*(-c) t1 := -c t1 := -c t2 := b*t1 t2 := b*t1 t3 := -c t5 := t2+t2 t4 := b*t3 a := t5 t5 := t2+t4 a := t5 Strom DAG dočasné proměnné = vnitřní uzly stromu (DAG) Příklad 2 var n,f:integer; begin 1: read n read n; 2: f := 1 f:=1; 3: if n<=1 goto 7 while n>1 do begin 4: f := f * n f:=f*n; n:=n-1 5: n := n - 1 end; 6: goto 3 write f,"\n" 7: write f end. 8: write "\n" Vnitřní reprezentace programu 17 Vnitřní reprezentace programu 18 Příkazy tříadresového kódu Příkazy tříadresového kódu x := y op z x := op y x := y goto L if x relop y goto L op binární operátor op - unární operátor (-, not, typová konverze, ) nepodmíněný skok podmíněný skok param x 1 param x n volání podprogramu call p,n p(x 1,,x n ) return y návrat z podprogramu Vnitřní reprezentace programu 19 Vnitřní reprezentace programu 20 5
Příkazy tříadresového kódu x := y[j] x[j] := y x := &y indexování reference (získání adresy) x := *y *x := y dereference ukazatele Čtveřice op arg1 arg2 výsledek (0) uminus c t1 (1) * b t1 t2 (2) uminus c t3 (3) * b t3 t4 (4) + t2 t4 t5 (5) := t5 a a:=b*(-c)+b*(-c) Vnitřní reprezentace programu 21 Vnitřní reprezentace programu 22 Příklad překlad výrazů Příklad překlad výrazů Atributy id.name jméno identifikátoru E.place jméno proměnné obsahující hodnotu E Pomocné funkce newtemp vytvoří novou proměnnou lookup vyhledá proměnnou v tabulce emit generuje instrukci error hlášení chyby S -> id := E E -> E 1 + E 2 E -> E 1 * E 2 { p = lookup(id.name); if( p!= null ) emit(p, :=,E.place); else error(); { E.place = newtemp(); emit(e.place, :=, E 1.place, +,E 2.place); { E.place := newtemp(); emit(e.place, :=, E 1.place, *,E 2.place); Vnitřní reprezentace programu 23 Vnitřní reprezentace programu 24 6
Příklad překlad výrazů E -> - E 1 { E.place = newtemp(); emit(e.place, :=, uminus,e 1.place); E -> (E 1 ) { E.place = E 1.place; E -> id { p := lookup(id.name); if( p!= null ) E.place := p; else error(); Přístup k prvkům pole array [low..high] of T low low+1 base w=sizeof(t) prvek a[j] leží na adrese: high base+(j-low)*w = j*w+(base-low*w) =konstanta! Vnitřní reprezentace programu 25 Vnitřní reprezentace programu 26 Přístup k prvkům pole base low1 high1 low2 a[j 1,j 2 ] high2 base+((j 1 -low 1 )*n 2 +j 2 -low 2 )*w => ((j 1 *n 2 )+j 2 )*w+(base-((low 1 *n 2 )+low 2 )*w) =konstanta! n2 := high2-low2+1 Přístup k prvkům pole Obecně: a[j 1,, j k ] addresa: ( (j 1 n 2 +j 2 )n 3 +j 3 ) )n k +j k )*w + base -( (low 1 n 2 +low 2 )n 3 +low 3 ) )n k +low k )*w mapovací funkce n j = high j -low j +1 Vnitřní reprezentace programu 27 Vnitřní reprezentace programu 28 7
Překlad výrazů s indexy Překlad výrazů s indexy S -> L := E E -> E 1 + E 2 (E 1 ) L L -> Elst ] id Elst -> Elst 1, E id [ E L.offset index (null=bez indexu) L.place proměnná E.place proměnná s hodnotou Elst.array popis pole Elst.ndim počet rozměrů Elst.place proměnná obsahující index id.place Vnitřní reprezentace programu 29 Vnitřní reprezentace programu 30 Překlad výrazů s indexy const(elst.array) konstantní část mapovací funkce width(elst.array) velikost prvku pole limit(elst.array,m) počet prvků v m-té dimenzi Překlad výrazů s indexy S -> L := E { if( L.offset==null ) /* bez indexu */ emit(l.place, :=,E.place); else emit(l.place, [,L.offset, ], :=,E.place); E -> E 1 + E 2 { E.place = newtemp(); emit(e.place, :=,E 1.place, +,E 2.place); Vnitřní reprezentace programu 31 Vnitřní reprezentace programu 32 8
Překlad výrazů s indexy E -> (E 1 ) { E.place = E 1.place E -> L { if( L.offset==null ) /* bez indexu */ E.place = L.place; else { E.place = newtemp(); emit(e.place, :=,L.place, [,L.offset, ] ) Překlad výrazů s indexy L -> Elst ] { L.place = newtemp(); L.offset = newtemp(); emit(l.place, :=,const(elst.array)); emit(l.offset, :=,Elst.place, *, width(elst.array)); L -> id { L.place = id.place; L.offset = null; Vnitřní reprezentace programu 33 Vnitřní reprezentace programu 34 Překlad výrazů s indexy Elst -> Elst 1, E { t = newtemp(); m = Elst 1.ndim+1; emit(t, :=,Elst 1.place, *, limit(elst 1.array,m)); emit(t, :=,t, +,E.place); Elst.array = Elst 1.array; Elst.place = t; Elst.ndim = m; Překlad výrazů s indexy Elst -> id [ E { Elst.array = id.place; Elst.place = E.place; Elst.ndim = 1; Vnitřní reprezentace programu 35 Vnitřní reprezentace programu 36 9
Příklad A: array [1..10,1..20] of integer; sizeof(integer) = 4 n 1 = 10 n 2 = 20 w = 4 x := A[y, z] Příklad x := A[y, z] t1 := y*20 t2 := t1+z t3 := c /* konstanta c = &A-84 */ t4 := 4*t2 (1*20+1)*4=84 t5 := t3[t4] x := t5 Vnitřní reprezentace programu 37 Vnitřní reprezentace programu 38 Překlad logických výrazů E -> E or E E and E (E) not E id relop id true false Překlad logických výrazů Reprezentace logických hodnot celými čísly: true=1, false=0 a or b and not c x<y 1: t1 := not c 1: if x<y goto 4 2: t2 := b and t1 2: t1 := 0 3: t3 := a or t2 3: goto 5 4: 4: t1 := 1 5: Vnitřní reprezentace programu 39 Vnitřní reprezentace programu 40 10
Překlad logických výrazů Zkrácené vyhodnocení reprezentace logických hodnot tokem řízení (pozicí v programu) a<b or c<d and e<f if a<b goto Ltrue goto L1 L1: if c<d goto L2 goto Lfalse L2: if e<f goto Ltrue goto Lfalse Vnitřní reprezentace programu 41 Překlad řídicích příkazů Instrukce zásobníkového kódu: LBL L definice návěští L pro skok JMP L nepodmíněný skok na návěští L FJP L - podmíněný skok na návěští L, pokud je na vrcholu zásobníku False výstupní symboly překladové gramatiky - {LBL Pomocné funkce: getlbl() vygeneruje nové číslo návěští zanoření příkazů nelze použít konstanty! Vnitřní reprezentace programu 42 Překlad příkazu IF Překlad příkazu IF S -> if ( E ) S <E> FJP L1 <S> LBL L1 S -> if ( E ) {FJP S {LBL FJP.l = LBL.l = getlbl(); E FJP L1 S LBL L1 S -> if ( E ) S 1 else S 2 S -> X {LBL LBL.l = X.l S -> X {JMP {LBL 1 else S {LBL 2 JMP.l = LBL 2.l = getlbl(); LBL 1.l = X.l X -> if (E) {FJP S FJP.l = getlbl() E FJP L1 S 1 JMP L2 L1: L2: S 1 Vnitřní reprezentace programu 43 Vnitřní reprezentace programu 44 11
Překlad příkazu WHILE Překlad příkazu WHILE S -> while ( E ) S LBL L1 <E> FJP L2 <S> JMP L1 LBL L2 L1: L2: E FJP L2 S JMP L1 S -> {LBL 1 while ( E ) {FJP 2 S {JMP 1 {LBL 2 LBL 1.l = JMP 1.l = getlbl(); LBL 2.l = FJP.l = getlbl(); S -> break/continue ; S.blab dědičný atribut, návěští pro break S.clab dědičný atribut, návěští pro continue while musí zajistit předání návěští speciální hodnota návěští poznáme, že nejsme uvnitř cyklu, break/continue může hlásit chybu Vnitřní reprezentace programu 45 Vnitřní reprezentace programu 46 12