newCTFE a "funny" bug

Stefan Koch uplink.coder at googlemail.com
Tue Jan 29 20:13:12 UTC 2019


Hi Guys,

I have exciting news for you.

I've made huge progress on issues which were confusing me for a 
while.

The following is a description of the problem:

class A { int f1; }
class B : A { int f2; }

int[2] f()
{
   B b;
   b.f2 = 2;
   b.f1 = 1;
   return [b.f2, b.f1];
}

pragma(msg, f()); // this had the output [1, 1]

What was indeed going on here looked like an ABI issue, but went 
deeper.
In order the have a stable ABI, I cannot relay on the class-sizes 
or field-offsets which dmd gives me.
Therefore I build my own representation of types and store them 
in type-tables.

when I get the request to store something in a field, I'll go 
look the type up in the type table and get the offset from the 
field information for that particular type.
For the above code this would have gone like this (code 
simplified):
> {b.f2 = 2};  const type = classes.indexOf(B); // would be 3 
> because there are 3 classes known (A, B and Object)
> const fieldIndex = type.fieldIndex(f2) // would be 1 because f2 
> is the first Field in B
> const fieldOffset = type.offsetOf(fieldIndex) // would be 0 
> because there is no field preceeding f2
> memoryLocationOf(b) + fieldOffset = 2; // same as 
> memoryLocationOf(b) becaue fieldOffset is zero
and then for the next statement
> {b.f2 = 2};  const type = classes.indexOf(B); // would be 3 
> because there are 3 classes known (A, B and Object)
> const fieldIndex = type.fieldIndex(f2) // can't find in B so 
> look in A; would be 1 because f1 is the first Field in A and 
> therfore falls onto the same index as f2
> const fieldOffset = type.offsetOf(fieldIndex) // would be 0 
> because there is no field preceeding f2 in B
> memoryLocationOf(b) + fieldOffset = 1; // same as 
> memoryLocationOf(b) because fieldOffset is zero
lastly:
> Return(CreateArrayOf([memoryLocation(b) + 0, memoryLocation(b) 
> + 0])); // this location has been set to one in the previous 
> statement.

In the actual code there is a multi-level lookup in a few 
diffrent tables going on, therefore this was much less straight 
forward to find as it seems.
Now that I have tracked down the root-cause of this problem is 
should not be too hard to fix.

Though it should be noted that about 40% of complexity in newCTFE 
is entirely for oop support, another 40% being delegates!

While I do think that delegates are genuinely useful I cannot the 
same about classes.
One of the reasons it took me so long to even notice this issue, 
is because I don't classes often myself, much less multi-level 
inheritance.

Cheers,

Stefan

P.S. I currently on a short vacation and working on getting 
newCTFE to a state where I can release it with a clear 
consciousness.


More information about the Digitalmars-d mailing list