Generování vnitřní reprezentace programu Miroslav Beneš Dušan Kolář
Vnitřní reprezentace programu2 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 programu3 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
Vnitřní reprezentace programu4 Formáty vnitřní reprezentace programu Grafová reprezentace Zásobníkový kód Tříadresový kód
Vnitřní reprezentace programu5 Grafová reprezentace Abstraktní syntaktický strom (AST) a:=b*(-c)+b*(-c) assign bb + * cc a * uminus Uzly - operátory Listy - operandy
Vnitřní reprezentace programu6 Grafová reprezentace DAG (Directed Acyclic Graph) a:=b*(-c)+b*(-c) assign b + * c a uminus Společné podvýrazy jako sdílené uzly Používá se pro optimalizaci
Vnitřní reprezentace programu7 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.
Vnitřní reprezentace programu8 Grafová reprezentace read seq := n1f> while 1n write seq \n f := f* fn n- n1
Vnitřní reprezentace programu9 Zásobníkový kód Postfixová notace a b c uminus * b c uminus * + assign výsledek průchodu AST nebo DAG typu post- order uzel následuje bezprostředně za svými následníky žádný formální rozdíl mezi operandy a operátory
Vnitřní reprezentace programu10 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 programu11 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, …)
Vnitřní reprezentace programu12 Příklad - JVM public class Priklad { public static void main(String[] args) { int x = 1; System.out.println(x + 2); }
Vnitřní reprezentace programu13 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
Vnitřní reprezentace programu14 Příklad - MSIL using System; public class Priklad { public static void Main(string[] args) { int x = 1; Console.WriteLine(x + 2); }
Vnitřní reprezentace programu15 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 }
Vnitřní reprezentace programu16 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 programu17 Příklad 1 a:=b*(-c)+b*(-c) t1 := -ct1 := -c t2 := b*t1t2 := b*t1 t3 := -ct5 := t2+t2 t4 := b*t3a := t5 t5 := t2+t4 a := t5 Strom DAG dočasné proměnné = vnitřní uzly stromu (DAG)
Vnitřní reprezentace programu18 Příklad 2 var n,f:integer; begin 1: read n read n;2: f := 1 f:=1;3: if n 1 do begin4: f := f * n f:=f*n; n:=n-15: n := n - 1 end;6: goto 3 write f,"\n"7: write f end.8: write "\n"
Vnitřní reprezentace programu19 Příkazy tříadresového kódu x := y op zop – binární operátor x := op yop - unární operátor (-, not, typová konverze, …) x := y goto Lnepodmíněný skok if x relop y goto Lpodmíněný skok
Vnitřní reprezentace programu20 Příkazy tříadresového kódu param x 1 … param x n volání podprogramu call p,np(x 1,…,x n ) return ynávrat z podprogramu
Vnitřní reprezentace programu21 Příkazy tříadresového kódu x := y[j] x[j] := yindexování x := &yreference (získání adresy) x := *y *x := ydereference ukazatele
Vnitřní reprezentace programu22 Čtveřice oparg1arg2výsledek (0)uminusct1 (1)*bt1t2 (2)uminusct3 (3)*bt3t4 (4)+t2t4t5 (5):=t5a a:=b*(-c)+b*(-c)
Vnitřní reprezentace programu23 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
Vnitřní reprezentace programu24 Příklad – překlad výrazů S -> id := E { p = lookup(id.name); if( p != null ) emit(p,‘:=’,E.place); else error(); } E -> E 1 + E 2 { E.place = newtemp(); emit(E.place,‘:=’, E 1.place,’+’,E 2.place);} E -> E 1 * E 2 { E.place := newtemp(); emit(E.place,‘:=’, E 1.place,’*’,E 2.place);}
Vnitřní reprezentace programu25 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(); }
Vnitřní reprezentace programu26 array [low..high] of T prvek a[j] leží na adrese: base+(j-low)*w = j*w+(base-low*w) =konstanta! Přístup k prvkům pole lowlow+1highw=sizeof(T) base
Vnitřní reprezentace programu27 Přístup k prvkům pole a[j 1,j 2 ] 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! base low1 low2 high1 n2 := high2-low2+1 high2
Vnitřní reprezentace programu28 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 programu29 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
Vnitřní reprezentace programu30 Překlad výrazů s indexy L.offset index (null=bez indexu) L.place proměnná E.place proměnná s hodnotou id.place Elst.array popis pole Elst.ndim počet rozměrů Elst.place proměnná obsahující index
Vnitřní reprezentace programu31 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
Vnitřní reprezentace programu32 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 programu33 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,‘]’) } }
Vnitřní reprezentace programu34 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 programu35 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; }
Vnitřní reprezentace programu36 Překlad výrazů s indexy Elst -> id [ E { Elst.array = id.place; Elst.place = E.place; Elst.ndim = 1; }
Vnitřní reprezentace programu37 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]
Vnitřní reprezentace programu38 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 programu39 Překlad logických výrazů E -> E or E | E and E | (E) | not E | id relop id | true | false
Vnitřní reprezentace programu40 Překlad logických výrazů Reprezentace logických hodnot celými čísly: true=1, false=0 a or b and not cx<y 1: t1 := not c1: if x<y goto 4 2: t2 := b and t12: t1 := 0 3: t3 := a or t23: goto 5 4: …4: t1 := 1 5: …
Vnitřní reprezentace programu41 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 programu42 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 programu43 Překlad příkazu IF S -> if ( E ) S FJP L1 LBL L1 S -> if ( E ) {FJP} S {LBL} FJP.l = LBL.l = getLbl(); E S FJP L1 LBL L1
Vnitřní reprezentace programu44 Překlad příkazu IF 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 S1S1 S1S1 JMP L2 L1: L2:
Vnitřní reprezentace programu45 Překlad příkazu WHILE S -> while ( E ) S LBL L1 FJP L2 JMP L1 LBL L2 E S L1: L2: FJP L2 JMP L1
Vnitřní reprezentace programu46 Překlad příkazu WHILE 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