INF april, 2015 Kap. 8 kodegenerering. Del 2

Like dokumenter
INF Noen oppgaver til kap. 8

INF Noen oppgaver til kap. 8

INF april, 2014 Stein Krogdahl Ifi, UiO. Svar på oppgaver til kap. 8

INF april, 2015 Stein Krogdahl Ifi, UiO. Svar på oppgaver til kap. 8. Ble lagt ut 24. april

Stein Krogdahl, Ifi UiO

INF april, 2013 Kap. 8 kodegenerering

INF og 23. april, 2014 Kap. 8 kodegenerering

INF-5110 Oppgaver kodegenerering etc. INF-5110, vår 2011

INF og 13. april, Stein Krogdahl, Ifi UiO

Kap. 8 kodegenerering INF april, 2009

INF og 27. april, 2010 Kap. 8 kodegenerering. Stein Krogdahl, Ifi UiO

Kap. 8 del 1 kodegenerering INF5110 Vår2007

INF april, 2013 Kap. 8 Noen oppgaver som er meget relevante for Oblig 2

Pensumoversikt - kodegenerering. Kap. 8 del 1 kodegenerering INF5110 v2006. Hvordan er instruksjonene i en virkelig CPU? Arne Maus, Ifi UiO

MED SVARFORSLAG UNIVERSITETET I OSLO

Kap. 8 del 1 kodegenerering INF april, 2008

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse

Kodegenerering, del 2: Resten av Kap. 8 pluss tilleggsnotat (fra kap. 9 i ASU ) INF5110 V2007

