Лекции по конструированию компиляторов. В.А. Серебряков (1134688), страница 19
Текст из файла (страница 19)
8.6.ТекущийуровеньSPЛокальныеПредыдущий BPSPBPТочка возвратаТочка возвратаФакт. параметрыФакт. параметры.............................Рис. 8.6Рис. 8.7После выполнения команды UNLK BP, которая эквивалентна такойпоследовательности команд:MOVE BP,SPMOVE (SP),BPADD #4,SP /*4 - размер слова*/магазин имеет содержимое, изображенное на рис. 8.7.Наконец, после выполнения команды RTD размер_фактических,которая эквивалентна последовательностиADD размер_фактических+4, SPJMP -размер_фактических-4(SP)магазин восстанавливается до состояния, которое было до вызова.В зависимости от наличия локальных переменных, фактическихпараметров и необходимости упрятывания регистров каждая из этихкоманд может отсутствовать.8.2.2.
Организация магазина с дисплеемРассмотрим теперь организацию магазина с дисплеем. Дисплей - это122массив (DISPLAY), i-й элемент которого представляет собой указатель наобласть активации процедуры i-го статического уровня. Доступ кпеременным самой внутренней процедуры осуществляется через регистрBP. При вызове процедуры меньшего статического уровня изменений вдисплее не производится. При вызове локальной процедуры в дисплееотводится элемент для текущей (вызывающей) процедуры.
При вызовепроцедуры того же уровня (i) i-й элемент замещается на указатель областиактивации текущей процедуры и при выходе восстанавливается. Темсамым DISPLAY[i] всегда указывает на область активации последнейвызванной процедуры i-го статического уровня.Минимальный адресСохраненныерегистрыТекущийстатическийуровеньОбластьпоследнейвызваннойпроцедурыЛокальныеПредыдущий BPBPТочка возвратаФакт.
параметрыСохраненныерегистрыDISPLAY[i]предыдущийDISPLAY[i]ПредыдущийстатическийуровеньЛокальныеПредыдущий BP.............Рис. 8.8Запоминание и восстановление DISPLAY[i] можно не выполнять,если процедура не имеет локальных переменных и параметров или если изпроцедуры нет вызовов описанных в ней процедур. Структура магазинапри использовании дисплея изображена на рис. 8.8. Дисплей может бытьреализован либо через регистры (если их достаточно), либо через массив впамяти.При вызове процедуры следующего (по отношению к вызывающей)уровня в дисплее отводится очередной элемент. Если вызывающая123процедура имеет статический уровень i, то при вызове процедуры уровняj<=i элементы дисплея j,…,i должны быть скопированы (обычно в стеквызывающей процедуры), текущим уровнем становится j и в DISPLAY[j]заносится указатель на область активации вызываемой процедуры.
Поокончании работы вызываемой процедуры содержимой дисплеявосстанавливается из стека.Иногда используется комбинированная схема - дисплей в магазине.Дисплей хранится в области активации каждой процедуры. Формированиедисплея для процедуры осуществляется в соответствии с правилами,описанными выше.Отдельного рассмотрения требует вопрос о технике передачифактических параметров.
Конечно, в случае простых параметров(например, чисел) проблем не возникает. Однако передача массивов позначению - операция довольно дорогая, поэтому с точки зрения экономиипамяти целесообразнее сначала в подпрограмму передать адрес массива, азатем уже из подпрограммы по адресу передать в магазин сам массив. Всвязи с передачей параметров следует упомянуть еще одно обстоятельство.Рассмотренная схема организации магазина допустима только дляязыков со статически известными размерами фактических параметров.Однако, например, в языке Модула-2 по значению может быть передангибкий массив, и в этом случае нельзя статически распределить память дляпараметров.
Обычно в таких случаях заводят так называемый "паспорт"массива, в котором хранится вся необходимая информация, а сам массивразмещается в магазине в рабочей области выше сохраненных регистров.1248.3. Назначение адресовНазначение адресов переменным, параметрам и полям записей происходитпри обработке соответствующих объявлений. В однопроходномтрансляторе это может производиться вместе с построением основнойтаблицы символов и соответствующие адреса (или смещения) могутхраниться в этой же таблице. В промежуточном представлении Лидеробъявления сохранены, что делает это промежуточное представлениемашинно-независимым. Напомним, что в Лидер-представлении каждомуописанию соответствует некоторый номер. В процессе работы генераторакодов поддерживается таблица Table, в которой по этому номеру (входу)содержится следующая информация:- для типа - его размер;- для переменной - адрес;- для поля записи - смещение внутри записи;- для процедуры - размер локальных;- для диапазона индексов массива - значение левой границы.Функция IncTab вырабатывает указатель (вход) на новый элементтаблицы, проверяя при этом наличие свободной памяти.Таблица LevelTab - это таблица уровней процедур, содержащаяуказатели на последовательно вложенные процедуры (см.
рис. 4.9).Для вычисления адресов определим для каждого объявления двасинтезируемых атрибута: DISP будет обозначать смещение внутри областипроцедуры (или единицы компиляции), а SIZE - размер. Тогда семантикаправила для списка объявлений принимает видRULEDeclPart ::= ( Decl )SEMANTICSDisp<1>=0;1A:Disp<1>=Disp<1>+Size<1>;Size<0>=Disp<1>.Это можно следующим образом изобразить на дереве объявлений (рис.8.10).125DeclPart SizeDeclDispSizeDecl DeclDispDispSize SizeРис.
8.10Все объявления, кроме объявлений переменных, имеют нулевой размер.Размер объявления переменной определяется следующим правилом:RULEDecl ::= 'VAR' TypeDesSEMANTICSTablentry Entry;0: Entry=IncTab;Size<0>=((Table[VAL<2>]+1) / 2)*2;// Выравнивание на границу словаTable[Entry]=Disp<0>+Size<0>.В качестве примера трансляции определения типа рассмотрим обработкуописания записи:RULETypeDes ::= 'REC' ( TypeDes ) 'END'SEMANTICSint Disp;Tablentry Temp;0: Entry<0>=IncTab;Disp=0;2A: { Temp=IncTab;Table[Temp]=Disp;Disp=Disp+Table[Entry<2>]+1) / 2)*2;// Выравнивание на границу слова}Table[Entry<0>]=Disp.1268.4. Трансляция переменных.Переменные отражают все многообразие механизмов доступа в языке.Переменная имеет синтезированный атрибут 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,Direct,IndPre,IndPost,DirPC,IndPrePC,IndPostPC,Abs,Imm};struct AddrType{Register Addreg,IndexREG;int IndexDisp,AddrDisp;short Scale;};Значение регистра NO означает, что соответствующий регистр в адресациине используется.Доступ к переменным осуществляется в зависимости от их уровня:глобальные переменные адресуются с помощью абсолютной адресации;переменные процедуры текущего уровня адресуются через регистр базыА6.Если стек организован с помощью статической цепочки, топеременные предыдущего статического уровня адресуются через регистрстатической цепочки А5; переменные остальных уровней адресуются"пробеганием"постатическойцепочкесиспользованиемвспомогательного регистра.
Адрес переменной формируется приобработке структуры переменной слева направо и передается сначаласверху вниз как наследуемый атрибут нетерминала VarTail, а затемпередается снизу-вверх как глобальный атрибут нетерминала Variable.Таким образом, правило для обращения к переменной имеет вид (первоевхождение Number в правую часть - это уровень переменной, второе - ееЛидер-номер):RULEVariable ::= VarMode Number Number VarTailSEMANTICS:int Temp;AddrType AddrTmp1,AddrTmp2;1273: 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;else if (Val<2>==Level<Block>-1)// Переменная предыдущего уровняAddress<4>.Addreg:=A5;else{Address<4>.Addreg=GetFree(RegSet<Block>);AddrTmp1.AddrMode=Direct;AddrTmp1.Addreg=A5;AddrTmp1.IndexReg=No;AddrTmp1.AddrDisp=0;Emit2(MOVEA,AddrTmp1,Address<4>.Addreg);AddrTmp1.Addreg=Address<4>.Addreg;AddrTmp2.AddrMode=A;AddrTmp2.Addreg=Address<4>.Addreg;for (Temp=Level<Block>-Val<2>;???;Temp)Emit2(MOVEA,AddrTmp1,AddrTmp2);}}if (Val<2>==Level<Block>)Address<4>.AddrDisp=Table[Val<3>];else Address<4>.AddrDisp=Table[Val<3>]+Table[LevelTAB[Val<2>]];}}.Функция GetFree выбирает очередной свободный регистр (либо регистрданных, либо адресный регистр) и отмечает его как использованный ватрибуте RegSet нетерминала Block.