Compiler trap in Real64 op ADR(x)

luowy
Posts: 88
Joined: Thu Dec 17, 2015 1:32 pm

Compiler trap in Real64 op ADR(x)

Post 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.
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Compiler trap in Real64 op ADR(x)

Post 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!
luowy
Posts: 88
Joined: Thu Dec 17, 2015 1:32 pm

Re: Compiler trap in Real64 op ADR(x)

Post 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/vie ... f=40&t=790
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Compiler trap in Real64 op ADR(x)

Post by adimetrius »

:D
luowy
Posts: 88
Joined: Thu Dec 17, 2015 1:32 pm

Re: Compiler trap in Real64 op ADR(x)

Post 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.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Compiler trap in Real64 op ADR(x)

Post by Robert »

luowy wrote:I created a discussion post on the center board https://forum.blackboxframework.org/vie ... f=40&t=790
The discussion is now at https://forum.blackboxframework.org/vie ... 7313#p7313 .
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Compiler trap in Real64 op ADR(x)

Post 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
luowy
Posts: 88
Joined: Thu Dec 17, 2015 1:32 pm

Re: Compiler trap in Real64 op ADR(x)

Post 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;
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Compiler trap in Real64 op ADR(x)

Post by adimetrius »

I'm pretty sure both DevCPL and DevCPC are in the backend.
luowy
Posts: 88
Joined: Thu Dec 17, 2015 1:32 pm

Re: Compiler trap in Real64 op ADR(x)

Post by luowy »

adimetrius wrote:I'm pretty sure both DevCPL and DevCPC are in the backend.
you are right .
Post Reply