Ein Source-Code kann direkt in die Zielmaschinencode übersetzt werden, warum dann überhaupt die wir brauchen, um den Quellcode in einen Zwischencode, der dann den Zielcode übersetzt übersetzen? Lassen Sie uns die Gründe, warum wir einen Zwischencode benötigen.
Wenn ein Compiler übersetzt die Quellsprache in die Zielmaschinensprache, ohne dass die Möglichkeit zur Erzeugung von Zwischencode, wird für jede neue Maschine, eine der vollen nativen Compiler erforderlich.
Zwischencode entfällt die Notwendigkeit eines neuen vollständigen Compiler für jede einzigartige Maschine, indem der Analyseabschnitt gleiche für alle Compiler.
Der zweite Teil der Compiler Synthese wird nach der Zielmaschine geändert.
Es wird einfacher zu gelten die quellcode modifikationen zu verbessern Codeleistung durch die Anwendung Code-Optimierung Techniken die auf dem Zwischencode.
Zwischencodes können in einer Vielzahl von Wege dargestellt werden, und sie haben ihre eigenen Vorteile.
hohen Niveau IR - Hochrangige Zwischencodedarstellung ist sehr nah an der Quelle Sprache selbst. Sie lassen sich leicht aus dem Quellcode erzeugt werden, und wir können CodeModifikationen leicht anzuwenden, um die Leistung zu verbessern. Aber Für ziel maschinen optimierung, ist es weniger bevorzugt ist.
niedrigen Niveau IR - Dieser ist in der Nähe der Zielmaschine, welche es sich für Register und Speicherzuweisung, Befehlssatz-Auswahl, etc. Es ist gut für die maschinenabhängige Optimierungen macht.
Zwischencode kann entweder sprachspezifisch sein (zB Byte-Code für Java) oder sprachunabhängig (Drei-Adressen-Code).
Zwischencodegenerator erhält ein Eingangssignal von seinem Vorgänger Phase Semantikanalysator in Form eines kommentierten Syntaxbaum. Das Syntaxbaum kann dann in eine lineare Darstellung, beispielsweise Postfixnotation umgewandelt werden. Zwischencode neigt dazu, maschinenunabhängigen Code. Daher Code-Generator übernimmt, um unbegrenzte Anzahl von Speicher (Register), um Code zu generieren.
Zum Beispiel:
a = b + c * d;
Der Zwischencode-Generator wird versuchen, diesen Ausdruck in Unterausdrücke zu teilen und erzeugen dann den entsprechenden Code.
r1 = c * d; r2 = b + r1; r3 = r2 + r1; a = r3
r als Registern im Zielprogramm verwendet.
Ein Drei-Adressen-Code hat höchstens drei Adressenstellen, um den Ausdruck zu berechnen. Ein Drei-Adressen-Code kann in zwei Formen dargestellt werden:. Vierbettzimmer und Dreibettzimmer
Jede Anweisung in vervierfacht-Präsentation ist in vier Felder aufgeteilt: Betreiber, arg1, arg2 und Ergebnis Das obige Beispiel ist unten in vervierfacht-Format dargestellt:
Op | arg1 | arg2 | Resultat |
* | c | d | r1 |
+ | b | r1 | r2 |
+ | r2 | r1 | r3 |
= | r3 | a |
Jeder Anweisung in Tripeln Darstellung hat drei Felder: op, arg1 und arg2.The Ergebnisse der jeweiligen Unterausdrücke werden durch die Position des Ausdrucks bezeichnet. Triples stellen Ähnlichkeit mit DAG und Syntaxbaum. Sie entsprechen DAG während Vertreter Ausdrücke.
Op | arg1 | arg2 |
* | c | d |
+ | b | (0) |
+ | (1) | (0) |
= | (2) |
Triples Gesicht vor dem Problem von Code Unbeweglichkeit während Optimierung, wie die Ergebnisse sind Positions- und Änderung der Reihenfolge oder Position eines Ausdrucks kann zu Problemen führen.
Diese Darstellung ist eine Erweiterung über verdreifacht Darstellung. Es verwendet Zeiger statt Position zu speichern Ergebnisse. Dies ermöglicht es den Optimierer frei neu positionieren Sie den Unterausdruck, um einen optimierten Code zu erzeugen.
Eine Variable oder Verfahren muss erklärt werden, bevor es verwendet werden kann. Erklärung beinhaltet Zuweisung von Speicherplatz im Speicher und Eingabe von Typ und den Namen in der Symboltabelle. Ein Programm kann codiert werden und entworfen halten den Zielrechner Struktur im Auge, aber es kann nicht immer möglich sein, präzise Konvertierung eines Quellcodes seiner Zielsprache.
Einnahme das ganze Programm als eine Sammlung von Prozeduren und Unter Verfahren wird es möglich, die Namen lokaler dem Verfahren erklären. Speicherzuordnung in einer fortlaufenden Weise durchgeführt und namen werden in den Speicher in der Reihenfolge, wie sie in dem Programm angegebenen zugeordnet. Wir verwenden Offset-Variable und setzen Sie ihn auf Null {offset = 0}, die die Basisadresse zu kennzeichnen.
Die Source-Programmiersprache und der ZielMaschine-Architektur kann in der Art Namen gespeichert werden variieren, so relative Adressierung verwendet wird. Während der erste Name wird zugewiesenen Speicher ab der Speicherstelle 0 {offset = 0}, den nächsten Namen erklärte später, sollte zugeteilt werden Speicher neben dem ersten.
Beispiel:
Wir Nehmen wir das Beispiel der Programmiersprache C, wo eine Integer-Variable ist zugewiesen 2 Byte Speicher und eine float-Variable ist zugewiesen mit 4 Byte Speicher.
int a; float b; Allocation process: {offset = 0} int a; id.type = int id.width = 2 offset = offset + id.width {offset = 2} float b; id.type = float id.width = 4 offset = offset + id.width {offset = 6}
Um dieses Detail in einer Symboltabelle eingeben, ein Verfahren, Enter benutzt werden. Diese Methode kann die folgende Struktur haben:
enter(name, type, offset)
Dieses Verfahren sollte einen Eintrag in der Symboltabelle zu erstellen, für die Variable name, haben seiner Art eingestellt zu Art und relative Adresse Offset im Datenbereich.