newCTFE Status July 2017

Stefan Koch via Digitalmars-d digitalmars-d at puremagic.com
Sun Jul 30 06:34:54 PDT 2017


On Thursday, 13 July 2017 at 12:45:19 UTC, Stefan Koch wrote:
> [ ... ]

Hey Guys!

working on the ctfe brainfuck compiler I finally figured out what 
was going wrong.

consider this:

uint fn ()
{
   uint[1] pointlessArray = [0];
   foreach(0 .. 42)
       pointlessArray[0]++;
   return pointlessArray[0];
}

static assert(fn() == 42);

until a few minutes ago this would have failed and the output 
would have been 0;
can you guess why ?

Well, while the ++array[0] would lower to BinAssignExp (array[0] 
+= 1) which does correctly deal with references
++ is actually not lowerd but it's own special expression.
which is handled with the following code:


                 auto expr = genExpr(e.e1); // in x++ expr is the x
                 if (!canWorkWithType(expr.type) || 
!canWorkWithType(retval.type))
                 {
                     bailout("++ only i32 is supported not " ~ 
to!string(expr.type.type) ~ " -- " ~ e.toString);
                     return;
                 }
                 assert(expr.vType != BCValueType.Immediate,
                     "++ does not make sense as on an Immediate 
Value");

                 Set(retval, expr); // return a copy of the old 
value
                 // the following code adds one the the original 
value
                 if (expr.type.type == BCTypeEnum.f23)
                 {
                     Add3(expr, expr, BCValue(Imm23f(1.0f)));
                 }
                 else if (expr.type.type == BCTypeEnum.f52)
                 {
                     Add3(expr, expr, BCValue(Imm52f(1.0)));
                 }
                 else
                 {
                     Add3(expr, expr, imm32(1));
                 }

  of course arr[x]++ will load the value into a temporary and add 
one to that temporary
  never modifying the array.
Luckily I introduced a a way for rmw (read-modify-write) 
operations to be done on structs on arrays a while back.

if the expr is not normal local i.e. a stack-variable it will 
have heapRef which tells you to which pointer you have to write 
to modify the actual value rather then just modifying the 
temporary in which it was loaded.

so this was fixed by adding the following 3 lines.

                 if (expr.heapRef)
                 {
                     StoreToHeapRef(expr);
                 }

Which will work for array's slices and structs alike :)


More information about the Digitalmars-d mailing list