Промежуточное представление ( IR ) — это структура данных или код, используемый внутри компилятора или виртуальной машины для представления исходного кода . IR предназначен для дальнейшей обработки, такой как оптимизация и перевод . [1] «Хороший» IR должен быть точным – способным представлять исходный код без потери информации [2] – и независимым от какого-либо конкретного исходного или целевого языка. [1] IR может принимать одну из нескольких форм: структуру данных в памяти или специальный код на основе кортежа или стека , читаемый программой. [3] В последнем случае его еще называют промежуточным языком .
Канонический пример можно найти в большинстве современных компиляторов. Например, интерпретатор CPython преобразует линейный удобочитаемый текст, представляющий программу, в промежуточную структуру графа , которая позволяет анализировать поток и переупорядочивать его перед выполнением. Использование такого промежуточного представления позволяет использовать системы компиляторов, такие как GNU Compiler Collection и LLVM , на многих различных исходных языках для генерации кода для множества различных целевых архитектур .
Промежуточный язык — это язык абстрактной машины , предназначенный для помощи в анализе компьютерных программ . Этот термин происходит от их использования в компиляторах , где исходный код программы переводится в форму, более подходящую для преобразований, улучшающих код, прежде чем использоваться для генерации объектного или машинного кода для целевой машины. Конструкция промежуточного языка обычно отличается от конструкции практического машинного языка тремя фундаментальными способами:
Популярным форматом промежуточных языков является трехадресный код .
Этот термин также используется для обозначения языков, используемых в качестве промежуточных звеньев в некоторых языках программирования высокого уровня , которые сами не выводят объектный или машинный код, а выводят только промежуточный язык. Этот промежуточный язык передается компилятору такого языка, который затем выводит готовый объектный или машинный код. Обычно это делается для облегчения процесса оптимизации или повышения переносимости за счет использования промежуточного языка, имеющего компиляторы для многих процессоров и операционных систем , таких как C. Языки, используемые для этого, по сложности делятся на языки высокого уровня и языки низкого уровня , такие как ассемблер .
Несмотря на то, что C явно не был задуман как промежуточный язык, природа C как абстракции ассемблера и его повсеместное распространение в качестве системного языка де-факто в Unix-подобных и других операционных системах сделали его популярным промежуточным языком: Eiffel , Sather , Esterel , некоторые диалекты Lisp (Lush, Gambit ), Squeak's Smalltalk-subset Slang, Nim, Cython, Seed7, SystemTap , Vala , V и другие используют C в качестве промежуточного языка. Варианты C были разработаны для обеспечения функций C как переносимого языка ассемблера , включая C-- и промежуточный язык C.
Любой язык, предназначенный для виртуальной машины или машины с p-кодом, можно считать промежуточным языком:
Коллекция компиляторов GNU (GCC) использует внутри себя несколько промежуточных языков для упрощения переносимости и кросс-компиляции . Среди этих языков есть
GCC поддерживает создание этих IR в качестве конечной цели:
Структура компилятора LLVM основана на промежуточном языке LLVM IR , компактное двоичное сериализованное представление которого также называется «битовым кодом» и было разработано Apple. [4] [5] Как и байт-код GIMPLE, биткод LLVM полезен для оптимизации времени соединения. Как и GCC, LLVM также нацелен на некоторые IR, предназначенные для прямого распространения, включая Google PNaCl IR и SPIR . Дальнейшим развитием LLVM является использование многоуровневого промежуточного представления ( MLIR ) с возможностью генерирования кода для различных гетерогенных целей и объединения результатов разных компиляторов. [6]
Промежуточный язык ILOC [7] используется на занятиях по проектированию компиляторов как простой целевой язык. [8]
Инструменты статического анализа часто используют промежуточное представление. Например, Radare2 — это набор инструментов для анализа и обратного проектирования двоичных файлов. Для анализа двоичных файлов он использует промежуточные языки ESIL [9] и REIL [10] .