Опубликован: 23.07.2006 | Доступ: свободный | Студентов: 2213 / 889 | Оценка: 4.28 / 4.17 | Длительность: 21:37:00
Специальности: Системный архитектор
Лекция 15:

Выбор инструкций при генерации кода

Свертка

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

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

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

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

На иллюстрации последовательность выбора нетерминалов в оптимальном выводе отражена с помощью сплошных стрелок, а сами эти нетерминалы подчеркнуты.

Свертка (продолжение)

void Reduce (N: Nonterminal; root: Tree)
{
   (R=N:p,c)=C[root][N];

   if (p = 'K') then Reduce (K, root);
   else if (p = 'b(K 1,…,K n)') then
      for i=1 to |sons(root)| do
          Reduce (K i, son(root,i));

   -- do some actions here --
}

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

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

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

Наконец, изначально корень дерева сворачивается по стартовому нетерминалу.

Свертка (окончание)

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

Каждый шаг свертки обладает следующей информацией:

  1. текущим правилом (и, следовательно, машинной командой или операндом, который должен быть порожден)
  2. текущим нетерминалом (и, следовательно, размещением результата текущей команды или операнда)
  3. списком нетерминалов, из которых выводятся поддеревья текущей вершины (и, следовательно, списком размещений аргументов текущей команды или операнда)
  4. вообще говоря, результатами свертки поддеревьев (то есть машинным кодом, построенным для их вычисления)

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

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