stringtranslate.com

Генерация кода (компилятор)

В вычислительной технике генерация кода является частью цепочки процессов компилятора и преобразует промежуточное представление исходного кода в форму (например, машинный код ), которая может быть легко выполнена целевой системой.

Сложные компиляторы обычно выполняют несколько проходов по различным промежуточным формам. Этот многоэтапный процесс используется потому, что многие алгоритмы оптимизации кода легче применять по одному или потому, что входные данные для одной оптимизации зависят от завершенной обработки, выполненной другой оптимизацией. Такая организация также облегчает создание единого компилятора, который может работать с несколькими архитектурами, поскольку только последний этап генерации кода (бэкэнд ) должен меняться от цели к цели. (Дополнительную информацию о разработке компилятора см. в разделе Компилятор .)

Входные данные генератора кода обычно представляют собой дерево синтаксического анализа или абстрактное синтаксическое дерево . [1] Дерево преобразуется в линейную последовательность инструкций, обычно на промежуточном языке, таком как трехадресный код . Дальнейшие этапы компиляции могут называться «генерацией кода», а могут и не называться, в зависимости от того, предполагают ли они значительные изменения в представлении программы. (Например, этап оптимизации «глазка» вряд ли будет называться «генерацией кода», хотя генератор кода может включать в себя этап оптимизации «глазка».)

Основные задачи

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

Задачи, которые обычно являются частью фазы «генерации кода» сложного компилятора, включают:

Выбор инструкций обычно выполняется путем рекурсивного обхода в обратном порядке абстрактного синтаксического дерева, сопоставляя определенные конфигурации дерева с шаблонами; например, дерево W := ADD(X,MUL(Y,Z))можно преобразовать в линейную последовательность инструкций, рекурсивно генерируя последовательности для t1 := Xи t2 := MUL(Y,Z), а затем выдавая инструкцию ADD W, t1, t2.

В компиляторе, использующем промежуточный язык, может быть два этапа выбора инструкций: один для преобразования дерева синтаксического анализа в промежуточный код, а второй этап, намного более поздний, для преобразования промежуточного кода в инструкции из набора команд целевой машины. Этот второй этап не требует обхода дерева; это можно сделать линейно и обычно включает в себя простую замену операций промежуточного языка соответствующими кодами операций . Однако если компилятор на самом деле является транслятором языка (например, конвертирующим Java в C++ ), то второй этап генерации кода может включать в себя построение дерева из линейного промежуточного кода.

Генерация кода во время выполнения

Когда генерация кода происходит во время выполнения , как при JIT- компиляции , важно, чтобы весь процесс был эффективным с точки зрения пространства и времени. Например, когда регулярные выражения интерпретируются и используются для генерации кода во время выполнения, часто генерируется недетерминированный конечный автомат вместо детерминированного, поскольку обычно первый может быть создан быстрее и занимает меньше места в памяти, чем второй. Несмотря на то, что JIT-генерация кода обычно генерирует менее эффективный код, она может использовать преимущества информации профилирования , доступной только во время выполнения.

Связанные понятия

Фундаментальную задачу приема входных данных на одном языке и получения результатов на нетривиально другом языке можно понять с точки зрения основных трансформационных операций теории формального языка . Следовательно, некоторые методы, которые изначально были разработаны для использования в компиляторах, стали использоваться и другими способами. Например, YACC (Еще один компилятор-компилятор ) принимает входные данные в форме Бэкуса-Наура и преобразует их в синтаксический анализатор на C. Хотя изначально yacc был создан для автоматической генерации парсера для компилятора, он также часто используется для автоматизации написания кода, который необходимо модифицировать каждый раз при изменении спецификаций. [3]

Многие интегрированные среды разработки (IDE) поддерживают ту или иную форму автоматической генерации исходного кода , часто используя алгоритмы, общие с генераторами кода компилятора, хотя обычно менее сложные. (См. также: Преобразование программ , Преобразование данных .)

Отражение

В общем, синтаксический и семантический анализатор пытается получить структуру программы из исходного кода, в то время как генератор кода использует эту структурную информацию (например, типы данных ) для создания кода. Другими словами, первый добавляет информацию, а второй теряет часть информации. Одним из последствий этой потери информации является то, что размышление становится трудным или даже невозможным. Чтобы решить эту проблему, генераторы кода часто встраивают синтаксическую и семантическую информацию в дополнение к коду, необходимому для выполнения.

Смотрите также

Рекомендации

  1. ^ Стивен Мучник; Мучник и партнеры (15 августа 1997 г.). Расширенная реализация проекта компилятора . Морган Кауфманн. ISBN 978-1-55860-320-2. генерация кода.
  2. ^ Ахо, Альфред В.; Рави Сетхи; Джеффри Д. Уллман (1987). Составители: принципы, методы и инструменты . Аддисон-Уэсли. п. 15. ISBN 0-201-10088-6.
  3. ^ Генерация кода: настоящий урок Rails. Artima.com (16 марта 2006 г.). Проверено 10 августа 2013 г.