Let DValue types handle memory-only types consistently

I.e., disallow memory-only values from being represented as DImValues
and disallow getRVal() for such types instead of returning the address.
This commit is contained in:
Martin 2016-06-05 16:15:37 +02:00
parent c1c285782d
commit 963a10b225
15 changed files with 221 additions and 223 deletions

View file

@ -85,7 +85,7 @@ struct LLTypeMemoryLayout {
/// Removes padding fields for (non-union-containing!) structs /// Removes padding fields for (non-union-containing!) structs
struct RemoveStructPadding : ABIRewrite { struct RemoveStructPadding : ABIRewrite {
LLValue *put(DValue *v) override { LLValue *put(DValue *v) override {
return DtoUnpaddedStruct(v->type->toBasetype(), v->getRVal()); return DtoUnpaddedStruct(v->type->toBasetype(), v->getLVal());
} }
LLValue *getLVal(Type *dty, LLValue *v) override { LLValue *getLVal(Type *dty, LLValue *v) override {
@ -197,7 +197,7 @@ struct ExplicitByvalRewrite : ABIRewrite {
".ExplicitByvalRewrite_dump"); ".ExplicitByvalRewrite_dump");
} }
LLValue *originalPointer = v->getRVal(); LLValue *originalPointer = v->getLVal();
LLType *type = originalPointer->getType()->getPointerElementType(); LLType *type = originalPointer->getType()->getPointerElementType();
LLValue *copyForCallee = LLValue *copyForCallee =
DtoRawAlloca(type, align, ".ExplicitByvalRewrite_dump"); DtoRawAlloca(type, align, ".ExplicitByvalRewrite_dump");
@ -228,7 +228,7 @@ struct HFAToArray : ABIRewrite {
LLValue *put(DValue *dv) override { LLValue *put(DValue *dv) override {
Logger::println("rewriting HFA %s -> as array", dv->type->toChars()); Logger::println("rewriting HFA %s -> as array", dv->type->toChars());
LLType *t = type(dv->type); LLType *t = type(dv->type);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t))); return DtoLoad(DtoBitCast(dv->getLVal(), getPtrToType(t)));
} }
LLValue *getLVal(Type *dty, LLValue *v) override { LLValue *getLVal(Type *dty, LLValue *v) override {
@ -252,7 +252,7 @@ struct CompositeToArray64 : ABIRewrite {
LLValue *put(DValue *dv) override { LLValue *put(DValue *dv) override {
Logger::println("rewriting %s -> as i64 array", dv->type->toChars()); Logger::println("rewriting %s -> as i64 array", dv->type->toChars());
LLType *t = type(dv->type); LLType *t = type(dv->type);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t))); return DtoLoad(DtoBitCast(dv->getLVal(), getPtrToType(t)));
} }
LLValue *getLVal(Type *dty, LLValue *v) override { LLValue *getLVal(Type *dty, LLValue *v) override {
@ -274,7 +274,7 @@ struct CompositeToArray32 : ABIRewrite {
LLValue *put(DValue *dv) override { LLValue *put(DValue *dv) override {
Logger::println("rewriting %s -> as i32 array", dv->type->toChars()); Logger::println("rewriting %s -> as i32 array", dv->type->toChars());
LLType *t = type(dv->type); LLType *t = type(dv->type);
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t))); return DtoLoad(DtoBitCast(dv->getLVal(), getPtrToType(t)));
} }
LLValue *getLVal(Type *dty, LLValue *v) override { LLValue *getLVal(Type *dty, LLValue *v) override {

View file

@ -38,15 +38,8 @@ llvm::Value *ABIRewrite::getRVal(Type *dty, LLValue *v) {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
LLValue *ABIRewrite::getAddressOf(DValue *v) { LLValue *ABIRewrite::getAddressOf(DValue *v) {
if (DtoIsInMemoryOnly(v->type)) { if (v->isLVal())
// v is lowered to a LL pointer to the struct/static array
return v->getRVal();
}
if (v->isLVal()) {
return v->getLVal(); return v->getLVal();
}
return DtoAllocaDump(v, ".getAddressOf_dump"); return DtoAllocaDump(v, ".getAddressOf_dump");
} }

View file

@ -31,16 +31,16 @@ static void DtoSetArray(DValue *array, LLValue *dim, LLValue *ptr);
static LLValue *DtoSlice(Expression *e) { static LLValue *DtoSlice(Expression *e) {
DValue *dval = toElem(e); DValue *dval = toElem(e);
LLValue *val = dval->getRVal();
if (dval->type->toBasetype()->ty == Tsarray) { if (dval->type->toBasetype()->ty == Tsarray) {
// Convert static array to slice // Convert static array to slice
LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context())); LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context()));
LLValue *array = DtoRawAlloca(type, 0, ".array"); LLValue *array = DtoRawAlloca(type, 0, ".array");
DtoStore(DtoArrayLen(dval), DtoGEPi(array, 0, 0, ".len")); DtoStore(DtoArrayLen(dval), DtoGEPi(array, 0, 0, ".len"));
DtoStore(DtoBitCast(val, getVoidPtrType()), DtoGEPi(array, 0, 1, ".ptr")); DtoStore(DtoBitCast(dval->getLVal(), getVoidPtrType()),
val = DtoLoad(array); DtoGEPi(array, 0, 1, ".ptr"));
return DtoLoad(array);
} }
return val; return dval->getRVal();
} }
static LLValue *DtoSlice(LLValue *ptr, LLValue *length, static LLValue *DtoSlice(LLValue *ptr, LLValue *length,
@ -69,7 +69,7 @@ static LLValue *DtoSlicePtr(Expression *e) {
} }
bool isStaticArray = vt->ty == Tsarray; bool isStaticArray = vt->ty == Tsarray;
LLValue *val = isStaticArray ? dval->getRVal() : makeLValue(loc, dval); LLValue *val = isStaticArray ? dval->getLVal() : makeLValue(loc, dval);
LLValue *array = DtoRawAlloca(type, 0, ".array"); LLValue *array = DtoRawAlloca(type, 0, ".array");
LLValue *len = isStaticArray ? DtoArrayLen(dval) : DtoConstSize_t(1); LLValue *len = isStaticArray ? DtoArrayLen(dval) : DtoConstSize_t(1);
DtoStore(len, DtoGEPi(array, 0, 0)); DtoStore(len, DtoGEPi(array, 0, 0));
@ -120,21 +120,26 @@ static void DtoArrayInit(Loc &loc, LLValue *ptr, LLValue *length,
IF_LOG Logger::println("DtoArrayInit"); IF_LOG Logger::println("DtoArrayInit");
LOG_SCOPE; LOG_SCOPE;
LLValue *value = dvalue->getRVal();
LLValue *elementSize = DtoConstSize_t(getTypeAllocSize(value->getType()));
// lets first optimize all zero/constant i8 initializations down to a memset. // lets first optimize all zero/constant i8 initializations down to a memset.
// this simplifies codegen later on as llvm null's have no address! // this simplifies codegen later on as llvm null's have no address!
if (isaConstant(value) && if (!dvalue->isLVal()) {
(isaConstant(value)->isNullValue() || LLConstant *constantVal = isaConstant(dvalue->getRVal());
value->getType() == LLType::getInt8Ty(gIR->context()))) { if (constantVal &&
LLValue *nbytes = gIR->ir->CreateMul(length, elementSize, ".nbytes"); (constantVal->isNullValue() ||
if (isaConstant(value)->isNullValue()) { constantVal->getType() == LLType::getInt8Ty(gIR->context()))) {
DtoMemSetZero(ptr, nbytes); LLValue *size = length;
} else { size_t elementSize = getTypeAllocSize(constantVal->getType());
DtoMemSet(ptr, value, nbytes); if (elementSize != 1) {
size = gIR->ir->CreateMul(length, DtoConstSize_t(elementSize),
".arraysize");
}
if (constantVal->isNullValue()) {
DtoMemSetZero(ptr, size);
} else {
DtoMemSet(ptr, constantVal, size);
}
return;
} }
return;
} }
// create blocks // create blocks
@ -224,8 +229,7 @@ static bool arrayNeedsPostblit(Type *t) {
} }
// Does array assignment (or initialization) from another array of the same // Does array assignment (or initialization) from another array of the same
// element type // element type or from an appropriate single element.
// or from an appropriate single element.
void DtoArrayAssign(Loc &loc, DValue *lhs, DValue *rhs, int op, void DtoArrayAssign(Loc &loc, DValue *lhs, DValue *rhs, int op,
bool canSkipPostblit) { bool canSkipPostblit) {
IF_LOG Logger::println("DtoArrayAssign"); IF_LOG Logger::println("DtoArrayAssign");
@ -1032,7 +1036,6 @@ LLValue *DtoArrayLen(DValue *v) {
if (t->ty == Tsarray) { if (t->ty == Tsarray) {
assert(!v->isSlice()); assert(!v->isSlice());
assert(!v->isNull()); assert(!v->isNull());
assert(t->ty == Tsarray);
TypeSArray *sarray = static_cast<TypeSArray *>(t); TypeSArray *sarray = static_cast<TypeSArray *>(t);
return DtoConstSize_t(sarray->dim->toUInteger()); return DtoConstSize_t(sarray->dim->toUInteger());
} }
@ -1061,7 +1064,7 @@ LLValue *DtoArrayPtr(DValue *v) {
} else if (t->ty == Tsarray) { } else if (t->ty == Tsarray) {
assert(!v->isSlice()); assert(!v->isSlice());
assert(!v->isNull()); assert(!v->isNull());
ptr = DtoGEPi(v->getRVal(), 0, 0, "sarrayptr"); ptr = v->getLVal();
} else { } else {
llvm_unreachable("Unexpected array type."); llvm_unreachable("Unexpected array type.");
} }
@ -1083,31 +1086,26 @@ DValue *DtoCastArray(Loc &loc, DValue *u, Type *to) {
fatal(); fatal();
} }
LLValue *rval;
LLValue *rval2;
bool isslice = false;
IF_LOG Logger::cout() << "from array or sarray" << '\n'; IF_LOG Logger::cout() << "from array or sarray" << '\n';
if (totype->ty == Tpointer) { if (totype->ty == Tpointer) {
IF_LOG Logger::cout() << "to pointer" << '\n'; IF_LOG Logger::cout() << "to pointer" << '\n';
rval = DtoArrayPtr(u); LLValue *ptr = DtoArrayPtr(u);
if (rval->getType() != tolltype) { if (ptr->getType() != tolltype) {
rval = gIR->ir->CreateBitCast(rval, tolltype); ptr = gIR->ir->CreateBitCast(ptr, tolltype);
} }
return new DImValue(to, ptr);
} else if (totype->ty == Tarray) { } else if (totype->ty == Tarray) {
IF_LOG Logger::cout() << "to array" << '\n'; IF_LOG Logger::cout() << "to array" << '\n';
LLType *ptrty = DtoArrayType(totype)->getContainedType(1); LLValue *length = nullptr;
LLType *ety = DtoMemType(fromtype->nextOf()); LLValue *ptr = nullptr;
if (fromtype->ty == Tsarray) { if (fromtype->ty == Tsarray) {
LLValue *uval = u->getRVal(); uinteger_t len = static_cast<TypeSArray *>(fromtype)->dim->toUInteger();
length = DtoConstSize_t(len);
IF_LOG Logger::cout() << "uvalTy = " << *uval->getType() << '\n'; ptr = u->getLVal();
assert(isaPointer(ptr->getType()));
assert(isaPointer(uval->getType())); LLArrayType *arrty = isaArray(ptr->getType()->getContainedType(0));
LLArrayType *arrty = isaArray(uval->getType()->getContainedType(0));
if (arrty->getNumElements() * fromtype->nextOf()->size() % if (arrty->getNumElements() * fromtype->nextOf()->size() %
totype->nextOf()->size() != totype->nextOf()->size() !=
@ -1117,60 +1115,46 @@ DValue *DtoCastArray(Loc &loc, DValue *u, Type *to) {
fromtype->toChars(), totype->toChars()); fromtype->toChars(), totype->toChars());
fatal(); fatal();
} }
uinteger_t len = static_cast<TypeSArray *>(fromtype)->dim->toUInteger();
rval2 = LLConstantInt::get(DtoSize_t(), len, false);
if (fromtype->nextOf()->size() != totype->nextOf()->size()) {
rval2 = DtoArrayCastLength(loc, rval2, ety, ptrty->getContainedType(0));
}
rval = DtoBitCast(uval, ptrty);
} else { } else {
rval2 = DtoArrayLen(u); length = DtoArrayLen(u);
if (fromtype->nextOf()->size() != totype->nextOf()->size()) { ptr = DtoArrayPtr(u);
rval2 = DtoArrayCastLength(loc, rval2, ety, ptrty->getContainedType(0));
}
rval = DtoArrayPtr(u);
rval = DtoBitCast(rval, ptrty);
} }
isslice = true;
LLType *ptrty = DtoArrayType(totype)->getContainedType(1);
LLType *ety = DtoMemType(fromtype->nextOf());
if (fromtype->nextOf()->size() != totype->nextOf()->size())
length = DtoArrayCastLength(loc, length, ety, ptrty->getContainedType(0));
return new DSliceValue(to, length, DtoBitCast(ptr, ptrty));
} else if (totype->ty == Tsarray) { } else if (totype->ty == Tsarray) {
IF_LOG Logger::cout() << "to sarray" << '\n'; IF_LOG Logger::cout() << "to sarray" << '\n';
size_t tosize = static_cast<TypeSArray *>(totype)->dim->toInteger(); LLValue *ptr = nullptr;
if (fromtype->ty == Tsarray) { if (fromtype->ty == Tsarray) {
LLValue *uval = u->getRVal(); ptr = u->getLVal();
IF_LOG Logger::cout() << "uvalTy = " << *uval->getType() << '\n';
rval = DtoBitCast(uval, getPtrToType(tolltype));
} else { } else {
size_t tosize = static_cast<TypeSArray *>(totype)->dim->toInteger();
size_t i = size_t i =
(tosize * totype->nextOf()->size() - 1) / fromtype->nextOf()->size(); (tosize * totype->nextOf()->size() - 1) / fromtype->nextOf()->size();
DConstValue index(Type::tsize_t, DtoConstSize_t(i)); DConstValue index(Type::tsize_t, DtoConstSize_t(i));
DtoIndexBoundsCheck(loc, u, &index); DtoIndexBoundsCheck(loc, u, &index);
ptr = DtoArrayPtr(u);
rval = DtoArrayPtr(u);
rval = DtoBitCast(rval, getPtrToType(tolltype));
} }
return new DVarValue(to, DtoBitCast(ptr, getPtrToType(tolltype)));
} else if (totype->ty == Tbool) { } else if (totype->ty == Tbool) {
// return (arr.ptr !is null) // return (arr.ptr !is null)
LLValue *ptr = DtoArrayPtr(u); LLValue *ptr = DtoArrayPtr(u);
LLConstant *nul = getNullPtr(ptr->getType()); LLConstant *nul = getNullPtr(ptr->getType());
rval = gIR->ir->CreateICmpNE(ptr, nul); return new DImValue(to, gIR->ir->CreateICmpNE(ptr, nul));
} else { } else {
rval = DtoArrayPtr(u); LLValue *ptr = DtoArrayPtr(u);
rval = DtoBitCast(rval, getPtrToType(tolltype)); ptr = DtoBitCast(ptr, getPtrToType(tolltype));
if (totype->ty != Tstruct) { return new DVarValue(to, ptr);
rval = DtoLoad(rval);
}
} }
if (isslice) { llvm_unreachable("Unexpected array cast");
Logger::println("isslice");
return new DSliceValue(to, rval2, rval);
}
return new DImValue(to, rval);
} }
void DtoIndexBoundsCheck(Loc &loc, DValue *arr, DValue *index) { void DtoIndexBoundsCheck(Loc &loc, DValue *arr, DValue *index) {

View file

@ -40,6 +40,13 @@ bool DValue::definedInFuncEntryBB() { return isDefinedInFuncEntryBB(val); }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DImValue::DImValue(Type *t, llvm::Value *v) : DValue(t, v) {
assert(!DtoIsInMemoryOnly(t) &&
"Cannot represent memory-only type as immediate DValue");
}
////////////////////////////////////////////////////////////////////////////////
DConstValue::DConstValue(Type *t, llvm::Constant *con) : DValue(t, con) {} DConstValue::DConstValue(Type *t, llvm::Constant *con) : DValue(t, con) {}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -77,12 +84,12 @@ LLValue *DVarValue::getLVal() { return isSpecialRefVar ? DtoLoad(val) : val; }
LLValue *DVarValue::getRVal() { LLValue *DVarValue::getRVal() {
LLValue *storage = val; LLValue *storage = val;
if (isSpecialRefVar) { if (isSpecialRefVar)
storage = DtoLoad(storage); storage = DtoLoad(storage);
}
if (DtoIsInMemoryOnly(type->toBasetype())) { if (DtoIsInMemoryOnly(type->toBasetype())) {
return storage; llvm_unreachable("getRVal() for memory-only type");
return nullptr;
} }
LLValue *rawValue = DtoLoad(storage); LLValue *rawValue = DtoLoad(storage);

View file

@ -42,12 +42,11 @@ class DSliceValue;
class DValue { class DValue {
public: public:
Type *const type; Type *const type;
llvm::Value *const val;
virtual ~DValue() = default; virtual ~DValue() = default;
virtual llvm::Value *getLVal() { virtual llvm::Value *getLVal() {
assert(0); assert(0 && "DValue is not a LL lvalue!");
return nullptr; return nullptr;
} }
virtual llvm::Value *getRVal() { return val; } virtual llvm::Value *getRVal() { return val; }
@ -72,6 +71,8 @@ public:
virtual DFuncValue *isFunc() { return nullptr; } virtual DFuncValue *isFunc() { return nullptr; }
protected: protected:
llvm::Value *const val;
DValue(Type *t, llvm::Value *v) : type(t), val(v) { DValue(Type *t, llvm::Value *v) : type(t), val(v) {
assert(type); assert(type);
assert(val); assert(val);
@ -81,7 +82,7 @@ protected:
// immediate d-value // immediate d-value
class DImValue : public DValue { class DImValue : public DValue {
public: public:
DImValue(Type *t, llvm::Value *v) : DValue(t, v) {} DImValue(Type *t, llvm::Value *v);
DImValue *isIm() override { return this; } DImValue *isIm() override { return this; }
}; };

View file

@ -1037,8 +1037,8 @@ DValue *DtoArgument(Parameter *fnarg, Expression *argexp) {
if (fnarg && (fnarg->storageClass & (STCref | STCout))) { if (fnarg && (fnarg->storageClass & (STCref | STCout))) {
Loc loc; Loc loc;
DValue *arg = toElem(argexp, true); DValue *arg = toElem(argexp, true);
return new DImValue(argexp->type, return new DVarValue(argexp->type,
arg->isLVal() ? arg->getLVal() : makeLValue(loc, arg)); arg->isLVal() ? arg->getLVal() : makeLValue(loc, arg));
} }
DValue *arg = toElem(argexp); DValue *arg = toElem(argexp);

View file

@ -152,15 +152,7 @@ DValue *DtoInlineIRExpr(Loc &loc, FuncDeclaration *fdecl,
if (type->ty == Tstruct) { if (type->ty == Tstruct) {
// make a copy // make a copy
llvm::Value *mem = DtoAlloca(type, ".__ir_tuple_ret"); llvm::Value *mem = DtoAlloca(type, ".__ir_tuple_ret");
DtoStore(rv, DtoBitCast(mem, getPtrToType(rv->getType())));
TypeStruct *ts = static_cast<TypeStruct *>(type);
size_t n = ts->sym->fields.dim;
for (size_t i = 0; i < n; i++) {
llvm::Value *v = gIR->ir->CreateExtractValue(rv, i, "");
llvm::Value *gep = DtoGEPi(mem, 0, i);
DtoStore(v, gep);
}
return new DVarValue(fdecl->type->nextOf(), mem); return new DVarValue(fdecl->type->nextOf(), mem);
} }

View file

@ -206,11 +206,11 @@ LLValue *DtoGcMalloc(Loc &loc, LLType *lltype, const char *name) {
} }
LLValue *DtoAllocaDump(DValue *val, const char *name) { LLValue *DtoAllocaDump(DValue *val, const char *name) {
return DtoAllocaDump(val->getRVal(), val->type, name); return DtoAllocaDump(val, val->type, name);
} }
LLValue *DtoAllocaDump(DValue *val, Type *asType, const char *name) { LLValue *DtoAllocaDump(DValue *val, Type *asType, const char *name) {
return DtoAllocaDump(val->getRVal(), asType, name); return DtoAllocaDump(val, DtoType(asType), DtoAlignment(asType), name);
} }
LLValue *DtoAllocaDump(DValue *val, LLType *asType, int alignment, LLValue *DtoAllocaDump(DValue *val, LLType *asType, int alignment,
@ -314,15 +314,14 @@ void DtoAssign(Loc &loc, DValue *lhs, DValue *rhs, int op,
} else if (t->ty == Tstruct) { } else if (t->ty == Tstruct) {
// don't copy anything to empty structs // don't copy anything to empty structs
if (static_cast<TypeStruct *>(t)->sym->fields.dim > 0) { if (static_cast<TypeStruct *>(t)->sym->fields.dim > 0) {
llvm::Value *src = rhs->getRVal(); llvm::Value *src = rhs->getLVal();
llvm::Value *dst = lhs->getLVal(); llvm::Value *dst = lhs->getLVal();
// Check whether source and destination values are the same at compile // Check whether source and destination values are the same at compile
// time as to not emit an invalid (overlapping) memcpy on trivial // time as to not emit an invalid (overlapping) memcpy on trivial
// struct self-assignments like 'A a; a = a;'. // struct self-assignments like 'A a; a = a;'.
if (src != dst) { if (src != dst)
DtoMemCpy(dst, src); DtoMemCpy(dst, src);
}
} }
} else if (t->ty == Tarray || t->ty == Tsarray) { } else if (t->ty == Tarray || t->ty == Tsarray) {
DtoArrayAssign(loc, lhs, rhs, op, canSkipPostblit); DtoArrayAssign(loc, lhs, rhs, op, canSkipPostblit);
@ -576,21 +575,13 @@ DValue *DtoCastVector(Loc &loc, DValue *val, Type *to) {
<< " (casting address)\n"; << " (casting address)\n";
return new DVarValue(to, DtoBitCast(vector, getPtrToType(tolltype))); return new DVarValue(to, DtoBitCast(vector, getPtrToType(tolltype)));
} }
LLValue *vector = val->getRVal(); LLValue *vector = val->getRVal();
IF_LOG Logger::cout() << "src: " << *vector << "to type: " << *tolltype IF_LOG Logger::cout() << "src: " << *vector << "to type: " << *tolltype
<< " (creating temporary)\n"; << " (creating temporary)\n";
LLValue *array = DtoAlloca(to); LLValue *array = DtoAlloca(to);
DtoStore(vector, DtoBitCast(array, getPtrToType(vector->getType())));
TypeSArray *st = static_cast<TypeSArray *>(totype); return new DVarValue(to, array);
for (int i = 0, n = st->dim->toInteger(); i < n; ++i) {
LLValue *lelem = DtoExtractElement(vector, i);
DImValue elem(type->elementType(), lelem);
lelem = DtoCast(loc, &elem, to->nextOf())->getRVal();
DtoStore(lelem, DtoGEPi(array, 0, i));
}
return new DImValue(to, array);
} }
if (totype->ty == Tvector && to->size() == val->type->size()) { if (totype->ty == Tvector && to->size() == val->type->size()) {
return new DImValue(to, DtoBitCast(val->getRVal(), tolltype)); return new DImValue(to, DtoBitCast(val->getRVal(), tolltype));
@ -606,10 +597,10 @@ DValue *DtoCastStruct(Loc &loc, DValue *val, Type *to) {
// This a cast to repaint a struct to another type, which the language // This a cast to repaint a struct to another type, which the language
// allows for identical layouts (opCast() and so on have been lowered // allows for identical layouts (opCast() and so on have been lowered
// earlier by the frontend). // earlier by the frontend).
llvm::Value *rv = val->getRVal(); llvm::Value *lval = val->getLVal();
llvm::Value *result = llvm::Value *result = DtoBitCast(lval, DtoType(to)->getPointerTo(),
DtoBitCast(rv, DtoType(to)->getPointerTo(), rv->getName() + ".repaint"); lval->getName() + ".repaint");
return new DImValue(to, result); return new DVarValue(to, result);
} }
error(loc, "Internal Compiler Error: Invalid struct cast from '%s' to '%s'", error(loc, "Internal Compiler Error: Invalid struct cast from '%s' to '%s'",

View file

@ -444,15 +444,7 @@ DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd,
if (type->ty == Tstruct) { if (type->ty == Tstruct) {
// make a copy // make a copy
llvm::Value *mem = DtoAlloca(type, ".__asm_tuple_ret"); llvm::Value *mem = DtoAlloca(type, ".__asm_tuple_ret");
DtoStore(rv, DtoBitCast(mem, getPtrToType(rv->getType())));
TypeStruct *ts = static_cast<TypeStruct *>(type);
size_t n = ts->sym->fields.dim;
for (size_t i = 0; i < n; i++) {
llvm::Value *v = gIR->ir->CreateExtractValue(rv, i, "");
llvm::Value *gep = DtoGEPi(mem, 0, i);
DtoStore(v, gep);
}
return new DVarValue(fd->type->nextOf(), mem); return new DVarValue(fd->type->nextOf(), mem);
} }

View file

@ -148,9 +148,8 @@ public:
DValue *rvar = new DVarValue(f->type->next, getIrFunc(f->decl)->retArg); DValue *rvar = new DVarValue(f->type->next, getIrFunc(f->decl)->retArg);
DValue *e = toElemDtor(stmt->exp); DValue *e = toElemDtor(stmt->exp);
// store return value // store return value
if (rvar->getLVal() != e->getRVal()) { if (!e->isLVal() || e->getLVal() != rvar->getLVal())
DtoAssign(stmt->loc, rvar, e, TOKblit); DtoAssign(stmt->loc, rvar, e, TOKblit);
}
// call postblit if necessary // call postblit if necessary
if (!irs->func()->type->isref && if (!irs->func()->type->isref &&
@ -171,9 +170,11 @@ public:
// call postblit if necessary // call postblit if necessary
if (!irs->func()->type->isref) { if (!irs->func()->type->isref) {
dval = toElemDtor(stmt->exp); dval = toElemDtor(stmt->exp);
callPostblit(stmt->loc, stmt->exp, dval->getRVal()); LLValue *vthis = (DtoIsInMemoryOnly(dval->type) ? dval->getLVal()
: dval->getRVal());
callPostblit(stmt->loc, stmt->exp, vthis);
} else { } else {
Expression *ae = stmt->exp->addressOf(); Expression *ae = stmt->exp;
dval = toElemDtor(ae); dval = toElemDtor(ae);
} }
// do abi specific transformations on the return value // do abi specific transformations on the return value
@ -185,9 +186,8 @@ public:
// If the function returns a struct or a static array, and the return // If the function returns a struct or a static array, and the return
// value is a pointer to a struct or a static array, load from it // value is a pointer to a struct or a static array, load from it
// before returning. // before returning.
int ty = f->type->next->toBasetype()->ty;
if (returnValue->getType() != irs->topfunc()->getReturnType() && if (returnValue->getType() != irs->topfunc()->getReturnType() &&
(ty == Tstruct || ty == Tsarray) && DtoIsInMemoryOnly(f->type->next) &&
isaPointer(returnValue->getType())) { isaPointer(returnValue->getType())) {
Logger::println("Loading value for return"); Logger::println("Loading value for return");
returnValue = DtoLoad(returnValue); returnValue = DtoLoad(returnValue);
@ -1620,9 +1620,10 @@ public:
// with(..) can either be used with expressions or with symbols // with(..) can either be used with expressions or with symbols
// wthis == null indicates the symbol form // wthis == null indicates the symbol form
if (stmt->wthis) { if (stmt->wthis) {
DValue *e = toElemDtor(stmt->exp);
LLValue *mem = DtoRawVarDeclaration(stmt->wthis); LLValue *mem = DtoRawVarDeclaration(stmt->wthis);
DtoStore(e->getRVal(), mem); DValue *e = toElemDtor(stmt->exp);
LLValue *val = (DtoIsInMemoryOnly(e->type) ? e->getLVal() : e->getRVal());
DtoStore(val, mem);
} }
if (stmt->_body) { if (stmt->_body) {

View file

@ -89,7 +89,7 @@ LLValue *DtoStructEquals(TOK op, DValue *lhs, DValue *rhs) {
// call memcmp // call memcmp
size_t sz = getTypeAllocSize(DtoType(t)); size_t sz = getTypeAllocSize(DtoType(t));
LLValue *val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz)); LLValue *val = DtoMemCmp(lhs->getLVal(), rhs->getLVal(), DtoConstSize_t(sz));
return gIR->ir->CreateICmp(cmpop, val, return gIR->ir->CreateICmp(cmpop, val,
LLConstantInt::get(val->getType(), 0, false)); LLConstantInt::get(val->getType(), 0, false));
} }

View file

@ -107,7 +107,7 @@ LLFunctionType *DtoExtractFunctionType(LLType *type) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs, static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
IrFuncTy &irFty, LLFunctionType *callableTy, IrFuncTy &irFty, LLFunctionType *calleeType,
const std::vector<DValue *> &argvals, const std::vector<DValue *> &argvals,
int numFormalParams) { int numFormalParams) {
// Number of arguments added to the LLVM type that are implicit on the // Number of arguments added to the LLVM type that are implicit on the
@ -169,29 +169,29 @@ static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
const size_t llArgIdx = const size_t llArgIdx =
implicitLLArgCount + implicitLLArgCount +
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i); (irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
llvm::Type *const callableArgType = llvm::Type *const paramType =
(isVararg ? nullptr : callableTy->getParamType(llArgIdx)); (isVararg ? nullptr : calleeType->getParamType(llArgIdx));
// Hack around LDC assuming structs and static arrays are in memory: // Hack around LDC assuming structs and static arrays are in memory:
// If the function wants a struct, and the argument value is a // If the function wants a struct, and the argument value is a
// pointer to a struct, load from it before passing it in. // pointer to a struct, load from it before passing it in.
if (isaPointer(llVal) && DtoIsInMemoryOnly(argType) && if (isaPointer(llVal) && DtoIsInMemoryOnly(argType) &&
((!isVararg && !isaPointer(callableArgType)) || ((!isVararg && !isaPointer(paramType)) ||
(isVararg && !irArg->byref && !irArg->isByVal()))) { (isVararg && !irArg->byref && !irArg->isByVal()))) {
Logger::println("Loading struct type for function argument"); Logger::println("Loading struct type for function argument");
llVal = DtoLoad(llVal); llVal = DtoLoad(llVal);
} }
// parameter type mismatch, this is hard to get rid of // parameter type mismatch, this is hard to get rid of
if (!isVararg && llVal->getType() != callableArgType) { if (!isVararg && llVal->getType() != paramType) {
IF_LOG { IF_LOG {
Logger::cout() << "arg: " << *llVal << '\n'; Logger::cout() << "arg: " << *llVal << '\n';
Logger::cout() << "expects: " << *callableArgType << '\n'; Logger::cout() << "expects: " << *paramType << '\n';
} }
if (isaStruct(llVal)) { if (isaStruct(llVal)) {
llVal = DtoAggrPaint(llVal, callableArgType); llVal = DtoAggrPaint(llVal, paramType);
} else { } else {
llVal = DtoBitCast(llVal, callableArgType); llVal = DtoBitCast(llVal, paramType);
} }
} }
@ -343,24 +343,27 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
Expression *exp1 = (*e->arguments)[0]; Expression *exp1 = (*e->arguments)[0];
Expression *exp2 = (*e->arguments)[1]; Expression *exp2 = (*e->arguments)[1];
int atomicOrdering = (*e->arguments)[2]->toInteger(); int atomicOrdering = (*e->arguments)[2]->toInteger();
LLValue *val = DtoRVal(exp1);
LLValue *ptr = DtoRVal(exp2);
if (!val->getType()->isIntegerTy()) { DValue *dval = toElem(exp1);
llvm::PointerType *v = isaPointer(val->getType()); LLValue *ptr = DtoRVal(exp2);
if (v && v->getContainedType(0)->isStructTy()) { LLType *pointeeType = ptr->getType()->getContainedType(0);
switch (const size_t N = getTypeBitSize(v->getContainedType(0))) {
LLValue *val = nullptr;
if (!pointeeType->isIntegerTy()) {
if (pointeeType->isStructTy()) {
val = dval->getLVal();
switch (size_t N = getTypeBitSize(pointeeType)) {
case 8: case 8:
case 16: case 16:
case 32: case 32:
case 64: case 64:
case 128: case 128: {
val = DtoLoad( LLType *intPtrType =
DtoBitCast(val, llvm::Type::getIntNPtrTy( LLType::getIntNPtrTy(gIR->context(), static_cast<unsigned>(N));
gIR->context(), static_cast<unsigned>(N)))); val = DtoLoad(DtoBitCast(val, intPtrType));
ptr = DtoBitCast(ptr, llvm::Type::getIntNPtrTy( ptr = DtoBitCast(ptr, intPtrType);
gIR->context(), static_cast<unsigned>(N)));
break; break;
}
default: default:
goto errorStore; goto errorStore;
} }
@ -370,6 +373,8 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
exp1->type->toChars()); exp1->type->toChars());
fatal(); fatal();
} }
} else {
val = dval->getRVal();
} }
llvm::StoreInst *ret = p->ir->CreateStore(val, ptr); llvm::StoreInst *ret = p->ir->CreateStore(val, ptr);
@ -389,19 +394,19 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
int atomicOrdering = (*e->arguments)[1]->toInteger(); int atomicOrdering = (*e->arguments)[1]->toInteger();
LLValue *ptr = DtoRVal(exp); LLValue *ptr = DtoRVal(exp);
LLType *ptrTy = ptr->getType()->getContainedType(0); LLType *pointeeType = ptr->getType()->getContainedType(0);
Type *retType = exp->type->nextOf(); Type *retType = exp->type->nextOf();
if (!ptrTy->isIntegerTy()) { if (!pointeeType->isIntegerTy()) {
if (ptrTy->isStructTy()) { if (pointeeType->isStructTy()) {
switch (const size_t N = getTypeBitSize(ptrTy)) { switch (const size_t N = getTypeBitSize(pointeeType)) {
case 8: case 8:
case 16: case 16:
case 32: case 32:
case 64: case 64:
case 128: case 128:
ptr = DtoBitCast(ptr, llvm::Type::getIntNPtrTy( ptr = DtoBitCast(ptr, LLType::getIntNPtrTy(gIR->context(),
gIR->context(), static_cast<unsigned>(N))); static_cast<unsigned>(N)));
break; break;
default: default:
goto errorLoad; goto errorLoad;
@ -418,10 +423,12 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
load->setAlignment(getTypeAllocSize(load->getType())); load->setAlignment(getTypeAllocSize(load->getType()));
load->setAtomic(llvm::AtomicOrdering(atomicOrdering)); load->setAtomic(llvm::AtomicOrdering(atomicOrdering));
llvm::Value *val = load; llvm::Value *val = load;
if (val->getType() != ptrTy) { if (val->getType() != pointeeType) {
val = DtoAllocaDump(val, retType); val = DtoAllocaDump(val, retType);
result = new DVarValue(retType, val);
} else {
result = new DImValue(retType, val);
} }
result = new DImValue(retType, val);
return true; return true;
} }
@ -434,30 +441,29 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
Expression *exp1 = (*e->arguments)[0]; Expression *exp1 = (*e->arguments)[0];
Expression *exp2 = (*e->arguments)[1]; Expression *exp2 = (*e->arguments)[1];
Expression *exp3 = (*e->arguments)[2]; Expression *exp3 = (*e->arguments)[2];
int atomicOrdering = (*e->arguments)[3]->toInteger(); auto atomicOrdering = llvm::AtomicOrdering((*e->arguments)[3]->toInteger());
LLValue *ptr = DtoRVal(exp1); LLValue *ptr = DtoRVal(exp1);
LLValue *cmp = DtoRVal(exp2); LLType *pointeeType = ptr->getType()->getContainedType(0);
LLValue *val = DtoRVal(exp3); DValue *dcmp = toElem(exp2);
LLType *retTy = val->getType(); DValue *dval = toElem(exp3);
if (!cmp->getType()->isIntegerTy()) { LLValue *cmp = nullptr;
llvm::PointerType *v = isaPointer(cmp->getType()); LLValue *val = nullptr;
if (v && v->getContainedType(0)->isStructTy()) { if (!pointeeType->isIntegerTy()) {
switch (const size_t N = getTypeBitSize(v->getContainedType(0))) { if (pointeeType->isStructTy()) {
switch (const size_t N = getTypeBitSize(pointeeType)) {
case 8: case 8:
case 16: case 16:
case 32: case 32:
case 64: case 64:
case 128: case 128: {
ptr = DtoBitCast(ptr, llvm::Type::getIntNPtrTy( LLType *intPtrType =
gIR->context(), static_cast<unsigned>(N))); LLType::getIntNPtrTy(gIR->context(), static_cast<unsigned>(N));
cmp = DtoLoad( ptr = DtoBitCast(ptr, intPtrType);
DtoBitCast(cmp, llvm::Type::getIntNPtrTy( cmp = DtoLoad(DtoBitCast(dcmp->getLVal(), intPtrType));
gIR->context(), static_cast<unsigned>(N)))); val = DtoLoad(DtoBitCast(dval->getLVal(), intPtrType));
val = DtoLoad(
DtoBitCast(val, llvm::Type::getIntNPtrTy(
gIR->context(), static_cast<unsigned>(N))));
break; break;
}
default: default:
goto errorCmpxchg; goto errorCmpxchg;
} }
@ -467,17 +473,21 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
exp2->type->toChars()); exp2->type->toChars());
fatal(); fatal();
} }
} else {
cmp = dcmp->getRVal();
val = dval->getRVal();
} }
LLValue *ret = p->ir->CreateAtomicCmpXchg(
ptr, cmp, val, llvm::AtomicOrdering(atomicOrdering), LLValue *ret = p->ir->CreateAtomicCmpXchg(ptr, cmp, val, atomicOrdering,
llvm::AtomicOrdering(atomicOrdering)); atomicOrdering);
// Use the same quickfix as for dragonegg - see r210956 // Use the same quickfix as for dragonegg - see r210956
ret = p->ir->CreateExtractValue(ret, 0); ret = p->ir->CreateExtractValue(ret, 0);
llvm::Value *retVal = ret; if (ret->getType() != pointeeType) {
if (retVal->getType() != retTy) { ret = DtoAllocaDump(ret, exp3->type);
retVal = DtoAllocaDump(retVal, exp3->type); result = new DVarValue(exp3->type, ret);
} else {
result = new DImValue(exp3->type, ret);
} }
result = new DImValue(exp3->type, retVal);
return true; return true;
} }
@ -683,9 +693,8 @@ private:
bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate); bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
bool nestedcall = irFty.arg_nest; bool nestedcall = irFty.arg_nest;
if (!thiscall && !delegatecall && !nestedcall) { if (!thiscall && !delegatecall && !nestedcall)
return; return;
}
size_t index = args.size(); size_t index = args.size();
LLType *llArgType = *(llArgTypesBegin + index); LLType *llArgType = *(llArgTypesBegin + index);
@ -981,7 +990,7 @@ DValue *DtoCallFunction(Loc &loc, Type *resulttype, DValue *fnval,
// set calling convention and parameter attributes // set calling convention and parameter attributes
llvm::AttributeSet &attrlist = attrs; llvm::AttributeSet &attrlist = attrs;
if (dfnval && dfnval->func) { if (dfnval && dfnval->func) {
LLFunction *llfunc = llvm::dyn_cast<LLFunction>(dfnval->val); LLFunction *llfunc = llvm::dyn_cast<LLFunction>(dfnval->getRVal());
if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs if (llfunc && llfunc->isIntrinsic()) // override intrinsic attrs
{ {
attrlist = llvm::Intrinsic::getAttributes( attrlist = llvm::Intrinsic::getAttributes(

View file

@ -300,8 +300,14 @@ public:
// adding more control flow. // adding more control flow.
if (result && result->type->ty != Tvoid && if (result && result->type->ty != Tvoid &&
!result->definedInFuncEntryBB()) { !result->definedInFuncEntryBB()) {
LLValue *alloca = DtoAllocaDump(result); if (result->isLVal()) {
result = new DVarValue(result->type, alloca); LLValue *copy = DtoAlloca(result->type);
DtoMemCpy(copy, result->getLVal());
result = new DVarValue(result->type, copy);
} else {
LLValue *copy = DtoAllocaDump(result);
result = new DVarValue(result->type, copy);
}
} }
llvm::BasicBlock *endbb = llvm::BasicBlock::Create( llvm::BasicBlock *endbb = llvm::BasicBlock::Create(
@ -645,8 +651,7 @@ public:
DtoAssign(loc, lval, assignedResult); DtoAssign(loc, lval, assignedResult);
// return the (casted) result // return the (casted) result
return e->type == assignedResult->type ? assignedResult return e->type == lval->type ? lval : DtoCast(loc, lval, e->type);
: DtoCast(loc, result, e->type);
} }
#define BIN_ASSIGN(Op, useLvalForBinExpLhs) \ #define BIN_ASSIGN(Op, useLvalForBinExpLhs) \
@ -959,9 +964,8 @@ public:
} }
} }
if (DtoLowerMagicIntrinsic(p, fndecl, e, result)) { if (DtoLowerMagicIntrinsic(p, fndecl, e, result))
return; return;
}
} }
result = DtoCallFunction(e->loc, e->type, fnval, e->arguments); result = DtoCallFunction(e->loc, e->type, fnval, e->arguments);
@ -1165,7 +1169,7 @@ public:
return; return;
} }
LLValue *l = DtoRVal(e->e1); DValue *l = toElem(e->e1);
Type *e1type = e->e1->type->toBasetype(); Type *e1type = e->e1->type->toBasetype();
@ -1178,17 +1182,17 @@ public:
if (e1type->ty == Tpointer) { if (e1type->ty == Tpointer) {
assert(e1type->nextOf()->ty == Tstruct); assert(e1type->nextOf()->ty == Tstruct);
TypeStruct *ts = static_cast<TypeStruct *>(e1type->nextOf()); TypeStruct *ts = static_cast<TypeStruct *>(e1type->nextOf());
arrptr = DtoIndexAggregate(l, ts->sym, vd); arrptr = DtoIndexAggregate(l->getRVal(), ts->sym, vd);
} }
// indexing normal struct // indexing normal struct
else if (e1type->ty == Tstruct) { else if (e1type->ty == Tstruct) {
TypeStruct *ts = static_cast<TypeStruct *>(e1type); TypeStruct *ts = static_cast<TypeStruct *>(e1type);
arrptr = DtoIndexAggregate(l, ts->sym, vd); arrptr = DtoIndexAggregate(l->getLVal(), ts->sym, vd);
} }
// indexing class // indexing class
else if (e1type->ty == Tclass) { else if (e1type->ty == Tclass) {
TypeClass *tc = static_cast<TypeClass *>(e1type); TypeClass *tc = static_cast<TypeClass *>(e1type);
arrptr = DtoIndexAggregate(l, tc->sym, vd); arrptr = DtoIndexAggregate(l->getRVal(), tc->sym, vd);
} else { } else {
llvm_unreachable("Unknown DotVarExp type for VarDeclaration."); llvm_unreachable("Unknown DotVarExp type for VarDeclaration.");
} }
@ -1210,14 +1214,15 @@ public:
// Get the actual function value to call. // Get the actual function value to call.
LLValue *funcval = nullptr; LLValue *funcval = nullptr;
if (nonFinal) { if (nonFinal) {
DImValue thisVal(e1type, l); funcval = DtoVirtualFunctionPointer(l, fdecl, e->toChars());
funcval = DtoVirtualFunctionPointer(&thisVal, fdecl, e->toChars());
} else { } else {
funcval = getIrFunc(fdecl)->func; funcval = getIrFunc(fdecl)->func;
} }
assert(funcval); assert(funcval);
result = new DFuncValue(fdecl, funcval, l); LLValue *vthis =
(DtoIsInMemoryOnly(l->type) ? l->getLVal() : l->getRVal());
result = new DFuncValue(fdecl, funcval, vthis);
} else { } else {
llvm_unreachable("Unknown target for VarDeclaration."); llvm_unreachable("Unknown target for VarDeclaration.");
} }
@ -1286,7 +1291,7 @@ public:
if (p->emitArrayBoundsChecks() && !e->indexIsInBounds) { if (p->emitArrayBoundsChecks() && !e->indexIsInBounds) {
DtoIndexBoundsCheck(e->loc, l, r); DtoIndexBoundsCheck(e->loc, l, r);
} }
arrptr = DtoGEP(l->getRVal(), DtoConstUint(0), r->getRVal(), arrptr = DtoGEP(l->getLVal(), DtoConstUint(0), r->getRVal(),
e->indexIsInBounds); e->indexIsInBounds);
} else if (e1type->ty == Tarray) { } else if (e1type->ty == Tarray) {
if (p->emitArrayBoundsChecks() && !e->indexIsInBounds) { if (p->emitArrayBoundsChecks() && !e->indexIsInBounds) {
@ -1547,8 +1552,6 @@ public:
DValue *l = toElem(e->e1); DValue *l = toElem(e->e1);
DValue *r = toElem(e->e2); DValue *r = toElem(e->e2);
LLValue *lv = l->getRVal();
LLValue *rv = r->getRVal();
Type *t = e->e1->type->toBasetype(); Type *t = e->e1->type->toBasetype();
@ -1570,6 +1573,8 @@ public:
default: default:
llvm_unreachable("Unsupported integral type equality comparison."); llvm_unreachable("Unsupported integral type equality comparison.");
} }
LLValue *lv = l->getRVal();
LLValue *rv = r->getRVal();
if (rv->getType() != lv->getType()) { if (rv->getType() != lv->getType()) {
rv = DtoBitCast(rv, lv->getType()); rv = DtoBitCast(rv, lv->getType());
} }
@ -2116,7 +2121,7 @@ public:
LLValue *contextptr = DtoNestedContext(e->loc, f->func); LLValue *contextptr = DtoNestedContext(e->loc, f->func);
uval = DtoBitCast(contextptr, getVoidPtrType()); uval = DtoBitCast(contextptr, getVoidPtrType());
} else { } else {
uval = u->getRVal(); uval = (DtoIsInMemoryOnly(u->type) ? u->getLVal() : u->getRVal());
} }
IF_LOG Logger::cout() << "context = " << *uval << '\n'; IF_LOG Logger::cout() << "context = " << *uval << '\n';
@ -2167,8 +2172,6 @@ public:
DValue *l = toElem(e->e1); DValue *l = toElem(e->e1);
DValue *r = toElem(e->e2); DValue *r = toElem(e->e2);
LLValue *lv = l->getRVal();
LLValue *rv = r->getRVal();
Type *t1 = e->e1->type->toBasetype(); Type *t1 = e->e1->type->toBasetype();
@ -2187,9 +2190,10 @@ public:
LLValue *eval = nullptr; LLValue *eval = nullptr;
if (t1->ty == Tdelegate) { if (t1->ty == Tdelegate) {
if (r->isNull()) { LLValue *lv = l->getRVal();
rv = nullptr; LLValue *rv = nullptr;
} else { if (!r->isNull()) {
rv = r->getRVal();
assert(lv->getType() == rv->getType()); assert(lv->getType() == rv->getType());
} }
eval = DtoDelegateEquals(e->op, lv, rv); eval = DtoDelegateEquals(e->op, lv, rv);
@ -2197,6 +2201,8 @@ public:
{ {
eval = DtoBinNumericEquals(e->loc, l, r, e->op); eval = DtoBinNumericEquals(e->loc, l, r, e->op);
} else if (t1->ty == Tpointer || t1->ty == Tclass) { } else if (t1->ty == Tpointer || t1->ty == Tclass) {
LLValue *lv = l->getRVal();
LLValue *rv = r->getRVal();
if (lv->getType() != rv->getType()) { if (lv->getType() != rv->getType()) {
if (r->isNull()) { if (r->isNull()) {
rv = llvm::ConstantPointerNull::get(isaPointer(lv->getType())); rv = llvm::ConstantPointerNull::get(isaPointer(lv->getType()));
@ -2206,7 +2212,15 @@ public:
} }
eval = (e->op == TOKidentity) ? p->ir->CreateICmpEQ(lv, rv) eval = (e->op == TOKidentity) ? p->ir->CreateICmpEQ(lv, rv)
: p->ir->CreateICmpNE(lv, rv); : p->ir->CreateICmpNE(lv, rv);
} else if (t1->ty == Tsarray) {
LLValue *lptr = l->getLVal();
LLValue *rptr = r->getLVal();
assert(lptr->getType() == rptr->getType());
eval = (e->op == TOKidentity) ? p->ir->CreateICmpEQ(lptr, rptr)
: p->ir->CreateICmpNE(lptr, rptr);
} else { } else {
LLValue *lv = l->getRVal();
LLValue *rv = r->getRVal();
assert(lv->getType() == rv->getType()); assert(lv->getType() == rv->getType());
eval = (e->op == TOKidentity) ? p->ir->CreateICmpEQ(lv, rv) eval = (e->op == TOKidentity) ? p->ir->CreateICmpEQ(lv, rv)
: p->ir->CreateICmpNE(lv, rv); : p->ir->CreateICmpNE(lv, rv);
@ -2498,7 +2512,14 @@ public:
llvm::Value *storage = llvm::Value *storage =
DtoRawAlloca(llStoType, DtoAlignment(e->type), "arrayliteral"); DtoRawAlloca(llStoType, DtoAlignment(e->type), "arrayliteral");
initializeArrayLiteral(p, e, storage); initializeArrayLiteral(p, e, storage);
result = new DImValue(e->type, storage); if (arrayType->ty == Tsarray) {
result = new DVarValue(e->type, storage);
} else if (arrayType->ty == Tpointer) {
storage = DtoBitCast(storage, llElemType->getPointerTo());
result = new DImValue(e->type, storage);
} else {
llvm_unreachable("Unexpected array literal type");
}
} }
} }
@ -2804,7 +2825,7 @@ public:
DValue *ep = toElem(el); DValue *ep = toElem(el);
LLValue *gep = DtoGEPi(val, 0, i); LLValue *gep = DtoGEPi(val, 0, i);
if (DtoIsInMemoryOnly(el->type)) { if (DtoIsInMemoryOnly(el->type)) {
DtoMemCpy(gep, ep->getRVal()); DtoMemCpy(gep, ep->getLVal());
} else if (el->type->ty != Tvoid) { } else if (el->type->ty != Tvoid) {
DtoStoreZextI8(ep->getRVal(), gep); DtoStoreZextI8(ep->getRVal(), gep);
} else { } else {

View file

@ -397,10 +397,11 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
} }
// cast 'this' to Object // cast 'this' to Object
LLValue *&thisArg = args[(!irFunc->irFty.arg_sret || const int thisArgIndex =
gABI->passThisBeforeSret(irFunc->type)) (!irFunc->irFty.arg_sret || gABI->passThisBeforeSret(irFunc->type))
? 0 ? 0
: 1]; : 1;
LLValue *&thisArg = args[thisArgIndex];
LLType *targetThisType = thisArg->getType(); LLType *targetThisType = thisArg->getType();
thisArg = DtoBitCast(thisArg, getVoidPtrType()); thisArg = DtoBitCast(thisArg, getVoidPtrType());
thisArg = DtoGEP1(thisArg, DtoConstInt(-thunkOffset), true); thisArg = DtoGEP1(thisArg, DtoConstInt(-thunkOffset), true);

View file

@ -36,6 +36,9 @@ llvm::Value *IrFuncTy::putRet(DValue *dval) {
return ret->rewrite->put(dval); return ret->rewrite->put(dval);
} }
if (ret->byref || DtoIsInMemoryOnly(dval->type))
return dval->getLVal();
return dval->getRVal(); return dval->getRVal();
} }
@ -75,6 +78,9 @@ llvm::Value *IrFuncTy::putParam(const IrFuncTyArg &arg, DValue *dval) {
return arg.rewrite->put(dval); return arg.rewrite->put(dval);
} }
if (arg.byref || DtoIsInMemoryOnly(dval->type))
return dval->getLVal();
return dval->getRVal(); return dval->getRVal();
} }