Kodgenerering

Kodgenerering  är en del av kompileringsprocessen , när en speciell del av kompilatorn , kodgeneratorn , omvandlar ett syntaktiskt korrekt program till en sekvens av instruktioner som kan köras på en maskin. I detta fall kan olika, i första hand maskinberoende optimeringar tillämpas. Ofta är en kodgenerator en vanlig del för många kompilatorer. Var och en av dem genererar en mellankod, som matas till kodgeneratorns ingång.

Vanligtvis ges ett parseträd eller ett abstrakt syntaxträd som indata till en kodgenerator . Trädet omvandlas till en linjär sekvens av mellanspråksinstruktioner (till exempel till en treadresskod).

Komplexa kompilatorer tenderar att göra flera passeringar genom olika mellanliggande former av kod. Denna flerstegsprocess används eftersom många kodoptimeringsalgoritmer är lättare att implementera individuellt, eller för att ett optimeringssteg beror på resultatet av ett annat steg. Dessutom, med en sådan organisation, är det lätt att skapa en kompilator som kommer att skapa kod för flera plattformar, eftersom det räcker för att ersätta det sista steget i kodgenereringen ( backend , engelsk backend).

Ytterligare kompileringssteg kan eller kanske inte hänvisas till som "kodgenerering", beroende på hur betydande ändringarna de gör kommer att vara. Lokal optimering kan alltså knappast kallas "kodgenerering", utan själva kodgeneratorn kan inkludera ett lokalt optimeringssteg.

Kodgeneratoruppgifter

Förutom huvuduppgiften att konvertera kod från en mellanrepresentation till maskininstruktioner försöker en kodgenerator vanligtvis optimera den genererade koden på ett eller annat sätt. Det kan till exempel använda snabbare instruktioner, använda färre instruktioner, använda befintliga register och förhindra redundanta beräkningar.

Några uppgifter som komplexa kodgeneratorer vanligtvis löser är:

Instruktionsval görs vanligtvis genom att rekursivt gå igenom det abstrakta syntaxträdet, i vilket fall delar av trädets konfigurationer jämförs med mönster; till exempel kan ett träd W:=ADD(X,MUL(Y,Z))omvandlas till en linjär sekvens av instruktioner för rekursiv sekvensgenerering t1:=Xoch t2:=MUL(Y,Z)följas av instruktionen ADD W,t1,t2.

I kompilatorer som använder ett mellanspråk kan det finnas två steg av instruktionsval - ett för att konvertera analysträdet till mellankod, och det andra (mycket senare) för att konvertera mellankoden till instruktioner i målinstruktionsuppsättningen. Det andra steget kräver ingen trädpassering: det kan utföras sekventiellt och består vanligtvis av en enkel ersättning av mellanspråksoperationer med deras motsvarande operationskoder. Faktum är att om kompilatorn faktiskt är en översättare (till exempel översätter man Eiffel till C ), så kan det andra steget av kodgenerering innebära att man bygger ett träd från den linjära mellankoden.

Kodgenerering vid körning

När kodgenerering sker under programexekvering, som i JIT , är det viktigt att hela kodgenereringsprocessen är effektiv i både tids- och minnesanvändning. Till exempel, när man tolkar reguljära uttryck, är det mer sannolikt att icke-deterministiska tillståndsmaskiner skapas än deterministiska, eftersom de är snabbare och tar upp mindre minne. Även om den genererar generellt mindre effektiv kod, kan JIT -kodgenerering ge möjligheten att profilera information som bara är tillgänglig under körning.

Litteratur