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 :)

Reply via email to