[Oberon] Question on ORG.SaveRegs / ORG.RestoreRegs in the FPGA Oberon compiler

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Sat Mar 2 13:45:19 CET 2019


  > > As a purely pedagogical addendum: A possible student exercise would be to
  > > rewrite ORG assuming *no* procedure variables existed in the language:
  > >
  > Having read PO2013 Compiler Application, and Compiler construction
  > books, still not feeling up to tinkering the compiler.

Tomas,
The question has been fully answered in the meantime. PS: In case you teach compiler construction,
below is *one” possible sequencing of student exercises to gradually build up one's understanding.
-ap

---------------------------------------------------------------------------------------

Step 0: Implement local/global procedure calls, assuming the language has *no* function procedures and *no* procedure variables

  PROCEDURE Call*(VAR x: Item);
  BEGIN Put3(BL, 7, (x.a DIV 4)-pc-1); RH := 0                                       (*see book “Compiler Construction"*)
  END Call;

Step 1: Add support for function procedures, but not procedure variables  => result of a function procedure may be part of an expression (held in regs)

  PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  BEGIN (*x.type.form = ORB.Proc*) r := RH;
    IF RH > 0 THEN SaveRegs(RH); RH := 0 END
  END PrepCall;

  PROCEDURE Call*(VAR x: Item; r: LONGINT);
  BEGIN (*x.mode = ORB.Const & x.type.form = ORB.Proc*) Put3(BL, 7, (x.a DIV 4)-pc-1);
    IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
    ELSE (*function*)
      IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
      x.mode := Reg; x.r := r; RH := r+1
    END
  END Call;

Step 2: Add support for *procedure variables* which are *not* de-referenced (as in ptr.handle) or selected (as in arr[3].handle, rec.fld.handle)

  PROCEDURE Call*(VAR x: Item; r: LONGINT);
  BEGIN (*x.type.form = ORB.Proc*)
    IF x.mode = ORB.Const THEN (*regular procedure*) Put3(BL, 7, (x.a DIV 4)-pc-1)
    ELSE (*procedure variable*) load(x); DEC(RH);                                                               (*e.g. x.mode = ORB.Var or ORB.Par*)
      IF check THEN Trap(EQ, 5) END ;
      Put3(BLR, 7, RH)
    END ;
    IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
    ELSE (*function*)
      IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
      x.mode := Reg; x.r := r; RH := r+1
    END
  END Call;

Step 3: Allow *de-referencing* (ptr.handle) and *selecting* (array[0].handle, record.field.handle) of procedure variables

  PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  BEGIN (*x.type.form = ORB.Proc*)
    IF x.mode > ORB.Par THEN load(x) END ;          (*if procedure variable has been dereferenced or selected => x.mode = RegI*)
    r := RH;
    IF RH > 0 THEN SaveRegs(RH); RH := 0 END
  END PrepCall;

  PROCEDURE Call*(VAR x: Item; r: LONGINT);
  BEGIN (*x.type.form = ORB.Proc*)
    IF x.mode = ORB.Const THEN  (*regular procedure*) Put3(BL, 7, (x.a DIV 4)-pc-1)
    ELSE  (*procedure variable*)
      IF x.mode <= ORB.Par THEN load(x); DEC(RH)                                (*x.mode = ORB.Var or ORB.Par*)
      ELSE Put2(Ldr, RH, SP, 0); Put1(Add, SP, SP, 4); DEC(r); DEC(frame, 4)   (*x.mode = RegI or Reg}*)
      END ;
      IF check THEN Trap(EQ, 5) END ;
      Put3(BLR, 7, RH)
    END ;
    IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
    ELSE (*function*)
      IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
      x.mode := Reg; x.r := r; RH := r+1
    END
  END Call;

Step 4: Allow imported procedures

  PROCEDURE Call*(VAR x: Item; r: LONGINT);
  BEGIN (*x.type.form = ORB.Proc*)
    IF x.mode = ORB.Const THEN  (*regular procedure*)
      IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
      ELSIF pc - fixorgP < 1000H THEN
        Put3(BL, 7, ((-x.r) (*mno*) * 100H + x.a (*exno*)) * 1000H + pc-fixorgP); fixorgP := pc-1
      ELSE ORS.Mark("fixup impossible")
      END
    ELSE  (*procedure variable*)
      IF x.mode <= ORB.Par THEN load(x); DEC(RH)
      ELSE Put2(Ldr, RH, SP, 0); Put1(Add, SP, SP, 4); DEC(r); DEC(frame, 4)
      END ;
      IF check THEN Trap(EQ, 5) END ;
      Put3(BLR, 7, RH)
    END ;
    IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
    ELSE (*function*)
      IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
      x.mode := Reg; x.r := r; RH := r+1
    END
  END Call;


More information about the Oberon mailing list