Учебный компилятор (для лекций по курсу "Разработка компиляторов")

Рассматривается небольшой учебный компилятор, иллюстрирующий современную технологию разработки компиляторов. Образцом для подражания является компилятор GCC.

Входной язык

Входным языком является ограниченное подмножество языка Си. Ограничения перечислены ниже.

Отметим, что логические выражения реализованы полностью, как положено по стандарту (например, второй аргумент конъюнкции "&&" не вычисляется, если первый равен false).

Устройство компилятора

Поскольку целью является иллюстрация современных средств и методов разработки, то компилятор максимально использует стандартные средства. При этом используются только свободно распространяемые GNU-программы. Компилятор реализован в системе Linux и, конечно, может быть скомпилирован в любом Unix'е с установленным пакетом GNU.

Компилятор считывает исходный текст Си-программы из файла и преобразует ее в программу на языке Ассемблера, которая записывается в выходной файл. Используется Аccемблер "as", входящий в пакет GNU, целевым процессором является Intel 80386. Машинно-зависимая чась компилятора, т.е. описание системы комманд процесора, локализована в одном файле (в одной таблице) и составляет его небольшую часть. Компилятор может быть легко адаптирован для любого другого процессора или Ассемблера.

Компилятор называется "TinyCC" (по аналогии со SmallC). В нем использовались некоторые идеи мини-компилятора "Small-C" (Ron Cain) и учебного компилятора "TinyC", разработанного Д.В.Варсанофьевым и А.Г.Дымченко для поддержки аналогичного спецкурса в Московсом университе. Вместе с тем данный компилятор достаточно сильно отличается от "TinyC" (написан заново без использования кода Tinyc, полностью реализует логические выражения, использует RTL в качестве машинно независитого внутреннего представления программы, что позволяет выполнять машинно независимую оптимизацию, и т.д.)

Исходный код компилятора:

Для сборки компилятора выполните "make" без аргументов. Затем "tinycc --help".

Архив содержит 3 тестовых файла "tstgcd.c", "tstsum.c" и "tstchar.c", написанных с соблюдением ограничений на входной язык, накладываемых компилятором "tinycc". Чтобы скомпилировать и запустить, например, программу "tstgcd.c", выполните (в Unix'е) следующую последовательность комманд:

./tinycc tstgcd.c gcc tstgcd.s ./a.out В первой команде вызывается компилятор "tinycc", которому передается входной файл "tstgcd.c". Результатом является файл "tstgcd.s", содержащий скомпилированную программу на языке Ассемблера. Во второй строке вызывается "gcc", который в данном случае выполняет роль компилятора с Ассемблера и построителя задачи (можно было также выполнить две команды as tstgcd.s gcc tstgcd.o которые делают то же самое). В третьей строке выполняется созданная программа "a.out".

Компиляция под Windows

Под Windows следует установить пакет Cygwin (это вообще-то полезно сделать безотносительно к "TinyCC"). Есть очень небольшие отличия в Ассемблерах "as" для Linux'а и для Windows в пакете Cygwin. А именно, глобальные имена в Windos начинаются с символа подчеркивания "_", в Linux'е он не нужен. Также почему-то Cygwin-ассемблер "as" не понимает директив ".type" и ".size" -- впрочем, как оказалось, они не обязательны, и ассемблерный текст отлично компилируется и без них. Все отличия между Linux и Windows-версиями TinyCC содержатся в файле "i80386.c", в котором применяется условная компиляция. Под Windos & Cygwin достаточно определить переменную "CYGWIN", это сделано в файле "Makefile.win". Таким образом, для компиляции и сборки TinyCC под Windows & Cygwin просто выполняйте команду

make -f Makefile.win

Вызывают восхищение разработчики пакета Cygwin: все GNU-утилиты Unix'а, такие как "flex", "bison", "gcc" работают под Windows абсолютно так же, как и под Linux'ом (кроме упомянутых незначительных отличий Ассемблеров). Поэтому никаких изменений проект "TinyCC" под Windows не требует.

Материалы к лекциям