Javas klasse-filer, byte-kode og utførelse (og litt om C# sin CIL-kode)

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse. INF 5110, 10/5-2011, Stein Krogdahl

Litt om Javas class-filer og byte-kode

Kodegenerering del 3: Tilleggsnotat fra AHU Samt litt om class-filer og byte-kode INF5110 V2007. Stein Krogdahl, Ifi UiO

Oppgaver til kodegenerering etc. INF-5110, 16. mai, 2014

Oppgaver til kodegenerering etc. INF-5110, 12. mai, 2015

Hovedstoffet i kap 4:

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Kap. 4: Ovenfra-ned (top-down) parsering

Hovedstoffet i kap 4: 16. Februar Ifi, UiO

Del 1 En oversikt over C-programmering

MED SVARFORSLAG UNIVERSITETET I OSLO

INF Repetisjon: Hvordan bygge treet og analysere? 8. september Typisk situasjon. De problematiske syntaks-diagrammene

INF5110, onsdag 19. februar, Dagens tema: Parsering ovenfra-ned (top-down)

Kap.4, del 2: Top Down Parsering Kap. 5, del 1: Bottom Up Parsing INF5110, 7/ Legger ut en oppgave til kap. 4 (se beskjed).

UNIVERSITETET I OSLO

Kap. 4, del I: Top Down Parsering Pluss oppgave til kapittel 3 INF5110 V2008

Generiske mekanismer i statisk typede programmeringsspråk

Beskrivelse av programmeringsspråket Compila15 INF Kompilatorteknikk Våren 2015

Velkommen til INF5110 Kompilatorteknikk

Velkommen til INF Kompilatorteknikk

Eivind Gard Lund. 24. Mars 2009 Foilene bygger på 2009 utgaven av Andreas Svendsen

INF Oblig 2 semantikksjekk og kodegenerering

INF5110, tirsdag 5. februar, Dagens temaer: - Oppgaver til kap. 3 Svar ligger på slutten av foilene, men forsøk deg først selv!!

Velkommen til INF Kompilatorteknikk

INF5110 V2013 Stoff som i boka står i kap 4, men som er generelt stoff om grammatikker

Viktig. Rettet i koden. Oppgaven. Obligatorisk oppgave 2 - Kort om oppgaven og litt informasjon. Fredrik Sørensen OMS-gruppen, IfI

INF5110. Oblig 2 presentasjon

Kapittel 1 En oversikt over C-språket

Del 4 Noen spesielle C-elementer

Introduksjon til DARK assembly

Obligatorisk Innlevering 2

Kap. 4 del I Top Down Parsering INF5110 v2006. Stein Krogdahl Ifi, UiO

Kap.4 del 2 Top Down Parsering INF5110 v2005. Arne Maus Ifi, UiO

Kjøresystemer. Hva er et kjøresystem? Den abstrakte maskinen SIMPLESEM (2.6) Klassifisering av språk: Parametre (2.7.7) Statiske språk (

Mer kodegenerering: Tilleggsnotat fra AHU Om Javas Byte-kode INF april 2009

Runtimesystemer Kap 7 - I

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen Oppsummering

INF mai 2014 Stein Krogdahl, Ifi, UiO

Programmeringsspråket C

Mer kodegenerering: Tilleggsnotat fra AHU. INF mai Stein Krogdahl,

Velkommen til INF Kompilatorteknikk

Velkommen til INF Kompilatorteknikk

INF5110 V2012 Kapittel 4: Parsering ovenfra-ned

UNIVERSITETET I OSLO

6. oktober Dagens program: Første time: Andre time, gjesteforelesning: Uavgjørbarhet. Stein Krogdahl. (Ikke pensum, egne foiler legges ut)

Betinget eksekvering og logiske tester i shell

INF 1000 høsten 2011 Uke september

INF1000 undervisningen INF 1000 høsten 2011 Uke september

UNIVERSITETET I OSLO

Runtime-omgivelser Kap 7 - I

Runtimesystemer Kap 7 - I

UNIVERSITETET I OSLO

Bakgrunnen for INF2100. Velkommen til INF2100. Prosjektet. Hva gjør en kompilator?

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Kap.4 del I Top Down Parsering INF5110 v2005. Arne Maus Ifi, UiO

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

INF oktober Stein Krogdahl. Kap 23.5: Trær og strategier for spill med to spillere

INF225 høsten 2003 Prosjekt del 4: kodegenerering

INF1000 (Uke 5) Mer om løkker, arrayer og metoder

Velkommen til INF2100

Velkommen til INF Kompilatorteknikk

Programmeringsspråket C Del 3

Semantikk. Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7) Semantikk. Semantikk. En måte å svare på: gi semantikken til språket!

Velkommen til INF2100 Jeg er Dag Langmyhr

Programmeringsspråket C Del 3

Velkommen til INF Kompilatorteknikk

Løsnings forslag i java In115, Våren 1996

E K S A M E N. Algoritmiske metoder I. EKSAMENSDATO: 11. desember HINDA / 00HINDB / 00HINEA ( 2DA / 2DB / 2EA ) TID:

Oversikt Kodegenerering Variabler Setninger Uttrykk While-setningen

MAT1030 Plenumsregning 1

Dagens tema: 12 gode råd for en kompilatorskriver

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

UNIVERSITETET I OSLO

Dagens tema: Kjøresystemer II

Programmeringsspråket C Del 3

Hva er kompilering? Dagens tema. En kompilator En kompilator leser Minila koden og lager Flok koden.

Programmeringsspråket C Del 3

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

Beskrivelse av programmeringsspråket Simpila INF Kompilatorteknikk Våren 2012

Velkommen til INF Kompilatorteknikk

Transkript:

INF5110 23. april, 2015 Kap. 8 kodegenerering. Del 2 Foilene inneholder også noe ekstra-stoff som ikke står i boka, men som er pensum! Stein Krogdahl, Ifi UiO Del-1 av foilene til kap. 8 er lagt ut (se 21/4-2015) Del 2 inneholder: 8.3 Kode for aksess av datastrukturer (ikke alt) 8.4 Kode for generereing for kontroll-setninger og logiske uttrykk Det blir noe mer om kodegenerering senere: - Registerallokering - Noe optimalisering 1

Fra første forelesning: Anatomien til en kompilator Se neste side Intern mellomkode er det som brukes inne i kodegeneratoren 23.04.2015 2

Anatomien til en kompilator - II Byte-kode for Java er også en slags mellomkode: utførbar mellomkode. Tilsvarende i.net og C#: Heter CIL (også her ofte kalt «bytekode»). CIL blir alltid kompilert videre til maskinkode. Tradisjonell Unix/Linux: asm: ---.s rel: ---.o rel fra bibl: ---.a abs: --- (tomt) Windows: abs: ---.exe (men.exe dekker også mer, og et assembly i.net dekker enda mer) 23.04.2015 3

Kommentarer til figurene på forrige to foiler Man kan godt generere utførbar maskin-kode for gitt maskin nokså direkte fra syntaks-treet Angitt som piler mot høyre på figur II Bruker da eventuelt bare intern mellomkode, som aldri sees av brukeren. Genereres tradisjonelt på én av tre former (ovenfra og ned på figuren): (1) Maskinkode på tekstlig assembly-format (som så gjøres om til format 2 eller 3 vha. en «assembler»). (2) Vanligst: Som relokerbart format som viderebehandles av tradisjonell loader til format 3 (3) Direkte som binær maskin-kode (som kan legges rett ned i maskinen) Men: Det kan også være greit å overføre programmet til en halvkompilert form som er veldefinert, og som ikke er rettet mot noen spesiell maskin: For Java: bytecode. For.NET og C#: CIL (Common Intermediate Language) Bytekode kan interpreteres, men blir nå oftest kompilert videre til maskinkode (JIT-kompilering). CIL blir alltid kompilert til maskinkode. Har en stakkorientert eksekverings-form (koden har postfiks form) Også intern mellomkode kan ha slik stakkorientert form, og i det vi tar med fra kap. 8 snakker boka mest om den interne typen, omtalt der som P-kode 4

Kap. 8.3 Detaljert aksess av datastrukturer Trenger da flere instruksjonstyper, bl.a. til adresse-beregning Vil lage kode for: «X [10] = 2;» Antar arrayen ligger på fast sted TA-kode: To nye måter å adressere på P-kode: To nye instruksjoner & X Adressen til x (ikke for temporære) *t Indirekte gjennom t indirect load indexed address &x 10 Sett inn 2 her 5

Aksessering av data i structer, objekter etc. Med slike instruksjoner kan vi lage TA-kode og P-kode for å aksessere lokale variable i structer, recorder, objekter etc. Vi ser imidlertid ikke på detaljene i dette rec Konstanter som kompiloatoren kjenner 6

Litt generelt til kap. 8.3 I boka lages det nokså lavnivå TA-kode og P-kode Ulempe: Man kan da ikke lenger se hva slags språkkonstruksjoner koden kommer fra. Dermed blir det vanskligere å optimalisere på lure steder. Det er altså ikke opplagt at bokas variant er det fornuftigste. Alternativ f.eks. i blokk-strukturerte språk: (1) Beholde aksess til en ikke-lokal variabel på formen: (rel.niv=2, rel.adr=3) Dette må da være en egen instruksjon i mellomkode-språket (2) Boka vil i stedet oversette til formen: fp.al.al.(reladr=3) (i TA- eller P-kode) Dette blir et lite antall i instruksjoner i TA-kode eller P-kode av den lav-nivå-typen som blir diskutert på forrige foiler Kan generelt gjerne tenke på oversettelse til lav-nivå T- eller P-kode som eksempel på oversettelse direkte til maskin-kode Bortsett fra at vi her slipper register-allokerings-problemet 7

8.4 : If/while Kan vi gjøre noe lurere her? Ja, se senere foiler! Kode for setningen: Skisse av TA-kode Skisse av P-kode 8

Treet for programmet til høyre: ReadStmt lnr = 1 nextstm x Program lnr = 1 firststmt IfStmt lnr = 2 nextstm cond stm1 stmt2 Const left lnr = 2 type=int 0 BinOp lnr = 2 type=bool < right Ident lnr = 2 type=int x fact lnr = 3 Assign nextstm lnr = 3 type=int 0 Merk at under kodegenerering er typen satt inn (av semantikk-analysatoren). ex left Ident = fact fact Assign lnr = 5 BinOp lnr = 5 type=int * right RepStm lnr = 4 nextstm stm nextstm ex cond Ident= x left Ident= x Assign lnr = 6 nextstm x BinOp lnr = 6 WriteStm lnr = 8 type=int nextstm ex ex - right Ident Const= 1 lnr = 8 type=int fact 9

while - setning Noe lurere her? TA-kode: Om det utføres en break inne i her skal det hoppes ut av (nærmest omsluttende) while-setning, her til L2. P-kode: 10

Behandling av boolske uttykk Mulighet 1: Behandle som vanlige uttrykk Mulighet 2: Behandling ved kort-slutning Men man må følge språkets semantikk! Eksempel i C der siste del bare beregnes dersom første del ikke avgjør svaret: P-kode for ldc Trykkfeil i boka <test på om det skal hoppes til else-gren> 11

P-kode for if/while-setninger Tre-node: For boolske uttrykk: Denne angir her bare false eller true bindes sammen Ser merkelig ut når alle boolske uttrykk her er konstanter 12

Rekursiv prosedyre for P-kodegenerering for setninger (med bokas noder!) En break i kildeprogr. skal bli et hopp til denne labelen Rek. kall Rek. kall Kode for S Rek. kall Rek. kall Label ved slutt av denne while-setn. ) ; Rek. kall ) ; 13

