mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-25 00:53:14 +01: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:
@@ -2005,10 +2005,7 @@ Expression *BinExp::scaleFactor(Scope *sc)
|
||||
stride = t1b->nextOf()->size(loc);
|
||||
if (!t->equals(t2b))
|
||||
e2 = e2->castTo(sc, t);
|
||||
// LDC: llvm uses typesafe pointer arithmetic
|
||||
#if !IN_LLVM
|
||||
e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
|
||||
#endif
|
||||
eoff = e2;
|
||||
e2->type = t;
|
||||
type = e1->type;
|
||||
@@ -2024,9 +2021,7 @@ Expression *BinExp::scaleFactor(Scope *sc)
|
||||
e = e1->castTo(sc, t);
|
||||
else
|
||||
e = e1;
|
||||
#if !IN_LLVM
|
||||
e = new MulExp(loc, e, new IntegerExp(0, stride, t));
|
||||
#endif
|
||||
eoff = e;
|
||||
e->type = t;
|
||||
type = e2->type;
|
||||
|
||||
@@ -670,17 +670,10 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
||||
Expression *val = agg1;
|
||||
TypeArray *tar = (TypeArray *)val->type;
|
||||
sinteger_t indx = ofs1;
|
||||
#if IN_LLVM // LDC: llvm uses typesafe pointer arithmetic
|
||||
if (op == TOKadd || op == TOKaddass || op == TOKplusplus)
|
||||
indx += ofs2;
|
||||
else if (op == TOKmin || op == TOKminass || op == TOKminusminus)
|
||||
indx -= ofs2;
|
||||
#else
|
||||
if (op == TOKadd || op == TOKaddass || op == TOKplusplus)
|
||||
indx = indx + ofs2/sz;
|
||||
else if (op == TOKmin || op == TOKminass || op == TOKminusminus)
|
||||
indx -= ofs2/sz;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
error(loc, "CTFE Internal compiler error: bad pointer operation");
|
||||
|
||||
@@ -8973,17 +8973,9 @@ L1:
|
||||
{ /* The handle to the monitor (call it a void*)
|
||||
* *(cast(void**)e + 1)
|
||||
*/
|
||||
#if IN_LLVM
|
||||
e = e->castTo(sc, tint8->pointerTo()->pointerTo());
|
||||
e = new AddExp(e->loc, e, new IntegerExp(1));
|
||||
e->type = tint8->pointerTo();
|
||||
e = e->castTo(sc, tvoidptr->pointerTo());
|
||||
e = new PtrExp(e->loc, e);
|
||||
#else
|
||||
e = e->castTo(sc, tvoidptr->pointerTo());
|
||||
e = new AddExp(e->loc, e, new IntegerExp(1));
|
||||
e = new PtrExp(e->loc, e);
|
||||
#endif
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
143
gen/toir.cpp
143
gen/toir.cpp
@@ -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