Россия |
Генерация MSIL
Основные черты MSIL
Трансляторы, ориентированные на платформу .NET, должны генерировать код на MSIL, являющемся языком ассемблера некоторой виртуальной машины. Поэтому мы начнем с рассмотрения основных свойств целевой платформы нашего компилятора. В данной лекции мы не пытаемся дать полного и детального описания всех команд платформы; задача данного обзора - дать представление об основных идеях MSIL.
Программы на MSIL переводятся в исполняемый код реального процессора лишь непосредственно перед исполнением c помощью так называемой компиляции времени исполнения (которую также называют Just-In-Time compilation или динамической компиляцией). При этом выполняется довольно сложный типовой анализ программы и проверки условий корректности кода.
Основные черты архитекутры виртуальной машины MSIL таковы:
- машина является стековой, причем стек является статически типизированным; это означает, что в каждой точке программы JIT-compiler должен иметь возможность статически определить типы содержимого всех ячеек стека. На практике это означает, например, невозможность написать код, кладущий в цикле значения на стек
- ячейки стека представлены как 4-байтовые или 8-байтовые знаковые целовые (обозначаемые как I4 и I8, соответстсвенно; более короткие значения представляются как 4-байтовые);
- стек используется как правило только для хранения промежуточных результатов вычисления (т.е. не рекомендуется хранить на стеке временные переменные, такие, как счетчик цикла и т.п.)
- большинство команд MSIL получают свои аргументы на стеке, удаляют их со стека и помещают вместо них результат(ы) вычисления.
- машина является объектно-ориентированной: структура MSIL отражает разбиение кода на классы, методы и т.п.
О хранении переменных в MSIL
Существует несколько вариантов хранения переменных в MSIL:
- в статической области памяти, существующей все время выполнения программы
- в локальной области, которая выделяется при входе в метод;
- внутри объекта, размещенного в куче.
Статическая область памяти предназначена, например, для статических полей класса, глобальных переменных, констант и т.п. Например, в этой области памяти должны находиться переменные, описанные с модификатором static в языке C.
Локальная память выделяется для автоматических и временных переменных, параметров и т.п.
Куча предназначена для хранения динамических объектов. Кроме того, при реализации языков со вложенными процедурами и процедурными значениями, необходимо обеспечить доступ из вложенной процедуры к переменным из объемлющей среды. При этом, если язык допускает использование вложенных процедур в качестве переменных процедурного типа, то единственным способом для реализации такого механизма в безопасном режиме является построение в куче так называемого замыкания процедуры (closure) , которое будет содержать переменные из объемляющих сред, необходимые для работы данной процедуры.