mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-29 00:30:22 +02:00
Revert meaning of AddExp/MinExp for pointers to DMD default.
It might be worth considering to move the stride multiplication down to the glue layer in the upstream sources. But assigning a different meaning to AST nodes was a giant maintenance liability, especially with regard to CTFE.
This commit is contained in:
+106
-37
@@ -682,14 +682,24 @@ static void errorOnIllegalArrayOp(Expression* base, Expression* e1, Expression*
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static dinteger_t undoStrideMul(const Loc& loc, Type* t, dinteger_t offset)
|
||||
{
|
||||
assert(t->ty == Tpointer);
|
||||
d_uns64 elemSize = t->nextOf()->size(loc);
|
||||
assert((offset % elemSize) == 0 &&
|
||||
"Expected offset by an integer amount of elements");
|
||||
|
||||
return offset / elemSize;
|
||||
}
|
||||
|
||||
LLConstant* AddExp::toConstElem(IRState* p)
|
||||
{
|
||||
// add to pointer
|
||||
if (e1->type->ty == Tpointer && e2->type->isintegral()) {
|
||||
LLConstant *ptr = e1->toConstElem(p);
|
||||
LLConstant *index = e2->toConstElem(p);
|
||||
ptr = llvm::ConstantExpr::getGetElementPtr(ptr, llvm::makeArrayRef(&index, 1));
|
||||
return ptr;
|
||||
Type* t1b = e1->type->toBasetype();
|
||||
if (t1b->ty == Tpointer && e2->type->isintegral()) {
|
||||
llvm::Constant* ptr = e1->toConstElem(p);
|
||||
dinteger_t idx = undoStrideMul(loc, t1b, e2->toInteger());
|
||||
return llvm::ConstantExpr::getGetElementPtr(ptr, DtoConstSize_t(idx));
|
||||
}
|
||||
|
||||
error("expression '%s' is not a constant", toChars());
|
||||
@@ -697,7 +707,77 @@ LLConstant* AddExp::toConstElem(IRState* p)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Tries to remove a MulExp by a constant value of baseSize from e. Returns
|
||||
/// NULL if not possible.
|
||||
static Expression* extractNoStrideInc(Expression* e, d_uns64 baseSize, bool& negate)
|
||||
{
|
||||
MulExp* mul;
|
||||
while (true)
|
||||
{
|
||||
if (e->op == TOKneg)
|
||||
{
|
||||
negate = !negate;
|
||||
e = static_cast<NegExp*>(e)->e1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->op == TOKmul)
|
||||
{
|
||||
mul = static_cast<MulExp*>(e);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mul->e2->isConst()) return NULL;
|
||||
dinteger_t stride = mul->e2->toInteger();
|
||||
|
||||
if (stride != baseSize) return NULL;
|
||||
|
||||
return mul->e1;
|
||||
}
|
||||
|
||||
static DValue* emitPointerOffset(IRState* p, Loc loc, DValue* base,
|
||||
Expression* offset, bool negateOffset, Type* resultType)
|
||||
{
|
||||
// The operand emitted by the frontend is in units of bytes, and not
|
||||
// pointer elements. We try to undo this before resorting to
|
||||
// temporarily bitcasting the pointer to i8.
|
||||
|
||||
llvm::Value* noStrideInc = NULL;
|
||||
if (offset->isConst())
|
||||
{
|
||||
dinteger_t byteOffset = offset->toInteger();
|
||||
if (byteOffset == 0)
|
||||
{
|
||||
Logger::println("offset is zero");
|
||||
return base;
|
||||
}
|
||||
noStrideInc = DtoConstSize_t(undoStrideMul(loc, base->type, byteOffset));
|
||||
}
|
||||
else if (Expression* inc = extractNoStrideInc(offset,
|
||||
base->type->nextOf()->size(loc), negateOffset))
|
||||
{
|
||||
noStrideInc = inc->toElem(p)->getRVal();
|
||||
}
|
||||
|
||||
if (noStrideInc)
|
||||
{
|
||||
if (negateOffset) noStrideInc = p->ir->CreateNeg(noStrideInc);
|
||||
return new DImValue(base->type,
|
||||
DtoGEP1(base->getRVal(), noStrideInc, 0, p->scopebb()));
|
||||
}
|
||||
|
||||
// This might not actually be generated by the frontend, just to be
|
||||
// safe.
|
||||
llvm::Value* inc = offset->toElem(p)->getRVal();
|
||||
if (negateOffset) inc = p->ir->CreateNeg(inc);
|
||||
llvm::Value* bytePtr = DtoBitCast(base->getRVal(), getVoidPtrType());
|
||||
DValue* result = new DImValue(Type::tvoidptr, DtoGEP1(bytePtr, inc));
|
||||
return DtoCast(loc, result, resultType);
|
||||
}
|
||||
|
||||
|
||||
DValue* AddExp::toElem(IRState* p)
|
||||
{
|
||||
@@ -705,7 +785,6 @@ DValue* AddExp::toElem(IRState* p)
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = type->toBasetype();
|
||||
Type* e1type = e1->type->toBasetype();
|
||||
@@ -713,35 +792,28 @@ DValue* AddExp::toElem(IRState* p)
|
||||
|
||||
errorOnIllegalArrayOp(this, e1, e2);
|
||||
|
||||
if (e1type != e2type && e1type->ty == Tpointer) {
|
||||
Logger::println("add to pointer");
|
||||
if (DConstValue* cv = r->isConst()) {
|
||||
if (cv->c->isNullValue()) {
|
||||
Logger::println("is zero");
|
||||
return new DImValue(type, l->getRVal());
|
||||
}
|
||||
}
|
||||
LLValue* v = llvm::GetElementPtrInst::Create(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
|
||||
return new DImValue(type, v);
|
||||
if (e1type != e2type && e1type->ty == Tpointer && e2type->isintegral())
|
||||
{
|
||||
Logger::println("Adding integer to pointer");
|
||||
return emitPointerOffset(p, loc, l, e2, false, type);
|
||||
}
|
||||
else if (t->iscomplex()) {
|
||||
return DtoComplexAdd(loc, type, l, r);
|
||||
return DtoComplexAdd(loc, type, l, e2->toElem(p));
|
||||
}
|
||||
else {
|
||||
return DtoBinAdd(l,r);
|
||||
return DtoBinAdd(l, e2->toElem(p));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLConstant* MinExp::toConstElem(IRState* p)
|
||||
{
|
||||
if (e1->type->ty == Tpointer && e2->type->isintegral()) {
|
||||
LLConstant *ptr = e1->toConstElem(p);
|
||||
LLConstant *index = e2->toConstElem(p);
|
||||
index = llvm::ConstantExpr::getNeg(index);
|
||||
ptr = llvm::ConstantExpr::getGetElementPtr(ptr, llvm::makeArrayRef(&index, 1));
|
||||
return ptr;
|
||||
Type* t1b = e1->type->toBasetype();
|
||||
if (t1b->ty == Tpointer && e2->type->isintegral()) {
|
||||
llvm::Constant* ptr = e1->toConstElem(p);
|
||||
dinteger_t idx = undoStrideMul(loc, t1b, e2->toInteger());
|
||||
|
||||
llvm::Constant* negIdx = llvm::ConstantExpr::getNeg(DtoConstSize_t(idx));
|
||||
return llvm::ConstantExpr::getGetElementPtr(ptr, negIdx);
|
||||
}
|
||||
|
||||
error("expression '%s' is not a constant", toChars());
|
||||
@@ -749,15 +821,12 @@ LLConstant* MinExp::toConstElem(IRState* p)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* MinExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("MinExp::toElem: %s @ %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = type->toBasetype();
|
||||
Type* t1 = e1->type->toBasetype();
|
||||
@@ -767,7 +836,7 @@ DValue* MinExp::toElem(IRState* p)
|
||||
|
||||
if (t1->ty == Tpointer && t2->ty == Tpointer) {
|
||||
LLValue* lv = l->getRVal();
|
||||
LLValue* rv = r->getRVal();
|
||||
LLValue* rv = e2->toElem(p)->getRVal();
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "lv: " << *lv << " rv: " << *rv << '\n';
|
||||
lv = p->ir->CreatePtrToInt(lv, DtoSize_t(), "tmp");
|
||||
@@ -777,16 +846,16 @@ DValue* MinExp::toElem(IRState* p)
|
||||
diff = p->ir->CreateIntToPtr(diff, DtoType(type), "tmp");
|
||||
return new DImValue(type, diff);
|
||||
}
|
||||
else if (t1->ty == Tpointer) {
|
||||
LLValue* idx = p->ir->CreateNeg(r->getRVal(), "tmp");
|
||||
LLValue* v = llvm::GetElementPtrInst::Create(l->getRVal(), idx, "tmp", p->scopebb());
|
||||
return new DImValue(type, v);
|
||||
else if (t1->ty == Tpointer && t2->isintegral())
|
||||
{
|
||||
Logger::println("Subtracting integer from pointer");
|
||||
return emitPointerOffset(p, loc, l, e2, true, type);
|
||||
}
|
||||
else if (t->iscomplex()) {
|
||||
return DtoComplexSub(loc, type, l, r);
|
||||
return DtoComplexSub(loc, type, l, e2->toElem(p));
|
||||
}
|
||||
else {
|
||||
return DtoBinSub(l,r);
|
||||
return DtoBinSub(l, e2->toElem(p));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user