символа дерева синтаксического разбора }
var
i: integer;
Opers: TOpArray;
Trd: TTriad;
begin { Создаем список триад }
Result:= MakeTriadListNOP(symbTop,listTriad);
if Result = nil then {Если ошибка, прерываем выполнение}
with listTriad do
begin { Создаем пустую триаду «NOP» в конце списка }
Opers[1].OpType:= OP_CONST;
Opers[1].ConstVal:= 0;
Opers[2].OpType:= OP_CONST;
Opers[2].ConstVal:= 0;
Add(TTriad.Create(TRD_NOP,Opers));
for i:=Count-1 downto 0 do
begin {Для всех триад в списке расставляем флаг ссылки}
Trd:= Triads[i];
if Trd.TrdType in [TRD_IF,TRD_JMP] then
begin { Если триада «переход» («IF» или «JMP»)
ссылается на другую триаду,}
if Trd.OpTypes[2] = OP_LINK then
listTriad[Trd.Links[2]].IsLinked:= True;
{ то ту триаду надо пометить }
end;
end;
end;
end;
end.
Модуль построения ассемблерного кода по списку триад
Листинг П3.13. Построение ассемблерного кода по списку триад
unit TrdAsm;
{!!! Зависит от целевой вычислительной системы!!! }
interface
{ Модуль распределения регистров и построения ассемблерного
кода по списку триад }
uses Classes, TrdType, Triads;
const { Префикс наименования временных переменных }
TEMP_VARNAME = _Tmp';
NUM_PROCREG = 6; { Количество доступных регистров }
{ Функция распределения регистров и временных переменных
для хранения промежуточных результатов триад }
function MakeRegisters(listTriad: TTriadList): integer;
{ Функция построения ассемблерного кода по списку триад }
function MakeAsmCode(listTriad: TTriadList;
listCode: TStrings;
flagOpt: Boolean): integer;
implementation
uses SysUtils;
function MakeRegisters(listTriad: TTriadList): integer;
{ Функция распределения регистров и временных переменных
для хранения промежуточных результатов триад.
Результат: количество необходимых временных переменных }
var
i,j,iR,iCnt,iNum: integer;{Счетчики и переменные циклов}
{ Динамический массив для запоминания занятых регистров }
listReg: TList;
begin { Создаем массив для хранения занятых регистров }
listReg:= TList.Create;
Result:= 0;
if listReg <> nil then
try { Обнуляем информационное поле у всех триад }
for i:=listTriad.Count-1 downto 0 do
listTriad[i].Info:= 0;
{ Цикл по всем триадам. Обязательно с конца списка! }
for i:=listTriad.Count-1 downto 0 do
for j:=1 to 2 do { Цикл по всем (2) операндам }
{ Если триада – линейная операция, или «IF»
(первый операнд), или присвоение (второй операнд) }
if ((listTriad[i].TrdType in TriadLineSet)
or (listTriad[i].TrdType = TRD_IF) and (j = 1)
or (listTriad[i].TrdType = TRD_ASSIGN) and (j = 2))
{ и операндом является ссылка на другую триаду }
and (listTriad[i][j].OpType = OP_LINK) then
begin { Запоминаем номер триады, на которую направлена ссылка }
iNum:= listTriad[i][j].TriadNum;
{ Если триаде еще не назначен регистр и если это
не предыдущая триада – надо ей назначить регистр }
if (listTriad[iNum].Info = 0) and (iNum <> i-1) then
begin { Количество назначенных регистров }
iCnt:= listReg.Count-1;
for iR:=0 to iCnt do
begin{ Цикл по массиву назначенных регистров }
{ Если область действия регистра за пределами
текущей триады, то его можно использовать }
if longint(listReg[iR]) >= i then
begin { Запоминаем область действия регистра }
listReg[iR]:= TObject(iNum);
{ Назначаем регистр триаде с номером iNum }
listTriad[iNum].Info:= iR+1;
Break; { Прерываем цикл по массиву регистров }
end;
end; { Если ни один из использованных регистров
не был назначен, надо брать новый регистр }
if listTriad[iNum].Info = 0 then
begin { Добавляем запись в массив регистров,
указываем ей область действия iNum }
listReg.Add(TObject(iNum));
{ Назначаем новый регистр триаде с номером iNum }
listTriad[iNum].Info:= listReg.Count;
end;
end;
end;{ Результат функции: количество записей в массиве
регистров -1, за вычетом числа доступных регистров}
Result:= listReg.Count – (NUM_PROCREG-1);
finally listReg.Free;
end;
end;
function GetRegName(iInfo: integer): string;
{ Функция наименования регистров процессора }
begin
case iInfo of
0: Result:= 'eax';
1: Result:= 'ebx';
2: Result:= 'ecx';
3: Result:= 'edx';
4: Result:= 'esi';
5: Result:= 'edi';
{ Если это не один из регистров – значит,
даем имя временной переменной }
else Result:=
Format(%s%d',[TEMP_VARNAME,iInfo-NUM_PROCREG]);
end{case};
end;
function GetOpName(i: integer; listTriad: TTriadList;
iOp: integer): string;
{ Функция наименования операнда триады
i – номер триады в списке;
listTriad – список триад;
iOp – номер операнда триады }
Читать дальше
Конец ознакомительного отрывка
Купить книгу