[Oberon] Bug? procedure variable in procedure call parameter

Peter De Wachter pdewacht at gmail.com
Sun Apr 6 20:18:45 CEST 2014


You've run into compiler bug here. I couldn't reproduce at first, as the
dummy assignment to Test in your original mail masked the problem. This
is a smaller test case:

MODULE Scratch2;

PROCEDURE Id(x: INTEGER): INTEGER;
BEGIN RETURN x
END Id;

PROCEDURE P(a, b: INTEGER)
BEGIN
END P;

PROCEDURE Test*;
VAR f: PROCEDURE (x: INTEGER): INTEGER;
BEGIN
  f := Id;
  P(100, f(101))
END Test;

END Scratch2.

The compiler generated the following code for the Test procedure:
(disassembled with the ORTool.DecObj command)

(* setup stack frame *)
  14     4EE90008    SUB SP SP      8
  15     AFE00000    STR  LNK SP       0
(* assignment of f *)
  16     F7000000    BL       0
  17     40F90044    SUB  R0 LNK     68
  18     A0E00004    STR   R0 SP       4
(* first parameter *)
  19     40000064    MOV  R0  R0    100
(* get value of f -> destroys the MT register! *)
(* should have been stored in R11 *)
  20     8CE00004    LDR MT SP       4
  21     D100EA5C    BLEQ  MT
(* now do the function call *)
(* the system will crash as R11 isn't initialized *)
  22     41000065    MOV  R1  R0    101
  23     4EE90004    SUB SP SP      4
  24     A0E00000    STR   R0 SP       0
  25     00000001    MOV  R0  R0  R1
  26     D700000B    BL  R11
(* ... *)

So the problem is that the function pointer is loaded in the wrong
register. Replacing the PrepCall procedure in the ORG module with the
following code seems to fix it.

  PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  BEGIN
    IF x.type.form = ORB.Proc THEN
      IF x.mode # ORB.Const THEN
        load(x); code[pc-1] := code[pc-1] + (11 - x.r) * 01000000H; x.r
:= 11; DEC(RH); inhibitCalls := TRUE;
        IF check THEN Trap(EQ, 5) END
      END
    ELSE ORS.Mark("not a procedure")
    END ;
    r := RH
  END PrepCall;


On 31-03-14 19:17, Volkert Barr wrote:
> Dear all,
>
> i have a "problem" with the evaluation of a "procedure variable" used as parameter in a procedure call.
>
> this case leads to a ABORT or TRAP in Line 1. Procedure variable is FunId.
>
> BEGIN
> (*1*) Texts.WriteRealFix(W, FunId(1.0), 5,3);
>   ...
> END...
>
> this case with the dummy assigment to "Test" gives the correct output
> BEGIN
>   Test := FunId(1.0);	
>   Texts.WriteRealFix(W, FunId(1.0), 5,3);
>   ...
> END...
>
> The complete code can be found in the appended Module
>
> Bug or Feature??
>
> I use the Oberon-Image (RISC.IMG) from Paul Reed´s "Project Oberon"-Website with the nice "Oberon RISC Emulator" from Peter De Wachter (thanks for it).
>
> BW,
> Volkert
> ----
>
> MODULE Scratch;
> IMPORT Texts, Oberon;
>
>     TYPE Function = PROCEDURE (x:REAL) : REAL;
>
>     VAR W: Texts.Writer;
> 	FunId : Function;
>
>     PROCEDURE RealId(x:REAL):REAL;
>     BEGIN
>         RETURN x
>     END RealId;
>
>
>     PROCEDURE DoIt*;
>     VAR
> 	Test : REAL;
>     BEGIN
> 	Test := FunId(1.0);			
> 	Texts.WriteRealFix(W, FunId(1.0), 5,3);
> 	Texts.WriteRealFix(W, RealId(1.0), 5,3);
> 	Texts.WriteLn(W);
> 	Texts.Append(Oberon.Log, W.buf)
>     END DoIt;
>
> BEGIN Texts.OpenWriter(W);
>       FunId := RealId;
> END Scratch.
>
>
>
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon




More information about the Oberon mailing list