300 likes | 607 Views
Techniki kompilacji. Wykład I. Adam Piotrowski Katedra Mikroelektroniki i Technik Informatycznych tel: 042 631 27 20 e-mail: komam@dmcs.pl http://lux.dmcs.pl/tk/ http://www.dmcs.pl/~komam/tkz. Literatura. Podstawowa
E N D
Techniki kompilacji Wykład I
Adam Piotrowski Katedra Mikroelektroniki i Technik Informatycznych tel: 042 631 27 20 e-mail: komam@dmcs.pl http://lux.dmcs.pl/tk/ http://www.dmcs.pl/~komam/tkz
Literatura • Podstawowa • A.V. Aho, R. Sethi, J. D. Ullman, "Compilers - Principles,Techniques, and Tools", Addison-Wesley 2007 (polskiewydanie WNT 2002) • W. M. Waite, G. Goos, "Konstrukcjakompilatorów", WNT 1989 • Uzupełniająca • John R. Levine, "Linkers and Loaders", MorganKaufmann Publishers 1999 (manuskryptdostepnyonline) • S. S. Muchnick, "Advanced Compiler Design andImplementation", Morgan Kaufmann Publishers 1997
Zagadnienia • Część teoretyczna • Kompilacjaprogramów • Translacja kodu języka wysokiego poziomu do języka symbolicznego • Analizatorleksykalny • Analizatorskładniowy • Gramatyka, języki używane w budowie kompilatora • Część praktyczna • Programy do budowy kompilatora (flex i bison) • Zarządzane kompilacją projektu (program make)
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
Napisaliśmy program, jak gouruchomić? • Kompilator • Przetwarza cały program na postać zrozumiałądlaprocesora (C/C++, Fortran) • Interpreter • Przetwarza osobno każdą pojedynczą instrukcję (Vbasic, Python, Języki skryptowe, Bash) • Rozwiązaniapośrednie • Kod pośredni, interpretowany przez procesor wirtualny (Java)
.file "main.c" .section .rodata .LC0: .string "Hello world" .text .globl main .type main, @function main: .LFB2: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: movl $.LC0, %edi call puts movl $0, %eax leave ret System przetwarzania języków Szkieletowy program główny gcc –E test.c –o test.i Preprocesor #include <stdio.h> int main() { printf("Hello world\n"); return 0; } Program źródłowy gcc –S test.c –o test.s Kompilator typedef unsigned char __u_char; typedef unsigned short int __u_short; typedef unsigned int __u_int; typedef unsigned long int __u_long; extern intfclose (FILE *__stream); extern intfflush (FILE *__stream); int main() { printf("Hello world\n"); return 0; } Wynikowy program w asemblerze as test.s –o test.o Asembler Przemieszczalny kod maszynowy Biblioteki, przemieszczalne pliki obiektowe gcc test.o –o test Program ładujący/konsolidator Bezwzględny kod maszynowy
Elementy kompilatora Program źródłowy Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
Elementy kompilatora Program źródłowy • 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 kodu Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
Elementy kompilatora Program źródłowy • W przypadku błędu nie przerywamy procesu kompilacji, próbujemy zastosować techniki odzyskiwania kontroli • Rodzaje 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) Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
Elementy kompilatora • 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 Program źródłowy Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
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)
Analiza leksykalna • Większość symboli leksykalnych należy do jednej z grup: • nazwy (identyfikatory) • słowa zarezerwowane (ustalony podzbiór zbioru nazw) • liczbycałkowite • liczbyrzeczywiste • łańcuchyznakowe • operatory: • addytywne (+, -), • unarne (+, -), • multiplikatywne (*, /) • relacyjne (<, >, =, <=, >=, <>) • logiczne (and, or, not) • przypisania (:=) • ogranicznikijednoznakowe: ; , [ ] ( ) . • ogranicznikidwuznakowe: (* , *), +=, ++ itd.
Analizator leksykalny Leksemy: Symbole leksykalne: identyfikator op_przypisania op_add op_mul identyfikator liczba identyfikator • 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 odejmowania • op_mul: • operatory mnożenia i dzielenia • op_przypisania: • operator składający się ze znaku „:” po którym następuje znak „=„ pozycja := poczatek + tempo * 60
Elementy kompilatora Program źródłowy • 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 Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
Formalna gramatykabezkontekstowa Zbiórtokenów (symboli leksykalnych)zwanychsymbolamiterminalnymi Zbiórsymbolinieterminalnych Zbiór produkcji, z których każda składa się z symbolunieterminalnego, zwanegolewą stroną produkcji, strzałki oraz sekwencji tokenów i symboli nieterminalnych, zwanej prawąstronąprodukcji Jednegowyróżnionegosymbolunieterminalnego, zwanegosymbolemstartowym
Analiza składniowa instrukcja przypisania identyfikator wyrażenie wyrażenie wyrażenie identyfikator wyrażenie wyrażenie identyfikator liczba := pozycja początek + tempo + 60 istrukcja_przypisania -> identyfikator ':=' wyrażenie wyrażenie -> liczba wyrażenie -> identyfikator wyrażenie -> wyrażenie '+' wyrażenie wyrażenie -> wyrażenie '*' wyrażenie
Elementy kompilatora Program źródłowy • 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 Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu Generator kodu Program wynikowy
Analiza semantyczna instrukcja przypisania identyfikator wyrażenie wyrażenie wyrażenie inttireal identyfikator wyrażenie wyrażenie identyfikator liczba pozycja := początek + tempo + 60
Elementy kompilatora Program źródłowy Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego • 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 Optymalizator kodu Generator kodu Program wynikowy
Generacja kodu pośredniego temp1 := inttoreal (60) temp2 := id1 * temp1 temp3 := id2 + temp2 id3 := temp3 • 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
Elementy kompilatora Program źródłowy Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego • 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) Optymalizator kodu Generator kodu Program 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
Optymalizacja temp1 := inttoreal (60) temp2 := id1 * temp1 temp3 := id2 + temp2 id3 := temp3 konwersja z liczby typu int na liczbę typu real na etapie generacji kodu redukcja zmiennej tmp3 temp1 := tempo * 60.0 pozycja := poczatek + temp1
Elementy kompilatora Program źródłowy Analizator leksykalny Analizator składniowy Analizator semantyczny Obsługa błędów Tablica symboli Gen. kodu pośredniego Optymalizator kodu • Zadania: • wygenerowanie kodu wynikowego w postaci: • kodu asemblera • przemieszczalnego kodu maszynowego • gotowego programu wykonywalnego • wybór rozkazów • przydział rejestrów Generator kodu Program wynikowy
Generacja kodu pozycja := poczatek + tempo * 60 MOVF 16, R2 MULF #60.0, R2 MOVF 8, R1 ADDF R2, R1 MOVF R1,0
Translacja pojedynczej instrukcji pozycja := poczatek + tempo * 60 Generacja kodu pośredniego Analizator leksykalny temp1 := inttoreal (60) temp2 := id1 * temp1 temp3 := id2 + temp2 id3 := temp3 := id1 := id2 + id3 * 60 + := id1 + Analizator składniowy * id2 Optymalizator kodu * id2 id3 id3 inttoreal 60 temp1 := tempo * 60.0 pozycja := poczatek + temp1 60 Generator kodu id1 Analizator semantyczny MOVF 16, R2 MULF #60.0, R2 MOVF 8, R1 ADDF R2, R1 MOVF R1,0
Przykład: budowa kompilatora gcc 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