binops.cpp (ldc-1.32.0) | : | binops.cpp (ldc-1.32.1) | ||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
#include "gen/complex.h" | #include "gen/complex.h" | |||
#include "gen/dvalue.h" | #include "gen/dvalue.h" | |||
#include "gen/irstate.h" | #include "gen/irstate.h" | |||
#include "gen/llvm.h" | #include "gen/llvm.h" | |||
#include "gen/llvmhelpers.h" | #include "gen/llvmhelpers.h" | |||
#include "gen/logger.h" | #include "gen/logger.h" | |||
#include "gen/tollvm.h" | #include "gen/tollvm.h" | |||
////////////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////////////// | |||
dinteger_t undoStrideMul(const Loc &loc, Type *t, dinteger_t offset) { | ||||
assert(t->ty == TY::Tpointer); | ||||
const auto elemSize = t->nextOf()->size(loc); | ||||
assert((offset % elemSize) == 0 && | ||||
"Expected offset by an integer amount of elements"); | ||||
return offset / elemSize; | ||||
} | ||||
////////////////////////////////////////////////////////////////////////////// | ||||
namespace { | namespace { | |||
struct RVals { | struct RVals { | |||
DRValue *lhs, *rhs; | DRValue *lhs, *rhs; | |||
}; | }; | |||
RVals evalSides(DValue *lhs, Expression *rhs, bool loadLhsAfterRhs) { | RVals evalSides(DValue *lhs, Expression *rhs, bool loadLhsAfterRhs) { | |||
RVals rvals; | RVals rvals; | |||
if (!loadLhsAfterRhs) { | if (!loadLhsAfterRhs) { | |||
rvals.lhs = lhs->getRVal(); | rvals.lhs = lhs->getRVal(); | |||
skipping to change at line 92 | skipping to change at line 81 | |||
return mul->e1; | return mul->e1; | |||
} | } | |||
DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset, | DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset, | |||
bool negateOffset, Type *resultType, | bool negateOffset, Type *resultType, | |||
bool loadLhsAfterRhs) { | bool loadLhsAfterRhs) { | |||
// The operand emitted by the frontend is in units of bytes, and not | // The operand emitted by the frontend is in units of bytes, and not | |||
// pointer elements. We try to undo this before resorting to | // pointer elements. We try to undo this before resorting to | |||
// temporarily bitcasting the pointer to i8. | // temporarily bitcasting the pointer to i8. | |||
LLType * llBaseTy = nullptr; | Type *const pointeeType = base->type->nextOf(); | |||
LLType * llBaseTy = DtoMemType(pointeeType); | ||||
LLValue *llBase = nullptr; | LLValue *llBase = nullptr; | |||
LLValue *llOffset = nullptr; | LLValue *llOffset = nullptr; | |||
LLValue *llResult = nullptr; | LLValue *llResult = nullptr; | |||
if (offset->isConst()) { | if (offset->isConst()) { | |||
llBase = DtoRVal(base); | llBase = DtoRVal(base); | |||
llBaseTy = DtoMemType(base->type->nextOf()); | const dinteger_t byteOffset = offset->toInteger(); | |||
dinteger_t byteOffset = offset->toInteger(); | ||||
if (byteOffset == 0) { | if (byteOffset == 0) { | |||
llResult = llBase; | llResult = llBase; | |||
} else { | } else { | |||
llOffset = DtoConstSize_t(undoStrideMul(loc, base->type, byteOffset)); | const auto pointeeSize = pointeeType->size(loc); | |||
if (pointeeSize && byteOffset % pointeeSize == 0) { // can do a nice GEP | ||||
llOffset = DtoConstSize_t(byteOffset / pointeeSize); | ||||
} else { // need to cast base to i8* | ||||
llBaseTy = getI8Type(); | ||||
llBase = DtoBitCast(llBase, getVoidPtrType()); | ||||
llOffset = DtoConstSize_t(byteOffset); | ||||
} | ||||
} | } | |||
} else { | } else { | |||
Expression *noStrideInc = extractNoStrideInc( | Expression *noStrideInc = | |||
offset, base->type->nextOf()->size(loc), negateOffset); | extractNoStrideInc(offset, pointeeType->size(loc), negateOffset); | |||
auto rvals = | auto rvals = | |||
evalSides(base, noStrideInc ? noStrideInc : offset, loadLhsAfterRhs); | evalSides(base, noStrideInc ? noStrideInc : offset, loadLhsAfterRhs); | |||
llBase = DtoRVal(rvals.lhs); | llBase = DtoRVal(rvals.lhs); | |||
llBaseTy = DtoMemType(rvals.lhs->type->nextOf()); | ||||
llOffset = DtoRVal(rvals.rhs); | llOffset = DtoRVal(rvals.rhs); | |||
if (!noStrideInc) { // byte offset => cast base to i8* | if (!noStrideInc) { // byte offset => cast base to i8* | |||
llBaseTy = LLType::getInt8Ty(gIR->context()); | llBaseTy = getI8Type(); | |||
llBase = DtoBitCast(llBase, getVoidPtrType()); | llBase = DtoBitCast(llBase, getVoidPtrType()); | |||
} | } | |||
} | } | |||
if (!llResult) { | if (!llResult) { | |||
if (negateOffset) | if (negateOffset) | |||
llOffset = gIR->ir->CreateNeg(llOffset); | llOffset = gIR->ir->CreateNeg(llOffset); | |||
llResult = DtoGEP1(llBaseTy, llBase, llOffset); | llResult = DtoGEP1(llBaseTy, llBase, llOffset); | |||
} | } | |||
End of changes. 7 change blocks. | ||||
19 lines changed or deleted | 15 lines changed or added |