mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 17:43:35 +03:00
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:
parent
c1c285782d
commit
963a10b225
15 changed files with 221 additions and 223 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
128
gen/arrays.cpp
128
gen/arrays.cpp
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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'",
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
119
gen/tocall.cpp
119
gen/tocall.cpp
|
@ -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(
|
||||||
|
|
69
gen/toir.cpp
69
gen/toir.cpp
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue