Kompilator napisany w Javie: implementacja optymalizatora wizjera

Piszę kompilator dla podzbioru Pascala. Kompilator tworzy instrukcje maszynowe dla gotowej maszyny. Chcę napisać optymalizator wizjera dla tego języka maszynowego, ale mam problem z zastąpieniem niektórych bardziej skomplikowanych wzorów.

Specyfikacja optymalizatora wizjera

Zbadałem kilka różnych podejść do pisania optymalizatora wizjera i zdecydowałem się na podejście back-end:

Enkoder dzwoni doemit() funkcja za każdym razem, gdy ma zostać wygenerowana instrukcja maszynowa.emit(Instruction currentInstr) sprawdza tabelę optymalizacji wizjera:Jeśli bieżąca instrukcja pasuje do ogona wzoru:Sprawdź wcześniej wydane instrukcje dopasowaniaJeśli wszystkie instrukcje pasują do wzorca, zastosuj optymalizację, modyfikując końcowy koniec składnicy koduJeśli nie znaleziono optymalizacji, wyślij instrukcję jak zwykleAktualne podejście do projektowania

Metoda jest łatwa, jest to implementacja, z którą mam problemy. W moim kompilatorze instrukcje maszynowe są przechowywane wInstruction klasa. NapisałemInstructionMatch klasa przechowuje wyrażenia regularne mające na celu dopasowanie każdego komponentu instrukcji maszynowej. Jegoequals(Instruction instr) zwraca metodętrue jeśli wzorce pasują do niektórych instrukcji maszynowychinstr.

Jednak nie mogę w pełnizastosować zasady, które mam. Po pierwsze, czuję, że biorąc pod uwagę moje obecne podejście, skończę z bałaganem niepotrzebnych przedmiotów. Biorąc pod uwagę, że pełna lista numerów optymalizacji wizjera może zawierać około 400 wzorów, szybko wymknie się spod kontroli. Co więcej, nie mogę uzyskać trudniejszych podstawień przy użyciu tego podejścia (patrz „Moje pytanie”).

Alternatywne podejścia

Jeden artykuł, który przeczytałem, składa poprzednie instrukcje w jeden długi ciąg, używając wyrażeń regularnych do dopasowania i zastąpienia, i konwertowania ciągu z powrotem do instrukcji maszyny. Wydawało mi się, że to złe podejście, popraw mnie, jeśli się mylę.

Przykładowe wzory, składnia wzorca
<code>x: JUMP x+1; x+1: JUMP y  -->  x: JUMP y
LOADL x; LOADL y; add     -->  LOADL x+y
LOADA d[r]; STOREI (n)    -->  STORE (n) d[r]
</code>

Zauważ, że każdy z tych przykładowych wzorców jest tylko czytelną dla człowieka reprezentacją następującego szablonu instrukcji maszynowej:

<code>op_code register n d
</code>

(n zwykle oznacza liczbę słów, a d przemieszczenie adresu). Składniax: <instr> wskazuje, że instrukcja jest przechowywana pod adresemx w magazynie kodów.

Tak więc instrukcjaLOADL 17 jest równoważne pełnej instrukcji maszyny5 0 0 17 kiedyLOADL opcode to 5 (n ir nie są używane w tej instrukcji)

Moje pytanie

Tak więc, biorąc pod uwagę to tło, moje pytanie brzmi: jak skutecznie dopasować i zastąpić wzory, gdy muszę zamienić części poprzednich instrukcji jako zmienne w moim zastępstwie? Na przykład mogę po prostu zastąpić wszystkie wystąpieniaLOADL 1; add z instrukcją maszyny przyrostowej - nie potrzebuję żadnej części poprzednich instrukcji, aby to zrobić. Ale nie potrafię skutecznie wykorzystać wartości „x” i „y” mojego drugiego przykładu we wzorze podstawienia.

edytować: Powinienem wspomnieć o każdym poluInstruction klasa jest po prostu liczbą całkowitą (co jest normalne dla instrukcji maszynowych). Każde użycie znaku „x” lub „y” w tabeli wzorca jest zmienną, w której można wstawić dowolną wartość całkowitą.

questionAnswers(1)

yourAnswerToTheQuestion