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

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

Пример входного файла lburg

%start stmt		-- стартовый нетерминал

%term CNSTF4=4113	-- терминалы
%term CNSTF8=8209
%term CNSTF16=16401
%term CNSTI1=1045
...
mem:  INDIRU4(addr)  	"dword ptr %0"
...
mrc3: mem  		"%0"  			3
mrc3: rc   		"%0"
...
reg:  addr         	"lea %c,%0\n"  	1
....

Рассмотрим формат описания основных элементов в грамматике для lburg.

Традиционно нетерминалы обозначаются идентификаторами, состоящими из строчных букв, терминалы - идентификаторами, состоящими из прописных букв. Конструкция %start <nonterminal> служит для описания стартового нетерминала. Конструкция %term <terminal>=<constant> определяет терминал, при этом числовое значение справа от знака равенства соответствует внутреннему коду узла дерева в представлении программы, выдаваемом frontend'ом.

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

В данном случае приведено четыре правила из описания кодогенератора для процессора x86: первое порождает команду косвенной адресации для четырехбайтового адреса, второе и третье выводит нетерминал, соответствующий режиму адресации mcr (memory+constant+register) из нетерминалов, соответствующих регистру и адресу в памяти, четвертое описывает команду загрузки содержимого памяти в регистр.

Форматная строка напоминает таковую в стандартных функциях обмена, однако ассортимент форматных символов несколько иной: так, " %0 " обозначает результат свертки 1-го сына текущего узла, " %c " - результат свертки текущего узла и т.д.

Ограничения BURS

Несмотря на простоту описания системы команд с помощью формализма BURS, построение кодогенератора с его помощью требует дополнительных усилий. Использование BURS кардинально упрощает стадию сопоставления с образцом и выбора режимов адресации, однако такие задачи, как линеаризация дерева (построение топологической сортировки) и распределение регистров должны быть решены отдельно. BURS представляется наилучшим выбором для CISС архитектур, в которых разнообразие команд и режимов адресации действительно велико. Для RISC же архитектур задачи распределения регистров и планирования оказываются более важными.

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

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

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

Литература

  • Aho A.V., Ganapathi M., Tjiang S.W.K. Code Generation Using Tree Matching and Dynamic Programming. ACM Transactions on Programming Languages and Systems, Vol. 11, №4, Oct. 1989, pages 491-516
  • Comon U., Dauchet M. et al. Tree Automata Techniques and Applications. http://l3ux02.univ-lille3.fr/~tommasi/TATAHTML/main.html
  • Christopher W.Fraser, David R.Hanson. A Retargetable C compiler: Design and Implementation. Benjamin/Cummings Publishing, 1995, pages 564