Я пишу компилятор для подмножества Паскаля. Компилятор производит машинные инструкции для выдуманной машины. Я хочу написать глазок-оптимизатор для этого машинного языка, но у меня возникли проблемы с заменой некоторых более сложных шаблонов.
Я изучил несколько разных подходов к написанию оптимизатора глазка и остановился на подходе к серверу:
emit()
срабатывает каждый раз, когда должна быть сгенерирована машинная инструкция.emit(Instruction currentInstr)
проверяет таблицу оптимизаций глазка:
Метод достаточно прост, вот с реализацией у меня возникли проблемы. В моем компиляторе машинные инструкции хранятся в классе Instruction
. Я написал класс InstructionMatch
, в котором хранятся регулярные выражения, предназначенные для соответствия каждому компоненту машинной инструкции.Его метод equals(Instruction instr)
возвращает true
, если шаблоны соответствуют некоторой машинной инструкции instr
.
Однако мне не удается полностью применитьправила, которые у меня есть. Во-первых, я чувствую, что при моем нынешнем подходе я получу беспорядок из ненужных объектов. Учитывая, что полный список чисел оптимизации глазка может насчитывать около 400 паттернов, это быстро выйдет из-под контроля. Кроме того, я не могу получить более сложные замены, работающие с этим подходом (см. «Мой вопрос»).
В одной статье, которую я читал, предыдущие инструкции складываются в одну длинную строку с использованием регулярных выражений для сопоставления и замены и преобразования строки обратно в машинные инструкции. Это показалось мне плохим подходом, пожалуйста, поправьте меня, если я ошибаюсь.
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]
Обратите внимание, что каждый из этих шаблонов является просто удобочитаемым представлением следующего шаблона машинной инструкции:
op_code register n d
(n обычно указывает количество слов, а d — смещение адреса) . Синтаксис x:
указывает, что инструкция хранится по адресу x
в хранилище кодов.
Таким образом, инструкция LOADL 17
эквивалентна полной машинной инструкции 5 0 0 17
, когда код операции LOADL
равен 5 (n
и r
не используются в этой инструкции)
Таким образом, учитывая этот фон, мой вопрос заключается в следующем: как мне эффективно сопоставлять и заменять шаблоны, когда мне нужно включить части предыдущие инструкции как переменные в моей замене? Например, я могу просто заменить все экземпляры LOADL 1; add
с инкрементной машинной инструкцией - для этого мне не нужна какая-либо часть предыдущих инструкций. Но я не понимаю, как эффективно использовать значения «x» и «y» моего второго примера в шаблоне замены.
edit: я должен упомянуть, что каждое поле класса Instruction
представляет собой просто целое число (как обычно для машинных инструкций). Любое использование «x» или «y» в таблице шаблонов является переменной, заменяющей любое целочисленное значение.