Московский государственный технический университет им. Н.Э. Баумана
Опубликован: 28.06.2006 | Доступ: свободный | Студентов: 12463 / 344 | Оценка: 4.54 / 3.83 | Длительность: 22:03:00
ISBN: 978-5-9556-0055-0
Лекция 10:

Динамическая генерация кода

Генерация линейных участков кода для стековой машины

В этом разделе мы рассмотрим специфику генерации линейных участков кода на языке CIL.

Линейными участками мы будем называть участки кода, не содержащие развилок и защищенных блоков.

Генерация кода для выражений

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

Абстрактный синтаксис выражений

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

Пусть абстрактный синтаксис для наших выражений содержит правила, приведенные в таблице 5.2.

Таблица 5.2. Абстрактный синтаксис выражений
Правило Описание
Expr ::= const c Некоторая константа. Мы не уточняем тип константы, так как для дальнейшего изложения это несущественно. Это может быть целое число, число с плавающей запятой, строка, значение null
Expr ::= local x Локальная переменная с именем х
Expr ::= arg x Параметр метода с именем х
Expr ::= Expr index Expr Доступ к элементу массива. Здесь первое выражение должно возвращать ссылку, а второе - целое число, означающее индекс элемента
Expr ::= Expr field f Доступ к полю f объекта
Expr ::= minus Expr Унарный минус
Expr ::= Expr BinOp Expr Бинарная арифметическая операция
Expr ::= local x assign Expr Операция присваивания переменной х значения выражения
Expr ::= arg x assign Expr Операция присваивания параметру х значения выражения
Expr ::= Expr index Expr assign Expr Операция присваивания элементу массива значения выражения
Expr ::= Expr field f assign Expr Операция присваивания полю f объекта значения выражения
Expr ::= Expr call s Arglist Вызов экземплярного метода s для некоторого объекта с передачей списка фактических параметров
Arglist ::= Expr Arglist Непустой список фактических параметров метода
Arglist ::= пусто Пустой список фактических параметров метода
BinaryOp ::= plus Сложение
BinaryOp ::= minus Вычитание
BinaryOp ::= mul Умножение
BinaryOp ::= div Деление
Отображение абстрактного синтаксиса выражений в CIL

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

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

GenExpr[const c] = нужный вариант инструкции ldc;
GenExpr[local x] = ldloc x;
GenExpr[arg x] = ldarg x;
GenExpr[Expr1 index Expr2] = 
  GenExpr[Expr1],
  GenExpr[Expr2],
  ldelem.нужный тип;
GenExpr[Expr field f] =
  GenExpr[Expr],
  ldfld f;
GenExpr[minus Expr] =
  GenExpr[Expr],
  neg;
GenExpr[Expr1 BinOp Expr2] =
  GenExpr[Expr1],
  GenExpr[Expr2],
  GenBinOp[BinOp];
GenExpr[local x assign Expr] =
  GenExpr[Expr],
  dup,
  stloc x;
GenExpr[arg x assign Expr] = 
  GenExpr[Expr],
  dup,
  starg x;
GenExpr[Expr1 index Expr2 assign Expr3] =
  GenExpr[Expr1],
  GenExpr[Expr2],
  GenExpr[Expr3],
  dup,
  stloc временная переменная,
  stelem.нужный тип,
  ldloc временная переменная;
GenExpr[Expr1 field f assign Expr2] =
  GenExpr[Expr1],
  GenExpr[Expr2],
  dup,
  stloc временная переменная,
  stfld f,
  ldloc временная переменная;
GenExpr[Expr call s ArgList] =
  GenExpr[Expr],
  GenArgList[ArgList],
  call(callvirt) s;

GenArgList[Expr ArgList] =
  GenExpr[Expr],
  GenArgList[ArgList];
GenArgList[пусто] = ;
GenBinOp[plus] = add;
GenBinOp[minus] = sub;
GenBinOp[mul] = mul;
GenBinOp[div] = div;
Анастасия Булинкова
Анастасия Булинкова
Рабочим названием платформы .NET было