[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