Лекции по построению компилятора на Pascal

       

ПЕРЕДАЧА ПО ССЫЛКЕ


Это просто теперь, когда мы уже имеем механизм. Мы только должны внести несколько изменений в генерацию кода. Вместо помещения значения в стек, мы должны помещать адрес. Оказывается, 68000 имеет инструкцию PEA которая как раз делает это.

Для этого мы сделаем новую версию тестовой программы. Перед тем, как сделать что-нибудь еще, сделайте копию программы в ее текущем состоянии, потому что позже она понадобится нам снова.

Давайте начнем с рассмотрения кода, который мы хотели бы видеть сгенерированным для нового случая. Используя тот же самый пример что и раньше, мы должны вызов

    FOO(X, Y)

оттранслировать в:

    PEA X(PC)           ; Сохранить адрес X

    PEA Y(PC)           ; Сохранить адрес Y

    BSR FOO             ; Вызвать FOO

Это просто вопрос небольших изменений в Param:

{--------------------------------------------------------------}

{ Process an Actual Parameter }

procedure Param;

begin

     EmitLn('PEA ' + GetName + '(PC)');

end;

{--------------------------------------------------------------}

(Обратите внимание, что при передачей по ссылке мы не можем использовать выражения в списке параметров, поэтому Param может просто непосредственно считывать имя).

На другой стороне, ссылки на формальные параметры должны получить один уровень косвенности:

    FOO: LINK A6,#0

         MOVE.L 12(A6),A0    ; Извлечь адрес A

         MOVE (A0),D0        ; Извлечь A

         MOVE D0,-(SP)       ; Сохранить

         MOVE.L 8(A6),A0     ; Извлечь адрес B


         MOVE (A0),D0        ; Извлечь B

         ADD (SP)+,D0        ; Добавить A

         MOVE.L 12(A6),A0    ; Извлечь адрес A

         MOVE D0,(A0)        : Сохранить A

         UNLK A6

         RTS

Все это может быть обработано с изменениями в LoadParam  and StoreParam:

{--------------------------------------------------------------}

{ Load a Parameter to the Primary Register }

procedure LoadParam(N: integer);

var Offset: integer;

begin

     Offset := 8 + 4 * (NumParams - N);

     Emit('MOVE.L ');

     WriteLn(Offset, '(A6),A0');

     EmitLn('MOVE (A0),D0');

end;

{--------------------------------------------------------------}

{ Store a Parameter from the Primary Register }

procedure StoreParam(N: integer);

var Offset: integer;

begin

     Offset := 8 + 4 * (NumParams - N);

     Emit('MOVE.L ');

     WriteLn(Offset, '(A6),A0');

     EmitLn('MOVE D0,(A0)');

end;

{--------------------------------------------------------------}

Для правильного расчета,  мы также должны изменить одну строку в ParamList:

    ParamList := 4 * N;

Теперь должно работать. Испытайте компилятор и посмотрите, генерирует ли он приемлемый код. Как вы увидите, код вряд ли оптимален, так как мы перезагружаем регистр адреса каждый раз, когда необходим параметр. Но это соответствует нашему принципу KISS - просто генерировать код который работает. Мы только сделаем здесь небольшое замечание, что есть еще один кандидат для оптимизации и пойдем дальше.

Теперь мы научились обрабатывать параметры использую передачу по значению и передачу по ссылке. В реальном мире, конечно, мы хотели бы иметь возможность работать с обоими методами. Однако пока мы не можем этого сделать, потому что у нас еще не было урока по типам.

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

Это, фактически, будет одним из различий между TINY и KISS. В следующей версии TINY мы будем использовать передачу по ссылке для всех параметров. KISS будет поддерживать оба метода.


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