Page 1 of 2

Compiler trap in Real64 op ADR(x)

PostPosted: Fri Jul 24, 2020 8:33 am
by luowy
This is an example that leads to a compiler trap:
Code: Select all
MODULE TestBugs;

   IMPORT SYSTEM;
   
   PROCEDURE Do();
      VAR
      r: REAL;
      x: INTEGER;
   BEGIN
      r := r+ SYSTEM.ADR(x);
   END Do;

END TestBugs.

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Fri Jul 24, 2020 9:24 pm
by adimetrius
Suggested temporary fix:
DevCPL486 wrote: PROCEDURE GenFLoad* (VAR src: Item);
VAR f: BYTE; mf: INTEGER;
BEGIN
IF src.mode = Con THEN (* predefined constants *)
DevCPE.GenByte(0D9H); DevCPE.GenByte(0E8H + src.offset)
ELSIF src.form = Int64 THEN
DevCPE.GenByte(0DFH); GenCExt(28H, src)
ELSE
f := src.form; IF src.form = Pointer THEN src.form := Int32 END; CheckForm(src.form, mf); src.form := f;
DevCPE.GenByte(0D9H + mf); GenCExt(0, src)
END
END GenFLoad;


Why:
A simpler offending program is
Code: Select all
VAR r: Real; x: INTEGER;
r := SYSTEM.ADR(x)

The front-end of the compiler inserts a conversion function application because this assignment has an implicit type conversion, and also SYSTEM.ADR is represented as a convertion function application, as well. Thus, after the front-end, this statement looks something like:
r := CONV(CONV(x, Pointer), Real64)
The procedure CheckForm, called from GenFLoad, checks that requested conversion is ok, and traps otherwise.
From looking at the text of CheckForm, my guess is that the possibility of Pointer->Real64 conversion, which is totally permissible under the language rules, was nonetheless forgotten by the authors of CheckForm, being obviously a very rare case.
Code: Select all
   PROCEDURE CheckForm (form: BYTE; VAR mf: INTEGER);
   BEGIN
      IF form = Real32 THEN mf := 0
      ELSIF form = Real64 THEN mf := 4
      ELSIF form = Int32 THEN mf := 2
      ELSE ASSERT(form = Int16); mf := 6
      END
   END CheckForm;

CheckForm is called from many places, so I hesitated to change it; rather, I made a workaround for a more specific case: GenFLoad generates code to load a floating-point value, and my fix tricks CheckForm to think that it's presented with an Int32. If my guess is right, CheckForm might be amended after some testing.

Testing
Here is the simple test I used:
Code: Select all
MODULE TmpLuowy;

   IMPORT SYSTEM;
 
   VAR r, s: REAL; x: INTEGER;

   PROCEDURE Do* ();
   BEGIN
      s := SYSTEM.ADR(x);
      x := SYSTEM.ADR(x);
      r := 0;
      r := r + SYSTEM.ADR(x)
   END Do;

END TmpLuowy.


Here are the global variables after a call to TmpLuowy.Do:
Code: Select all
   .r   REAL   -173993812.0
   .s   REAL   -173993812.0
   .x   INTEGER   -173993812

Looks good to me!

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Sat Jul 25, 2020 12:05 pm
by luowy
adimetrius wrote:Suggested temporary fix:

thanks your work!
yes, the bug is in the bakckend, your fixup worked well;
I created a discussion post on the center board https://forum.blackboxframework.org/viewtopic.php?f=40&t=790

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Sat Jul 25, 2020 1:11 pm
by adimetrius
:D

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 9:16 am
by luowy
another choice:
DevCPC486.ConvMove
Code: Select all
    ELSE (* not sysval *) (* int -> float *)
        IF y.form =Pointer THEN y.form:=Int32 END;(*add this line*)         
        IF y.mode = Reg THEN Push(y) END;

or DevCPC486.GetAdr:
Code: Select all
   x.form := Int32(*Pointer*); x.typ := DevCPT.int32typ(*anyptrtyp*);
   Assert(x, hint, stop);

I prefer first one.

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 9:46 am
by Robert
luowy wrote:I created a discussion post on the center board https://forum.blackboxframework.org/viewtopic.php?f=40&t=790


The discussion is now at https://forum.blackboxframework.org/vie ... 7313#p7313 .

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 10:55 am
by adimetrius
For a permanent correction, why not amend CheckForm?

It would be the most 'straight' logic: CheckForm checks that the format of data is correct. It is correct to convert a Pointer to a Real64, and that't what CheckForm should return. Amending other procedures looks as a workaround to me.
Code: Select all
   PROCEDURE CheckForm (form: BYTE; VAR mf: INTEGER);
   BEGIN
      IF form = Real32 THEN mf := 0
      ELSIF form = Real64 THEN mf := 4
      ELSIF form = Int32 THEN mf := 2
      ELSIF form = Pointer THEN mf := 2       (* this is the addition *)
      ELSE ASSERT(form = Int16); mf := 6
      END
   END CheckForm;


P.S. It seems I can't post at the other discussion page

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 11:11 am
by luowy
The earlier is the better, the DevCPL is lower than DevCPC,
it's better to correct it whithin the frontend instead of the backend.
This is just my opinion, Not a rule;

adimetrius wrote:P.S. It seems I can't post at the other discussion page
the center forum need a membership, You need to apply for one, you can ask Ivan how to do;

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 3:52 pm
by adimetrius
I'm pretty sure both DevCPL and DevCPC are in the backend.

Re: Compiler trap in Real64 op ADR(x)

PostPosted: Tue Jul 28, 2020 4:15 pm
by luowy
adimetrius wrote:I'm pretty sure both DevCPL and DevCPC are in the backend.
you are right .