Laboratorium MRJP - projekt zaliczeniowy

Zaliczenie laboratorium odbywa się na podstawie projektu obejmującego implementację kompilatora dla prostego jezyka imperatywnego Latte.

Etapy

Projekt składa się z trzech etapów

  1. Front-end: analiza składniowa i semantyczna. Termin 18 listopada.
  2. Generator kodu dla JVM. Termin 16 grudnia.
  3. Generator kodu dla LLVM albo x86 oraz ewentualne rozszerzenia. Termin 20 stycznia.
Prowadzący grupę może wyznaczyć inne terminy, w szczególności wymagać osobistej prezentacji projektu.

Punktacja

Łącznie do zdobycia jest maksymalnie 30 punktów, które liczą się do ostatecznej oceny z przedmiotu. Dla zaliczenia laboratorium (i dopuszczenia do egzaminu) należy oddać zadowalające implementacje wszystkich etapów i uzyskać łącznie co najmniej 15p.

Punkty mozna uzyskać za:

  1. front-end (4)
  2. dodatkowo do 2 punktów, jesli parser jest napisany bez użycia generatora
  3. back-end JVM (5)
  4. back-end LLVM (8) albo x86 (10)
  5. kod LLVM w postaci SSA - dodatkowo 1p
  6. alokacja rejestrów dla x86 - dodatkowo do 3p
  7. optymalizacje - do 3p
  8. Rozszerzenia (notacja x/y oznacza punkty za backend w wersji odpowiednio LLVM/x86)
    1. tablice (2)
    2. struktury (2)
    3. obiekty (atrybuty, metody, dziedziczenie bez zastępowania metod) - dodatkowo (3/4)
    4. metody wirtualne - dodatkowo (3/4), czyli za obiekty z metodami wirtualnymi mozna uzyskać 8/10 punktów.
    5. odśmiecanie (2)
Szczegółowy opis rozszerzeń zawarty jest w opisie języka.

Uwaga: punktacja trzeciego etapu może ulegać jeszcze korektom do czasu jego rozpoczęcia.

Spóźnienia, termin poprawkowy

Programy oddane po terminie będą obciążane karą 2p za każdy (rozpoczęty) tydzień opóźnienia. Ostatecznym terminem, po którym programy nie będą przyjmowane ("termin poprawkowy") jest 22 lutego.

Zasady

Projekt zaliczeniowy ma być pisany samodzielnie. Wszelkie przejawy niesamodzielności będą karane. W szczególności:

Wymagania techniczne

  1. Projekt powinien być oddany w postaci spakowanego archiwum TAR (.tar.gz lub .tgz)
  2. W korzeniu projektu muszą się znajdować co najmniej:
  3. Program musi się kompilować na students poleceniem make (które oczywiście może wywoływać inne programy).
  4. Wszelkie używane biblioteki (poza biblioteką standardową używanego jezyka programowania) muszą być opisane w README
  5. Po zbudowaniu kompilatora, w korzeniu musi się znajdować plik wykonywalny o nazwie latc (może być skryptem uruchamiającym inne programy)
  6. Kompilator musi akceptować wszystkie programy testowe z katalogu good i odrzucać ze stosownym komunikatem wszystkie programy z katalogu bad. Dla rozszerzeń musi akceptować wszystkie programy z odpowiednich podkatalogów extension. Uruchomienie poprawnego programu testowego ma dawać wyjście takie jak w odpowiednim pliku .output (dla wejścia zawartego w odpowiednim pliku .input, o ile istnieje)
  7. Gdy kompilator akceptuje program, musi wypisać w pierwszej linii stderr napis OK ("OK\n"). Dalsze linie i stdout - dowolne. Kompilator musi się w takiej sytuacji zakończyć z kodem powrotu 0.
  8. Gdy kompilator odrzuca program musi wypisać w pierwszej linii stderr napis ERROR ("ERROR\n"). Dalsze linie powinny zawierać stosowne informacje o błędach. Kompilator musi się w takiej sytuacji zakończyć z kodem powrotu różnym od 0.

Etap II - generacja kodu JVM

Program musi spełniać wszystkie warunki opisane powyżej, a ponadto:
  1. Wykonanie latc foo/bar/baz.lat dla poprawnego programu wejściowego baz.lat ma stworzyć pliki baz.j (kod Jasmin) oraz baz.class w katalogu foo/bar (przydatna może być opcja -d dla Jasmina).
  2. Wykorzystywany jasmin.jar należy umieścić w katalogu lib
  3. Ewentualne metody biblioteczne (printInt etc.) należy umieścić wc klasie Runtime.class w katalogu lib

Etap III - generacja kodu LLVM

  1. Po wykonaniu make w korzeniu projektu ma się znajdować program wykonywalny latc_llvm
  2. Wykonanie latc_llvm foo/bar/baz.lat dla poprawnego programu wejściowego baz.lat ma stworzyć pliki baz.ll (kod LLVM) oraz wykonywalny a.out w katalogu foo/bar.
  3. Ewentualne funkcje biblioteczne (printInt etc.) należy umieścić w pliku runtime.bc w katalogu lib

Etap III - generacja kodu asemblera

  1. Po wykonaniu make w korzeniu projektu ma się znajdować program wykonywalny latc_ARCH gdzie ARCH to x86 lub x86_64
  2. Wykonanie latc_ARCH foo/bar/baz.lat dla poprawnego programu wejściowego baz.lat ma stworzyć pliki baz.s (kod asemblera) oraz wykonywalny a.out w katalogu foo/bar.
  3. Ewentualne funkcje biblioteczne (printInt etc.) należy umieścić w pliku runtime.o w katalogu lib (dodatkowo proszę zamieścić jego źródło)

Archiwum z programami testowymi:

lattests121017.tgz z 17.10.2012, MD5:49ca5702ca9795fb8f33d52b0b3c6fc3