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

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Tue Dec 18 21:05:16 CET 2018

Question regarding the FPGA compiler:

The book "Project Oberon 2013 Edition" states (ch.12.7.7, p.47 of PO.Applications.pdf) that registers are saved prior to a *function* call and restored upon return, using procedures ORG.SaveRegs and ORG.RestoreRegs.

    PROCEDURE SaveRegs(r: LONGINT);  (* R[0 .. r-1]*)
      VAR r0: LONGINT;
    BEGIN (*r > 0*) r0 := 0;
      Put1(Sub, SP, SP, r*4); INC(frame, 4*r);
      REPEAT Put2(Str, r0, SP, (r-r0-1)*4); INC(r0) UNTIL r0 = r
    END SaveRegs;

    PROCEDURE RestoreRegs(r: LONGINT); (*R[0 .. r-1]*)
      VAR r0: LONGINT;
    BEGIN (*r > 0*) r0 := r;
      REPEAT DEC(r0); Put2(Ldr, r0, SP, (r-r0-1)*4) UNTIL r0 = 0;
      Put1(Add, SP, SP, r*4); DEC(frame, 4*r)
    END RestoreRegs;

However, procedure ORG.PrepCall (which calls ORG.SaveRegs):

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

is called not only for *function* procedures, i.e. in ORP.factor:

    PROCEDURE factor(VAR x: ORG.Item);
      IF (x.type.form = ORB.Proc) & (x.type.base.form # ORB.NoTyp) THEN
       ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx); x.type := x.type.base
but ALSO for *regular* procedures, i.e. in ORP.StatSequence:

    PROCEDURE StatSequence;
      IF (x.type.form = ORB.Proc) & (x.type.base.form = ORB.NoTyp) THEN
        ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx)

whereas after a procedure has been called, the registers are *only* restored for *function* procedures in ORG.Call

   PROCEDURE Call*(VAR x: Item; r: LONGINT);
   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

but not for regular procedures.

Can someone explain this asymmetry? Shouldn’t there be a "frame error" for regular procedures if the registers are not restored (i.e. if frame is not adjusted)?

PS: In Ceres-Oberon, OCC.SaveRegisters is called only in Factor (i.e. for function procedures), but not in StatSequence (i.e. for regular procedures) ... as one would expect.


More information about the Oberon mailing list