Rekursiv prosedyre for P-kodegenerering for setninger, penere utgave. Merk: Stakken antas å være tom før og etter kodegenerering for setning, men at stakken øker med én i løpet av kodegenerering for uttrykk. void gencode(treenode t, String label){ String lab1, lab2; if t!= null{ // For et tomt tre, ikke gjør noe switch t.kind { case ExprKind { // I boka (forrige foil) er det veldig forenklet, pga. bare false eller true // Skal generelt behandles slik vanlige uttrykk blir behandlet case IfKind { // If-setning gencode(t.child[0], label); // Lag kode for det boolske uttrykket. «break» inne i uttrykk bare for // spesielle språk, ellers er label-parameter unødvendig. lab1= genlabel(); emit2( fjp, lab1); // Hopp til mulig else-gren (eller til slutten om det ikke er ikke else-gren) gencode(t.child[1], label); // kode for then-del, gå helt ut om break opptrer if t.child[2]!= null { // Test på om det er else-gren? lab2 = genlabel(); emit2( ujp, lab2); // Hopp over else-grenen En break i kildeprogr. skal bli et hopp til denne labelen. Den vi angi første instruksjon etter nærmest omsluttende while-setning. emit2( label, lab1); if t.child[2]!= null { gencode(t.child[2], label); // Kode for else-gren, gå helt ut om break opptrer emit2( lab, lab2); // Hopp over else-gren går hit // Start på else-grenen, eller slutt på if- setningen // En gang til: test om det er else-gren? (litt plundrete programmering) case WhileKind { /* Se neste foil (som er laget etter forelesningen 23/4) */ case BreakKind { emit2( ujp, label); // Hopp helt ut av koden som dette gencode-kallet lager // (og helt ut av nærmest omsluttende while-setning) 14

Penere utgave også for while-setning (Ny foil etter forelesninge 24/4) void gencode(treenode t, String label){ String lab1, lab2; if t!= null{ // Tomt tre, ikke gjør noe switch t.kind { case ExprKind {... case IfKind {... case WhileKind { // While-setning lab1= genlabel(); emit2( lab, lab1); // Hopp hit om repetisjon og ny test En break i kildeprogr. skal bli et hopp til denne labelen. Den vi angi første instruksjon etter nærmest omsluttende while-setning. gencode(t.child[0], label); // Lag kode for det boolske uttrykket. «break» inne i uttrykk bare for // spesielle språk. Egentlig litt uklart hvor man her skal hoppe. lab2 = genlabel(); emit2( fjp, lab2); // Hopp ut av while-setning om false gencode(t.child[1], lab2); // kode for setninger, gå helt ut til lab2 om break opptrer emit2( ujp, lab1); // Repeter, og gjør testen en gang til emit2( lab, lab2); // Hopp hit ved while-slutt, og fra indre break-setning case BreakKind { emit2( ujp, label); // Hopp helt ut av koden som dette gencode-kallet lager // (og helt til bak nærmest omsluttende while-setning) 15

Om lur kodegen. av boolske uttrykk i if- og while-setninger NB: ER PENSUM, og det står litt om dette i kap 8.4.3. Men det meste av stoffet finnes bare på disse foilene. Vi har så langt tenkt at vi genererer kode for boolske uttrykk omtrent som for aritmetiske uttrykk, Vi får da altså true eller false som verdi, i stedet for f.eks. et heltall Boolske uttrykk kan imidlertid bare ha to verdier (true og false), og dette gjør at bergningen kan forenkles. Dette gjelder spesielt om uttrykket forekommer som betingelse i en while- eller if-setning Mange språk foreskriver at and og or i boolske uttrykk skal beregnes slik at om man etter første operanden vet svaret på hele opersjonen, så skal man ikke beregne den andre operanden. Dette er omtalt i boka, kap. 8.4.3, og kalles der short circuit - beregning Vi kaller det på norsk kortslutning av boolske uttrykk. Vi vil i fortsettelsen anta at språk-def. sier at det skal være slik

Eksempel på TA-kode for kortsluttet beregning (pensum!) Vi antar altså at språket foreskriver at and og or i boolske uttrykk skal beregnes slik at om man etter første operanden vet svaret på hele opersjonen, så skal man ikke beregne den andre operanden Vi skal altså kortslutte i følgende tilfeller: For or -operasjon om første operand blir true (hele svaret er da true) For and -operasjon om første operand er false (hele svaret blir da false) Oversett (pr hånd) følgende setning: if a<b (c>d && e>=f) then x=8 else y=5 endif t1 = a < b if-true t1 goto 1 // Vi vet at hele uttrykket er sant t2 = c > d if-false t2 goto 2 // Vi vet at hele uttrykket er galt t3 = e >= f if-false t3 goto 2 // Vi vet at hele uttrykket er galt, ellers er det sant og vi fortsetter label 1 x = 8 goto 3 label 2 y = 5 label 3

Om å lage kodegenerator for kortslutning etc. (pensum!) Vi velger her å generere TA.kode slik at vi slipper å tenke på at stakkdybden etc. må stemme overens ved hoppet og ved labelen (slik man må ved P-kode) Hovedsaken med den koden som er angitt på forrige foil er altså at man aldri beregner hele det boolske uttrykket (som en boolsk verdi), men at man, så fort man vet om hele uttrykket (eller et subuttrykk) blir true eller false, så hopper man direkte dit dette tilfellet skal behandles videre. Hvordan slik kode kan genereres vil avhenge veldig om vi bare skal ha symbolske labeler (strenger) som vi kan velge fritt, eller om hoppene skal gå til faktiske fysiske adresser, f.eks. til der else-grenen starter (som vanligvis ikke er kjent når det boolske uttrykket behandles). Det første tilfellet behandles på de neste foilene Det siste tilfellet er noe mer fiklete, men ikke prinsippielt annerledes. Dette tilfellet er ikke med som pensum (men er litt omtalt i kap. 8.4.2).

Vi skal lage tekstlig TA-kode, og lar oss inspirere av (den gamle) foilen under. Men merk at denne altså lager P-kode, men på de to neste foilene lages TAkode (men det blir liten forskjell) Til denne labelen skal en break i kildeprogrammet gå void gencode(treenode t, String label){ String lab1, lab2; if t!= null{ // Er vi falt ut av treet? switch t.kind { case ExprKind { // Dette tilfellet behandles som for generelle uttrykk (se foiler til kap 8, del1) case IfKind { // If-setning gencode(t.child[0], label); // Lag kode for det boolske uttrykket lab1= genlabel(); emit2( fjp, lab1); // Hopp til mulig else-gren, eller til slutten av for-setning gencode(t.child[1], label); // kode for then-del, gå helt ut om break opptrer (inne i uttrykk??) if t.child[2]!= null { // Test på om det er else-gren? lab2 = genlabel(); emit2( ujp, lab2); // Hopp over else-grenen emit2( label, lab1); // Start på else-grenen, eller slutt på if- setningen if t.child[2]!= null { gencode(t.child[2], label); // Kode for else-gren, gå helt ut om break opptrer emit2( lab, lab2); // Hopp over else-gren går hit // En gang til: test om det er else-gren? (litt plundrete programmering) case WhileKind { /* mye som over, men OBS ved indre break. Se boka */ case BreakKind { emit2( ujp, label); // Hopp helt ut av koden dette gencode-kallet lager // (og helt ut av nærmest omsluttende while-setning) 19

Kodegenerering for If-setning til TA-kode Vi lager behandlingen av if-setning ved å justere på den fra forrige foilen (som laget P-kode) Det å gå over fra P-kode til TA-kode blir knapt synlig her. Vi antar nå at språket ikke har noen break-setning (altså ingen parameter «label»)!! Men vi må likevel gi med parametere til den metoden som behandler det boolske uttrykket: Disse parametrene er to strenger, som er navn på planlagte labler. Disse vil angi hvor det skal hoppes når det blir klart om svaret er hhv. true eller false. case IfKind { String labt = genlabel(); String labf = genlabel(); // Skal hoppes til om betingelse er True/False genboolcode(t.child[0], labt, labf); // Lag kode for betingelsen. Vil alltid hoppe til labt eller labf emit2( lab, labt); // True-hopp fra betingelsen skal gå hit gencode(t.child[1]); // kode for then-gren (nå uten label-parameter for break-setning) String labx = genlabel(); if t.child[2]!= null { emit2( ujp, labx); // Skal angi slutten av en eventuell else-gren. // Test på om det er noen else-gren? // I så fall, hopp over else-grenen emit2( label, labf); // False-hopp fra betingelsen skal gå hit if t.child[2]!= null { // En gang til: test om det er else-gren? (litt plundrete programmering) gencode(t.child[2]); // Kode for else-gren emit2( label, labx); // Hopp forbi else-grenen går hit more cases Eneste viktige forskjell er kall på ny metode her. Se neste foil 20

Genere TA-kode for boolske uttrykk Men heller ikke denne vil lage helt god kode! Hvorfor?? (se helt nederst) void genboolcode(string labt, labf) { Vi bryr oss ikke med For : retur-navnet, siden de case : { alltid vil hoppe ut String labx = genlabel(); left.genboolcode(labt, labx); true emit2( label, labx); left right.genboolcode(labt, labf); false labt case && : { String labx = genlabel(); labx left.genboolcode(labx, labf); // som over true emit2( label, labx); right right.genboolcode(labt, labf); // som over false labt case not : { // Har bare left -subtre left.genboolcode(labf, labt); // Ingen kode lages!!! labf case < : { String temp1, temp2, temp3; // temp3 skal holde den boolsk verdi for relasjonen temp1 = left.genintcode(); temp2 = right.genintcode(); temp3 = genlabel(); emit4(temp3, temp1, «lt», temp2); // temp3 får (det boolske) svaret på relasjonen emit3(«jmp-false», temp3, labf); emit2(«ujp», labt); // Denne er unødvendig dersom det som følger etter er merket labt // Dette kan vi oppdage med en ekstra parameter som angir labelen bak // den konstrusksjonen man kaller kodegenererings-metoden for. // Dette blir en av oppgavene til kap 8 21