[Oberon] Bug? procedure variable in procedure call parameter

volkert at nivoba.de volkert at nivoba.de
Mon Apr 7 07:02:23 CEST 2014


Thank you. Very interesting, this ORTool.DecObj command.

What is the best way get the original sources fixed?

BW,
Volkert



Am 06.04.2014 20:18, schrieb Peter De Wachter:
> 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
>
> --
> 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