22. Vorlesung Dr.-Ing. Wolfgang Heenes - Ra.informatik.tu ...
22. Vorlesung Dr.-Ing. Wolfgang Heenes - Ra.informatik.tu ...
22. Vorlesung Dr.-Ing. Wolfgang Heenes - Ra.informatik.tu ...
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Grundlagen der Informatik III<br />
Wintersemester 2010/2011 – <strong>22.</strong> <strong>Vorlesung</strong><br />
<strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong><br />
int main() {<br />
printf("Hello, world!");<br />
re<strong>tu</strong>rn 0;<br />
}<br />
msg:<br />
main:<br />
.data<br />
.asciiz "Hello, world!"<br />
.text<br />
.globl main<br />
la $a0,msg<br />
li $v0,4<br />
syscall<br />
jr $ra<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 1
Inhalt<br />
1. Litera<strong>tu</strong>r<br />
2. Compiler III<br />
3. Lexikalische Analyse<br />
4. Symboltabellen<br />
5. Zwischencodegenerierung<br />
6. Zusammenfassung der Phasen der Übersetzung<br />
7. Ausgewählte Probleme<br />
8. Lex und Yacc<br />
9. Zusammenfassung und Ausblick<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 2
Litera<strong>tu</strong>r<br />
[ALSU08] Aho, Alfred V., Monica S. Lam, <strong>Ra</strong>vi Sethi und Jeffrey D. Ullmann:<br />
Compiler - Prinzipien, Techniken und Werkzeuge.<br />
Pearson, 2008.<br />
[BO10]<br />
Bryant, <strong>Ra</strong>ndal E. und David R. O´Hallaron: Computer Systems - A<br />
Programmer´s Perspective.<br />
Prentice Hall, 2010.<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 3
Compiler III<br />
Wiederholung<br />
◮ Grammatiken zur Syntaxbeschreibung<br />
◮ Syntaxanalyse<br />
◮ Parse-Bäume<br />
◮ Im Folgenden<br />
◮ Lexikalische Analyse<br />
◮ Symboltabellen<br />
◮ Zwischencodegenerierung<br />
◮ Zusammenfassung der Phasen der Übersetzung<br />
◮ Ausgewählte Probleme<br />
◮ Lex und Yacc<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 4
Lexikalische Analyse I<br />
◮ Modell des Compiler-Front-Ends<br />
Abbildung: Quelle: [ALSU08, S. 51]<br />
◮ Lexikalische Analyse gruppiert Eingabezeichen zu Tokenobjekten<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 5
Lexikalische Analyse II<br />
◮ Lexikalische Analyse gruppiert Eingabezeichen zu Tokenobjekten<br />
◮ Neben einem Terminal, das für Parsing-Entscheidungen verwendet wird,<br />
enthalten Tokenobjekte zusätzliche Informationen in der Form von<br />
Attributwerten<br />
◮ Bisher keine Unterscheidung zwischen den Begriffen Token und Terminal ⇒<br />
Token ist ein Terminal mit zusätzlichen Symbolen<br />
◮ Erinnerung: Die Sequenz von Eingabezeichen, die ein einzelnes Token bildet,<br />
wird als Lexem bezeichnet<br />
◮ Aufgaben der lexikalischen Analyse sind außerdem: Entfernen von<br />
Leerzeichen und Kommentaren<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 6
Lexikalische Analyse III<br />
◮ Viele Sprachen lassen beliebig viele Leerzeichen zu ⇒ werden bei der<br />
Analyse ignoriert<br />
◮ Auch Kommentare können ignoriert werden<br />
◮ Wenn z. B. Leerzeichen vom lexikalischen Scanner elimniert werden, muss<br />
der Parser sich keine Gedanken machen<br />
◮ Pseudoalgorithmus<br />
for ( ; ; peek = nächstes Eingabezeichen) {<br />
if (peek ist leer oder Tabulatorsprung) <strong>tu</strong>e nichts;<br />
else if (peek ist Zeilenumbruchzeichen)<br />
line = line + 1;<br />
else break;<br />
}<br />
◮ Zeilennummern sind für Fehlermeldungen nützlich ⇒ line zählt die Anzahl der<br />
Zeilenumbruchzeichen<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 7
Lexikalische Analyse IV<br />
◮ Vorausschauendes Lesen: Ein lexikalischer Scanner muss gegebenfalls<br />
einige Zeichen im Voraus lesen, um feststellen zu können, welches Token an<br />
den Parser zurückgegeben werden muss<br />
◮ Ein lexikalischer Scanner (z. B. für C) muss Zeichen vom Voraus lesen,<br />
nachdem er das Zeichen > gefunden hat<br />
◮ Ist das folgende Zeichen das Gleichheitszeichen =, dass ist > Teil der<br />
Zeichensequenz >=<br />
◮ >= Lexem des Tokens für den Operator „größer oder gleich“<br />
◮ Andernfalls stellt > den Operator „größer als“ dar ⇒ Scanner hat ein Zeichen<br />
zu viel gelesen<br />
◮ Realisierung eines Eingabepuffers ⇒ effizienter, Zeichenblöcke zu verarbeiten<br />
◮ Es gibt aber auch Operatoren z. B. * die ohne Vorauslesen identifiziert werden<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 8
Lexikalische Analyse V<br />
◮ Erkennen von Schlüsselwörtern und Bezeichnern: Die meisten Sprachen<br />
verwenden feste Zeichenketten (z. B. for, do und if) zur Identifizierung von<br />
Konstrukten ⇒ Zeichenkette wird als Schlüsselwort bezeichnet<br />
◮ Zeichenketten werden als Bezeichner für Variablen, Arrayzugriffe, Funktionen<br />
usw. verwendet<br />
◮ Grammatiken behandeln Bezeichner als Terminale, um den Parser zu<br />
vereinfachen<br />
◮ Der Parser erwartet dann, wenn ein Bezeichner Teil der Eingabe ist, das<br />
gleiche Terminal, z. B. id<br />
◮ Eingabe von count = count + increment;<br />
◮ Der Parser arbeitet dann den Terminalstream id = id + id ab.<br />
◮ Token id hat ein Attribut, das das Lexem speichert<br />
◮ <br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 9
Lexikalische Analyse VI<br />
◮ Da Schlüsselwörter den Regeln zur Erstellung von Bezeichnern entsprechen,<br />
muss ein Mechanismus gefunden werden, anhand dessen festgelegt werden<br />
kann, wann ein Lexem ein Schlüsselwort ist und wann es einen Bezeichner<br />
bildet<br />
◮ Problem ist einfacher zu lösen, wenn Schlüsselwörter reserviert sind ⇒<br />
dürfen dann nicht als Bezeichner verwendet werden<br />
◮ In ABAP können identische Zeichenketten für Bezeichner und Schlüsselworte<br />
verwendet werden (außerdem ist “+“ nicht gleich “ +“)<br />
◮ Zeichenketten können nur dann Bezeichner sein, wenn sie kein Schlüsselwort<br />
sind<br />
◮ Scanner kann in einer Tabelle auf die reservierten Wörter zugreifen und<br />
einfach unterscheiden, ist es ein Bezeichner oder Schlüsselwort<br />
◮ Pseudocode, weitere Erläuterungen [ALSU08, S. 98 f.]<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 10
Symboltabellen I<br />
◮ Bei Symboltabellen handelt es sich um Datenstruk<strong>tu</strong>ren, die von Compilern<br />
zur Speicherung von Informationen über Quellprogrammkonstrukte verwendet<br />
werden.<br />
◮ Die Informationen (= Symboltabelleneinträge) werden schrittweise während<br />
der Analysephase des Compilers gesammelt und in der Synthesephase<br />
verwendet, um den Zielcode zu erstellen<br />
◮ Einträge in der Symboltabelle enthalten Informationen über einen Bezeichner<br />
(z. B. Zeichenstring), seinen Typ, seinen Speicherplatz<br />
◮ Symboltabellen müssen normalerweise mehrere Deklarationen des gleichen<br />
Bezeichners in einem Programm unterstützen können<br />
◮ Gültigkeitsbereich einer Deklaration ist der Teil eines Programms, für das die<br />
Deklaration zutrifft<br />
◮ Für jeden Gültigkeitsbereich wird eine separate Symboltabelle eingerichtet<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 11
Symboltabellen II<br />
◮ Pseudocode: Indizes werden verwendet, um zwischen verschiedenen<br />
Deklarationen des gleichen Bezeichners zu unterscheiden<br />
1) {int x1; int y1;<br />
2) {int w2; bool y2; int z2;<br />
3) ...w2...;...x1...;...y2...;...z2...;<br />
4) }<br />
5) ...w0...;...x1...; ...y1...;<br />
6) }<br />
◮ Ach<strong>tu</strong>ng: Index ist nicht Teil des Bezeichners<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 12
Symboltabellen III<br />
◮ Das Vorkommen von y in Zeile 3 befindet sich im Gültigkeitsbereich von y in<br />
Zeile 2, da y innerhalb eines inneren Blocks neu deklariert wird<br />
◮ Das Vorkommen von y in Zeile 5 liegt jedoch im Gültigkeitsbereich der<br />
Deklaration von y in Zeile 1<br />
◮ Das Vorkommen von w in Zeile 5 liegt wahrscheinlich innerhalb des<br />
Gültigkeitsbereichs einer Deklaration von w außerhalb dieses Codefragments<br />
⇒ mit Index 0 wird eine Deklaration angegeben, die entweder global ist oder<br />
außerhalb dieses Blocks liegt<br />
◮ Deklaration von z ⇒ kann nur innerhalb des verschachtelten Blocks<br />
verwendet werden.<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 13
Symboltabellen IV<br />
◮ Symboltabellen werden miteinander verkettet<br />
Abbildung: Quelle: [ALSU08, S. 108]<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 14
Zwischencodegenerierung I<br />
◮ Zwischencodegenerierung, zwei Möglichkeiten<br />
◮ Bäume, Parse-Bäume und abstrakte Syntaxbäume<br />
◮ Lineare Darstellung ⇒ <strong>Dr</strong>ei-Adress-Code<br />
◮ Das Compiler-Front-End erstellt aber nicht nur eine Zwischendarstellung,<br />
sondern überprüpft auch, ob das Quellprogramm den syntaktischen und<br />
semantischen Regeln der Quellsprache folgt<br />
◮ Diese Prüfung wird auch als statische Überprüfung 1 bezeichnet<br />
◮ Ablei<strong>tu</strong>ng des <strong>Dr</strong>ei-Adress-Codes aus Syntaxbaum<br />
1 dynamische Überprüfung z. B. in Java<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 15
Zwischencodegenerierung II<br />
<strong>Dr</strong>ei-Adress-Befehle<br />
◮ Bei <strong>Dr</strong>ei-Adress-Code handelt es sich um Befehl im Format<br />
x = y op z<br />
◮ x, y und z sind Namen, Konstanten oder temporäre Werte<br />
◮ Arrayzugriff kann durch folgende Befehlsvariante realisiert werden<br />
x [y] = z<br />
x = y[z]<br />
◮ <strong>Dr</strong>ei-Adress-Befehle werden nacheinander ausgeführt, Ausnahme bedingte<br />
oder unbedingte Sprünge<br />
if False x goto L<br />
if True A goto L<br />
goto L<br />
◮ Kopieren von Werten<br />
x = y<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 16
Zwischencodegenerierung III<br />
Syntaxbaum<br />
◮ Teil eines Syntaxbaums<br />
Abbildung: Quelle: [ALSU08, S. 118]<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 17
Zwischencodegenerierung IV<br />
Übersetzung von Ausdrücken<br />
◮ Aufgabe: Übersetzen einfacher Ausdrücke: i - j + k<br />
◮ Für jeden Operatorknoten im Syntaxbaum eines Ausdrucks wird nun ein<br />
<strong>Dr</strong>ei-Adress-Befehl generiert<br />
◮ Dazu werden auch „temporäre“ Namen verwegen<br />
◮ Obiges Konstrukt wird zu<br />
t1 = i - j<br />
t2 = t1 + k<br />
◮ Arrayzugriff: a[i] = 2 * a[j-k]<br />
◮ Übersetzung aus Syntaxbaum zu:<br />
t3 = j - k<br />
t2 = a[t3]<br />
t1 = 2 * t2<br />
a[i] = t1<br />
◮ Pseudocode vgl. [ALSU08, S. 125 ff.]<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 18
Zusammenfassung: Phasen der Übersetzung I<br />
Abbildung: Quelle: [ALSU08, S. 130]<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 19
Zusammenfassung: Phasen der Übersetzung II<br />
◮ Ausgangspunkt bei einem syntaxgerichteten Übersetzer ist eine Grammatik<br />
für die Quellsprache<br />
◮ Mit der Grammatik wird die hierarchische Struk<strong>tu</strong>r von Programmen<br />
beschrieben<br />
◮ Grammatik wird mit grundlegenden Symbolen (Terminale) und variablen<br />
Symbolen (Nichtterminale) definiert ⇒ Symbole stellen Sprachkonstrukte dar<br />
◮ Die Regeln der Grammatik werden als Produktionen bezeichnet<br />
◮ Produktionen bestehen aus Nichtermial (oder Kopf, linke Seite) und einer<br />
Sequenz von Terminalen und Nichtterminalen<br />
◮ Rechte Seite ist der Rumpf der Produktion<br />
◮ Ein Nichtermial wird als Startsymbol festgelegt<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 20
Zusammenfassung: Phasen der Übersetzung III<br />
◮ Bei der Spezifikation eines Übersetzers ist es hilfreich,<br />
Programmierkonstrukten Attribute hinzuzufügen<br />
◮ Konstrukte werden durch Grammatiksymbole dargestellt ⇒ Attributkonzept<br />
wird auf Grammatiksymbole ausgeweitet<br />
◮ Beispiel für Attribute: ein mit einem Terminal num verknüpfter Integerwert<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 21
Zusammenfassung: Phasen der Übersetzung IV<br />
◮ Ein lexikalischer Scanner liest bei der Eingabe einzelne Zeichen und erstellt<br />
einen Tokenstream als Ausgabe, wobei ein Token aus einem Terminalsymbol<br />
mit zusätzlichen Informationen in der Form von Attributwerten besteht.<br />
◮ Schreibweise der Token z. B. als Tupel und in < > eingeschlossen<br />
◮ Beispiel: Token (id, “peek“) besteht aus dem Terminal id und einem Zeiger auf<br />
den Symboltabelleneintrag, der den String “peek“enthält.<br />
◮ Der Übersetzer verwendet die Tabelle, um reservierte Wörter und Bezeichner,<br />
die bereits aufgetreten sind, zu verfolgen<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 22
Zusammenfassung: Phasen der Übersetzung V<br />
◮ Die Syntaxanalyse (Parsing) wird dazu verwendet, beginnend mit dem<br />
Startsymbol einer Grammatik einen String mit Terminalen abzuleiten, indem<br />
ein Nichtterminal durch den Rumpf einer seiner Produktionen ersetzt wird<br />
◮ Der Parser erstellt einen Parse-Baum, in dem die Wurzel mit dem Startsymbol<br />
bezeichnet wird, jeder interne Knoten einer Produktion entspricht und jedes<br />
Blatt mit einem Terminal oder dem leeren String ɛ gekennzeichnet wird.<br />
◮ Die syntaxgerichtete Übersetzung erfolgt, indem den Produktionen in einer<br />
Grammatik entweder Regeln oder Programmfragmente hinzugefügt werden.<br />
◮ Eingebettete Programmfragmente werden auch semantische Aktionen<br />
genannt<br />
◮ Das Ergebnis der Syntaxanalyse wird als Zwischencode bezeichnet ⇒<br />
abstrakter Syntaxbaum, <strong>Dr</strong>ei-Adress-Code<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 23
Zusammenfassung: Phasen der Übersetzung VI<br />
◮ Symboltabellen sind Datenstruk<strong>tu</strong>ren, in denen Informationen über<br />
Bezeichner gespeichert werden.<br />
◮ Diese Informationen werden der Tabelle hinzugefügt, wenn die Deklaration<br />
eines Bezeichners analysiert wird<br />
◮ Eine semantische Aktion ruft Informationen aus der Symboltabelle ab<br />
◮ Ausführliche (wenn auch nicht immer ganz einfach verständliche)<br />
Informationen mit Beispiel im Pseudocode sind in [ALSU08] dargestellt<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 24
Ausgewählte Probleme I<br />
Registervergabe<br />
◮ Für die Programmierung in Assembler ist eine Übersicht der Register wichtig<br />
◮ Programmiermodell für die IA32-Architek<strong>tu</strong>r<br />
Abbildung: Quelle: [BO10, S. 202]<br />
◮ Abbildung der Zwischencodes (in dem potentiell sehr viele Variablen benutzt<br />
werden können) auf eine Maschine mit 8 Registern<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 25
Ausgewählte Probleme II<br />
Registervergabe<br />
◮ Ein wesentliches Problem bei der Codeerzeugung ist die Entscheidung,<br />
welche Werte in welchen Registern abgelegt werden sollen<br />
◮ Erinnerung: Speicherhierarchie (langsamer Hauptspeicher, schneller<br />
Registerspeicher)<br />
◮ Bei der Codeerzeugung muss darauf geachtet werden, eine optimale<br />
Zuweisung von Registern zu Variablen zu finden<br />
◮ Und das ist selbst bei Maschinen mit nur einem Register ggf. schwierig<br />
◮ Mathematisch gesehen ist das Problem NP-vollständig<br />
◮ Komplexität wird dadurch gesteigert, dass Prozessoren evt. bestimmte<br />
Konventionen für die Registernutzung haben<br />
◮ Im Prinzip kann man Register für die Aufnahme von Werten für die Dauer<br />
eines Blocks zuweisen<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 26
Ausgewählte Probleme III<br />
Registervergabe<br />
◮ Globale Registervergabe kann z. B. für eine feste Anzahl von Registern für die<br />
aktivsten Werten jeder Schleife vorgenommen werden<br />
◮ In frühen C-Compilern konnte der Programmierer einen Teil der Register<br />
explizit vergeben<br />
◮ Datentyp register<br />
◮ Überlegte Einsatz von Registern beschleunigte viele Programme<br />
◮ Aber: Programmierer musste ein Profil der Programme erstellen, um die<br />
entscheidenden Programmstellen zu ermitteln<br />
◮ Reminder: Schlüsselwort register immernoch vorhanden, Analyse hat aber<br />
gezeigt, das es ignoriert wird<br />
◮ Verwendungszähler, Registervergabe durch Graphfärbung (vgl. [ALSU08, S.<br />
679])<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 27
Ausgewählte Probleme IV<br />
Peephole-Optimierung<br />
◮ Eine Möglichkeit der Verbesserung des Zielcodes ist die<br />
Peephole 2 -Optimierung (vgl. [ALSU08, S. 670])<br />
◮ Das Guckloch ist ein kleines verschiebares Fenster zu einem Programm<br />
◮ Charakteristische Beispiele für Programmtransformationen<br />
◮ Beseitigung redundanter Befehle<br />
◮ Optimierung des Kontrollflusses<br />
◮ Algebraische Vereinfachung<br />
2 Guckloch<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 28
Ausgewählte Probleme V<br />
Peephole-Optimierung<br />
◮ Entfernen redundanter Lade- und Speicherbefehle<br />
◮ Zielprogramm hat folgenden Code<br />
LD R0,a<br />
ST a ,R0<br />
◮ Speicherbefehl nicht notwendig<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 29
Ausgewählte Probleme VI<br />
Peephole-Optimierung<br />
◮ Entfernen von unerreichbaren Codes<br />
◮ Ein Befehl ohne Sprungmarke direkt hinter einem unbedingten Sprung kann<br />
gelöscht werden<br />
◮ Weiteres Beispiel<br />
if debug == 1 goto L1<br />
goto L2<br />
L1: print debugging information<br />
L2: ...<br />
◮ Optimierung durch Beseitigung von Sprüngen<br />
if debug != 1 goto L2<br />
print debugging information<br />
L2: ...<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 30
Ausgewählte Probleme VII<br />
Peephole-Optimierung<br />
◮ Optimierung des Kontrollflusses<br />
goto L1<br />
...<br />
L1: goto L2<br />
◮ Wird durch folgende Konstruktion ersetzt<br />
goto L2<br />
...<br />
L1: goto L2<br />
◮ Weitere Optimierungen: Gibt es keine Sprünge mehr zu L1, kann die<br />
Anweisung L1: goto L2 gelöscht werden ⇒ Vorausgesetzt, davor steht ein<br />
unbedingter Sprung<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 31
Ausgewählte Probleme VII<br />
Peephole-Optimierung<br />
◮ Algebraische Vereinfachung und Kostenreduzierung<br />
◮ Oder<br />
x = x + 0<br />
x = x * 1<br />
◮ Reminder: Multiplikation und Division 2 wird durch Shift-Befehle realisiert<br />
◮ Für die Gleichung d = a·b− a·c werden 2 Multiplikationen und eine<br />
Subtraktion benötigt.<br />
◮ Die Gleichung kann umgeformt werden:<br />
d = a·b− a·c<br />
d = a·(b− c)<br />
◮ Außerdem: Common Subexpression Elimination, Zusammenfassen von<br />
Ausdrücken<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 32
Lex und Yacc<br />
◮ Im Prinzip ist der Entwurf von Compilern für eine Sprache sehr reguläres<br />
Problem<br />
◮ Für eine Sprache liegt eine Grammatik vor<br />
◮ Warum nicht automatisierte Generierung für lexikalische Scanner?<br />
◮ Tool: Lex bzw. Flex ist ein solcher Scanner (vgl. [ALSU08, S. 170 ff.])<br />
◮ Eingabesprache wird als Lex-Sprache bezeichnet, das Tool selbst als<br />
Lex-Compiler<br />
◮ Struk<strong>tu</strong>r eines Lex-Programms<br />
Deklaration<br />
%%<br />
Übersetzungsregeln<br />
%%<br />
Hilfsfunktionen<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 33
Lex und Yacc<br />
◮ Yacc ist ein Parsergenerator (vgl. [ALSU08, S. 343 ff.])<br />
◮ Erleichterung beim Bau eines Compiler-Front-Ends<br />
Deklaration<br />
%%<br />
Übersetzungsregeln<br />
%%<br />
Unterstützende C-Routinen<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 34
C2H Compiler<br />
◮ Compiler: Sprachübersetzer<br />
◮ Quellsprache C, Zielsprache HDL 3<br />
◮ Wird verwendet für Designspezifikation (auf unterschiedlichen Ebenen),<br />
Simulation, Verifikation und Dokumentation<br />
◮ Aber auch Synthese für Zielarchitek<strong>tu</strong>ren (ASIC bzw. FPGA)<br />
◮ C2H Compiler übersetzt C-Quellcode in eine Hardwarebeschreibungssprache<br />
◮ Welchen Sinn macht das?<br />
◮ Problem: Sequentielle Beschreibung ⇒ Zielarchitek<strong>tu</strong>r arbeitet parallel<br />
3 Hardware Description Language<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 35
Weiterführende Veranstal<strong>tu</strong>ng und Forschung<br />
am Fachbereich Informatik<br />
◮ FG Eingebettete Systeme und ihre Anwendungen<br />
◮ Prof. <strong>Dr</strong>. A. Koch<br />
◮ <strong>Vorlesung</strong>: Optimierende Compiler im Sommersemester 2011<br />
◮ Grundkenntnisse Algorithmen und Datenstruk<strong>tu</strong>ren<br />
◮ Java<br />
◮ Rechnerarchitek<strong>tu</strong>r (erworben z. B. durch Technische Grundlagen der Informatik)<br />
◮ Praktikum: Compiler für Java-artige Sprache und MIPS<br />
◮ Forschung: Entwurf adaptiver Rechensysteme<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 36
Zusammenfassung und Ausblick<br />
◮ Compiler III<br />
Nächste <strong>Vorlesung</strong> behandelt<br />
◮ Betriebssysteme I<br />
19. Januar 2011 | Technische Universität Darmstadt | <strong>Dr</strong>.-<strong>Ing</strong>. <strong>Wolfgang</strong> <strong>Heenes</strong> | 37