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:
David Nadlinger
2013-06-10 19:09:53 +02:00
parent 049f784e5f
commit f5e276d6a6
4 changed files with 106 additions and 57 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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));
}
}