bmx-ng / bcc

A next-generation bcc parser for BlitzMax
zlib License
33 stars 13 forks source link

VarPtr and Ptr-array issues #586

Open GWRon opened 2 years ago

GWRon commented 2 years ago

This compiles - while I forgot a "varptr"

Local value:Object = String(1.2345:Float)
Local q:Byte Ptr[10]
(Int Ptr q)[0] = value.ToString().ToFloat()

But with "compiles" I mean it generates invalid C code.

Added the varptr ... and the compiled thing segfaulted.. until I rewrote it partially:

Local value:Object = String(1.2345:Float)
Local q:Byte Ptr[10]
'segfault
'(Int Ptr (Varptr q[0]))[0] = value.ToString().ToFloat()
'works
Local qPtr:Byte Ptr = Varptr(q[0])
(Int Ptr qptr)[0] = value.ToString().ToFloat()

(yfyi it is extracted from reflection.mod - tried stuff because of invoke() failing with floats)

GWRon commented 7 months ago
SuperStrict
framework brl.standardio

Local value:Object = String(1.2345:Float)
Local q:Byte Ptr[10]
'segfault
(Int Ptr (Varptr q[0]))[0] = value.ToString().ToFloat()
'works
Local qPtr:Byte Ptr = Varptr(q[0])
(Int Ptr qptr)[0] = value.ToString().ToFloat()

becomes:

        BBOBJECT bbt_value=(BBOBJECT)((BBString*)&_s0);
        BBARRAY bbt_q=bbArrayNew1D("*b", 10);
//segfault
        BBINT* bbt_=((BBINT*)((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]);
        bbt_[0]=((BBINT)bbStringToFloat((BBSTRING)(bbt_value)->clas->ToString((BBOBJECT)bbt_value)));
//works
        BBBYTE* bbt_qPtr=(&((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]);
        BBINT* bbt_=((BBINT*)bbt_qPtr);
        bbt_[0]=((BBINT)bbStringToFloat((BBSTRING)(bbt_value)->clas->ToString((BBOBJECT)bbt_value)));

As you see the difference is only in the way bbt_ and bbt_qPtr are constructed (pointer stuff). Yet both pieces of code should in my opinion be of the same "logic" (within bmx language)

GWRon commented 7 months ago

Using the "direct c-code" allows to play around with the generated code right from within BlitzMax:

SuperStrict
framework brl.standardio

Local q:Byte Ptr[10]
'works
'!BBBYTE* bbt_qPtrTEST=(&((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]);
'!BBINT* bbt_=((BBINT*)bbt_qPtrTEST);
'!bbt_[0]=1;
'segfault
'!//BBINT* bbt_=((BBINT*)((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]);
'!//bbt_[0]=1;

merging the two lines of the "works" into a single line ... exposes the difference more easily:

//works
BBINT* bbt_=((BBINT*)(&((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]));
//segfault
BBINT* bbt_=((BBINT*)  ((BBBYTE**)BBARRAYDATA(bbt_q,1))[0U]) ;

So somehow it misses to add the ampersand in the single-line-blitzmax version