Dagens tema: Kodegenerering Listing Minila Hovedansvarlig Listeansvarlig Flok Tegngenerator Linjegenerator Symbolgenerator Flinkrepresentant Tregenerator Kodegenerator Del 0 Del 1 Del 2 Introduksjon FlinkRepresentation Enkle variable Noen enkle setninger Uttrykk Litt mer kompliserte setninger med betingelser Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 1 av 20
Oversikt Formålet med kodegenereringen er å lage Flok kode som Flink maskinen kan utføre: Inndata er trerepresentasjonen av Minila programmet. Utdata er en fil med Flok kode. Eksempel Anta at vi har Minila programmet prog begprog outint(1) 1; outline; endprog Den genererte Flok filen ser slik ut: #! /store/bin/flink 5 6 12 1 0 20 1 0 10 1 0 11 0 0 0 0 0 0 0 0 0 0 0 Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 2 av 20
Genererte instruksjoner Til hjelp under uttesting (og etterpå!) finnes opsjonen I som lar kompilatoren fortelle hvilken kode den lager: 1: prog I(resVar) 0: 1 cpfrom I(resVar) 1: 1 cpto I(resVar) 2: 1 cpc I(resVar) 3: 1 xin I(resVar) 4: 1 xinc I(resVar) 5: 1 xbet 2: begprog 3: outint(1) 1; outline; 4: endprog I(Instr) 0: JMP(12) 1 0 I(fillOld) 0: 1 I(Instr) 1: SETI(20) 1 0 I(Instr) 2: OUTI(10) 1 0 I(Instr) 3: OLIN(11) 0 0 I(Instr) 4: STOP(0) 0 0 Å implementere denne opsjonen er en del av den obligatoriske oppgaven. Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 3 av 20
Hvordan lage kodegenerering Det beste er å følge samme opplegg som for å skrive ut programkoden i del 1: Legg en metode inn i alle klasser som representerer en bit av Minila programmet: class WhileSent {. void analyze (DeclSeqv ds) {.... void makecode () {... Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 4 av 20
class FlinkRepresentation Man kan skrive kodefilen direkte, men det er enklere (i hvert fall tankemessig) å plassere koden rett inn i en slags Flink maskin: class FlinkRepresentation { private String flokfile; private int[] func, adr, corr, istore; private void makeinst (int f, int a, int c) { listresp.testinstout(nextinst, instname, f, a, c); if (nextinst > maxinst) mainresp.error("instruksjonslageret er fullt" ); func[nextinst] = f; adr[nextinst] = a; corr[nextinst] = c; nextinst++;. public void makeflokfile () {... Så kan kodefilen skrives ut til slutt. Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 5 av 20
Variable Det må settes av plass i heltallsminnet til alle enkle variable. Dette løses enkelt med en metode i FlinkRepresentation: class FlinkRepresentation { private int nextint=0, maxint=1000; private int[] istore = new int[maxint]; int resvar (String name) { // Denne reserverer 1 celle i heltallslageret, ved å // øke nextint. Returnér adressen til cellen. // (Parameteren name er bare med // for I testutskriften.) listresp.testresvarout(nextint, 1, name); ++nextint; if (nextint > maxint) mainresp.error("heltallslageret er fullt"); return nextint 1;. Dette fungerer for Minila; de fleste andre programmeringsspråk trenger mer kompliserte opplegg. Array er er tema neste uke. Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 6 av 20
Setninger På tilsvarende måte lager vi metoder for å legge de ulike instruksjonene i instruksjonslagrene: class FlinkRepresentation { private int nextinst=0, maxinst=1000; private int[] func, adr, corr; private void makeinst (String instname, int f, int a, int c) { listresp.testinstout(nextinst, instname, f, a, c); if (nextinst > maxinst) mainresp.error("instruksjonslageret er fullt" ); func[nextinst] = f; adr[nextinst] = a; corr[nextinst] = c; nextinst++;. public void makeoutc (int a, int c) { makeinst("outc", 28, a, c);. Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 7 av 20
Setningen outchar Da har vi apparatet for å lage kode for enkle setninger som outchar. Kodeskjemaer for alle setningene finnes i kompendiet. Minila Flink kode outchar uttrykk Beregn uttrykk class OutCharSent { private Expression expr; OUTC void analyze (DeclSeqv ds) {... void makecode () { listresp.testkout("inn", "OutCharSent"); expr.makecode(); flinkrepr.makeoutc(0, 0); listresp.testkout("ut", "OutCharSent"); Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 8 av 20
Testutskrift K På samme måte som A var nyttig til å finne feil under analysen, trenger vi en opsjon K som forteller hvilke metoder kodegeneratoren er innom: 1: prog 2: begprog 3: outint(1) 1; outline; 4: endprog K: INN Program K: INN DeclSeqv K: UT DeclSeqv K: INN SentSeqv K: INN OutIntSent K: INN Expression K: INN ConstPart K: UT ConstPart K: UT Expression K: UT OutIntSent K: INN OutLineSent K: UT OutLineSent K: UT SentSeqv K: UT Program Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 9 av 20
Uttrykk Hvordan lager vi kode for et uttrykk som i a := 4 * a 17? Første operand Det er ganske enkelt å lage kode som legger en konstant eller en variabel i I registeret: Minila Flink kode tallkonstant SETI Konstantens verdi tegn SETI Tegnets verdi enkel variabel LDI Variabelens adresse Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 10 av 20
Resten av uttrykket Resten av uttrykket består av 0 eller flere par (operator,konstant/variabel) som vi kan ta etter tur. Minila arop enkel variabel Flink kode arop I variabelens adresse arop konstant adr INTG konstantens verdi arop I adr (Legg merke til at konstanter må ligge i minnet.) Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 11 av 20
1: prog I(resVar) 0: 1 cpfrom I(resVar) 1: 1 cpto I(resVar) 2: 1 cpc I(resVar) 3: 1 xin I(resVar) 4: 1 xinc I(resVar) 5: 1 xbet 2: var a; 3: begprog 4: a := 3; 5: a := 4 * a 17; 6: outint(1) a; 7: endprog I(Instr) 0: JMP(12) 1 0 I(resVar) 6: 1 a I(fillOld) 0: 1 I(Instr) 1: SETI(20) 3 0 I(Instr) 2: STI(2) 6 0 I(Instr) 3: SETI(20) 4 0 I(Instr) 4: MULI(7) 6 0 I(resConst) 7: 17 I(Instr) 5: SUBI(6) 7 0 I(Instr) 6: STI(2) 6 0 I(Instr) 7: LDI(1) 6 0 I(Instr) 8: OUTI(10) 1 0 I(Instr) 9: STOP(0) 0 0 Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 12 av 20
#! /store/bin/flink 10 8 12 1 0 20 3 0 2 6 0 20 4 0 7 6 0 6 7 0 2 6 0 1 6 0 10 1 0 0 0 0 0 0 0 0 0 0 0 17 Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 13 av 20
Setninger Noen setninger er litt mer kompliserte å generere kode for. While setningen Minila koden i := 10; while i <> 0 do v := v + i; i := i 1; endwhile; skal generere denne koden: I(Instr) 1: SETI(20) 10 0 I(Instr) 2: STI(2) 6 0 I(Instr) 3: LDI(1) 6 0 I(Instr) 4: STI(2) 5 0 I(Instr) 5: SETI(20) 0 0 I(Instr) 6: SUBI(6) 5 0 I(Instr) 7: JEQI(16) 1 0 I(Instr) 8: LDI(1) 7 0 I(Instr) 9: ADDI(5) 6 0 I(Instr) 10: STI(2) 7 0 I(Instr) 11: LDI(1) 6 0 I(resConst) 8: 1 I(Instr) 12: SUBI(6) 8 0 I(Instr) 13: STI(2) 6 0 I(Instr) 14: JMP(12) 3 0 Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 14 av 20
Hoppadresser Koden inneholder to hopp: Minila Flink kode while betingelse do xw Som angitt J xrel I xew. oversettes som vanlig endwhile xew.. JMP xw Hopp til kjent adresse Den siste hoppet er greit nok: Bare husk adressen (dvs indeksen i istore) da man begynte å lage kode for setningen. Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 15 av 20
Hopp til ukjent adresse Hva med det første hoppet? Når koden skal lages, vet vi ikke hvor langt vi skal hoppe. Løsningen er: ❶ Generér en hoppinstruksjon til adresse 1. (Husk også adressen til denne instruksjonen.) ❷ Når vi en stund senere vet den riktige adressen, kan vi sette inn denne i stedet. class FlinkRepresentation { private int[] func, adr, corr;. void filloldadr (int instnr, int newadr) { // Fyll instruksjon instnr med adresse newadr listresp.testfilloldadrout(instnr, newadr); adr[instnr] = newadr; Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 16 av 20
Hele koden Da har vi hele koden for While setningen: void makecode () { listresp.testkout("inn", "WhileSent"); int whilestart = flinkrepr.nextinstadr(); cond.makecode(); int falsecond = flinkrepr.nextinstadr() 1; SS.makeCode(); flinkrepr.makejmp(whilestart,0); flinkrepr.filloldadr(falsecond, flinkrepr.nextinstadr()); listresp.testkout("ut", "WhileSent"); Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 17 av 20
Betingelser Hvordan skal vi lage kode for en betingelse som while a*2 > b+1 do? Det er i grunnen bare én måte å gjøre det på: ❶ Beregn uttrykket til venstre for relasjonen. ❷ Beregn uttrykket til høyre. ❸ Trekk det venstre uttrykket fra det høyre. ❹ Lag et betinget hopp (som sjekker I registeret mot 0). Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 18 av 20
Mellomlagring Når vi har beregnet den venstre verdien, må vi lagre den et sted mens vi beregner den høyre. Ingen registre er ledige, så vi må sette av en lokasjon xbet et fast sted i minnet. Valg av hoppinstruksjon Litt tankearbeid gir oss denne tabellen for hvilke instruksjoner vi skal lage: xrel = =/=,<> < <= > >= J xrel I JNEI JEQI JLEI JLTI JGEI JGTI Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 19 av 20
1: prog I(resVar) 0: 1 cpfrom I(resVar) 1: 1 cpto I(resVar) 2: 1 cpc I(resVar) 3: 1 xin I(resVar) 4: 1 xinc I(resVar) 5: 1 xbet 2: var a, b; 3: begprog 4: a := 10; 5: b := 7; 6: while a*2 > b+1 do 7: a := a 1; 8: endwhile; 9: endprog I(Instr) 0: JMP(12) 1 0 I(resVar) 6: 1 a I(resVar) 7: 1 b I(fillOld) 0: 1 I(Instr) 1: SETI(20) 10 0 I(Instr) 2: STI(2) 6 0 I(Instr) 3: SETI(20) 7 0 I(Instr) 4: STI(2) 7 0 I(Instr) 5: LDI(1) 6 0 I(resConst) 8: 2 I(Instr) 6: MULI(7) 8 0 I(Instr) 7: STI(2) 5 0 I(Instr) 8: LDI(1) 7 0 I(resConst) 9: 1 I(Instr) 9: ADDI(5) 9 0 I(Instr) 10: SUBI(6) 5 0 I(Instr) 11: JGEI(19) 1 0 I(Instr) 12: LDI(1) 6 0 I(resConst) 10: 1 I(Instr) 13: SUBI(6) 10 0 I(Instr) 14: STI(2) 6 0 I(Instr) 15: JMP(12) 5 0 I(fillOld) 11: 16 I(Instr) 16: STOP(0) 0 0 Dag Langmyhr,Ifi,UiO: Forelesning 8. november 2005 Ark 20 av 20