Techniki kompilacji
Wykład I
1
Adam Piotrowski
Katedra Mikroelektroniki i Technik Informatycznych
tel: 042 631 27 20e-mail: [email protected]
http://lux.dmcs.pl/tk/http://www.dmcs.pl/~komam/tkz
2
Literatura• Podstawowa
– A.V. Aho, R. Sethi, J. D. Ullman, "Compilers - Principles, Techniques, and Tools", Addison-Wesley 2007 (polskie wydanie WNT 2002)
– W. M. Waite, G. Goos, "Konstrukcjakompilatorów", WNT 1989
• Uzupełniająca– John R. Levine, "Linkers and
Loaders", Morgan Kaufmann Publishers 1999 (manuskrypt dostepny online)
– S. S. Muchnick, "Advanced Compiler Design and Implementation", Morgan Kaufmann Publishers 1997
3
Zagadnienia• Część teoretyczna
– Kompilacja programów– Translacja kodu języka wysokiego poziomu
do języka symbolicznego– Analizator leksykalny– Analizator składniowy– Gramatyka, języki używane w budowie
kompilatora• Część praktyczna
– Programy do budowy kompilatora (flex i bison)
– Zarządzane kompilacją projektu (program make)
4
Wykład I - Zagadnienia
• Kompilacja programów– proces kompilacji– budowa kompilatora
• Translacja kodu języka wysokiego poziomu do języka symbolicznego – projekt kompilatora dla wirtualnego procesora
5
Napisaliśmy program, jak go
uruchomić?• Kompilator– Przetwarza cały program na postać
zrozumiałądla procesora (C/C++, Fortran)
• Interpreter– Przetwarza osobno każdą pojedynczą
instrukcję (Vbasic, Python, Języki skryptowe, Bash)
• Rozwiązania pośrednie– Kod pośredni, interpretowany przez
procesor wirtualny (Java)6
System przetwarzania języków
7
Szkieletowy program główny
Preprocesor
Program źródłowy
Kompilator
Wynikowy program w asemblerze
Asembler
Przemieszczalny kod maszynowy
Program ładujący/konsolidator
Bezwzględny kod maszynowy
Biblioteki, przemieszczalne pliki obiektowe
gcc test.o –o test
gcc –E test.c –o test.i
gcc –S test.c –o test.s
as test.s –o test.o
typedef unsigned char __u_char;typedef unsigned short int __u_short;typedef unsigned int __u_int;typedef unsigned long int __u_long;
extern int fclose (FILE *__stream);
extern int fflush (FILE *__stream);
int main(){ printf("Hello world\n"); return 0;}
#include <stdio.h>
int main(){ printf("Hello world\n"); return 0;}
.file "main.c" .section .rodata.LC0: .string "Hello world" .text.globl main .type main, @functionmain:.LFB2: pushq %rbp.LCFI0: movq %rsp, %rbp.LCFI1: movl $.LC0, %edi call puts movl $0, %eax leave ret
Elementy kompilatora
8
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Elementy kompilatora
9
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Przechowuje informacje na temat stałych, zmiennych, funkcji, procedur zadeklarowanych w programie. MAKRA NIE SĄ UMIESZCZANE W TABLICY SYMBOLI
Informacje w tablicy symboli są zbierane podczas analizy leksykalnej i składniowej, natomiast są wykorzystywane podczas analizy syntaktycznej, optymalizacji i generacji koduidentyfikator typ adres
pozycja real 0
poczatek real 8
tempo real 16
Elementy kompilatora
10
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
W przypadku błędu nie przerywamy procesu kompilacji, próbujemy zastosować techniki odzyskiwania kontroliRodzaje błędów:
•leksykalne (błędnie wpisany identyfikator, słowo kluczowe lub operator)•składniowe (wyrażenie arytmetyczne z niewyważonymi nawiasami)•semantyczne (zastosowanie operatora do niekompatybilnego typu)•logiczne (wywołanie rekurencji w nieskończonej pętli, sprawdzanie warunku który nigdy nie będzie prawdziwy)
Elementy kompilatora
11
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•czytanie znaków z wejścia i produkcja sekwencji symboli leksykalnych dla analizatora składniowego•eliminacja komentarzy i białych znaków•informowanie o aktualnym numerze analizowanego wiersza•rozwijanie makr preprocesora•uzupełnianie tablicy symboli
Analiza leksykalna• Pojęcia podstawowe
– symbol leksykalny (atomy leksykalne)• np. id, liczba_rzeczywista, liczba_calkowita
– leksem• np. „ala”, 3.14, 3
– wzór• Powody rozdzielenia analizy leksykalnej i
składniowej– prostota projektowania– poprawienie wydajności– zwiększenie przenośności kompilatora
• opisywane za pomocą prostych gramatyk lub wyrażeń regularnych (automaty stanowe)
12
Analiza leksykalna• Większość symboli leksykalnych należy do jednej z grup:
– nazwy (identyfikatory)– słowa zarezerwowane (ustalony podzbiór zbioru nazw)– liczby całkowite– liczby rzeczywiste– łańcuchy znakowe– operatory:
• addytywne (+, -),• unarne (+, -),• multiplikatywne (*, /)• relacyjne (<, >, =, <=, >=, <>)• logiczne (and, or, not)• przypisania (:=)
– ograniczniki jednoznakowe: ; , [ ] ( ) .– ograniczniki dwuznakowe: (* , *), +=, ++ itd.
13
Analizator leksykalny
pozycja := poczatek + tempo * 60
14
identyfikator
identyfikator identyfikator liczba
op_mul
op_add
op_przypisania
identyfikator
typ adres
pozycja real 0
poczatek real 8
tempo real 16
Symbole leksykalne:
Leksemy:
identyfikator:zbiór zaczynający się od litery lub podkreślenia, po którym następuje dowolnie długi ciąg liter, cyfr, podkreśleń
op_add: operator dodawania lub odejmowaniaop_mul:
operatory mnożenia i dzieleniaop_przypisania: operator składający się ze znaku „:” po którym następuje znak „=„
Elementy kompilatora
15
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•weryfikacja poprawności składniowej programu źródłowego•wykrycie i neutralizacja błędów składniowych•transformacja struktury programu do postaci drzewa wywodu
Formalna gramatykabezkontekstowa
• Zbiór tokenów (symboli leksykalnych) zwanych symbolami terminalnymi
• Zbiór symboli nieterminalnych• Zbiór produkcji, z których każda składa się
z symbolu nieterminalnego, zwanego lewą stroną produkcji, strzałki oraz sekwencji tokenów i symboli nieterminalnych, zwanej prawą stroną produkcji
• Jednego wyróżnionego symbolu nieterminalnego, zwanego symbolem startowym
16
Analiza składniowaistrukcja_przypisania -> identyfikator ':=' wyrażenie
wyrażenie -> liczba wyrażenie -> identyfikator wyrażenie -> wyrażenie '+' wyrażenie wyrażenie -> wyrażenie '*' wyrażenie
17
instrukcja przypisania
identyfikator wyrażenie
wyrażenie
wyrażeniewyrażenie
identyfikator
pozycja := początek +
identyfikator
wyrażenie
tempo +
liczba
60
Elementy kompilatora
18
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•weryfikacja poprawności semantycznej programu źródłowego•sprawdzenie czy zmienne są zadeklarowane•sprawdzenie zgodności pomiędzy parametrami aktualnymi i formalnymi procedur i funkcji•sprawdzenie czy obiekty nie są deklarowane wielokrotnie
Analiza semantyczna
19
instrukcja przypisania
identyfikator wyrażenie
wyrażenie
wyrażeniewyrażenie
identyfikator
pozycja := początek +
identyfikator
wyrażenie
tempo +
liczba
60
inttireal
identyfikator
typ adres
pozycja real 0
poczatek real 8
tempo real 16
Elementy kompilatora
20
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•generacja kodu pośredniego, niezależnego od sprzętu oraz wejściowego języka programowania•umożliwia przenośność kompilatora pomiędzy różnymi architekturami oraz językami•umożliwia implementację optymalizacji niezależnych od docelowej architektury oraz wejściowego języka programowania
Generacja kodu pośredniego• Trójadresowy kod pośredni
– każdy rozkaz oprócz przypisania może mieć co najwyżej jeden operator
– podczas translacji kodu drzewa wyprowadzeń do kodu trójadresowego kompilator może wstawić dodatkowe zmienne tymczasowe przechowujące tymczasowe wyniki operacji
– niektóre z operacji trójadresowych mogą mieć mniej niż trzy argumenty
21
temp1 := inttoreal (60)temp2 := id1 * temp1temp3 := id2 + temp2id3 := temp3
Elementy kompilatora
22
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•poprawa efektywności kodu wynikowego, ograniczenie rozmiaru oraz czasu wykonania programu•może być wykonywana na wielu poziomach (kod źródłowy, kod pośredni, kod wynikowy)
Przykładowe algorytmy optymalizacji
• usuwanie kodu martwego• eliminacja podwyrażeń wspólnych• propagacja kopii• zmienne indukcyjne• redukcja mocy• użycie tożsamości algebraicznych
23
Optymalizacja
24
temp1 := inttoreal (60)temp2 := id1 * temp1temp3 := id2 + temp2id3 := temp3
konwersja z liczby typu int na liczbę typu real na etapie generacji kodu
temp1 := tempo * 60.0pozycja := poczatek + temp1
redukcja zmiennej tmp3
Elementy kompilatora
25
Analizator leksykalny
Analizator składniowy
Analizator semantyczny
Gen. kodu pośredniego
Optymalizator kodu
Generator kodu
Program źródłowy
Program wynikowy
Tablica symboli
Obsługa błędów
Zadania:•wygenerowanie kodu wynikowego w postaci:
•kodu asemblera•przemieszczalnego kodu maszynowego•gotowego programu wykonywalnego
•wybór rozkazów•przydział rejestrów
Generacja kodu
26
pozycja := poczatek + tempo * 60
MOVF 16, R2MULF #60.0, R2MOVF 8, R1ADDF R2, R1MOVF R1,0
identyfikator
typ adres
pozycja real 0
poczatek real 8
tempo real 16
Translacja pojedynczej instrukcji
27
Analizator leksykalny
pozycja := poczatek + tempo * 60
id1 := id2 + id3 * 60
:=
id1 +
id2id3
*
60
Analizator składniowy
Analizator semantyczny
id1
:=+
id2id3
*
60
inttoreal
Generacja kodu pośredniego
temp1 := inttoreal (60)temp2 := id1 * temp1temp3 := id2 + temp2id3 := temp3
Optymalizator kodu
temp1 := tempo * 60.0pozycja := poczatek + temp1
Generator kodu
MOVF 16, R2MULF #60.0, R2MOVF 8, R1ADDF R2, R1MOVF R1,0
Przykład: budowa kompilatora gcc
28
Brak tablicy symboli !!!
Generacja kodu
• Procesor docelowy– architektura harwardzka– architektura pamięć-pamięć– kompilacja do postaci asemblera
symbolicznego• z adresami bezwzględnymi zmiennych• z adresami symbolicznymi rozkazów
• Dostępna implementacja wzorcowa kompilatora oraz maszyny wirtualnej
29
Dziękuję za uwagę
30
Top Related