newCTFE Status July 2017
Stefan Koch via Digitalmars-d
digitalmars-d at puremagic.com
Fri Jul 28 09:22:58 PDT 2017
On Thursday, 13 July 2017 at 12:45:19 UTC, Stefan Koch wrote:
> [ ... ]
Hi Guys I just fixed another bug that had me puzzled for a while.
The following function
ulong swap(ulong val)
{
ulong result;
result |= (val & 0xFF) << 56;
result |= (val & 0xFF00) << 40;
result |= (val & 0xFF00_00) << 24;
result |= (val & 0xFF00_0000) << 8;
result |= (val & 0xFF00_0000_00) >> 8;
result |= (val & 0xFF00_0000_0000) >> 24;
result |= (val & 0xFF00_0000_0000_00) >> 40;
result |= (val & 0xFF00_0000_0000_0000) >> 56;
return result;
}
would return strange values.
pragma(msg, swap(0xABCD_EF01_2345_6789)); // returns
9900958322423496704
// expected
9900958322455989675
On further inspection the actual return value has only zeros in
the lower 32 bits.
The generated IR however looks completey correct.
Initialize();
Line(1);
auto val_1 = genParameter(BCType(BCTypeEnum.i64));//SP[4]
beginFunction(0);//swap
Line(2);
Line(3);
auto result_1 = genLocal(BCType(BCTypeEnum.i64),
"result");//SP[8]
Set(result_1, BCValue(Imm64(0)));
Line(5);
auto tmp1 =
genTemporary(BCType(BCTypeEnum.i64));//SP[16]
auto tmp2 =
genTemporary(BCType(BCTypeEnum.i64));//SP[24]
And3(tmp2, val_1, BCValue(Imm64(255)));
auto tmp3 =
genTemporary(BCType(BCTypeEnum.i32));//SP[32]
Le3(tmp3, BCValue(Imm32(56)), BCValue(Imm32(63)));
auto tmp4 =
genTemporary(BCType(BCTypeEnum.i32));//SP[36]
Set(tmp4, BCValue(Imm32(56)));
auto tmp5 =
genTemporary(BCType(BCTypeEnum.i32));//SP[40]
Set(tmp5, BCValue(Imm32(63)));
Assert(tmp3, Imm32(1) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(56)), BCValue(Imm32(63))*/;);
Lsh3(tmp1, tmp2, BCValue(Imm32(56)));
Or3(result_1, result_1, tmp1);
Line(6);
auto tmp6 =
genTemporary(BCType(BCTypeEnum.i64));//SP[44]
auto tmp7 =
genTemporary(BCType(BCTypeEnum.i64));//SP[52]
And3(tmp7, val_1, BCValue(Imm64(65280)));
auto tmp8 =
genTemporary(BCType(BCTypeEnum.i32));//SP[60]
Le3(tmp8, BCValue(Imm32(40)), BCValue(Imm32(63)));
auto tmp9 =
genTemporary(BCType(BCTypeEnum.i32));//SP[64]
Set(tmp9, BCValue(Imm32(40)));
auto tmp10 =
genTemporary(BCType(BCTypeEnum.i32));//SP[68]
Set(tmp10, BCValue(Imm32(63)));
Assert(tmp8, Imm32(2) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(40)), BCValue(Imm32(63))*/;);
Lsh3(tmp6, tmp7, BCValue(Imm32(40)));
Or3(result_1, result_1, tmp6);
Line(7);
auto tmp11 =
genTemporary(BCType(BCTypeEnum.i64));//SP[72]
auto tmp12 =
genTemporary(BCType(BCTypeEnum.i64));//SP[80]
And3(tmp12, val_1, BCValue(Imm64(16711680)));
auto tmp13 =
genTemporary(BCType(BCTypeEnum.i32));//SP[88]
Le3(tmp13, BCValue(Imm32(24)), BCValue(Imm32(63)));
auto tmp14 =
genTemporary(BCType(BCTypeEnum.i32));//SP[92]
Set(tmp14, BCValue(Imm32(24)));
auto tmp15 =
genTemporary(BCType(BCTypeEnum.i32));//SP[96]
Set(tmp15, BCValue(Imm32(63)));
Assert(tmp13, Imm32(3) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(24)), BCValue(Imm32(63))*/;);
Lsh3(tmp11, tmp12, BCValue(Imm32(24)));
Or3(result_1, result_1, tmp11);
Line(8);
auto tmp16 =
genTemporary(BCType(BCTypeEnum.i64));//SP[100]
auto tmp17 =
genTemporary(BCType(BCTypeEnum.i64));//SP[108]
And3(tmp17, val_1, BCValue(Imm64(4278190080)));
auto tmp18 =
genTemporary(BCType(BCTypeEnum.i32));//SP[116]
Le3(tmp18, BCValue(Imm32(8)), BCValue(Imm32(63)));
auto tmp19 =
genTemporary(BCType(BCTypeEnum.i32));//SP[120]
Set(tmp19, BCValue(Imm32(8)));
auto tmp20 =
genTemporary(BCType(BCTypeEnum.i32));//SP[124]
Set(tmp20, BCValue(Imm32(63)));
Assert(tmp18, Imm32(4) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(8)), BCValue(Imm32(63))*/;);
Lsh3(tmp16, tmp17, BCValue(Imm32(8)));
Or3(result_1, result_1, tmp16);
Line(10);
auto tmp21 =
genTemporary(BCType(BCTypeEnum.i64));//SP[128]
auto tmp22 =
genTemporary(BCType(BCTypeEnum.i64));//SP[136]
And3(tmp22, val_1, BCValue(Imm64(1095216660480)));
auto tmp23 =
genTemporary(BCType(BCTypeEnum.i32));//SP[144]
Le3(tmp23, BCValue(Imm32(8)), BCValue(Imm32(63)));
auto tmp24 =
genTemporary(BCType(BCTypeEnum.i32));//SP[148]
Set(tmp24, BCValue(Imm32(8)));
auto tmp25 =
genTemporary(BCType(BCTypeEnum.i32));//SP[152]
Set(tmp25, BCValue(Imm32(63)));
Assert(tmp23, Imm32(5) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(8)), BCValue(Imm32(63))*/;);
Rsh3(tmp21, tmp22, BCValue(Imm32(8)));
Or3(result_1, result_1, tmp21);
Line(11);
auto tmp26 =
genTemporary(BCType(BCTypeEnum.i64));//SP[156]
auto tmp27 =
genTemporary(BCType(BCTypeEnum.i64));//SP[164]
And3(tmp27, val_1, BCValue(Imm64(280375465082880)));
auto tmp28 =
genTemporary(BCType(BCTypeEnum.i32));//SP[172]
Le3(tmp28, BCValue(Imm32(24)), BCValue(Imm32(63)));
auto tmp29 =
genTemporary(BCType(BCTypeEnum.i32));//SP[176]
Set(tmp29, BCValue(Imm32(24)));
auto tmp30 =
genTemporary(BCType(BCTypeEnum.i32));//SP[180]
Set(tmp30, BCValue(Imm32(63)));
Assert(tmp28, Imm32(6) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(24)), BCValue(Imm32(63))*/;);
Rsh3(tmp26, tmp27, BCValue(Imm32(24)));
Or3(result_1, result_1, tmp26);
Line(12);
auto tmp31 =
genTemporary(BCType(BCTypeEnum.i64));//SP[184]
auto tmp32 =
genTemporary(BCType(BCTypeEnum.i64));//SP[192]
And3(tmp32, val_1, BCValue(Imm64(71776119061217280)));
auto tmp33 =
genTemporary(BCType(BCTypeEnum.i32));//SP[200]
Le3(tmp33, BCValue(Imm32(40)), BCValue(Imm32(63)));
auto tmp34 =
genTemporary(BCType(BCTypeEnum.i32));//SP[204]
Set(tmp34, BCValue(Imm32(40)));
auto tmp35 =
genTemporary(BCType(BCTypeEnum.i32));//SP[208]
Set(tmp35, BCValue(Imm32(63)));
Assert(tmp33, Imm32(7) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(40)), BCValue(Imm32(63))*/;);
Rsh3(tmp31, tmp32, BCValue(Imm32(40)));
Or3(result_1, result_1, tmp31);
Line(13);
auto tmp36 =
genTemporary(BCType(BCTypeEnum.i64));//SP[212]
auto tmp37 =
genTemporary(BCType(BCTypeEnum.i64));//SP[220]
And3(tmp37, val_1,
BCValue(Imm64(18374686479671623680)));
auto tmp38 =
genTemporary(BCType(BCTypeEnum.i32));//SP[228]
Le3(tmp38, BCValue(Imm32(56)), BCValue(Imm32(63)));
auto tmp39 =
genTemporary(BCType(BCTypeEnum.i32));//SP[232]
Set(tmp39, BCValue(Imm32(56)));
auto tmp40 =
genTemporary(BCType(BCTypeEnum.i32));//SP[236]
Set(tmp40, BCValue(Imm32(63)));
Assert(tmp38, Imm32(8) /*"shift by %d is outside the
range 0..%d", BCValue(Imm32(56)), BCValue(Imm32(63))*/;);
Rsh3(tmp36, tmp37, BCValue(Imm32(56)));
Or3(result_1, result_1, tmp36);
Line(26);
Ret(result_1);
Line(27);
endFunction();
Line(28);
Finalize();
So what is going wrong here ?
The 4 lines responsible for the lower 32bit of the result
have immediate and-instructions with constants larger then 32
bits.
like : And3(tmp37, val_1, BCValue(Imm64(18374686479671623680)));
which will cause the bytecode-interpreter to the
immediate-bytecode instruction And tmp37, (immvalue & 0xFFFF_FFFF)
Which in this case will become And tmp37, #0 (since the lower
bits of 18374686479671623680 are zero)
This is now fixed by pushing 64bit value into a register and
issuing a reg-reg instruction.
So, you see, there is never a boring day in newCTFE-land :)
Cheers, Stefan
More information about the Digitalmars-d
mailing list