From 1ab2204e0b0a9d72391e11a91253632f0f856202 Mon Sep 17 00:00:00 2001 From: kai Date: Sat, 2 Mar 2013 19:30:34 +0100 Subject: [PATCH] Fix big-endian code generation for btc, btr and bts. These intrinsics operate on size_t words. The generated LLVM IR operates on bytes and therefore assumes a little-endian architecture. The fix is to change the generated IR to work on size_t words. --- gen/toir.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index cec9a779..c7410fe2 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1096,12 +1096,14 @@ DValue* CallExp::toElem(IRState* p) LLValue* ptr = exp1->toElem(p)->getRVal(); LLValue* bitnum = exp2->toElem(p)->getRVal(); - // auto q = cast(ubyte*)ptr + (bitnum >> 3); - LLValue* q = DtoBitCast(ptr, DtoType(Type::tuns8->pointerTo())); - q = DtoGEP1(q, p->ir->CreateLShr(bitnum, 3), "bitop.q"); + unsigned bitmask = DtoSize_t()->getBitWidth() - 1; + assert(bitmask == 31 || bitmask == 63); + // auto q = cast(size_t*)ptr + (bitnum >> (64bit ? 6 : 5)); + LLValue* q = DtoBitCast(ptr, DtoSize_t()->getPointerTo()); + q = DtoGEP1(q, p->ir->CreateLShr(bitnum, bitmask == 63 ? 6 : 5), "bitop.q"); - // auto mask = 1 << (bitnum & 7); - LLValue* mask = p->ir->CreateAnd(bitnum, DtoConstSize_t(7), "bitop.tmp"); + // auto mask = 1 << (bitnum & bitmask); + LLValue* mask = p->ir->CreateAnd(bitnum, DtoConstSize_t(bitmask), "bitop.tmp"); mask = p->ir->CreateShl(DtoConstSize_t(1), mask, "bitop.mask"); // auto result = (*q & mask) ? -1 : 0; @@ -1127,7 +1129,7 @@ DValue* CallExp::toElem(IRState* p) } LLValue *newVal = p->ir->CreateBinOp(op, val, mask, "bitop.new_val"); - newVal = p->ir->CreateTrunc(newVal, DtoType(Type::tuns8), "bitop.tmp"); + newVal = p->ir->CreateTrunc(newVal, DtoSize_t(), "bitop.tmp"); DtoStore(newVal, q); }