Лекции по конструированию компиляторов. В.А. Серебряков (1134688), страница 20
Текст из файла (страница 20)
Процедура Emit2 генерируетдвухадресную команду. Первый параметр этой процедуры - код команды,второй и третий параметры имеют тип Address и служат операндамикоманды (здесь для упрощения изложения в качестве параметров этойпроцедуры используются контрукции типа '(А)'; имеется в виду косвеннаяадресация через адресный регистр). Смещение переменной текущегоуровня отсчитывается от базы (А6), а других уровней - от указателястатической цепочки, поэтому оно определяется как алгебраическая суммаLOCALSize и величины смещения переменной (отрицательного!).Если стек организован с помощью дисплея, то трансляция длядоступа к переменным может быть осуществлена следующим образом:128RULEVariable ::= VarMode Number Number VarTailSEMANTICSint Temp;3: if (Val<2>==0) // Глобальная переменная{Address<4>.AddrMode=Abs;Address<4>.AddrDisp=0;}else // Локальная переменная{Address<4>.AddrMode=Direct;if (Val<2>=Level<Block>)// Переменная текущего уровня }{Address<4>.Addreg=A6;Address<4>.AddrDisp=Table[Val<3>];}else {Address<4>.AddrMode=IndPost;Address<4>.Addreg=NO;Address<4>.IndexREG=NO;Address<4>.AddrDisp=DispLAY[Val<2>];Address<4>.IndexDisp=Table[Val<3>];}}}.Рассмотрим трансляцию доступа к полям записи.
Она описываетсяследующим правилом (Number - это Лидер-номер описания поля):RULEVarTail ::= 'FIL' Number VarTailSEMANTICSif (Address<0>.AddrMode==Abs){Address<3>.AddrMode=Abs;Address<3>.AddrDisp=Address<0>.AddrDisp+Table[Val<2>];}else {Address<3>=Address<0>;if (Address<0>.AddrMode==Direct)Address<3>.AddrDisp=Address<0>.AddrDisp+Table[Val<2>];else Address<3>.IndexDisp=Address<0>.IndexDisp+Table[Val<2>];}.Смещение в случае абсолютной и прямой адресации определяется полемAddrDisp, а в остальных случаях - полем IndexDisp. Таким образом, видно,что при обработке полей записей идет только накопление смещения поля129без генерации каких-либо команд.Атрибутные зависимости для этого правила могут быть изображеныследующим образом (рис.
8.11):VarTail DispNumberVarTailDispTableDispРис. 8.11Рассмотрим теперь выборку элементаобращения к элементу массива следующий:массива.Лидер-синтаксисVarTail ::= 'ARR' Number Typexpr VarTailЗдесь Number - Лидер номер описания диапазона индексов; Typexpr индексное выражение.
По адресу левой части правила, представляющейпеременную-массив, от которого берется индекс, и по индексномувыражению, представленному нетерминалом Typexpr, мы должнысформировать адрес элемента массива. В приведенной ниже таблицерешений функция GetAddr выбирает очередной свободный адресныйрегистр.Под "рабочим" регистром в таблице решений имеется в виду регистр,значение которого может быть испорчено (примером "не рабочего"регистра может служить регистр А6 или регистр А5, если он используетсякак указатель процедуры предыдущего статического уровня).MaxReg - максимальный номер адресного регистра, которым можнопользоваться как рабочим.
Все адресные регистры разделены на двамножества: имеющие номера, большие MaxReg, заняты предварительнымраспределением, остальные - рабочие. Функция GetAddr выдает очереднойсвободный рабочий адресный регистр.130Тип адресации VarTail левой части:IndPre || Direct||IndexReg==NOElSize<3>==AddrDisp<4>=AddrDisp<4>:=1,2,4,8AddrDisp<0>Left<2>*ElSize<3>AddrMode<3>==D-Left<2>*ElSize<3>AddrMode<4>=IndPostAddreg<4>=Addreg<0>IndexReg<4>=(Addreg<0>==рабочий)Addreg<3>AddrMode<4>=IndPostScale<4>=ElSize<3>(IndPost || Abs)((Direct || IndPre)&& (IndexReg!=NO))-Addreg<4>=?Addreg<0>:GetAddrIndexReg<4>=Addreg<3>Scale<4>=ElSize<3>LEA Address<0>,Address<4>ElSize<3>AddrDisp<4>=!=1,2,4,8AddrDIP<0>AddrMode<3>==DLeft<2>*ElSize<3>Addreg<4>=Addreg<0>IndexReg<4>=(Addreg<0>==рабочий)Addreg<3>?Addreg<0>Scale<4>=1AddrMode<4>=IndPostMUL ElSize<3>,Addreg<3>131AddrDisp<4>=-Left<2>*ElSize<3>AddrMode<4>=IndPostAddreg<4>=:GetAddrIndexReg<4>=Addreg<3>Scale=1LEA Address<0>,Address<4>MUL ElSize<4>,IndexReg<4>ElSize<3>==AddrDisp<4>=AddrDisp<4>=1,2,4,8AddrDisp<0>-Left<2>*ElSize<3>AddrMode<3>!=D Left<2>*ElSize<3> AddrMode<4>=IndPostAddreg<4>=Addreg<0>Addreg<4>=IndexReg<4>=GetFree (Addreg<0>==рабочий)AddrMode<4>=IndPost?Addreg<0>Scale<4>=ElSize<3>:GetAddrIndexReg<4>=GetFree()MOVE Address<3>,Scale<4>=ElSize<3>IndexReg<4>LEA Address<0>,Address<4>MOVE Address<3>,IndexReg<4>ElSize<3><>1,2,4,8AddrMode<3><>DAddrDisp<4>=AddrDisp<0>Left<2>*ElSize<3>Addreg<4>=Addreg<0>IndexReg<4>=GetFreeAddrMode<4>=IndPreScale<4>=ElSize<3>MOVE Address<3>,IndexReg<4>MUL ElSize<3>,IndexReg<4>AddrDisp<4>:=-Left<2>*ElSizeAddrMode<4>=IndPreAddreg<4>=(Addreg<0>==рабочий)?Addreg<0>:GetAddrIndexReg<4>=GetFree()Scale<4>=1LEA Address<0>,Address<4>MOVE Address<3>,IndexReg<4>MUL ElSize<3>,IndexReg<4>Приведенная таблица реализуется следующим правилом:RULEVarTail ::= 'ARR' Number Typexpr VarTailSEMANTICSint Size;bool Flag;AddrType AddrTmp1,AddrTmp2;Flag= ((Address<0>.AddrMode==IndPre)|| (Address<0>.AddrMode==Direct))&& (Address<0>.IndexReg==NO);Size=Table[Val<2>];if (Address<3>.AddrMode==D)132IndexReg<4>=Addreg<3>;else IndexReg<4>=GetFree;AddrMode<4>=IndPre;if (Flag){Address<4>.AddrDisp=Address<0>.AddrDisp-Table[Val<2>]*Size;Addreg<4>=Addreg<0>;}else {Address<4>.AddrDisp=-Table[Val<2>]*Size;if (Address<0>.Addreg<=MaxReg)Addreg<4>=Addreg<0>;else Addreg<4>=GetAddr;}if (Size & 14) // 2,4,8Address<4>.Scale=Size);else Address<4>.Scale=1;AddrTmp1.AddrMode=D;AddrTmp1.Addreg=IndexReg<4>;if (Flag) Emit2(LEA,Address<0>,Address<4>);if (Address<3>.AddrMode!=D)Emit2(MOVE,Address<3>,AddrTmp1);AddrTmp2.AddrMode=IMM;AddrTmp2.AddrDisp=ElSize<3>;if (!(Size & 15)) // 1,2,4,8Emit2(MUL,AddrTmp2,AddrTmp1).8.5.
Трансляция целых выраженийТрансляция выражений различных типов управляется синтаксическиблагодаря наличию указателя типа перед каждой операцией. Мырассмотрим некоторые наиболее характерные проблемы генерации кодадля выражений.Система команд МС68020 обладает двумя особенностями,сказывающимися на генерации кода для арифметических выражений (тоже можно сказать и о генерации кода для выражений типа "множества"):1) один из операндов выражения (правый) должен при выполненииоперации находиться на регистре, поэтому если оба операнда не нарегистрах, то перед выполнением операции один из них надо загрузить нарегистр;2) система команд довольно "симметрична", т.е.
нет специальныхтребований к регистрам при выполнении операций (таких, например, какпары регистров или требования четности и т.д.).133Поэтому выбор команд при генерации арифметических выраженийопределяется довольно простыми таблицами решений. Например, дляцелочисленного сложения такая таблица приведена на рис.8.12.Правый операнд А2RVЛевыйоперандA1RADD A1,A2ADD A2,A1VADD A1,A2MOVE A1,RADD A2,RРис. 8.12Здесь имеется в виду, что R - операнд на регистре, V - операнд переменная или константа. Такая таблица решений должна такжеучитывать коммутативность операций.RULEIntExpr ::= 'PLUS' IntExpr IntExprSEMANTICSif (Address<2>.AddrMode!=D)&& (Address<3>.AddrMode!=D){Address<0>.AddrMode=D;Address<0>.Addreg=GetFree(RegSet<Block>);Emit2(MOVE,Address<2>,Address<0>);Emit2(ADD,Address<2>,Address<0>);}else if (Address<2>.AddrMode==D){Emit2(ADD,Address<3>,Address<2>);Address<0>:=Address<2>);}else {Emit2(ADD,Address<2>,Address<3>);Address<0>:=Address<3>);}.1348.6.