[Oberon] Bug? procedure variable in procedure call parameter
volkert at nivoba.de
volkert at nivoba.de
Mon Apr 7 21:26:27 CEST 2014
Dear Peter,
i recompiled "ORG.Mod" including your fix and it seems to work.
BW,
Volkert
Am 07.04.2014 07:02, schrieb volkert at nivoba.de:
> 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
>
> --
> 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