Основы конструирования компиляторов

         

Трансляция переменных


Переменные отражают все многообразие механизмов доступа в языке. Переменная имеет синтезированный атрибут ADDRESS - это запись, описывающая адрес в команде МС68020. Этот атрибут сопоставляется всем нетерминалам, представляющим

значения. В системе команд МС68020 много способов адресации, и они отражены в структуре значения атрибута ADDRESS, имеющего следующий тип:

enum Register  
{D0,D1,D2,D3,D4,D5,D6,D7,A0,A1,A2,A3,A4,A5,A6,SP,NO};  

 
enum AddrMode  
{D,A,Post,Pre,Indirect,IndPre,IndPost,IndirPC,  
IndPrePC,IndPostPC,InDisp,Index,IndexPC,Abs,Imm};  

 
struct AddrType{  
  Register AddrReg,IndexReg;  
  int IndexDisp,AddrDisp;  
  short Scale;  
};

Значение регистра NO означает, что соответствующий регистр в адресации не используется.

Доступ к переменным осуществляется в зависимости от их уровня: глобальные переменные адресуются с помощью абсолютной адресации; переменные в процедуре текущего уровня адресуются через регистр базы А6.

Если стек организован

с помощью статической цепочки, то переменные предыдущего статического уровня адресуются через регистр статической цепочки А5; переменные остальных уровней адресуются «пробеганием» по статической цепочке с использованием вспомогательного регистра. Адрес переменной формируется при обработке структуры переменной слева направо и передается сначала сверху вниз как наследуемый атрибут нетерминала VarTail, а затем передается снизу-вверх как глобальный атрибут нетерминала Variable. Таким

образом, правило для обращения к переменной имеет вид (первое вхождение Number в правую часть - это уровень переменной, второе - ее Лидер-номер):

RULE  
Variable ::= VarMode Number Number VarTail  
SEMANTICS  
int Temp;  
struct AddrType AddrTmp1, AddrTmp2;  
3: if (Val==0) // Глобальная переменная  
      {Address.AddrMode=Abs;  
       Address.AddrDisp=0;  
      }  
   else // Локальная переменная  
      {Address.AddrMode=Index;  
       if (Val==Level) // Переменная текущего уровня  
          Address.AddrReg=A6;  
       else if (Val==Level-1)  
               // Переменная предыдущего уровня  
               Address.AddrReg=A5;  
            else  
               {Address.Addreg=GetFree(RegSet);  
                AddrTmp1.AddrMode=Indirect;  
                AddrTmp1.AddrReg=A5;  
                Emit2(MOVEA,AddrTmp1,Address.AddrReg);  
                AddrTmp1.AddrReg=Address.AddrReg;  
                AddrTmp2.AddrMode=A;  
                AddrTmp2.AddrReg=Address.AddrReg;  
                for (Temp=Level-Val;Temp>=2;Temp-)  
                    Emit2(MOVEA,AddrTmp1,AddrTmp2);  
               }  
       if (Val==Level)  
          Address.AddrDisp=Table[Val];  
       else  
          Address.AddrDisp=Table[Val]+Table[LevelTab[Val]];  
      }.

<
Функция GetFree выбирает очередной свободный регистр (либо регистр данных, либо адресный

регистр) и отмечает его как использованный в атрибуте RegSet нетерминала Block. Процедура Emit2 генерирует двухадресную команду. Первый параметр этой процедуры - код команды, второй и третий параметры имеют тип AddrType и служат операндами команды. Смещение переменной текущего уровня отсчитывается от базы (А6), а других уровней - от указателя статической цепочки, поэтому оно определяется как алгебраическая сумма размера локальных параметров и величины смещения переменной. Таблица

LevelTab - это таблица уровней процедур, содержащая указатели на последовательно вложенные процедуры.

Если стек организован с помощью дисплея, то трансляция для доступа к переменным может быть осуществлена следующим образом:

RULE  
Variable ::= VarMode Number Number VarTail  
SEMANTICS  
int Temp;  
3: if (Val==0) // Глобальная переменная  
      {Address.AddrMode=Abs;  
       Address.AddrDisp=0;  
      }  
   else // Локальная переменная  
      {Address.AddrMode=Index;  
       if (Val=Level) // Переменная текущего уровня  
          {Address.AddrReg=A6;  
           Address.AddrDisp=Table[Val];  
          }  
       else  
          {Address.AddrMode=IndPost;  
           Address.AddrReg=NO;  
           Address.IndexReg=NO;  
           Address.AddrDisp=Display[Val];  
           Address.IndexDisp=Table[Val];  
          }  
      }.

Рассмотрим трансляцию доступа к полям записи. Она описывается следующим правилом (Number - это Лидер-номер описания поля):

RULE  
VarTail ::= 'FIL' Number VarTail  
SEMANTICS  
if (Address.AddrMode==Abs)  
   {Address.AddrMode=Abs;  
    Address.AddrDisp=Address.AddrDisp+Table[Val];  
   }  
else  
   {Address=Address;  
    if (Address.AddrMode==Index)  
       Address.AddrDisp=Address.AddrDisp+Table[Val];  
    else  
       Address.IndexDisp=Address.IndexDisp+Table[Val];  
   }.


Содержание раздела