mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-29 06:30:39 +03:00
Skip superfluous IR pointer bitcasts, now that they are always opaque
This commit is contained in:
parent
ee9f3a142c
commit
d140f2a283
28 changed files with 182 additions and 399 deletions
45
gen/aa.cpp
45
gen/aa.cpp
|
@ -27,12 +27,11 @@
|
||||||
using namespace dmd;
|
using namespace dmd;
|
||||||
|
|
||||||
// returns the keytype typeinfo
|
// returns the keytype typeinfo
|
||||||
static LLConstant *to_keyti(const Loc &loc, DValue *aa, LLType *targetType) {
|
static LLConstant *to_keyti(const Loc &loc, DValue *aa) {
|
||||||
// keyti param
|
// keyti param
|
||||||
assert(aa->type->toBasetype()->ty == TY::Taarray);
|
assert(aa->type->toBasetype()->ty == TY::Taarray);
|
||||||
TypeAArray *aatype = static_cast<TypeAArray *>(aa->type->toBasetype());
|
TypeAArray *aatype = static_cast<TypeAArray *>(aa->type->toBasetype());
|
||||||
LLConstant *ti = DtoTypeInfoOf(loc, aatype->index, /*base=*/false);
|
return DtoTypeInfoOf(loc, aatype->index, /*base=*/false);
|
||||||
return DtoBitCast(ti, targetType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -53,31 +52,25 @@ DLValue *DtoAAIndex(const Loc &loc, Type *type, DValue *aa, DValue *key,
|
||||||
|
|
||||||
// aa param
|
// aa param
|
||||||
LLValue *aaval = lvalue ? DtoLVal(aa) : DtoRVal(aa);
|
LLValue *aaval = lvalue ? DtoLVal(aa) : DtoRVal(aa);
|
||||||
aaval = DtoBitCast(aaval, funcTy->getParamType(0));
|
assert(aaval->getType()->isPointerTy());
|
||||||
|
|
||||||
// pkey param
|
// pkey param
|
||||||
LLValue *pkey = makeLValue(loc, key);
|
LLValue *pkey = makeLValue(loc, key);
|
||||||
pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2));
|
|
||||||
|
|
||||||
// call runtime
|
// call runtime
|
||||||
LLValue *ret;
|
LLValue *ret;
|
||||||
if (lvalue) {
|
if (lvalue) {
|
||||||
auto t = mutableOf(unSharedOf(aa->type));
|
auto t = mutableOf(unSharedOf(aa->type));
|
||||||
LLValue *rawAATI = DtoTypeInfoOf(loc, t, /*base=*/false);
|
LLValue *aati = DtoTypeInfoOf(loc, t, /*base=*/false);
|
||||||
LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1));
|
|
||||||
LLValue *valsize = DtoConstSize_t(getTypeAllocSize(DtoType(type)));
|
LLValue *valsize = DtoConstSize_t(getTypeAllocSize(DtoType(type)));
|
||||||
ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey,
|
ret = gIR->CreateCallOrInvoke(func, aaval, aati, valsize, pkey,
|
||||||
"aa.index");
|
"aa.index");
|
||||||
} else {
|
} else {
|
||||||
LLValue *keyti = to_keyti(loc, aa, funcTy->getParamType(1));
|
LLValue *keyti = to_keyti(loc, aa);
|
||||||
ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index");
|
ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index");
|
||||||
}
|
}
|
||||||
|
|
||||||
// cast return value
|
assert(ret->getType()->isPointerTy());
|
||||||
LLType *targettype = DtoPtrToType(type);
|
|
||||||
if (ret->getType() != targettype) {
|
|
||||||
ret = DtoBitCast(ret, targettype);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only check bounds for rvalues ('aa[key]').
|
// Only check bounds for rvalues ('aa[key]').
|
||||||
// Lvalue use ('aa[key] = value') auto-adds an element.
|
// Lvalue use ('aa[key] = value') auto-adds an element.
|
||||||
|
@ -118,28 +111,20 @@ DValue *DtoAAIn(const Loc &loc, Type *type, DValue *aa, DValue *key) {
|
||||||
|
|
||||||
// aa param
|
// aa param
|
||||||
LLValue *aaval = DtoRVal(aa);
|
LLValue *aaval = DtoRVal(aa);
|
||||||
|
assert(aaval->getType()->isPointerTy());
|
||||||
IF_LOG {
|
IF_LOG {
|
||||||
Logger::cout() << "aaval: " << *aaval << '\n';
|
Logger::cout() << "aaval: " << *aaval << '\n';
|
||||||
Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n';
|
|
||||||
}
|
}
|
||||||
aaval = DtoBitCast(aaval, funcTy->getParamType(0));
|
|
||||||
|
|
||||||
// keyti param
|
// keyti param
|
||||||
LLValue *keyti = to_keyti(loc, aa, funcTy->getParamType(1));
|
LLValue *keyti = to_keyti(loc, aa);
|
||||||
|
|
||||||
// pkey param
|
// pkey param
|
||||||
LLValue *pkey = makeLValue(loc, key);
|
LLValue *pkey = makeLValue(loc, key);
|
||||||
pkey = DtoBitCast(pkey, getVoidPtrType());
|
|
||||||
|
|
||||||
// call runtime
|
// call runtime
|
||||||
LLValue *ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.in");
|
LLValue *ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.in");
|
||||||
|
|
||||||
// cast return value
|
|
||||||
LLType *targettype = DtoType(type);
|
|
||||||
if (ret->getType() != targettype) {
|
|
||||||
ret = DtoBitCast(ret, targettype);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DImValue(type, ret);
|
return new DImValue(type, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,18 +147,16 @@ DValue *DtoAARemove(const Loc &loc, DValue *aa, DValue *key) {
|
||||||
|
|
||||||
// aa param
|
// aa param
|
||||||
LLValue *aaval = DtoRVal(aa);
|
LLValue *aaval = DtoRVal(aa);
|
||||||
|
assert(aaval->getType()->isPointerTy());
|
||||||
IF_LOG {
|
IF_LOG {
|
||||||
Logger::cout() << "aaval: " << *aaval << '\n';
|
Logger::cout() << "aaval: " << *aaval << '\n';
|
||||||
Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n';
|
|
||||||
}
|
}
|
||||||
aaval = DtoBitCast(aaval, funcTy->getParamType(0));
|
|
||||||
|
|
||||||
// keyti param
|
// keyti param
|
||||||
LLValue *keyti = to_keyti(loc, aa, funcTy->getParamType(1));
|
LLValue *keyti = to_keyti(loc, aa);
|
||||||
|
|
||||||
// pkey param
|
// pkey param
|
||||||
LLValue *pkey = makeLValue(loc, key);
|
LLValue *pkey = makeLValue(loc, key);
|
||||||
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
|
|
||||||
|
|
||||||
// call runtime
|
// call runtime
|
||||||
LLValue *res = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey);
|
LLValue *res = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey);
|
||||||
|
@ -190,8 +173,10 @@ LLValue *DtoAAEquals(const Loc &loc, EXP op, DValue *l, DValue *r) {
|
||||||
llvm::Function *func = getRuntimeFunction(loc, gIR->module, "_aaEqual");
|
llvm::Function *func = getRuntimeFunction(loc, gIR->module, "_aaEqual");
|
||||||
LLFunctionType *funcTy = func->getFunctionType();
|
LLFunctionType *funcTy = func->getFunctionType();
|
||||||
|
|
||||||
LLValue *aaval = DtoBitCast(DtoRVal(l), funcTy->getParamType(1));
|
LLValue *aaval = DtoRVal(l);
|
||||||
LLValue *abval = DtoBitCast(DtoRVal(r), funcTy->getParamType(2));
|
assert(aaval->getType()->isPointerTy());
|
||||||
|
LLValue *abval = DtoRVal(r);
|
||||||
|
assert(abval->getType()->isPointerTy());
|
||||||
LLValue *aaTypeInfo = DtoTypeInfoOf(loc, t);
|
LLValue *aaTypeInfo = DtoTypeInfoOf(loc, t);
|
||||||
LLValue *res =
|
LLValue *res =
|
||||||
gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes");
|
gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes");
|
||||||
|
|
|
@ -32,7 +32,7 @@ using namespace dmd;
|
||||||
|
|
||||||
llvm::Value *ABIRewrite::getRVal(Type *dty, LLValue *v) {
|
llvm::Value *ABIRewrite::getRVal(Type *dty, LLValue *v) {
|
||||||
llvm::Type *t = DtoType(dty);
|
llvm::Type *t = DtoType(dty);
|
||||||
return DtoLoad(t, DtoBitCast(getLVal(dty, v), t->getPointerTo()));
|
return DtoLoad(t, getLVal(dty, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -191,8 +191,8 @@ void TargetABI::rewriteVarargs(IrFuncTy &fty,
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue *TargetABI::prepareVaStart(DLValue *ap) {
|
LLValue *TargetABI::prepareVaStart(DLValue *ap) {
|
||||||
// pass a i8* pointer to ap to LLVM's va_start intrinsic
|
// pass an opaque pointer to ap to LLVM's va_start intrinsic
|
||||||
return DtoBitCast(DtoLVal(ap), getVoidPtrType());
|
return DtoLVal(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -209,8 +209,8 @@ void TargetABI::vaCopy(DLValue *dest, DValue *src) {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLValue *TargetABI::prepareVaArg(DLValue *ap) {
|
LLValue *TargetABI::prepareVaArg(DLValue *ap) {
|
||||||
// pass a i8* pointer to ap to LLVM's va_arg intrinsic
|
// pass an opaque pointer to ap to LLVM's va_arg intrinsic
|
||||||
return DtoBitCast(DtoLVal(ap), getVoidPtrType());
|
return DtoLVal(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -148,7 +148,6 @@ struct BaseBitcastABIRewrite : ABIRewrite {
|
||||||
return DtoLoad(asType, paddedDump, name);
|
return DtoLoad(asType, paddedDump, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
address = DtoBitCast(address, getPtrToType(asType));
|
|
||||||
return DtoLoad(asType, address, name);
|
return DtoLoad(asType, address, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +247,7 @@ struct IndirectByvalRewrite : ABIRewrite {
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue *getLVal(Type *dty, LLValue *v) override {
|
LLValue *getLVal(Type *dty, LLValue *v) override {
|
||||||
return DtoBitCast(v, DtoPtrToType(dty));
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLType *type(Type *t) override { return DtoPtrToType(t); }
|
LLType *type(Type *t) override { return DtoPtrToType(t); }
|
||||||
|
|
|
@ -110,8 +110,7 @@ struct HardfloatRewrite : ABIRewrite {
|
||||||
DtoRawAlloca(asType, alignment, ".HardfloatRewrite_arg_storage");
|
DtoRawAlloca(asType, alignment, ".HardfloatRewrite_arg_storage");
|
||||||
for (unsigned i = 0; i < (unsigned)flat.length; ++i) {
|
for (unsigned i = 0; i < (unsigned)flat.length; ++i) {
|
||||||
DtoMemCpy(DtoGEP(asType, buffer, 0, i),
|
DtoMemCpy(DtoGEP(asType, buffer, 0, i),
|
||||||
DtoGEP1(getI8Type(), DtoBitCast(address, getVoidPtrType()),
|
DtoGEP1(getI8Type(), address, flat.fields[i].offset),
|
||||||
flat.fields[i].offset),
|
|
||||||
DtoConstSize_t(flat.fields[i].ty->size()));
|
DtoConstSize_t(flat.fields[i].ty->size()));
|
||||||
}
|
}
|
||||||
return DtoLoad(asType, buffer, ".HardfloatRewrite_arg");
|
return DtoLoad(asType, buffer, ".HardfloatRewrite_arg");
|
||||||
|
@ -126,8 +125,7 @@ struct HardfloatRewrite : ABIRewrite {
|
||||||
LLValue *ret = DtoRawAlloca(DtoType(dty), alignment,
|
LLValue *ret = DtoRawAlloca(DtoType(dty), alignment,
|
||||||
".HardfloatRewrite_param_storage");
|
".HardfloatRewrite_param_storage");
|
||||||
for (unsigned i = 0; i < (unsigned)flat.length; ++i) {
|
for (unsigned i = 0; i < (unsigned)flat.length; ++i) {
|
||||||
DtoMemCpy(DtoGEP1(getI8Type(), DtoBitCast(ret, getVoidPtrType()),
|
DtoMemCpy(DtoGEP1(getI8Type(), ret, flat.fields[i].offset),
|
||||||
flat.fields[i].offset),
|
|
||||||
DtoGEP(asType, buffer, 0, i),
|
DtoGEP(asType, buffer, 0, i),
|
||||||
DtoConstSize_t(flat.fields[i].ty->size()));
|
DtoConstSize_t(flat.fields[i].ty->size()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,27 +352,25 @@ LLValue *X86_64TargetABI::prepareVaStart(DLValue *ap) {
|
||||||
// invoking va_start, we first need to allocate the actual __va_list_tag struct
|
// invoking va_start, we first need to allocate the actual __va_list_tag struct
|
||||||
// and set `ap` to its address.
|
// and set `ap` to its address.
|
||||||
LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
||||||
DtoStore(valistmem,
|
DtoStore(valistmem, DtoLVal(ap));
|
||||||
DtoBitCast(DtoLVal(ap), getPtrToType(valistmem->getType())));
|
// Pass an opaque pointer to the actual struct to LLVM's va_start intrinsic.
|
||||||
// Pass a i8* pointer to the actual struct to LLVM's va_start intrinsic.
|
return valistmem;
|
||||||
return DtoBitCast(valistmem, getVoidPtrType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86_64TargetABI::vaCopy(DLValue *dest, DValue *src) {
|
void X86_64TargetABI::vaCopy(DLValue *dest, DValue *src) {
|
||||||
// Analog to va_start, we first need to allocate a new __va_list_tag struct on
|
// Analog to va_start, we first need to allocate a new __va_list_tag struct on
|
||||||
// the stack and set `dest` to its address.
|
// the stack and set `dest` to its address.
|
||||||
LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
LLValue *valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
||||||
DtoStore(valistmem,
|
DtoStore(valistmem, DtoLVal(dest));
|
||||||
DtoBitCast(DtoLVal(dest), getPtrToType(valistmem->getType())));
|
|
||||||
// Then fill the new struct with a bitcopy of the source struct.
|
// Then fill the new struct with a bitcopy of the source struct.
|
||||||
// `src` is a __va_list_tag* pointer to the source struct.
|
// `src` is a __va_list_tag* pointer to the source struct.
|
||||||
DtoMemCpy(getValistType(), valistmem, DtoRVal(src));
|
DtoMemCpy(getValistType(), valistmem, DtoRVal(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue *X86_64TargetABI::prepareVaArg(DLValue *ap) {
|
LLValue *X86_64TargetABI::prepareVaArg(DLValue *ap) {
|
||||||
// Pass a i8* pointer to the actual __va_list_tag struct to LLVM's va_arg
|
// Pass an opaque pointer to the actual __va_list_tag struct to LLVM's va_arg
|
||||||
// intrinsic.
|
// intrinsic.
|
||||||
return DtoBitCast(DtoRVal(ap), getVoidPtrType());
|
return DtoRVal(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *X86_64TargetABI::vaListType() {
|
Type *X86_64TargetABI::vaListType() {
|
||||||
|
|
|
@ -36,15 +36,6 @@ static void DtoSetArray(DValue *array, DValue *rhs);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace {
|
|
||||||
LLValue *DtoSlice(LLValue *ptr, LLValue *length, LLType *elemType) {
|
|
||||||
elemType = i1ToI8(voidToI8(elemType));
|
|
||||||
return DtoAggrPair(length, DtoBitCast(ptr, elemType->getPointerTo()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
LLStructType *DtoArrayType(Type *arrayTy) {
|
LLStructType *DtoArrayType(Type *arrayTy) {
|
||||||
assert(arrayTy->nextOf());
|
assert(arrayTy->nextOf());
|
||||||
llvm::Type *elems[] = {DtoSize_t(), DtoPtrToType(arrayTy->nextOf())};
|
llvm::Type *elems[] = {DtoSize_t(), DtoPtrToType(arrayTy->nextOf())};
|
||||||
|
@ -223,20 +214,19 @@ void DtoArrayAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
Type *const elemType = t->nextOf()->toBasetype();
|
Type *const elemType = t->nextOf()->toBasetype();
|
||||||
const bool needsDestruction =
|
const bool needsDestruction =
|
||||||
(!isConstructing && elemType->needsDestruction());
|
(!isConstructing && elemType->needsDestruction());
|
||||||
LLValue *realLhsPtr = DtoArrayPtr(lhs);
|
LLValue *lhsPtr = DtoArrayPtr(lhs);
|
||||||
LLValue *lhsPtr = DtoBitCast(realLhsPtr, getVoidPtrType());
|
|
||||||
LLValue *lhsLength = DtoArrayLen(lhs);
|
LLValue *lhsLength = DtoArrayLen(lhs);
|
||||||
|
|
||||||
// Be careful to handle void arrays correctly when modifying this (see tests
|
// Be careful to handle void arrays correctly when modifying this (see tests
|
||||||
// for DMD issue 7493).
|
// for DMD issue 7493).
|
||||||
// TODO: This should use AssignExp::memset.
|
// TODO: This should use AssignExp::memset.
|
||||||
LLValue *realRhsArrayPtr = (t2->ty == TY::Tarray || t2->ty == TY::Tsarray)
|
LLValue *rhsArrayPtr = (t2->ty == TY::Tarray || t2->ty == TY::Tsarray)
|
||||||
? DtoArrayPtr(rhs)
|
? DtoArrayPtr(rhs)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (realRhsArrayPtr && DtoMemType(t2->nextOf()) == DtoMemType(t->nextOf())) {
|
if (rhsArrayPtr && DtoMemType(t2->nextOf()) == DtoMemType(t->nextOf())) {
|
||||||
// T[] = T[] T[] = T[n]
|
// T[] = T[] T[] = T[n]
|
||||||
// T[n] = T[n] T[n] = T[]
|
// T[n] = T[n] T[n] = T[]
|
||||||
LLValue *rhsPtr = DtoBitCast(realRhsArrayPtr, getVoidPtrType());
|
LLValue *rhsPtr = rhsArrayPtr;
|
||||||
LLValue *rhsLength = DtoArrayLen(rhs);
|
LLValue *rhsLength = DtoArrayLen(rhs);
|
||||||
|
|
||||||
const bool needsPostblit = (op != EXP::blit && arrayNeedsPostblit(t) &&
|
const bool needsPostblit = (op != EXP::blit && arrayNeedsPostblit(t) &&
|
||||||
|
@ -274,9 +264,9 @@ void DtoArrayAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
LLFunction *fn = getRuntimeFunction(
|
LLFunction *fn = getRuntimeFunction(
|
||||||
loc, gIR->module,
|
loc, gIR->module,
|
||||||
!canSkipPostblit ? "_d_arrayassign_l" : "_d_arrayassign_r");
|
!canSkipPostblit ? "_d_arrayassign_l" : "_d_arrayassign_r");
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, DtoTypeInfoOf(loc, elemType),
|
||||||
fn, DtoTypeInfoOf(loc, elemType), DtoSlice(rhsPtr, rhsLength, getI8Type()),
|
DtoAggrPair(rhsLength, rhsPtr),
|
||||||
DtoSlice(lhsPtr, lhsLength, getI8Type()), DtoBitCast(tmpSwap, getVoidPtrType()));
|
DtoAggrPair(lhsLength, lhsPtr), tmpSwap);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// scalar rhs:
|
// scalar rhs:
|
||||||
|
@ -291,7 +281,6 @@ void DtoArrayAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
getTypeAllocSize(DtoMemType(lhs->type->nextOf()));
|
getTypeAllocSize(DtoMemType(lhs->type->nextOf()));
|
||||||
LLType *rhsType = DtoMemType(t2);
|
LLType *rhsType = DtoMemType(t2);
|
||||||
const size_t rhsSize = getTypeAllocSize(rhsType);
|
const size_t rhsSize = getTypeAllocSize(rhsType);
|
||||||
LLValue *actualPtr = DtoBitCast(realLhsPtr, rhsType->getPointerTo());
|
|
||||||
LLValue *actualLength = lhsLength;
|
LLValue *actualLength = lhsLength;
|
||||||
if (rhsSize != lhsElementSize) {
|
if (rhsSize != lhsElementSize) {
|
||||||
LLValue *lhsSize = computeSize(lhsLength, lhsElementSize);
|
LLValue *lhsSize = computeSize(lhsLength, lhsElementSize);
|
||||||
|
@ -300,7 +289,7 @@ void DtoArrayAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
? lhsSize
|
? lhsSize
|
||||||
: gIR->ir->CreateExactUDiv(lhsSize, DtoConstSize_t(rhsSize));
|
: gIR->ir->CreateExactUDiv(lhsSize, DtoConstSize_t(rhsSize));
|
||||||
}
|
}
|
||||||
DtoArrayInit(loc, actualPtr, actualLength, rhs);
|
DtoArrayInit(loc, lhsPtr, actualLength, rhs);
|
||||||
} else if (isConstructing) {
|
} else if (isConstructing) {
|
||||||
error(loc, "ICE: array construction should have been lowered to "
|
error(loc, "ICE: array construction should have been lowered to "
|
||||||
"`_d_arraysetctor`");
|
"`_d_arraysetctor`");
|
||||||
|
@ -309,7 +298,7 @@ void DtoArrayAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
LLFunction *fn =
|
LLFunction *fn =
|
||||||
getRuntimeFunction(loc, gIR->module, "_d_arraysetassign");
|
getRuntimeFunction(loc, gIR->module, "_d_arraysetassign");
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(
|
||||||
fn, lhsPtr, DtoBitCast(makeLValue(loc, rhs), getVoidPtrType()),
|
fn, lhsPtr, makeLValue(loc, rhs),
|
||||||
gIR->ir->CreateTruncOrBitCast(lhsLength,
|
gIR->ir->CreateTruncOrBitCast(lhsLength,
|
||||||
LLType::getInt32Ty(gIR->context())),
|
LLType::getInt32Ty(gIR->context())),
|
||||||
DtoTypeInfoOf(loc, stripModifiers(t2)));
|
DtoTypeInfoOf(loc, stripModifiers(t2)));
|
||||||
|
@ -461,7 +450,7 @@ LLConstant *DtoConstArrayInitializer(ArrayInitializer *arrinit,
|
||||||
|
|
||||||
if (arrty->ty == TY::Tpointer) {
|
if (arrty->ty == TY::Tpointer) {
|
||||||
// we need to return pointer to the static array.
|
// we need to return pointer to the static array.
|
||||||
return DtoBitCast(gvar, DtoType(arrty));
|
return gvar;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLConstant *gep = DtoGEP(gvar->getValueType(), gvar, 0u, 0u);
|
LLConstant *gep = DtoGEP(gvar->getValueType(), gvar, 0u, 0u);
|
||||||
|
@ -607,7 +596,7 @@ void initializeArrayLiteral(IRState *p, ArrayLiteralExp *ale,
|
||||||
// optimizer can still decide to promote the memcpy intrinsic, so
|
// optimizer can still decide to promote the memcpy intrinsic, so
|
||||||
// the cutoff merely affects compilation speed.
|
// the cutoff merely affects compilation speed.
|
||||||
if (elemCount <= 4) {
|
if (elemCount <= 4) {
|
||||||
DtoStore(constarr, DtoBitCast(dstMem, getPtrToType(constarr->getType())));
|
DtoStore(constarr, dstMem);
|
||||||
} else {
|
} else {
|
||||||
auto gvar = new llvm::GlobalVariable(gIR->module, constarr->getType(),
|
auto gvar = new llvm::GlobalVariable(gIR->module, constarr->getType(),
|
||||||
true, LLGlobalValue::InternalLinkage,
|
true, LLGlobalValue::InternalLinkage,
|
||||||
|
@ -622,7 +611,7 @@ void initializeArrayLiteral(IRState *p, ArrayLiteralExp *ale,
|
||||||
Expression *rhsExp = indexArrayLiteral(ale, i);
|
Expression *rhsExp = indexArrayLiteral(ale, i);
|
||||||
|
|
||||||
LLValue *lhsPtr = DtoGEP(dstType, dstMem, 0, i, "", p->scopebb());
|
LLValue *lhsPtr = DtoGEP(dstType, dstMem, 0, i, "", p->scopebb());
|
||||||
DLValue lhs(rhsExp->type, DtoBitCast(lhsPtr, DtoPtrToType(rhsExp->type)));
|
DLValue lhs(rhsExp->type, lhsPtr);
|
||||||
|
|
||||||
// try to construct it in-place
|
// try to construct it in-place
|
||||||
if (!toInPlaceConstruction(&lhs, rhsExp))
|
if (!toInPlaceConstruction(&lhs, rhsExp))
|
||||||
|
@ -640,20 +629,6 @@ LLConstant *DtoConstSlice(LLConstant *dim, LLConstant *ptr, Type *type) {
|
||||||
return LLConstantStruct::get(lltype, values);
|
return LLConstantStruct::get(lltype, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static DSliceValue *getSlice(Type *arrayType, LLValue *array) {
|
|
||||||
LLType *llArrayType = DtoType(arrayType);
|
|
||||||
if (array->getType() == llArrayType)
|
|
||||||
return new DSliceValue(arrayType, array);
|
|
||||||
|
|
||||||
LLValue *len = DtoExtractValue(array, 0, ".len");
|
|
||||||
LLValue *ptr = DtoExtractValue(array, 1, ".ptr");
|
|
||||||
ptr = DtoBitCast(ptr, llArrayType->getContainedType(1));
|
|
||||||
|
|
||||||
return new DSliceValue(arrayType, len, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
DSliceValue *DtoNewDynArray(const Loc &loc, Type *arrayType, DValue *dim,
|
DSliceValue *DtoNewDynArray(const Loc &loc, Type *arrayType, DValue *dim,
|
||||||
bool defaultInit) {
|
bool defaultInit) {
|
||||||
|
@ -684,8 +659,7 @@ DSliceValue *DtoNewDynArray(const Loc &loc, Type *arrayType, DValue *dim,
|
||||||
gIR->CreateCallOrInvoke(fn, arrayTypeInfo, arrayLen, ".gc_mem");
|
gIR->CreateCallOrInvoke(fn, arrayTypeInfo, arrayLen, ".gc_mem");
|
||||||
|
|
||||||
// return a DSliceValue with the well-known length for better optimizability
|
// return a DSliceValue with the well-known length for better optimizability
|
||||||
auto ptr =
|
auto ptr = DtoExtractValue(newArray, 1, ".ptr");
|
||||||
DtoBitCast(DtoExtractValue(newArray, 1, ".ptr"), DtoPtrToType(eltType));
|
|
||||||
return new DSliceValue(arrayType, arrayLen, ptr);
|
return new DSliceValue(arrayType, arrayLen, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,11 +674,11 @@ DSliceValue *DtoAppendDChar(const Loc &loc, DValue *arr, Expression *exp,
|
||||||
|
|
||||||
// Call function (ref string x, dchar c)
|
// Call function (ref string x, dchar c)
|
||||||
LLValue *newArray = gIR->CreateCallOrInvoke(
|
LLValue *newArray = gIR->CreateCallOrInvoke(
|
||||||
fn, DtoBitCast(DtoLVal(arr), fn->getFunctionType()->getParamType(0)),
|
fn, DtoLVal(arr),
|
||||||
DtoBitCast(valueToAppend, fn->getFunctionType()->getParamType(1)),
|
DtoBitCast(valueToAppend, fn->getFunctionType()->getParamType(1)),
|
||||||
".appendedArray");
|
".appendedArray");
|
||||||
|
|
||||||
return getSlice(arr->type, newArray);
|
return new DSliceValue(arr->type, newArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -753,7 +727,7 @@ LLValue *DtoArrayEqCmp_impl(const Loc &loc, const char *func, DValue *l,
|
||||||
// pass array typeinfo ?
|
// pass array typeinfo ?
|
||||||
if (useti) {
|
if (useti) {
|
||||||
LLValue *tival = DtoTypeInfoOf(loc, l->type);
|
LLValue *tival = DtoTypeInfoOf(loc, l->type);
|
||||||
args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2)));
|
args.push_back(tival);
|
||||||
}
|
}
|
||||||
|
|
||||||
return gIR->CreateCallOrInvoke(fn, args);
|
return gIR->CreateCallOrInvoke(fn, args);
|
||||||
|
@ -833,8 +807,7 @@ llvm::CallInst *callMemcmp(const Loc &loc, IRState &irs, LLValue *l_ptr,
|
||||||
sizeInBytes = irs.ir->CreateMul(sizeInBytes, DtoConstSize_t(elementSize));
|
sizeInBytes = irs.ir->CreateMul(sizeInBytes, DtoConstSize_t(elementSize));
|
||||||
}
|
}
|
||||||
// Call memcmp.
|
// Call memcmp.
|
||||||
LLValue *args[] = {DtoBitCast(l_ptr, getVoidPtrType()),
|
LLValue *args[] = {l_ptr, r_ptr, sizeInBytes};
|
||||||
DtoBitCast(r_ptr, getVoidPtrType()), sizeInBytes};
|
|
||||||
return irs.ir->CreateCall(fn, args);
|
return irs.ir->CreateCall(fn, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,7 +956,7 @@ LLValue *DtoArrayPtr(DValue *v) {
|
||||||
llvm_unreachable("Unexpected array type.");
|
llvm_unreachable("Unexpected array type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtoBitCast(ptr, wantedLLPtrType);
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -991,8 +964,6 @@ DValue *DtoCastArray(const Loc &loc, DValue *u, Type *to) {
|
||||||
IF_LOG Logger::println("DtoCastArray");
|
IF_LOG Logger::println("DtoCastArray");
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
LLType *tolltype = DtoType(to);
|
|
||||||
|
|
||||||
Type *totype = to->toBasetype();
|
Type *totype = to->toBasetype();
|
||||||
Type *fromtype = u->type->toBasetype();
|
Type *fromtype = u->type->toBasetype();
|
||||||
if (fromtype->ty != TY::Tarray && fromtype->ty != TY::Tsarray) {
|
if (fromtype->ty != TY::Tarray && fromtype->ty != TY::Tsarray) {
|
||||||
|
@ -1005,9 +976,6 @@ DValue *DtoCastArray(const Loc &loc, DValue *u, Type *to) {
|
||||||
if (totype->ty == TY::Tpointer) {
|
if (totype->ty == TY::Tpointer) {
|
||||||
IF_LOG Logger::cout() << "to pointer" << '\n';
|
IF_LOG Logger::cout() << "to pointer" << '\n';
|
||||||
LLValue *ptr = DtoArrayPtr(u);
|
LLValue *ptr = DtoArrayPtr(u);
|
||||||
if (ptr->getType() != tolltype) {
|
|
||||||
ptr = gIR->ir->CreateBitCast(ptr, tolltype);
|
|
||||||
}
|
|
||||||
return new DImValue(to, ptr);
|
return new DImValue(to, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,8 +1015,7 @@ DValue *DtoCastArray(const Loc &loc, DValue *u, Type *to) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLType *ptrty = tolltype->getStructElementType(1);
|
return new DSliceValue(to, length, ptr);
|
||||||
return new DSliceValue(to, length, DtoBitCast(ptr, ptrty));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totype->ty == TY::Tsarray) {
|
if (totype->ty == TY::Tsarray) {
|
||||||
|
@ -1066,7 +1033,7 @@ DValue *DtoCastArray(const Loc &loc, DValue *u, Type *to) {
|
||||||
ptr = DtoArrayPtr(u);
|
ptr = DtoArrayPtr(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DLValue(to, DtoBitCast(ptr, getPtrToType(tolltype)));
|
return new DLValue(to, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totype->ty == TY::Tbool) {
|
if (totype->ty == TY::Tbool) {
|
||||||
|
@ -1076,7 +1043,7 @@ DValue *DtoCastArray(const Loc &loc, DValue *u, Type *to) {
|
||||||
return new DImValue(to, gIR->ir->CreateICmpNE(ptr, nul));
|
return new DImValue(to, gIR->ir->CreateICmpNE(ptr, nul));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto castedPtr = DtoBitCast(DtoArrayPtr(u), getPtrToType(tolltype));
|
const auto castedPtr = DtoArrayPtr(u);
|
||||||
return new DLValue(to, castedPtr);
|
return new DLValue(to, castedPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,6 @@ DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset,
|
||||||
llOffset = DtoConstSize_t(byteOffset / pointeeSize);
|
llOffset = DtoConstSize_t(byteOffset / pointeeSize);
|
||||||
} else { // need to cast base to i8*
|
} else { // need to cast base to i8*
|
||||||
llBaseTy = getI8Type();
|
llBaseTy = getI8Type();
|
||||||
llBase = DtoBitCast(llBase, getVoidPtrType());
|
|
||||||
llOffset = DtoConstSize_t(byteOffset);
|
llOffset = DtoConstSize_t(byteOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +108,6 @@ DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset,
|
||||||
llOffset = DtoRVal(rvals.rhs);
|
llOffset = DtoRVal(rvals.rhs);
|
||||||
if (!noStrideInc) { // byte offset => cast base to i8*
|
if (!noStrideInc) { // byte offset => cast base to i8*
|
||||||
llBaseTy = getI8Type();
|
llBaseTy = getI8Type();
|
||||||
llBase = DtoBitCast(llBase, getVoidPtrType());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +117,7 @@ DValue *emitPointerOffset(Loc loc, DValue *base, Expression *offset,
|
||||||
llResult = DtoGEP1(llBaseTy, llBase, llOffset);
|
llResult = DtoGEP1(llBaseTy, llBase, llOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DImValue(resultType, DtoBitCast(llResult, DtoType(resultType)));
|
return new DImValue(resultType, llResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDC issue #2537 / DMD issue #18317: associative arrays can be
|
// LDC issue #2537 / DMD issue #18317: associative arrays can be
|
||||||
|
|
|
@ -87,12 +87,9 @@ DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
||||||
const bool useEHAlloc = global.params.ehnogc && newexp->thrownew;
|
const bool useEHAlloc = global.params.ehnogc && newexp->thrownew;
|
||||||
llvm::Function *fn = getRuntimeFunction(
|
llvm::Function *fn = getRuntimeFunction(
|
||||||
loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass");
|
loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass");
|
||||||
LLConstant *ci =
|
LLConstant *ci = irClass->getClassInfoSymbol();
|
||||||
DtoBitCast(irClass->getClassInfoSymbol(), DtoType(getClassInfoType()));
|
|
||||||
mem = gIR->CreateCallOrInvoke(
|
mem = gIR->CreateCallOrInvoke(
|
||||||
fn, ci, useEHAlloc ? ".newthrowable_alloc" : ".newclass_gc_alloc");
|
fn, ci, useEHAlloc ? ".newthrowable" : ".newclass_gc");
|
||||||
mem = DtoBitCast(mem, DtoType(tc),
|
|
||||||
useEHAlloc ? ".newthrowable" : ".newclass_gc");
|
|
||||||
doInit = !useEHAlloc;
|
doInit = !useEHAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +105,7 @@ DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
||||||
LLValue *src = DtoRVal(newexp->thisexp);
|
LLValue *src = DtoRVal(newexp->thisexp);
|
||||||
LLValue *dst = DtoGEP(irClass->getLLStructType(), mem, 0, idx);
|
LLValue *dst = DtoGEP(irClass->getLLStructType(), mem, 0, idx);
|
||||||
IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
||||||
DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType())));
|
DtoStore(src, dst);
|
||||||
}
|
}
|
||||||
// set the context for nested classes
|
// set the context for nested classes
|
||||||
else if (tc->sym->isNested() && tc->sym->vthis) {
|
else if (tc->sym->isNested() && tc->sym->vthis) {
|
||||||
|
@ -169,7 +166,6 @@ void DtoInitClass(TypeClass *tc, LLValue *dst) {
|
||||||
|
|
||||||
// init symbols might not have valid types
|
// init symbols might not have valid types
|
||||||
LLValue *initsym = irClass->getInitSymbol();
|
LLValue *initsym = irClass->getInitSymbol();
|
||||||
initsym = DtoBitCast(initsym, DtoType(tc));
|
|
||||||
LLValue *srcarr = DtoGEP(st, initsym, 0, firstDataIdx);
|
LLValue *srcarr = DtoGEP(st, initsym, 0, firstDataIdx);
|
||||||
|
|
||||||
DtoMemCpy(dstarr, srcarr, DtoConstSize_t(dataBytes));
|
DtoMemCpy(dstarr, srcarr, DtoConstSize_t(dataBytes));
|
||||||
|
@ -182,8 +178,7 @@ void DtoFinalizeClass(const Loc &loc, LLValue *inst) {
|
||||||
llvm::Function *fn =
|
llvm::Function *fn =
|
||||||
getRuntimeFunction(loc, gIR->module, "_d_callfinalizer");
|
getRuntimeFunction(loc, gIR->module, "_d_callfinalizer");
|
||||||
|
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, inst, "");
|
||||||
fn, DtoBitCast(inst, fn->getFunctionType()->getParamType(0)), "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -244,9 +239,7 @@ DValue *DtoCastClass(const Loc &loc, DValue *val, Type *_to) {
|
||||||
// class -> pointer
|
// class -> pointer
|
||||||
if (to->ty == TY::Tpointer) {
|
if (to->ty == TY::Tpointer) {
|
||||||
IF_LOG Logger::println("to pointer");
|
IF_LOG Logger::println("to pointer");
|
||||||
LLType *tolltype = DtoType(_to);
|
return new DImValue(_to, DtoRVal(val));
|
||||||
LLValue *rval = DtoBitCast(DtoRVal(val), tolltype);
|
|
||||||
return new DImValue(_to, rval);
|
|
||||||
}
|
}
|
||||||
// class -> bool
|
// class -> bool
|
||||||
if (to->ty == TY::Tbool) {
|
if (to->ty == TY::Tbool) {
|
||||||
|
@ -288,7 +281,6 @@ DValue *DtoCastClass(const Loc &loc, DValue *val, Type *_to) {
|
||||||
// else if from is interface: _d_interface_cast(to)
|
// else if from is interface: _d_interface_cast(to)
|
||||||
// else if from is class: _d_dynamic_cast(to)
|
// else if from is class: _d_dynamic_cast(to)
|
||||||
|
|
||||||
LLType *toType = DtoType(_to);
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (tc->sym->isBaseOf(fc->sym, &offset)) {
|
if (tc->sym->isBaseOf(fc->sym, &offset)) {
|
||||||
Logger::println("static down cast");
|
Logger::println("static down cast");
|
||||||
|
@ -300,14 +292,11 @@ DValue *DtoCastClass(const Loc &loc, DValue *val, Type *_to) {
|
||||||
LLValue *v = orig;
|
LLValue *v = orig;
|
||||||
if (offset != 0) {
|
if (offset != 0) {
|
||||||
assert(offset > 0);
|
assert(offset > 0);
|
||||||
v = DtoBitCast(v, getVoidPtrType());
|
v = DtoGEP1(getI8Type(), v, DtoConstUint(offset));
|
||||||
v = DtoGEP1(LLType::getInt8Ty(gIR->context()), v, DtoConstUint(offset));
|
|
||||||
}
|
}
|
||||||
IF_LOG {
|
IF_LOG {
|
||||||
Logger::cout() << "V = " << *v << std::endl;
|
Logger::cout() << "V = " << *v << std::endl;
|
||||||
Logger::cout() << "T = " << *toType << std::endl;
|
|
||||||
}
|
}
|
||||||
v = DtoBitCast(v, toType);
|
|
||||||
|
|
||||||
// Check whether the original value was null, and return null if so.
|
// Check whether the original value was null, and return null if so.
|
||||||
// Sure we could have jumped over the code above in this case, but
|
// Sure we could have jumped over the code above in this case, but
|
||||||
|
@ -316,8 +305,8 @@ DValue *DtoCastClass(const Loc &loc, DValue *val, Type *_to) {
|
||||||
// null.
|
// null.
|
||||||
LLValue *isNull = gIR->ir->CreateICmpEQ(
|
LLValue *isNull = gIR->ir->CreateICmpEQ(
|
||||||
orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
|
orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
|
||||||
v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(toType), v,
|
v = gIR->ir->CreateSelect(
|
||||||
".interface");
|
isNull, LLConstant::getNullValue(getVoidPtrType()), v, ".interface");
|
||||||
// return r-value
|
// return r-value
|
||||||
return new DImValue(_to, v);
|
return new DImValue(_to, v);
|
||||||
}
|
}
|
||||||
|
@ -325,8 +314,8 @@ DValue *DtoCastClass(const Loc &loc, DValue *val, Type *_to) {
|
||||||
if (fc->sym->classKind == ClassKind::cpp) {
|
if (fc->sym->classKind == ClassKind::cpp) {
|
||||||
Logger::println("C++ class/interface cast");
|
Logger::println("C++ class/interface cast");
|
||||||
LLValue *v = tc->sym->classKind == ClassKind::cpp
|
LLValue *v = tc->sym->classKind == ClassKind::cpp
|
||||||
? DtoBitCast(DtoRVal(val), toType)
|
? DtoRVal(val)
|
||||||
: LLConstant::getNullValue(toType);
|
: LLConstant::getNullValue(getVoidPtrType());
|
||||||
return new DImValue(_to, v);
|
return new DImValue(_to, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +352,6 @@ DValue *DtoDynamicCastObject(const Loc &loc, DValue *val, Type *_to) {
|
||||||
|
|
||||||
// Object o
|
// Object o
|
||||||
LLValue *obj = DtoRVal(val);
|
LLValue *obj = DtoRVal(val);
|
||||||
obj = DtoBitCast(obj, funcTy->getParamType(0));
|
|
||||||
assert(funcTy->getParamType(0) == obj->getType());
|
assert(funcTy->getParamType(0) == obj->getType());
|
||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
|
@ -371,18 +359,11 @@ DValue *DtoDynamicCastObject(const Loc &loc, DValue *val, Type *_to) {
|
||||||
DtoResolveClass(to->sym);
|
DtoResolveClass(to->sym);
|
||||||
|
|
||||||
LLValue *cinfo = getIrAggr(to->sym)->getClassInfoSymbol();
|
LLValue *cinfo = getIrAggr(to->sym)->getClassInfoSymbol();
|
||||||
// unfortunately this is needed as the implementation of object differs
|
|
||||||
// somehow from the declaration
|
|
||||||
// this could happen in user code as well :/
|
|
||||||
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
|
||||||
assert(funcTy->getParamType(1) == cinfo->getType());
|
assert(funcTy->getParamType(1) == cinfo->getType());
|
||||||
|
|
||||||
// call it
|
// call it
|
||||||
LLValue *ret = gIR->CreateCallOrInvoke(func, obj, cinfo);
|
LLValue *ret = gIR->CreateCallOrInvoke(func, obj, cinfo);
|
||||||
|
|
||||||
// cast return value
|
|
||||||
ret = DtoBitCast(ret, DtoType(_to));
|
|
||||||
|
|
||||||
return new DImValue(_to, ret);
|
return new DImValue(_to, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,23 +381,15 @@ DValue *DtoDynamicCastInterface(const Loc &loc, DValue *val, Type *_to) {
|
||||||
|
|
||||||
// void* p
|
// void* p
|
||||||
LLValue *ptr = DtoRVal(val);
|
LLValue *ptr = DtoRVal(val);
|
||||||
ptr = DtoBitCast(ptr, funcTy->getParamType(0));
|
|
||||||
|
|
||||||
// ClassInfo c
|
// ClassInfo c
|
||||||
TypeClass *to = static_cast<TypeClass *>(_to->toBasetype());
|
TypeClass *to = static_cast<TypeClass *>(_to->toBasetype());
|
||||||
DtoResolveClass(to->sym);
|
DtoResolveClass(to->sym);
|
||||||
LLValue *cinfo = getIrAggr(to->sym)->getClassInfoSymbol();
|
LLValue *cinfo = getIrAggr(to->sym)->getClassInfoSymbol();
|
||||||
// unfortunately this is needed as the implementation of object differs
|
|
||||||
// somehow from the declaration
|
|
||||||
// this could happen in user code as well :/
|
|
||||||
cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
|
|
||||||
|
|
||||||
// call it
|
// call it
|
||||||
LLValue *ret = gIR->CreateCallOrInvoke(func, ptr, cinfo);
|
LLValue *ret = gIR->CreateCallOrInvoke(func, ptr, cinfo);
|
||||||
|
|
||||||
// cast return value
|
|
||||||
ret = DtoBitCast(ret, DtoType(_to));
|
|
||||||
|
|
||||||
return new DImValue(_to, ret);
|
return new DImValue(_to, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,9 +433,6 @@ DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl) {
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
|
IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
|
||||||
|
|
||||||
// cast to funcptr type
|
|
||||||
funcval = DtoBitCast(funcval, getPtrToType(DtoFunctionType(fdecl)));
|
|
||||||
|
|
||||||
// postpone naming until after casting to get the name in call instructions
|
// postpone naming until after casting to get the name in call instructions
|
||||||
funcval->setName(name);
|
funcval->setName(name);
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ DBitFieldLValue::DBitFieldLValue(Type *t, LLValue *ptr, BitFieldDeclaration *bf)
|
||||||
|
|
||||||
DRValue *DBitFieldLValue::getRVal() {
|
DRValue *DBitFieldLValue::getRVal() {
|
||||||
const auto sizeInBits = intType->getBitWidth();
|
const auto sizeInBits = intType->getBitWidth();
|
||||||
const auto ptr = DtoBitCast(val, getPtrToType(intType));
|
const auto ptr = val;
|
||||||
LLValue *v = gIR->ir->CreateAlignedLoad(intType, ptr, llvm::MaybeAlign(1));
|
LLValue *v = gIR->ir->CreateAlignedLoad(intType, ptr, llvm::MaybeAlign(1));
|
||||||
|
|
||||||
if (bf->type->isunsigned()) {
|
if (bf->type->isunsigned()) {
|
||||||
|
@ -206,7 +206,7 @@ DRValue *DBitFieldLValue::getRVal() {
|
||||||
void DBitFieldLValue::store(LLValue *value) {
|
void DBitFieldLValue::store(LLValue *value) {
|
||||||
assert(value->getType()->isIntegerTy());
|
assert(value->getType()->isIntegerTy());
|
||||||
|
|
||||||
const auto ptr = DtoBitCast(val, getPtrToType(intType));
|
const auto ptr = val;
|
||||||
|
|
||||||
const auto mask =
|
const auto mask =
|
||||||
llvm::APInt::getLowBitsSet(intType->getBitWidth(), bf->fieldWidth);
|
llvm::APInt::getLowBitsSet(intType->getBitWidth(), bf->fieldWidth);
|
||||||
|
|
|
@ -1221,11 +1221,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
if (!irFty.arg_this->byref) {
|
if (!irFty.arg_this->byref) {
|
||||||
if (fd->interfaceVirtual) {
|
if (fd->interfaceVirtual) {
|
||||||
// Adjust the 'this' pointer instead of using a thunk
|
// Adjust the 'this' pointer instead of using a thunk
|
||||||
LLType *targetThisType = thismem->getType();
|
|
||||||
thismem = DtoBitCast(thismem, getVoidPtrType());
|
|
||||||
auto off = DtoConstInt(-fd->interfaceVirtual->offset);
|
auto off = DtoConstInt(-fd->interfaceVirtual->offset);
|
||||||
thismem = DtoGEP1(llvm::Type::getInt8Ty(gIR->context()), thismem, off);
|
thismem = DtoGEP1(getI8Type(), thismem, off);
|
||||||
thismem = DtoBitCast(thismem, targetThisType);
|
|
||||||
}
|
}
|
||||||
thismem = DtoAllocaDump(thismem, 0, "this");
|
thismem = DtoAllocaDump(thismem, 0, "this");
|
||||||
irFunc->thisArg = thismem;
|
irFunc->thisArg = thismem;
|
||||||
|
|
|
@ -238,7 +238,7 @@ DValue *DtoInlineIRExpr(const Loc &loc, FuncDeclaration *fdecl,
|
||||||
Type *type = fdecl->type->nextOf();
|
Type *type = fdecl->type->nextOf();
|
||||||
|
|
||||||
if (sretPointer) {
|
if (sretPointer) {
|
||||||
DtoStore(rv, DtoBitCast(sretPointer, getPtrToType(rv->getType())));
|
DtoStore(rv, sretPointer);
|
||||||
return new DLValue(type, sretPointer);
|
return new DLValue(type, sretPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,17 +155,16 @@ IRState::setGlobalVarInitializer(LLGlobalVariable *&globalVar,
|
||||||
|
|
||||||
defineGlobal(globalHelperVar, initializer, symbolForLinkageAndVisibility);
|
defineGlobal(globalHelperVar, initializer, symbolForLinkageAndVisibility);
|
||||||
|
|
||||||
// Replace all existing uses of globalVar by the bitcast pointer.
|
// Replace all existing uses of globalVar by the helper variable.
|
||||||
auto castHelperVar = DtoBitCast(globalHelperVar, globalVar->getType());
|
globalVar->replaceAllUsesWith(globalHelperVar);
|
||||||
globalVar->replaceAllUsesWith(castHelperVar);
|
|
||||||
|
|
||||||
// Register replacement for later occurrences of the original globalVar.
|
// Register replacement for later occurrences of the original globalVar.
|
||||||
globalsToReplace.emplace_back(globalVar, castHelperVar);
|
globalsToReplace.emplace_back(globalVar, globalHelperVar);
|
||||||
|
|
||||||
// Reset globalVar to the helper variable.
|
// Reset globalVar to the helper variable.
|
||||||
globalVar = globalHelperVar;
|
globalVar = globalHelperVar;
|
||||||
|
|
||||||
return castHelperVar;
|
return globalHelperVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRState::replaceGlobals() {
|
void IRState::replaceGlobals() {
|
||||||
|
|
|
@ -90,39 +90,31 @@ LLValue *DtoNew(const Loc &loc, Type *newtype) {
|
||||||
LLConstant *ti = DtoTypeInfoOf(loc, newtype);
|
LLConstant *ti = DtoTypeInfoOf(loc, newtype);
|
||||||
assert(isaPointer(ti));
|
assert(isaPointer(ti));
|
||||||
// call runtime allocator
|
// call runtime allocator
|
||||||
LLValue *mem = gIR->CreateCallOrInvoke(fn, ti, ".gc_mem");
|
return gIR->CreateCallOrInvoke(fn, ti, ".gc_mem");
|
||||||
// cast
|
|
||||||
return DtoBitCast(mem, DtoPtrToType(newtype), ".gc_mem");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtoDeleteMemory(const Loc &loc, DValue *ptr) {
|
void DtoDeleteMemory(const Loc &loc, DValue *ptr) {
|
||||||
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delmemory");
|
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delmemory");
|
||||||
LLValue *lval = (ptr->isLVal() ? DtoLVal(ptr) : makeLValue(loc, ptr));
|
LLValue *lval = (ptr->isLVal() ? DtoLVal(ptr) : makeLValue(loc, ptr));
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, lval);
|
||||||
fn, DtoBitCast(lval, fn->getFunctionType()->getParamType(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtoDeleteStruct(const Loc &loc, DValue *ptr) {
|
void DtoDeleteStruct(const Loc &loc, DValue *ptr) {
|
||||||
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delstruct");
|
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delstruct");
|
||||||
LLValue *lval = (ptr->isLVal() ? DtoLVal(ptr) : makeLValue(loc, ptr));
|
LLValue *lval = (ptr->isLVal() ? DtoLVal(ptr) : makeLValue(loc, ptr));
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, lval, DtoTypeInfoOf(loc, ptr->type->nextOf()));
|
||||||
fn, DtoBitCast(lval, fn->getFunctionType()->getParamType(0)),
|
|
||||||
DtoBitCast(DtoTypeInfoOf(loc, ptr->type->nextOf()),
|
|
||||||
fn->getFunctionType()->getParamType(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtoDeleteClass(const Loc &loc, DValue *inst) {
|
void DtoDeleteClass(const Loc &loc, DValue *inst) {
|
||||||
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delclass");
|
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delclass");
|
||||||
LLValue *lval = (inst->isLVal() ? DtoLVal(inst) : makeLValue(loc, inst));
|
LLValue *lval = (inst->isLVal() ? DtoLVal(inst) : makeLValue(loc, inst));
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, lval);
|
||||||
fn, DtoBitCast(lval, fn->getFunctionType()->getParamType(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtoDeleteInterface(const Loc &loc, DValue *inst) {
|
void DtoDeleteInterface(const Loc &loc, DValue *inst) {
|
||||||
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delinterface");
|
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_delinterface");
|
||||||
LLValue *lval = (inst->isLVal() ? DtoLVal(inst) : makeLValue(loc, inst));
|
LLValue *lval = (inst->isLVal() ? DtoLVal(inst) : makeLValue(loc, inst));
|
||||||
gIR->CreateCallOrInvoke(
|
gIR->CreateCallOrInvoke(fn, lval);
|
||||||
fn, DtoBitCast(lval, fn->getFunctionType()->getParamType(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DtoDeleteArray(const Loc &loc, DValue *arr) {
|
void DtoDeleteArray(const Loc &loc, DValue *arr) {
|
||||||
|
@ -137,8 +129,7 @@ void DtoDeleteArray(const Loc &loc, DValue *arr) {
|
||||||
: DtoTypeInfoOf(loc, elementType);
|
: DtoTypeInfoOf(loc, elementType);
|
||||||
|
|
||||||
LLValue *lval = (arr->isLVal() ? DtoLVal(arr) : makeLValue(loc, arr));
|
LLValue *lval = (arr->isLVal() ? DtoLVal(arr) : makeLValue(loc, arr));
|
||||||
gIR->CreateCallOrInvoke(fn, DtoBitCast(lval, fty->getParamType(0)),
|
gIR->CreateCallOrInvoke(fn, lval, typeInfo);
|
||||||
DtoBitCast(typeInfo, fty->getParamType(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -249,8 +240,8 @@ LLValue *DtoAllocaDump(LLValue *val, LLType *asType, int alignment,
|
||||||
(getTypeStoreSize(memType) <= getTypeAllocSize(asMemType) ? asMemType
|
(getTypeStoreSize(memType) <= getTypeAllocSize(asMemType) ? asMemType
|
||||||
: memType);
|
: memType);
|
||||||
LLValue *mem = DtoRawAlloca(allocaType, alignment, name);
|
LLValue *mem = DtoRawAlloca(allocaType, alignment, name);
|
||||||
DtoStoreZextI8(val, DtoBitCast(mem, memType->getPointerTo()));
|
DtoStoreZextI8(val, mem);
|
||||||
return DtoBitCast(mem, asMemType->getPointerTo());
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -337,7 +328,7 @@ void DtoCAssert(Module *M, const Loc &loc, LLValue *msg) {
|
||||||
|
|
||||||
void DtoThrow(const Loc &loc, DValue *e) {
|
void DtoThrow(const Loc &loc, DValue *e) {
|
||||||
LLFunction *fn = getRuntimeFunction(loc, gIR->module, "_d_throw_exception");
|
LLFunction *fn = getRuntimeFunction(loc, gIR->module, "_d_throw_exception");
|
||||||
LLValue *arg = DtoBitCast(DtoRVal(e), fn->getFunctionType()->getParamType(0));
|
LLValue *arg = DtoRVal(e);
|
||||||
|
|
||||||
gIR->CreateCallOrInvoke(fn, arg);
|
gIR->CreateCallOrInvoke(fn, arg);
|
||||||
gIR->ir->CreateUnreachable();
|
gIR->ir->CreateUnreachable();
|
||||||
|
@ -426,7 +417,6 @@ void DtoAssign(const Loc &loc, DValue *lhs, DValue *rhs, EXP op,
|
||||||
Logger::cout() << "l : " << *l << '\n';
|
Logger::cout() << "l : " << *l << '\n';
|
||||||
Logger::cout() << "r : " << *r << '\n';
|
Logger::cout() << "r : " << *r << '\n';
|
||||||
}
|
}
|
||||||
r = DtoBitCast(r, DtoType(lhs->type));
|
|
||||||
DtoStore(r, l);
|
DtoStore(r, l);
|
||||||
} else if (t->iscomplex()) {
|
} else if (t->iscomplex()) {
|
||||||
LLValue *dst = DtoLVal(lhs);
|
LLValue *dst = DtoLVal(lhs);
|
||||||
|
@ -680,9 +670,7 @@ DValue *DtoCastStruct(const Loc &loc, DValue *val, Type *to) {
|
||||||
// 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 *lval = DtoLVal(val);
|
llvm::Value *lval = DtoLVal(val);
|
||||||
llvm::Value *result = DtoBitCast(lval, DtoType(to)->getPointerTo(),
|
return new DLValue(to, lval);
|
||||||
lval->getName() + ".repaint");
|
|
||||||
return new DLValue(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`",
|
||||||
|
@ -705,8 +693,7 @@ DValue *DtoCast(const Loc &loc, DValue *val, Type *to) {
|
||||||
// implemented as structs.
|
// implemented as structs.
|
||||||
if (totype->ty == TY::Tpointer) {
|
if (totype->ty == TY::Tpointer) {
|
||||||
IF_LOG Logger::println("Casting AA to pointer.");
|
IF_LOG Logger::println("Casting AA to pointer.");
|
||||||
LLValue *rval = DtoBitCast(DtoRVal(val), DtoType(to));
|
return new DImValue(to, DtoRVal(val));
|
||||||
return new DImValue(to, rval);
|
|
||||||
}
|
}
|
||||||
if (totype->ty == TY::Tbool) {
|
if (totype->ty == TY::Tbool) {
|
||||||
IF_LOG Logger::println("Casting AA to bool.");
|
IF_LOG Logger::println("Casting AA to bool.");
|
||||||
|
@ -771,20 +758,16 @@ DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to) {
|
||||||
Type *tb = to->toBasetype();
|
Type *tb = to->toBasetype();
|
||||||
|
|
||||||
if (val->isLVal()) {
|
if (val->isLVal()) {
|
||||||
auto ptr = DtoBitCast(DtoLVal(val), DtoPtrToType(tb));
|
return new DLValue(to, DtoLVal(val));
|
||||||
return new DLValue(to, ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto slice = val->isSlice()) {
|
if (auto slice = val->isSlice()) {
|
||||||
if (tb->ty == TY::Tarray) {
|
if (tb->ty == TY::Tarray) {
|
||||||
auto ptr = DtoBitCast(slice->getPtr(), DtoPtrToType(tb->nextOf()));
|
return new DSliceValue(to, slice->getLength(), slice->getPtr());
|
||||||
return new DSliceValue(to, slice->getLength(), ptr);
|
|
||||||
}
|
}
|
||||||
} else if (auto func = val->isFunc()) {
|
} else if (auto func = val->isFunc()) {
|
||||||
if (tb->ty == TY::Tdelegate) {
|
if (tb->ty == TY::Tdelegate) {
|
||||||
auto funcptr =
|
return new DFuncValue(to, func->func, DtoRVal(func), func->vthis);
|
||||||
DtoBitCast(DtoRVal(func), DtoType(tb)->getContainedType(1));
|
|
||||||
return new DFuncValue(to, func->func, funcptr, func->vthis);
|
|
||||||
}
|
}
|
||||||
} else { // generic rvalue
|
} else { // generic rvalue
|
||||||
LLValue *rval = DtoRVal(val);
|
LLValue *rval = DtoRVal(val);
|
||||||
|
@ -794,12 +777,11 @@ DValue *DtoPaintType(const Loc &loc, DValue *val, Type *to) {
|
||||||
return new DImValue(to, rval);
|
return new DImValue(to, rval);
|
||||||
}
|
}
|
||||||
if (rval->getType()->isPointerTy() && tll->isPointerTy()) {
|
if (rval->getType()->isPointerTy() && tll->isPointerTy()) {
|
||||||
return new DImValue(to, DtoBitCast(rval, tll));
|
return new DImValue(to, rval);
|
||||||
}
|
}
|
||||||
if (from->ty == TY::Tdelegate && tb->ty == TY::Tdelegate) {
|
if (from->ty == TY::Tdelegate && tb->ty == TY::Tdelegate) {
|
||||||
LLValue *context = gIR->ir->CreateExtractValue(rval, 0, ".context");
|
LLValue *context = gIR->ir->CreateExtractValue(rval, 0, ".context");
|
||||||
LLValue *funcptr = gIR->ir->CreateExtractValue(rval, 1, ".funcptr");
|
LLValue *funcptr = gIR->ir->CreateExtractValue(rval, 1, ".funcptr");
|
||||||
funcptr = DtoBitCast(funcptr, tll->getContainedType(1));
|
|
||||||
return new DImValue(to, DtoAggrPair(context, funcptr));
|
return new DImValue(to, DtoAggrPair(context, funcptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1520,8 +1502,7 @@ DValue *DtoSymbolAddress(const Loc &loc, Type *type, Declaration *decl) {
|
||||||
if (vd->isClassMember() && vd == vd->isClassMember()->vtblsym) {
|
if (vd->isClassMember() && vd == vd->isClassMember()->vtblsym) {
|
||||||
Logger::println("vtbl symbol");
|
Logger::println("vtbl symbol");
|
||||||
auto cd = vd->isClassMember();
|
auto cd = vd->isClassMember();
|
||||||
return new DLValue(
|
return new DLValue(type, getIrAggr(cd)->getVtblSymbol());
|
||||||
type, DtoBitCast(getIrAggr(cd)->getVtblSymbol(), DtoPtrToType(type)));
|
|
||||||
}
|
}
|
||||||
// nested variable
|
// nested variable
|
||||||
if (vd->nestedrefs.length) {
|
if (vd->nestedrefs.length) {
|
||||||
|
@ -1546,7 +1527,7 @@ DValue *DtoSymbolAddress(const Loc &loc, Type *type, Declaration *decl) {
|
||||||
assert(!isSpecialRefVar(vd) && "Code not expected to handle special "
|
assert(!isSpecialRefVar(vd) && "Code not expected to handle special "
|
||||||
"ref vars, although it can easily be "
|
"ref vars, although it can easily be "
|
||||||
"made to.");
|
"made to.");
|
||||||
return new DLValue(type, DtoBitCast(getIrValue(vd), DtoPtrToType(type)));
|
return new DLValue(type, getIrValue(vd));
|
||||||
}
|
}
|
||||||
Logger::println("a normal variable");
|
Logger::println("a normal variable");
|
||||||
|
|
||||||
|
@ -1597,10 +1578,9 @@ DValue *DtoSymbolAddress(const Loc &loc, Type *type, Declaration *decl) {
|
||||||
if (tb->ty != TY::Tstruct) {
|
if (tb->ty != TY::Tstruct) {
|
||||||
assert(tb->ty == TY::Tarray && tb->nextOf()->ty == TY::Tvoid);
|
assert(tb->ty == TY::Tarray && tb->nextOf()->ty == TY::Tvoid);
|
||||||
const auto size = DtoConstSize_t(ad->structsize);
|
const auto size = DtoConstSize_t(ad->structsize);
|
||||||
llvm::Constant *ptr =
|
llvm::Constant *ptr = sd && sd->zeroInit()
|
||||||
sd && sd->zeroInit()
|
? getNullValue(getVoidPtrType())
|
||||||
? getNullValue(getVoidPtrType())
|
: getIrAggr(ad)->getInitSymbol();
|
||||||
: DtoBitCast(getIrAggr(ad)->getInitSymbol(), getVoidPtrType());
|
|
||||||
return new DSliceValue(type, size, ptr);
|
return new DSliceValue(type, size, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1611,7 +1591,7 @@ DValue *DtoSymbolAddress(const Loc &loc, Type *type, Declaration *decl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
|
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
|
||||||
return new DLValue(type, DtoBitCast(initsym, DtoPtrToType(sd->type)));
|
return new DLValue(type, initsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Unimplemented VarExp type");
|
llvm_unreachable("Unimplemented VarExp type");
|
||||||
|
@ -1878,9 +1858,8 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
|
||||||
LLValue *ptr = src;
|
LLValue *ptr = src;
|
||||||
LLType * ty = nullptr;
|
LLType * ty = nullptr;
|
||||||
if (!isFieldIdx) {
|
if (!isFieldIdx) {
|
||||||
// Cast to void* to apply byte-wise offset from object start.
|
// apply byte-wise offset from object start
|
||||||
ptr = DtoBitCast(ptr, getVoidPtrType());
|
ptr = DtoGEP1(getI8Type(), ptr, off);
|
||||||
ptr = DtoGEP1(llvm::Type::getInt8Ty(gIR->context()), ptr, off);
|
|
||||||
ty = DtoType(vd->type);
|
ty = DtoType(vd->type);
|
||||||
} else {
|
} else {
|
||||||
if (ad->structsize == 0) { // can happen for extern(C) structs
|
if (ad->structsize == 0) { // can happen for extern(C) structs
|
||||||
|
@ -1894,15 +1873,11 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
|
||||||
} else {
|
} else {
|
||||||
st = irTypeAggr->getLLType();
|
st = irTypeAggr->getLLType();
|
||||||
}
|
}
|
||||||
ptr = DtoBitCast(ptr, st->getPointerTo());
|
|
||||||
ptr = DtoGEP(st, ptr, 0, off);
|
ptr = DtoGEP(st, ptr, 0, off);
|
||||||
ty = isaStruct(st)->getElementType(off);
|
ty = isaStruct(st)->getElementType(off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast the (possibly void*) pointer to the canonical variable type.
|
|
||||||
ptr = DtoBitCast(ptr, DtoPtrToType(vd->type));
|
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "Pointer: " << *ptr << '\n';
|
IF_LOG Logger::cout() << "Pointer: " << *ptr << '\n';
|
||||||
if (auto p = isaPointer(ty)) {
|
if (auto p = isaPointer(ty)) {
|
||||||
if (p->getAddressSpace())
|
if (p->getAddressSpace())
|
||||||
|
|
|
@ -160,30 +160,25 @@ llvm::Function *buildOrderIndependentModuleCtor(Module *m) {
|
||||||
|
|
||||||
/// Builds the (constant) data content for the importedModules[] array.
|
/// Builds the (constant) data content for the importedModules[] array.
|
||||||
llvm::Constant *buildImportedModules(Module *m, size_t &count) {
|
llvm::Constant *buildImportedModules(Module *m, size_t &count) {
|
||||||
const auto moduleInfoPtrTy = DtoPtrToType(getModuleInfoType());
|
|
||||||
|
|
||||||
std::vector<LLConstant *> importInits;
|
std::vector<LLConstant *> importInits;
|
||||||
for (auto mod : m->aimports) {
|
for (auto mod : m->aimports) {
|
||||||
if (!mod->needModuleInfo() || mod == m) {
|
if (!mod->needModuleInfo() || mod == m) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
importInits.push_back(
|
importInits.push_back(getIrModule(mod)->moduleInfoSymbol());
|
||||||
DtoBitCast(getIrModule(mod)->moduleInfoSymbol(), moduleInfoPtrTy));
|
|
||||||
}
|
}
|
||||||
count = importInits.size();
|
count = importInits.size();
|
||||||
|
|
||||||
if (importInits.empty())
|
if (importInits.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto type = llvm::ArrayType::get(moduleInfoPtrTy, importInits.size());
|
const auto type = llvm::ArrayType::get(getVoidPtrType(), importInits.size());
|
||||||
return LLConstantArray::get(type, importInits);
|
return LLConstantArray::get(type, importInits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the (constant) data content for the localClasses[] array.
|
/// Builds the (constant) data content for the localClasses[] array.
|
||||||
llvm::Constant *buildLocalClasses(Module *m, size_t &count) {
|
llvm::Constant *buildLocalClasses(Module *m, size_t &count) {
|
||||||
const auto classinfoTy = DtoType(getClassInfoType());
|
|
||||||
|
|
||||||
ClassDeclarations aclasses;
|
ClassDeclarations aclasses;
|
||||||
getLocalClasses(m, aclasses);
|
getLocalClasses(m, aclasses);
|
||||||
|
|
||||||
|
@ -205,15 +200,14 @@ llvm::Constant *buildLocalClasses(Module *m, size_t &count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::println("class: %s", cd->toPrettyChars());
|
IF_LOG Logger::println("class: %s", cd->toPrettyChars());
|
||||||
classInfoRefs.push_back(
|
classInfoRefs.push_back(getIrAggr(cd)->getClassInfoSymbol());
|
||||||
DtoBitCast(getIrAggr(cd)->getClassInfoSymbol(), classinfoTy));
|
|
||||||
}
|
}
|
||||||
count = classInfoRefs.size();
|
count = classInfoRefs.size();
|
||||||
|
|
||||||
if (classInfoRefs.empty())
|
if (classInfoRefs.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto type = llvm::ArrayType::get(classinfoTy, classInfoRefs.size());
|
const auto type = llvm::ArrayType::get(getVoidPtrType(), classInfoRefs.size());
|
||||||
return LLConstantArray::get(type, classInfoRefs);
|
return LLConstantArray::get(type, classInfoRefs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,13 +151,12 @@ LLFunction *build_module_reference_and_ctor(const char *moduleMangle,
|
||||||
// make sure _Dmodule_ref is declared
|
// make sure _Dmodule_ref is declared
|
||||||
const auto mrefIRMangle = getIRMangledVarName("_Dmodule_ref", LINK::c);
|
const auto mrefIRMangle = getIRMangledVarName("_Dmodule_ref", LINK::c);
|
||||||
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
|
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
|
||||||
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
|
LLType *modulerefPtrTy = getVoidPtrType();
|
||||||
if (!mref) {
|
if (!mref) {
|
||||||
mref =
|
mref =
|
||||||
declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false,
|
declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false,
|
||||||
false, global.params.dllimport != DLLImport::none);
|
false, global.params.dllimport != DLLImport::none);
|
||||||
}
|
}
|
||||||
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
|
|
||||||
|
|
||||||
// make the function insert this moduleinfo as the beginning of the
|
// make the function insert this moduleinfo as the beginning of the
|
||||||
// _Dmodule_ref linked list
|
// _Dmodule_ref linked list
|
||||||
|
@ -199,9 +198,9 @@ void emitModuleRefToSection(std::string moduleMangle,
|
||||||
|
|
||||||
const auto thismrefIRMangle =
|
const auto thismrefIRMangle =
|
||||||
getIRMangledModuleRefSymbolName(moduleMangle.c_str());
|
getIRMangledModuleRefSymbolName(moduleMangle.c_str());
|
||||||
auto thismref = defineGlobal(Loc(), gIR->module, thismrefIRMangle,
|
auto thismref =
|
||||||
DtoBitCast(thisModuleInfo, moduleInfoPtrTy),
|
defineGlobal(Loc(), gIR->module, thismrefIRMangle, thisModuleInfo,
|
||||||
LLGlobalValue::LinkOnceODRLinkage, false, false);
|
LLGlobalValue::LinkOnceODRLinkage, false, false);
|
||||||
thismref->setVisibility(LLGlobalValue::HiddenVisibility);
|
thismref->setVisibility(LLGlobalValue::HiddenVisibility);
|
||||||
thismref->setSection(sectionName);
|
thismref->setSection(sectionName);
|
||||||
gIR->usedArray.push_back(thismref);
|
gIR->usedArray.push_back(thismref);
|
||||||
|
|
|
@ -482,7 +482,7 @@ DValue *DtoInlineAsmExpr(const Loc &loc, FuncDeclaration *fd,
|
||||||
auto lvalue = sretPointer;
|
auto lvalue = sretPointer;
|
||||||
if (!lvalue)
|
if (!lvalue)
|
||||||
lvalue = DtoAlloca(returnType, ".__asm_tuple_ret");
|
lvalue = DtoAlloca(returnType, ".__asm_tuple_ret");
|
||||||
DtoStore(rv, DtoBitCast(lvalue, getPtrToType(irReturnType)));
|
DtoStore(rv, lvalue);
|
||||||
return new DLValue(returnType, lvalue);
|
return new DLValue(returnType, lvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,9 +138,8 @@ DValue *DtoNestedVariable(const Loc &loc, Type *astype, VarDeclaration *vd,
|
||||||
// Extract variable from nested context
|
// Extract variable from nested context
|
||||||
|
|
||||||
assert(irfunc->frameType);
|
assert(irfunc->frameType);
|
||||||
const auto pframeType = LLPointerType::getUnqual(irfunc->frameType);
|
|
||||||
IF_LOG { Logger::cout() << "casting to: " << *irfunc->frameType << '\n'; }
|
IF_LOG { Logger::cout() << "casting to: " << *irfunc->frameType << '\n'; }
|
||||||
LLValue *val = DtoBitCast(ctx, pframeType);
|
LLValue *val = ctx;
|
||||||
llvm::StructType *currFrame = irfunc->frameType;
|
llvm::StructType *currFrame = irfunc->frameType;
|
||||||
// Make the DWARF variable address relative to the context pointer (ctx);
|
// Make the DWARF variable address relative to the context pointer (ctx);
|
||||||
// register all ops (offsetting, dereferencing) required to get there in the
|
// register all ops (offsetting, dereferencing) required to get there in the
|
||||||
|
@ -228,7 +227,7 @@ void DtoResolveNestedContext(const Loc &loc, AggregateDeclaration *decl,
|
||||||
unsigned idx = getVthisIdx(decl);
|
unsigned idx = getVthisIdx(decl);
|
||||||
llvm::StructType *st = getIrAggr(decl)->getLLStructType();
|
llvm::StructType *st = getIrAggr(decl)->getLLStructType();
|
||||||
LLValue *gep = DtoGEP(st, value, 0, idx, ".vthis");
|
LLValue *gep = DtoGEP(st, value, 0, idx, ".vthis");
|
||||||
DtoStore(DtoBitCast(nest, st->getElementType(idx)), gep);
|
DtoStore(nest, gep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +342,6 @@ LLValue *DtoNestedContext(const Loc &loc, Dsymbol *sym) {
|
||||||
"Calling sibling function or directly nested function");
|
"Calling sibling function or directly nested function");
|
||||||
} else {
|
} else {
|
||||||
llvm::StructType *type = getIrFunc(ctxfd)->frameType;
|
llvm::StructType *type = getIrFunc(ctxfd)->frameType;
|
||||||
val = DtoBitCast(val, LLPointerType::getUnqual(type));
|
|
||||||
val = DtoGEP(type, val, 0, neededDepth);
|
val = DtoGEP(type, val, 0, neededDepth);
|
||||||
val = DtoAlignedLoad(type->getElementType(neededDepth),
|
val = DtoAlignedLoad(type->getElementType(neededDepth),
|
||||||
val, (std::string(".frame.") + frameToPass->toChars()).c_str());
|
val, (std::string(".frame.") + frameToPass->toChars()).c_str());
|
||||||
|
@ -503,7 +501,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
||||||
LLValue *mem =
|
LLValue *mem =
|
||||||
gIR->CreateCallOrInvoke(fn, DtoConstSize_t(size), ".gc_frame");
|
gIR->CreateCallOrInvoke(fn, DtoConstSize_t(size), ".gc_frame");
|
||||||
if (frameAlignment <= 16) {
|
if (frameAlignment <= 16) {
|
||||||
frame = DtoBitCast(mem, frameType->getPointerTo(), ".frame");
|
frame = mem;
|
||||||
} else {
|
} else {
|
||||||
const uint64_t mask = frameAlignment - 1;
|
const uint64_t mask = frameAlignment - 1;
|
||||||
mem = gIR->ir->CreatePtrToInt(mem, DtoSize_t());
|
mem = gIR->ir->CreatePtrToInt(mem, DtoSize_t());
|
||||||
|
@ -529,14 +527,11 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
||||||
src = indexVThis(ad, thisptr);
|
src = indexVThis(ad, thisptr);
|
||||||
}
|
}
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
src = DtoBitCast(src, getVoidPtrType());
|
DtoMemCpy(frame, src, DtoConstSize_t((depth - 1) * target.ptrsize),
|
||||||
LLValue *dst = DtoBitCast(frame, getVoidPtrType());
|
|
||||||
DtoMemCpy(dst, src, DtoConstSize_t((depth - 1) * target.ptrsize),
|
|
||||||
getABITypeAlign(getVoidPtrType()));
|
getABITypeAlign(getVoidPtrType()));
|
||||||
}
|
}
|
||||||
// Copy nestArg into framelist; the outer frame is not in the list of
|
// Copy nestArg into framelist; the outer frame is not in the list of
|
||||||
// pointers
|
// pointers
|
||||||
src = DtoBitCast(src, frameType->getContainedType(depth - 1));
|
|
||||||
LLValue *gep = DtoGEP(frameType, frame, 0, depth - 1);
|
LLValue *gep = DtoGEP(frameType, frame, 0, depth - 1);
|
||||||
DtoAlignedStore(src, gep);
|
DtoAlignedStore(src, gep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ LLGlobalVariable *ObjCState::getMethVarRef(const ObjcSelector &sel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCState::retain(LLConstant *sym) {
|
void ObjCState::retain(LLConstant *sym) {
|
||||||
retainedSymbols.push_back(DtoBitCast(sym, getVoidPtrType()));
|
retainedSymbols.push_back(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCState::finalize() {
|
void ObjCState::finalize() {
|
||||||
|
|
|
@ -71,7 +71,7 @@ void RTTIBuilder::push_null_void_array() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_void_array(uint64_t dim, llvm::Constant *ptr) {
|
void RTTIBuilder::push_void_array(uint64_t dim, llvm::Constant *ptr) {
|
||||||
push(DtoConstSlice(DtoConstSize_t(dim), DtoBitCast(ptr, getVoidPtrType())));
|
push(DtoConstSlice(DtoConstSize_t(dim), ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_void_array(llvm::Constant *CI, Type *valtype,
|
void RTTIBuilder::push_void_array(llvm::Constant *CI, Type *valtype,
|
||||||
|
@ -113,7 +113,7 @@ void RTTIBuilder::push_array(llvm::Constant *CI, uint64_t dim, Type *valtype,
|
||||||
setLinkage(lwc, G);
|
setLinkage(lwc, G);
|
||||||
G->setAlignment(llvm::MaybeAlign(DtoAlignment(valtype)));
|
G->setAlignment(llvm::MaybeAlign(DtoAlignment(valtype)));
|
||||||
|
|
||||||
push_array(dim, DtoBitCast(G, DtoType(pointerTo(valtype))));
|
push_array(dim, G);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_array(uint64_t dim, llvm::Constant *ptr) {
|
void RTTIBuilder::push_array(uint64_t dim, llvm::Constant *ptr) {
|
||||||
|
@ -128,15 +128,10 @@ void RTTIBuilder::push_size_as_vp(uint64_t s) {
|
||||||
push(llvm::ConstantExpr::getIntToPtr(DtoConstSize_t(s), getVoidPtrType()));
|
push(llvm::ConstantExpr::getIntToPtr(DtoConstSize_t(s), getVoidPtrType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_funcptr(FuncDeclaration *fd, Type *castto) {
|
void RTTIBuilder::push_funcptr(FuncDeclaration *fd) {
|
||||||
if (fd) {
|
if (fd) {
|
||||||
LLConstant *F = DtoCallee(fd);
|
LLConstant *F = DtoCallee(fd);
|
||||||
if (castto) {
|
|
||||||
F = DtoBitCast(F, DtoType(castto));
|
|
||||||
}
|
|
||||||
push(F);
|
push(F);
|
||||||
} else if (castto) {
|
|
||||||
push_null(castto);
|
|
||||||
} else {
|
} else {
|
||||||
push_null_vp();
|
push_null_vp();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
void push_typeinfo(Type *t);
|
void push_typeinfo(Type *t);
|
||||||
|
|
||||||
/// pushes the function pointer or a null void* if it cannot.
|
/// pushes the function pointer or a null void* if it cannot.
|
||||||
void push_funcptr(FuncDeclaration *fd, Type *castto = nullptr);
|
void push_funcptr(FuncDeclaration *fd);
|
||||||
|
|
||||||
/// pushes the array slice given.
|
/// pushes the array slice given.
|
||||||
void push_array(uint64_t dim, llvm::Constant *ptr);
|
void push_array(uint64_t dim, llvm::Constant *ptr);
|
||||||
|
|
|
@ -886,7 +886,7 @@ static void emitInstrumentationFn(const char *name) {
|
||||||
// Grab the address of the calling function
|
// Grab the address of the calling function
|
||||||
auto *caller =
|
auto *caller =
|
||||||
gIR->ir->CreateCall(GET_INTRINSIC_DECL(returnaddress), DtoConstInt(0));
|
gIR->ir->CreateCall(GET_INTRINSIC_DECL(returnaddress), DtoConstInt(0));
|
||||||
auto callee = DtoBitCast(gIR->topfunc(), getVoidPtrType());
|
auto callee = gIR->topfunc();
|
||||||
|
|
||||||
gIR->ir->CreateCall(fn, {callee, caller});
|
gIR->ir->CreateCall(fn, {callee, caller});
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,6 @@ LLValue *DtoUnpaddedStruct(Type *dty, LLValue *v) {
|
||||||
fieldval = DtoUnpaddedStruct(fields[i]->type, fieldptr);
|
fieldval = DtoUnpaddedStruct(fields[i]->type, fieldptr);
|
||||||
} else {
|
} else {
|
||||||
assert(!fields[i]->isBitFieldDeclaration());
|
assert(!fields[i]->isBitFieldDeclaration());
|
||||||
fieldptr = DtoBitCast(fieldptr, DtoPtrToType(fields[i]->type));
|
|
||||||
fieldval = DtoLoad(DtoType(fields[i]->type), fieldptr);
|
fieldval = DtoLoad(DtoType(fields[i]->type), fieldptr);
|
||||||
}
|
}
|
||||||
newval = DtoInsertValue(newval, fieldval, i);
|
newval = DtoInsertValue(newval, fieldval, i);
|
||||||
|
@ -174,7 +173,6 @@ void DtoPaddedStruct(Type *dty, LLValue *v, LLValue *lval) {
|
||||||
DtoPaddedStruct(fields[i]->type, fieldval, fieldptr);
|
DtoPaddedStruct(fields[i]->type, fieldval, fieldptr);
|
||||||
} else {
|
} else {
|
||||||
assert(!fields[i]->isBitFieldDeclaration());
|
assert(!fields[i]->isBitFieldDeclaration());
|
||||||
fieldptr = DtoBitCast(fieldptr, DtoPtrToType(fields[i]->type));
|
|
||||||
DtoStoreZextI8(fieldval, fieldptr);
|
DtoStoreZextI8(fieldval, fieldptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,9 +411,8 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
val = DtoRVal(dval);
|
val = DtoRVal(dval);
|
||||||
} else if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
} else if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
||||||
LLType *atype = getAtomicType(pointeeType);
|
LLType *atype = getAtomicType(pointeeType);
|
||||||
ptr = DtoBitCast(ptr, intPtrType);
|
|
||||||
auto lval = makeLValue(exp1->loc, dval);
|
auto lval = makeLValue(exp1->loc, dval);
|
||||||
val = DtoLoad(atype, DtoBitCast(lval, intPtrType));
|
val = DtoLoad(atype, lval);
|
||||||
} else {
|
} else {
|
||||||
error(e->loc,
|
error(e->loc,
|
||||||
"atomic store only supports types of size 1/2/4/8/16 bytes, not `%s`",
|
"atomic store only supports types of size 1/2/4/8/16 bytes, not `%s`",
|
||||||
|
@ -446,7 +445,6 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
|
|
||||||
if (!pointeeType->isIntegerTy()) {
|
if (!pointeeType->isIntegerTy()) {
|
||||||
if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
||||||
ptr = DtoBitCast(ptr, intPtrType);
|
|
||||||
loadedType = getAtomicType(pointeeType);
|
loadedType = getAtomicType(pointeeType);
|
||||||
} else {
|
} else {
|
||||||
error(e->loc,
|
error(e->loc,
|
||||||
|
@ -503,11 +501,10 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
val = DtoRVal(dval);
|
val = DtoRVal(dval);
|
||||||
} else if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
} else if (auto intPtrType = getPtrToAtomicType(pointeeType)) {
|
||||||
LLType *atype = getAtomicType(pointeeType);
|
LLType *atype = getAtomicType(pointeeType);
|
||||||
ptr = DtoBitCast(ptr, intPtrType);
|
|
||||||
auto cmpLVal = makeLValue(exp2->loc, dcmp);
|
auto cmpLVal = makeLValue(exp2->loc, dcmp);
|
||||||
cmp = DtoLoad(atype, DtoBitCast(cmpLVal, intPtrType));
|
cmp = DtoLoad(atype, cmpLVal);
|
||||||
auto lval = makeLValue(exp3->loc, dval);
|
auto lval = makeLValue(exp3->loc, dval);
|
||||||
val = DtoLoad(atype, DtoBitCast(lval, intPtrType));
|
val = DtoLoad(atype, lval);
|
||||||
} else {
|
} else {
|
||||||
error(e->loc,
|
error(e->loc,
|
||||||
"`cmpxchg` only supports types of size 1/2/4/8/16 bytes, not `%s`",
|
"`cmpxchg` only supports types of size 1/2/4/8/16 bytes, not `%s`",
|
||||||
|
@ -526,8 +523,7 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
// because of i1)
|
// because of i1)
|
||||||
auto mem = DtoAlloca(e->type);
|
auto mem = DtoAlloca(e->type);
|
||||||
llvm::Type* memty = DtoType(e->type);
|
llvm::Type* memty = DtoType(e->type);
|
||||||
DtoStore(p->ir->CreateExtractValue(ret, 0),
|
DtoStore(p->ir->CreateExtractValue(ret, 0), DtoGEP(memty, mem, 0u, 0));
|
||||||
DtoBitCast(DtoGEP(memty, mem, 0u, 0), ptr->getType()));
|
|
||||||
DtoStoreZextI8(p->ir->CreateExtractValue(ret, 1), DtoGEP(memty, mem, 0, 1));
|
DtoStoreZextI8(p->ir->CreateExtractValue(ret, 1), DtoGEP(memty, mem, 0, 1));
|
||||||
|
|
||||||
result = new DLValue(e->type, mem);
|
result = new DLValue(e->type, mem);
|
||||||
|
@ -591,8 +587,9 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e,
|
||||||
unsigned bitmask = DtoSize_t()->getBitWidth() - 1;
|
unsigned bitmask = DtoSize_t()->getBitWidth() - 1;
|
||||||
assert(bitmask == 31 || bitmask == 63);
|
assert(bitmask == 31 || bitmask == 63);
|
||||||
// auto q = cast(size_t*)ptr + (bitnum >> (64bit ? 6 : 5));
|
// auto q = cast(size_t*)ptr + (bitnum >> (64bit ? 6 : 5));
|
||||||
LLValue *q = DtoBitCast(ptr, DtoSize_t()->getPointerTo());
|
LLValue *q =
|
||||||
q = DtoGEP1(DtoSize_t(), q, p->ir->CreateLShr(bitnum, bitmask == 63 ? 6 : 5), "bitop.q");
|
DtoGEP1(DtoSize_t(), ptr,
|
||||||
|
p->ir->CreateLShr(bitnum, bitmask == 63 ? 6 : 5), "bitop.q");
|
||||||
|
|
||||||
// auto mask = 1 << (bitnum & bitmask);
|
// auto mask = 1 << (bitnum & bitmask);
|
||||||
LLValue *mask =
|
LLValue *mask =
|
||||||
|
@ -764,12 +761,10 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LLValue *contextptr = DtoBitCast(thisptrLval, getVoidPtrType());
|
args.push_back(thisptrLval);
|
||||||
args.push_back(contextptr);
|
|
||||||
} else if (thiscall && dfnval && dfnval->vthis) {
|
} else if (thiscall && dfnval && dfnval->vthis) {
|
||||||
// ... or a normal 'this' argument
|
// ... or a normal 'this' argument
|
||||||
LLValue *thisarg = DtoBitCast(dfnval->vthis, llArgType);
|
args.push_back(dfnval->vthis);
|
||||||
args.push_back(thisarg);
|
|
||||||
} else if (isDelegateCall) {
|
} else if (isDelegateCall) {
|
||||||
// ... or a delegate context arg
|
// ... or a delegate context arg
|
||||||
LLValue *ctxarg;
|
LLValue *ctxarg;
|
||||||
|
@ -778,13 +773,11 @@ private:
|
||||||
} else {
|
} else {
|
||||||
ctxarg = gIR->ir->CreateExtractValue(DtoRVal(fnval), 0, ".ptr");
|
ctxarg = gIR->ir->CreateExtractValue(DtoRVal(fnval), 0, ".ptr");
|
||||||
}
|
}
|
||||||
ctxarg = DtoBitCast(ctxarg, llArgType);
|
|
||||||
args.push_back(ctxarg);
|
args.push_back(ctxarg);
|
||||||
} else if (nestedcall) {
|
} else if (nestedcall) {
|
||||||
// ... or a nested function context arg
|
// ... or a nested function context arg
|
||||||
if (dfnval) {
|
if (dfnval) {
|
||||||
LLValue *contextptr = DtoNestedContext(loc, dfnval->func);
|
LLValue *contextptr = DtoNestedContext(loc, dfnval->func);
|
||||||
contextptr = DtoBitCast(contextptr, getVoidPtrType());
|
|
||||||
args.push_back(contextptr);
|
args.push_back(contextptr);
|
||||||
} else {
|
} else {
|
||||||
args.push_back(llvm::UndefValue::get(getVoidPtrType()));
|
args.push_back(llvm::UndefValue::get(getVoidPtrType()));
|
||||||
|
@ -806,8 +799,7 @@ private:
|
||||||
const auto selector = dfnval->func->objc.selector;
|
const auto selector = dfnval->func->objc.selector;
|
||||||
assert(selector);
|
assert(selector);
|
||||||
LLGlobalVariable *selptr = gIR->objc.getMethVarRef(*selector);
|
LLGlobalVariable *selptr = gIR->objc.getMethVarRef(*selector);
|
||||||
args.push_back(DtoBitCast(DtoLoad(selptr->getValueType(), selptr),
|
args.push_back(DtoLoad(selptr->getValueType(), selptr));
|
||||||
getVoidPtrType()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,9 +911,7 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval,
|
||||||
if (irFty.arg_objcSelector) {
|
if (irFty.arg_objcSelector) {
|
||||||
// Use runtime msgSend function bitcasted as original call
|
// Use runtime msgSend function bitcasted as original call
|
||||||
const char *msgSend = gABI->objcMsgSendFunc(resulttype, irFty);
|
const char *msgSend = gABI->objcMsgSendFunc(resulttype, irFty);
|
||||||
LLType *t = callable->getType();
|
|
||||||
callable = getRuntimeFunction(loc, gIR->module, msgSend);
|
callable = getRuntimeFunction(loc, gIR->module, msgSend);
|
||||||
callable = DtoBitCast(callable, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the function
|
// call the function
|
||||||
|
@ -971,9 +961,7 @@ DValue *DtoCallFunction(const Loc &loc, Type *resulttype, DValue *fnval,
|
||||||
|
|
||||||
case TY::Tsarray:
|
case TY::Tsarray:
|
||||||
if (nextbase->ty == TY::Tvector && !tf->isref()) {
|
if (nextbase->ty == TY::Tvector && !tf->isref()) {
|
||||||
if (retValIsLVal) {
|
if (!retValIsLVal) {
|
||||||
retllval = DtoBitCast(retllval, DtoType(pointerTo(rbase)));
|
|
||||||
} else {
|
|
||||||
// static arrays need to be dumped to memory; use vector alignment
|
// static arrays need to be dumped to memory; use vector alignment
|
||||||
retllval =
|
retllval =
|
||||||
DtoAllocaDump(retllval, DtoType(rbase), DtoAlignment(nextbase),
|
DtoAllocaDump(retllval, DtoType(rbase), DtoAlignment(nextbase),
|
||||||
|
|
|
@ -80,7 +80,6 @@ public:
|
||||||
|
|
||||||
if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) {
|
if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) {
|
||||||
result = DtoTypeInfoOf(e->loc, ti->tinfo, /*base=*/false);
|
result = DtoTypeInfoOf(e->loc, ti->tinfo, /*base=*/false);
|
||||||
result = DtoBitCast(result, DtoType(e->type));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +178,7 @@ public:
|
||||||
LLConstant *arrptr = DtoGEP(gvar->getValueType(), gvar, 0u, 0u);
|
LLConstant *arrptr = DtoGEP(gvar->getValueType(), gvar, 0u, 0u);
|
||||||
|
|
||||||
if (t->ty == TY::Tpointer) {
|
if (t->ty == TY::Tpointer) {
|
||||||
result = DtoBitCast(arrptr, DtoType(t));
|
result = arrptr;
|
||||||
} else if (t->ty == TY::Tarray) {
|
} else if (t->ty == TY::Tarray) {
|
||||||
LLConstant *clen = LLConstantInt::get(DtoSize_t(), e->len, false);
|
LLConstant *clen = LLConstantInt::get(DtoSize_t(), e->len, false);
|
||||||
result = DtoConstSlice(clen, arrptr, e->type);
|
result = DtoConstSlice(clen, arrptr, e->type);
|
||||||
|
@ -210,7 +209,6 @@ public:
|
||||||
llResult = llvm::ConstantExpr::getGetElementPtr(DtoMemType(pointeeType),
|
llResult = llvm::ConstantExpr::getGetElementPtr(DtoMemType(pointeeType),
|
||||||
llBase, llOffset);
|
llBase, llOffset);
|
||||||
} else { // need to cast base to i8*
|
} else { // need to cast base to i8*
|
||||||
llBase = DtoBitCast(llBase, getVoidPtrType());
|
|
||||||
LLConstant *llOffset = DtoConstSize_t(byteOffset);
|
LLConstant *llOffset = DtoConstSize_t(byteOffset);
|
||||||
if (negateOffset)
|
if (negateOffset)
|
||||||
llOffset = llvm::ConstantExpr::getNeg(llOffset);
|
llOffset = llvm::ConstantExpr::getNeg(llOffset);
|
||||||
|
@ -218,7 +216,7 @@ public:
|
||||||
llvm::ConstantExpr::getGetElementPtr(getI8Type(), llBase, llOffset);
|
llvm::ConstantExpr::getGetElementPtr(getI8Type(), llBase, llOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtoBitCast(llResult, DtoType(e->type));
|
return llResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(AddExp *e) override {
|
void visit(AddExp *e) override {
|
||||||
|
@ -323,7 +321,7 @@ public:
|
||||||
if (type->ty == TY::Tarray || type->ty == TY::Tdelegate) {
|
if (type->ty == TY::Tarray || type->ty == TY::Tdelegate) {
|
||||||
value = DtoGEP(irg->getType(), value, 0u, 1u);
|
value = DtoGEP(irg->getType(), value, 0u, 1u);
|
||||||
}
|
}
|
||||||
result = DtoBitCast(value, DtoType(tb));
|
result = value;
|
||||||
} else if (tb->ty == TY::Tclass && e->e1->type->ty == TY::Tclass &&
|
} else if (tb->ty == TY::Tclass && e->e1->type->ty == TY::Tclass &&
|
||||||
e->e1->op == EXP::classReference) {
|
e->e1->op == EXP::classReference) {
|
||||||
auto cd = static_cast<ClassReferenceExp *>(e->e1)->originalClass();
|
auto cd = static_cast<ClassReferenceExp *>(e->e1)->originalClass();
|
||||||
|
@ -341,7 +339,7 @@ public:
|
||||||
// offset pointer
|
// offset pointer
|
||||||
instance = DtoGEP(DtoType(e->e1->type), instance, 0, i_index);
|
instance = DtoGEP(DtoType(e->e1->type), instance, 0, i_index);
|
||||||
}
|
}
|
||||||
result = DtoBitCast(instance, DtoType(tb));
|
result = instance;
|
||||||
} else {
|
} else {
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
}
|
}
|
||||||
|
@ -384,14 +382,10 @@ public:
|
||||||
} else {
|
} else {
|
||||||
// Offset isn't a multiple of base type size, just cast to i8* and
|
// Offset isn't a multiple of base type size, just cast to i8* and
|
||||||
// apply the byte offset.
|
// apply the byte offset.
|
||||||
auto i8 = LLType::getInt8Ty(gIR->context());
|
|
||||||
result = llvm::ConstantExpr::getGetElementPtr(
|
result = llvm::ConstantExpr::getGetElementPtr(
|
||||||
i8, DtoBitCast(base, i8->getPointerTo()),
|
getI8Type(), base, DtoConstSize_t(e->offset));
|
||||||
DtoConstSize_t(e->offset));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = DtoBitCast(result, DtoType(e->type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -405,8 +399,7 @@ public:
|
||||||
|
|
||||||
// address of global variable
|
// address of global variable
|
||||||
if (auto vexp = e->e1->isVarExp()) {
|
if (auto vexp = e->e1->isVarExp()) {
|
||||||
LLConstant *c = DtoConstSymbolAddress(e->loc, vexp->var);
|
result = DtoConstSymbolAddress(e->loc, vexp->var);
|
||||||
result = c ? DtoBitCast(c, DtoType(e->type)) : nullptr;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,13 +421,11 @@ public:
|
||||||
// gep
|
// gep
|
||||||
LLConstant *idxs[2] = {DtoConstSize_t(0), index};
|
LLConstant *idxs[2] = {DtoConstSize_t(0), index};
|
||||||
LLConstant *val = isaConstant(getIrGlobal(vd)->value);
|
LLConstant *val = isaConstant(getIrGlobal(vd)->value);
|
||||||
val = DtoBitCast(val, DtoType(pointerTo(vd->type)));
|
|
||||||
LLConstant *gep = llvm::ConstantExpr::getGetElementPtr(
|
LLConstant *gep = llvm::ConstantExpr::getGetElementPtr(
|
||||||
DtoType(vd->type), val, idxs, true);
|
DtoType(vd->type), val, idxs, true);
|
||||||
|
|
||||||
// bitcast to requested type
|
|
||||||
assert(e->type->toBasetype()->ty == TY::Tpointer);
|
assert(e->type->toBasetype()->ty == TY::Tpointer);
|
||||||
result = DtoBitCast(gep, DtoType(e->type));
|
result = gep;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,18 +532,16 @@ public:
|
||||||
llvm::GlobalValue::InternalLinkage, initval, ".dynarrayStorage");
|
llvm::GlobalValue::InternalLinkage, initval, ".dynarrayStorage");
|
||||||
gvar->setUnnamedAddr(canBeConst ? llvm::GlobalValue::UnnamedAddr::Global
|
gvar->setUnnamedAddr(canBeConst ? llvm::GlobalValue::UnnamedAddr::Global
|
||||||
: llvm::GlobalValue::UnnamedAddr::None);
|
: llvm::GlobalValue::UnnamedAddr::None);
|
||||||
llvm::Constant *store = DtoBitCast(gvar, getPtrToType(arrtype));
|
|
||||||
|
|
||||||
if (bt->ty == TY::Tpointer) {
|
if (bt->ty == TY::Tpointer) {
|
||||||
// we need to return pointer to the static array.
|
// we need to return pointer to the static array.
|
||||||
result = store;
|
result = gvar;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a constant dynamic array reference with the .ptr field pointing
|
// build a constant dynamic array reference with the .ptr field pointing
|
||||||
// into store
|
// into store
|
||||||
LLConstant *globalstorePtr = DtoGEP(arrtype, store, 0u, 0u);
|
result = DtoConstSlice(DtoConstSize_t(e->elements->length), gvar);
|
||||||
result = DtoConstSlice(DtoConstSize_t(e->elements->length), globalstorePtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -673,7 +662,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(e->type->ty == TY::Tclass || e->type->ty == TY::Tenum);
|
assert(e->type->ty == TY::Tclass || e->type->ty == TY::Tenum);
|
||||||
result = DtoBitCast(result, DtoType(e->type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -729,7 +717,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
result = DtoTypeInfoOf(e->loc, t, /*base=*/false);
|
result = DtoTypeInfoOf(e->loc, t, /*base=*/false);
|
||||||
result = DtoBitCast(result, DtoType(e->type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
109
gen/toir.cpp
109
gen/toir.cpp
|
@ -67,7 +67,6 @@ bool walkPostorder(Expression *e, StoppableVisitor *v);
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static LLValue *write_zeroes(LLValue *mem, unsigned start, unsigned end) {
|
static LLValue *write_zeroes(LLValue *mem, unsigned start, unsigned end) {
|
||||||
mem = DtoBitCast(mem, getVoidPtrType());
|
|
||||||
LLType *i8 = LLType::getInt8Ty(gIR->context());
|
LLType *i8 = LLType::getInt8Ty(gIR->context());
|
||||||
LLValue *gep = DtoGEP1(i8, mem, start, ".padding");
|
LLValue *gep = DtoGEP1(i8, mem, start, ".padding");
|
||||||
DtoMemSetZero(i8, gep, DtoConstSize_t(end - start));
|
DtoMemSetZero(i8, gep, DtoConstSize_t(end - start));
|
||||||
|
@ -166,8 +165,7 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "merged IR value: " << *val << '\n';
|
IF_LOG Logger::cout() << "merged IR value: " << *val << '\n';
|
||||||
gIR->ir->CreateAlignedStore(val, DtoBitCast(ptr, getPtrToType(intType)),
|
gIR->ir->CreateAlignedStore(val, ptr, llvm::MaybeAlign(1));
|
||||||
llvm::MaybeAlign(1));
|
|
||||||
offset += group.sizeInBytes;
|
offset += group.sizeInBytes;
|
||||||
|
|
||||||
i += group.bitFields.size() - 1; // skip the other bit fields of the group
|
i += group.bitFields.size() - 1; // skip the other bit fields of the group
|
||||||
|
@ -191,8 +189,7 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
|
||||||
assert(vd == sd->vthis);
|
assert(vd == sd->vthis);
|
||||||
IF_LOG Logger::println("initializing vthis");
|
IF_LOG Logger::println("initializing vthis");
|
||||||
LOG_SCOPE
|
LOG_SCOPE
|
||||||
DImValue val(vd->type,
|
DImValue val(vd->type, DtoNestedContext(loc, sd));
|
||||||
DtoBitCast(DtoNestedContext(loc, sd), DtoType(vd->type)));
|
|
||||||
DtoAssign(loc, field, &val, EXP::blit);
|
DtoAssign(loc, field, &val, EXP::blit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,9 +446,9 @@ public:
|
||||||
result = new DSliceValue(e->type, DtoConstSlice(clen, arrptr, dtype));
|
result = new DSliceValue(e->type, DtoConstSlice(clen, arrptr, dtype));
|
||||||
} else if (dtype->ty == TY::Tsarray) {
|
} else if (dtype->ty == TY::Tsarray) {
|
||||||
// array length matches string length with or without null terminator
|
// array length matches string length with or without null terminator
|
||||||
result = new DLValue(e->type, DtoBitCast(gvar, DtoPtrToType(dtype)));
|
result = new DLValue(e->type, gvar);
|
||||||
} else if (dtype->ty == TY::Tpointer) {
|
} else if (dtype->ty == TY::Tpointer) {
|
||||||
result = new DImValue(e->type, DtoBitCast(arrptr, DtoType(dtype)));
|
result = new DImValue(e->type, arrptr);
|
||||||
} else {
|
} else {
|
||||||
llvm_unreachable("Unknown type for StringExp.");
|
llvm_unreachable("Unknown type for StringExp.");
|
||||||
}
|
}
|
||||||
|
@ -799,9 +796,7 @@ public:
|
||||||
if (canEmitVTableUnchangedAssumption && !dfnval->vtable &&
|
if (canEmitVTableUnchangedAssumption && !dfnval->vtable &&
|
||||||
dfnval->vthis && dfnval->func->isVirtual()) {
|
dfnval->vthis && dfnval->func->isVirtual()) {
|
||||||
dfnval->vtable =
|
dfnval->vtable =
|
||||||
DtoLoad(getVoidPtrType(),
|
DtoLoad(getVoidPtrType(), dfnval->vthis, "saved_vtable");
|
||||||
DtoBitCast(dfnval->vthis, getVoidPtrType()->getPointerTo()),
|
|
||||||
"saved_vtable");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,9 +807,7 @@ public:
|
||||||
// Reload vtable ptr. It's the first element so instead of GEP+load we can
|
// Reload vtable ptr. It's the first element so instead of GEP+load we can
|
||||||
// do a void* load+bitcast (at this point in the code we don't have easy
|
// do a void* load+bitcast (at this point in the code we don't have easy
|
||||||
// access to the type of the class to do a GEP).
|
// access to the type of the class to do a GEP).
|
||||||
auto vtable = DtoLoad(
|
auto vtable = DtoLoad(dfnval->vtable->getType(), dfnval->vthis);
|
||||||
dfnval->vtable->getType(),
|
|
||||||
DtoBitCast(dfnval->vthis, dfnval->vtable->getType()->getPointerTo()));
|
|
||||||
auto cmp = p->ir->CreateICmpEQ(vtable, dfnval->vtable);
|
auto cmp = p->ir->CreateICmpEQ(vtable, dfnval->vtable);
|
||||||
p->ir->CreateCall(GET_INTRINSIC_DECL(assume), {cmp});
|
p->ir->CreateCall(GET_INTRINSIC_DECL(assume), {cmp});
|
||||||
}
|
}
|
||||||
|
@ -910,12 +903,11 @@ public:
|
||||||
if (!offsetValue) {
|
if (!offsetValue) {
|
||||||
// Offset isn't a multiple of base type size, just cast to i8* and
|
// Offset isn't a multiple of base type size, just cast to i8* and
|
||||||
// apply the byte offset.
|
// apply the byte offset.
|
||||||
auto castBase = DtoBitCast(baseValue, getVoidPtrType());
|
|
||||||
if (target.ptrsize == 8) {
|
if (target.ptrsize == 8) {
|
||||||
offsetValue = DtoGEP1i64(getI8Type(), castBase, e->offset);
|
offsetValue = DtoGEP1i64(getI8Type(), baseValue, e->offset);
|
||||||
} else {
|
} else {
|
||||||
offsetValue =
|
offsetValue =
|
||||||
DtoGEP1(getI8Type(), castBase, static_cast<unsigned>(e->offset));
|
DtoGEP1(getI8Type(), baseValue, static_cast<unsigned>(e->offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -945,7 +937,7 @@ public:
|
||||||
LLConstant *addr = toConstElem(e, p);
|
LLConstant *addr = toConstElem(e, p);
|
||||||
IF_LOG Logger::cout()
|
IF_LOG Logger::cout()
|
||||||
<< "returning address of struct literal global: " << addr << '\n';
|
<< "returning address of struct literal global: " << addr << '\n';
|
||||||
result = new DImValue(e->type, DtoBitCast(addr, DtoType(e->type)));
|
result = new DImValue(e->type, addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,7 +968,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "lval: " << *lval << '\n';
|
IF_LOG Logger::cout() << "lval: " << *lval << '\n';
|
||||||
result = new DImValue(e->type, DtoBitCast(lval, DtoType(e->type)));
|
result = new DImValue(e->type, lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1004,7 +996,7 @@ public:
|
||||||
// get the rvalue and return it as an lvalue
|
// get the rvalue and return it as an lvalue
|
||||||
LLValue *V = DtoRVal(e->e1);
|
LLValue *V = DtoRVal(e->e1);
|
||||||
|
|
||||||
result = new DLValue(e->type, DtoBitCast(V, DtoPtrToType(e->type)));
|
result = new DLValue(e->type, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static llvm::PointerType * getWithSamePointeeType(llvm::PointerType *p, unsigned addressSpace) {
|
static llvm::PointerType * getWithSamePointeeType(llvm::PointerType *p, unsigned addressSpace) {
|
||||||
|
@ -1065,11 +1057,9 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ptrty = DtoType(e->type);
|
ptrty = DtoType(e->type);
|
||||||
result = new DDcomputeLValue(e->type, i1ToI8(ptrty),
|
result = new DDcomputeLValue(e->type, i1ToI8(ptrty), DtoLVal(d));
|
||||||
DtoBitCast(DtoLVal(d), DtoPtrToType(e->type)));
|
|
||||||
} else {
|
} else {
|
||||||
LLValue *p = DtoBitCast(DtoLVal(ptr), DtoPtrToType(e->type));
|
result = new DLValue(e->type, DtoLVal(ptr));
|
||||||
result = new DLValue(e->type, p);
|
|
||||||
}
|
}
|
||||||
} else if (FuncDeclaration *fdecl = e->var->isFuncDeclaration()) {
|
} else if (FuncDeclaration *fdecl = e->var->isFuncDeclaration()) {
|
||||||
// This is a bit more convoluted than it would need to be, because it
|
// This is a bit more convoluted than it would need to be, because it
|
||||||
|
@ -1138,7 +1128,7 @@ public:
|
||||||
if (ident == Id::ensure || ident == Id::require) {
|
if (ident == Id::ensure || ident == Id::require) {
|
||||||
Logger::println("contract this exp");
|
Logger::println("contract this exp");
|
||||||
LLValue *v = p->func()->nestArg; // thisptr lvalue
|
LLValue *v = p->func()->nestArg; // thisptr lvalue
|
||||||
result = new DLValue(e->type, DtoBitCast(v, DtoPtrToType(e->type)));
|
result = new DLValue(e->type, v);
|
||||||
} else if (vd->toParent2() != p->func()->decl) {
|
} else if (vd->toParent2() != p->func()->decl) {
|
||||||
Logger::println("nested this exp");
|
Logger::println("nested this exp");
|
||||||
result =
|
result =
|
||||||
|
@ -1146,7 +1136,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
Logger::println("normal this exp");
|
Logger::println("normal this exp");
|
||||||
LLValue *v = p->func()->thisArg;
|
LLValue *v = p->func()->thisArg;
|
||||||
result = new DLValue(e->type, DtoBitCast(v, DtoPtrToType(e->type)));
|
result = new DLValue(e->type, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,7 +1180,7 @@ public:
|
||||||
IF_LOG Logger::println("e1type: %s", e1type->toChars());
|
IF_LOG Logger::println("e1type: %s", e1type->toChars());
|
||||||
llvm_unreachable("Unknown IndexExp target.");
|
llvm_unreachable("Unknown IndexExp target.");
|
||||||
}
|
}
|
||||||
result = new DLValue(e->type, DtoBitCast(arrptr, DtoPtrToType(e->type)));
|
result = new DLValue(e->type, arrptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1287,10 +1277,6 @@ public:
|
||||||
if (etype->ty == TY::Tsarray) {
|
if (etype->ty == TY::Tsarray) {
|
||||||
TypeSArray *tsa = static_cast<TypeSArray *>(etype);
|
TypeSArray *tsa = static_cast<TypeSArray *>(etype);
|
||||||
elen = DtoConstSize_t(tsa->dim->toUInteger());
|
elen = DtoConstSize_t(tsa->dim->toUInteger());
|
||||||
|
|
||||||
// in this case, we also need to make sure the pointer is cast to the
|
|
||||||
// innermost element type
|
|
||||||
eptr = DtoBitCast(eptr, DtoType(pointerTo(tsa->nextOf())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1298,14 +1284,13 @@ public:
|
||||||
// fixed-width slice to a static array.
|
// fixed-width slice to a static array.
|
||||||
Type *const ety = e->type->toBasetype();
|
Type *const ety = e->type->toBasetype();
|
||||||
if (ety->ty == TY::Tsarray) {
|
if (ety->ty == TY::Tsarray) {
|
||||||
result = new DLValue(e->type, DtoBitCast(eptr, DtoPtrToType(e->type)));
|
result = new DLValue(e->type, eptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ety->ty == TY::Tarray);
|
assert(ety->ty == TY::Tarray);
|
||||||
if (!elen)
|
if (!elen)
|
||||||
elen = DtoArrayLen(v);
|
elen = DtoArrayLen(v);
|
||||||
eptr = DtoBitCast(eptr, DtoPtrToType(ety->nextOf()));
|
|
||||||
|
|
||||||
result = new DSliceValue(e->type, elen, eptr);
|
result = new DSliceValue(e->type, elen, eptr);
|
||||||
}
|
}
|
||||||
|
@ -1623,8 +1608,7 @@ public:
|
||||||
else if (auto taa = ntype->isTypeAArray()) {
|
else if (auto taa = ntype->isTypeAArray()) {
|
||||||
LLFunction *func = getRuntimeFunction(e->loc, gIR->module, "_aaNew");
|
LLFunction *func = getRuntimeFunction(e->loc, gIR->module, "_aaNew");
|
||||||
LLValue *aaTypeInfo =
|
LLValue *aaTypeInfo =
|
||||||
DtoBitCast(DtoTypeInfoOf(e->loc, stripModifiers(taa), /*base=*/false),
|
DtoTypeInfoOf(e->loc, stripModifiers(taa), /*base=*/false);
|
||||||
DtoType(getAssociativeArrayTypeInfoType()));
|
|
||||||
LLValue *aa = gIR->CreateCallOrInvoke(func, aaTypeInfo, "aa");
|
LLValue *aa = gIR->CreateCallOrInvoke(func, aaTypeInfo, "aa");
|
||||||
result = new DImValue(e->type, aa);
|
result = new DImValue(e->type, aa);
|
||||||
}
|
}
|
||||||
|
@ -1821,8 +1805,7 @@ public:
|
||||||
getIRMangledFuncName("_D9invariant12_d_invariantFC6ObjectZv", LINK::d);
|
getIRMangledFuncName("_D9invariant12_d_invariantFC6ObjectZv", LINK::d);
|
||||||
const auto fn = getRuntimeFunction(e->loc, gIR->module, fnMangle.c_str());
|
const auto fn = getRuntimeFunction(e->loc, gIR->module, fnMangle.c_str());
|
||||||
|
|
||||||
const auto arg =
|
const auto arg = DtoRVal(cond);
|
||||||
DtoBitCast(DtoRVal(cond), fn->getFunctionType()->getParamType(0));
|
|
||||||
|
|
||||||
gIR->CreateCallOrInvoke(fn, arg);
|
gIR->CreateCallOrInvoke(fn, arg);
|
||||||
} else if (condty->ty == TY::Tpointer &&
|
} else if (condty->ty == TY::Tpointer &&
|
||||||
|
@ -1965,32 +1948,27 @@ public:
|
||||||
e->func->toChars());
|
e->func->toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
LLPointerType *int8ptrty = getPtrToType(LLType::getInt8Ty(gIR->context()));
|
|
||||||
|
|
||||||
assert(e->type->toBasetype()->ty == TY::Tdelegate);
|
assert(e->type->toBasetype()->ty == TY::Tdelegate);
|
||||||
LLType *dgty = DtoType(e->type);
|
LLType *dgty = DtoType(e->type);
|
||||||
|
|
||||||
DValue *u = toElem(e->e1);
|
DValue *u = toElem(e->e1);
|
||||||
LLValue *uval;
|
LLValue *contextptr;
|
||||||
if (DFuncValue *f = u->isFunc()) {
|
if (DFuncValue *f = u->isFunc()) {
|
||||||
assert(f->func);
|
assert(f->func);
|
||||||
LLValue *contextptr = DtoNestedContext(e->loc, f->func);
|
contextptr = DtoNestedContext(e->loc, f->func);
|
||||||
uval = DtoBitCast(contextptr, getVoidPtrType());
|
|
||||||
} else {
|
} else {
|
||||||
uval = (DtoIsInMemoryOnly(u->type) ? DtoLVal(u) : DtoRVal(u));
|
contextptr = (DtoIsInMemoryOnly(u->type) ? DtoLVal(u) : DtoRVal(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "context = " << *uval << '\n';
|
IF_LOG Logger::cout() << "context = " << *contextptr << '\n';
|
||||||
|
|
||||||
LLValue *castcontext = DtoBitCast(uval, int8ptrty);
|
|
||||||
|
|
||||||
IF_LOG Logger::println("func: '%s'", e->func->toPrettyChars());
|
IF_LOG Logger::println("func: '%s'", e->func->toPrettyChars());
|
||||||
|
|
||||||
LLValue *castfptr;
|
LLValue *fptr;
|
||||||
|
|
||||||
if (e->e1->op != EXP::super_ && e->e1->op != EXP::dotType &&
|
if (e->e1->op != EXP::super_ && e->e1->op != EXP::dotType &&
|
||||||
e->func->isVirtual() && !e->func->isFinalFunc()) {
|
e->func->isVirtual() && !e->func->isFinalFunc()) {
|
||||||
castfptr = DtoVirtualFunctionPointer(u, e->func).first;
|
fptr = DtoVirtualFunctionPointer(u, e->func).first;
|
||||||
} else if (e->func->isAbstract()) {
|
} else if (e->func->isAbstract()) {
|
||||||
llvm_unreachable("Delegate to abstract method not implemented.");
|
llvm_unreachable("Delegate to abstract method not implemented.");
|
||||||
} else if (e->func->toParent()->isInterfaceDeclaration()) {
|
} else if (e->func->toParent()->isInterfaceDeclaration()) {
|
||||||
|
@ -2010,13 +1988,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
castfptr = DtoCallee(e->func);
|
fptr = DtoCallee(e->func);
|
||||||
}
|
}
|
||||||
|
|
||||||
castfptr = DtoBitCast(castfptr, dgty->getContainedType(1));
|
|
||||||
|
|
||||||
result = new DImValue(
|
result = new DImValue(
|
||||||
e->type, DtoAggrPair(DtoType(e->type), castcontext, castfptr, ".dg"));
|
e->type, DtoAggrPair(DtoType(e->type), contextptr, fptr, ".dg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2135,7 +2111,7 @@ public:
|
||||||
DValue *u = toElem(e->e1);
|
DValue *u = toElem(e->e1);
|
||||||
if (retPtr && u->type->toBasetype()->ty != TY::Tnoreturn) {
|
if (retPtr && u->type->toBasetype()->ty != TY::Tnoreturn) {
|
||||||
LLValue *lval = makeLValue(e->loc, u);
|
LLValue *lval = makeLValue(e->loc, u);
|
||||||
DtoStore(lval, DtoBitCast(retPtr, lval->getType()->getPointerTo()));
|
DtoStore(lval, retPtr);
|
||||||
}
|
}
|
||||||
llvm::BranchInst::Create(condend, p->scopebb());
|
llvm::BranchInst::Create(condend, p->scopebb());
|
||||||
|
|
||||||
|
@ -2143,7 +2119,7 @@ public:
|
||||||
DValue *v = toElem(e->e2);
|
DValue *v = toElem(e->e2);
|
||||||
if (retPtr && v->type->toBasetype()->ty != TY::Tnoreturn) {
|
if (retPtr && v->type->toBasetype()->ty != TY::Tnoreturn) {
|
||||||
LLValue *lval = makeLValue(e->loc, v);
|
LLValue *lval = makeLValue(e->loc, v);
|
||||||
DtoStore(lval, DtoBitCast(retPtr, lval->getType()->getPointerTo()));
|
DtoStore(lval, retPtr);
|
||||||
}
|
}
|
||||||
llvm::BranchInst::Create(condend, p->scopebb());
|
llvm::BranchInst::Create(condend, p->scopebb());
|
||||||
|
|
||||||
|
@ -2308,14 +2284,8 @@ public:
|
||||||
LLFunction *callee = DtoCallee(fd, false);
|
LLFunction *callee = DtoCallee(fd, false);
|
||||||
|
|
||||||
if (fd->isNested()) {
|
if (fd->isNested()) {
|
||||||
LLType *dgty = DtoType(e->type);
|
|
||||||
|
|
||||||
LLValue *cval = DtoNestedContext(e->loc, fd);
|
LLValue *cval = DtoNestedContext(e->loc, fd);
|
||||||
cval = DtoBitCast(cval, dgty->getContainedType(0));
|
result = new DImValue(e->type, DtoAggrPair(cval, callee, ".func"));
|
||||||
|
|
||||||
LLValue *castfptr = DtoBitCast(callee, dgty->getContainedType(1));
|
|
||||||
|
|
||||||
result = new DImValue(e->type, DtoAggrPair(cval, castfptr, ".func"));
|
|
||||||
} else {
|
} else {
|
||||||
result = new DFuncValue(e->type, fd, callee);
|
result = new DFuncValue(e->type, fd, callee);
|
||||||
}
|
}
|
||||||
|
@ -2368,7 +2338,6 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage = DtoBitCast(storage, llElemType->getPointerTo());
|
|
||||||
if (arrayType->ty == TY::Tarray) {
|
if (arrayType->ty == TY::Tarray) {
|
||||||
result = new DSliceValue(e->type, DtoConstSize_t(len), storage);
|
result = new DSliceValue(e->type, DtoConstSize_t(len), storage);
|
||||||
} else if (arrayType->ty == TY::Tpointer) {
|
} else if (arrayType->ty == TY::Tpointer) {
|
||||||
|
@ -2385,15 +2354,12 @@ public:
|
||||||
auto global = new llvm::GlobalVariable(gIR->module, init->getType(), true,
|
auto global = new llvm::GlobalVariable(gIR->module, init->getType(), true,
|
||||||
llvm::GlobalValue::InternalLinkage,
|
llvm::GlobalValue::InternalLinkage,
|
||||||
init, ".immutablearray");
|
init, ".immutablearray");
|
||||||
result = new DSliceValue(arrayType, DtoConstSize_t(len),
|
result = new DSliceValue(arrayType, DtoConstSize_t(len), global);
|
||||||
DtoBitCast(global, getPtrToType(llElemType)));
|
|
||||||
} else {
|
} else {
|
||||||
DSliceValue *dynSlice = DtoNewDynArray(
|
DSliceValue *dynSlice = DtoNewDynArray(
|
||||||
e->loc, arrayType,
|
e->loc, arrayType,
|
||||||
new DConstValue(Type::tsize_t, DtoConstSize_t(len)), false);
|
new DConstValue(Type::tsize_t, DtoConstSize_t(len)), false);
|
||||||
initializeArrayLiteral(
|
initializeArrayLiteral(p, e, dynSlice->getPtr(), llStoType);
|
||||||
p, e, DtoBitCast(dynSlice->getPtr(), getPtrToType(llStoType)),
|
|
||||||
llStoType);
|
|
||||||
result = dynSlice;
|
result = dynSlice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2417,7 +2383,6 @@ public:
|
||||||
DtoMemSetZero(DtoType(e->type), dstMem);
|
DtoMemSetZero(DtoType(e->type), dstMem);
|
||||||
} else {
|
} else {
|
||||||
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
|
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
|
||||||
initsym = DtoBitCast(initsym, DtoType(pointerTo(e->type)));
|
|
||||||
assert(dstMem->getType() == initsym->getType());
|
assert(dstMem->getType() == initsym->getType());
|
||||||
DtoMemCpy(DtoType(e->type), dstMem, initsym);
|
DtoMemCpy(DtoType(e->type), dstMem, initsym);
|
||||||
}
|
}
|
||||||
|
@ -2559,9 +2524,8 @@ public:
|
||||||
llvm::Function *func =
|
llvm::Function *func =
|
||||||
getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX");
|
getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX");
|
||||||
LLFunctionType *funcTy = func->getFunctionType();
|
LLFunctionType *funcTy = func->getFunctionType();
|
||||||
LLValue *aaTypeInfo = DtoBitCast(
|
LLValue *aaTypeInfo =
|
||||||
DtoTypeInfoOf(e->loc, stripModifiers(aatype), /*base=*/false),
|
DtoTypeInfoOf(e->loc, stripModifiers(aatype), /*base=*/false);
|
||||||
DtoType(getAssociativeArrayTypeInfoType()));
|
|
||||||
|
|
||||||
LLConstant *initval = arrayConst(keysInits, indexType);
|
LLConstant *initval = arrayConst(keysInits, indexType);
|
||||||
LLConstant *globalstore = new LLGlobalVariable(
|
LLConstant *globalstore = new LLGlobalVariable(
|
||||||
|
@ -2625,7 +2589,7 @@ public:
|
||||||
DValue * dv = toElem(exp->e1);
|
DValue * dv = toElem(exp->e1);
|
||||||
LLValue *val = makeLValue(exp->loc, dv);
|
LLValue *val = makeLValue(exp->loc, dv);
|
||||||
LLValue *v = DtoGEP(DtoType(dv->type), val, 0, index);
|
LLValue *v = DtoGEP(DtoType(dv->type), val, 0, index);
|
||||||
return new DLValue(exp->type, DtoBitCast(v, DtoPtrToType(exp->type)));
|
return new DLValue(exp->type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(DelegatePtrExp *e) override {
|
void visit(DelegatePtrExp *e) override {
|
||||||
|
@ -2849,10 +2813,9 @@ public:
|
||||||
// member, so we have to add an extra layer of indirection.
|
// member, so we have to add an extra layer of indirection.
|
||||||
resultType = getInterfaceTypeInfoType();
|
resultType = getInterfaceTypeInfoType();
|
||||||
LLType *pres = DtoType(pointerTo(resultType));
|
LLType *pres = DtoType(pointerTo(resultType));
|
||||||
typinf = DtoLoad(pres, DtoBitCast(typinf, pres->getPointerTo()));
|
typinf = DtoLoad(pres, typinf);
|
||||||
} else {
|
} else {
|
||||||
resultType = getClassInfoType();
|
resultType = getClassInfoType();
|
||||||
typinf = DtoBitCast(typinf, DtoType(pointerTo(resultType)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = new DLValue(resultType, typinf);
|
result = new DLValue(resultType, typinf);
|
||||||
|
|
|
@ -407,10 +407,6 @@ LLValue *DtoGEP1i64(LLType *pointeeTy, LLValue *ptr, uint64_t i0, const char *na
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DtoMemSet(LLValue *dst, LLValue *val, LLValue *nbytes, unsigned align) {
|
void DtoMemSet(LLValue *dst, LLValue *val, LLValue *nbytes, unsigned align) {
|
||||||
LLType *VoidPtrTy = getVoidPtrType();
|
|
||||||
|
|
||||||
dst = DtoBitCast(dst, VoidPtrTy);
|
|
||||||
|
|
||||||
gIR->ir->CreateMemSet(dst, val, nbytes, llvm::MaybeAlign(align),
|
gIR->ir->CreateMemSet(dst, val, nbytes, llvm::MaybeAlign(align),
|
||||||
false /*isVolatile*/);
|
false /*isVolatile*/);
|
||||||
}
|
}
|
||||||
|
@ -429,11 +425,6 @@ void DtoMemSetZero(LLType *type, LLValue *dst, unsigned align) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DtoMemCpy(LLValue *dst, LLValue *src, LLValue *nbytes, unsigned align) {
|
void DtoMemCpy(LLValue *dst, LLValue *src, LLValue *nbytes, unsigned align) {
|
||||||
LLType *VoidPtrTy = getVoidPtrType();
|
|
||||||
|
|
||||||
dst = DtoBitCast(dst, VoidPtrTy);
|
|
||||||
src = DtoBitCast(src, VoidPtrTy);
|
|
||||||
|
|
||||||
auto A = llvm::MaybeAlign(align);
|
auto A = llvm::MaybeAlign(align);
|
||||||
gIR->ir->CreateMemCpy(dst, A, src, A, nbytes, false /*isVolatile*/);
|
gIR->ir->CreateMemCpy(dst, A, src, A, nbytes, false /*isVolatile*/);
|
||||||
}
|
}
|
||||||
|
@ -459,9 +450,6 @@ LLValue *DtoMemCmp(LLValue *lhs, LLValue *rhs, LLValue *nbytes) {
|
||||||
&gIR->module);
|
&gIR->module);
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs = DtoBitCast(lhs, VoidPtrTy);
|
|
||||||
rhs = DtoBitCast(rhs, VoidPtrTy);
|
|
||||||
|
|
||||||
return gIR->ir->CreateCall(fn, {lhs, rhs, nbytes});
|
return gIR->ir->CreateCall(fn, {lhs, rhs, nbytes});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,8 +270,7 @@ void emitBeginCatchMSVC(IRState &irs, Catch *ctch,
|
||||||
if (!isCPPclass) {
|
if (!isCPPclass) {
|
||||||
auto enterCatchFn =
|
auto enterCatchFn =
|
||||||
getRuntimeFunction(ctch->loc, irs.module, "_d_eh_enter_catch");
|
getRuntimeFunction(ctch->loc, irs.module, "_d_eh_enter_catch");
|
||||||
irs.CreateCallOrInvoke(enterCatchFn, DtoBitCast(exnObj, getVoidPtrType()),
|
irs.CreateCallOrInvoke(enterCatchFn, exnObj, clssInfo);
|
||||||
clssInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,9 +729,8 @@ llvm::BasicBlock *TryCatchFinallyScopes::emitLandingPad() {
|
||||||
|
|
||||||
// "Call" llvm.eh.typeid.for, which gives us the eh selector value to
|
// "Call" llvm.eh.typeid.for, which gives us the eh selector value to
|
||||||
// compare the landing pad selector value with.
|
// compare the landing pad selector value with.
|
||||||
llvm::Value *ehTypeId =
|
llvm::Value *ehTypeId = irs.ir->CreateCall(
|
||||||
irs.ir->CreateCall(GET_INTRINSIC_DECL(eh_typeid_for),
|
GET_INTRINSIC_DECL(eh_typeid_for), cb.classInfoPtr);
|
||||||
DtoBitCast(cb.classInfoPtr, getVoidPtrType()));
|
|
||||||
|
|
||||||
// Compare the selector value from the unwinder against the expected
|
// Compare the selector value from the unwinder against the expected
|
||||||
// one and branch accordingly.
|
// one and branch accordingly.
|
||||||
|
|
|
@ -196,7 +196,6 @@ LLConstant *IrClass::getVtblInit() {
|
||||||
if (!cd->isCPPclass()) {
|
if (!cd->isCPPclass()) {
|
||||||
if (!suppressTypeInfo()) {
|
if (!suppressTypeInfo()) {
|
||||||
c = getClassInfoSymbol();
|
c = getClassInfoSymbol();
|
||||||
c = DtoBitCast(c, voidPtrType);
|
|
||||||
} else {
|
} else {
|
||||||
// use null if there are no TypeInfos
|
// use null if there are no TypeInfos
|
||||||
c = llvm::Constant::getNullValue(voidPtrType);
|
c = llvm::Constant::getNullValue(voidPtrType);
|
||||||
|
@ -235,7 +234,7 @@ LLConstant *IrClass::getVtblInit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = DtoBitCast(DtoCallee(fd), voidPtrType);
|
c = DtoCallee(fd);
|
||||||
|
|
||||||
if (cd->isFuncHidden(fd) && !fd->isFuture()) {
|
if (cd->isFuncHidden(fd) && !fd->isFuture()) {
|
||||||
// fd is hidden from the view of this class. If fd overlaps with any
|
// fd is hidden from the view of this class. If fd overlaps with any
|
||||||
|
@ -381,7 +380,7 @@ LLConstant *IrClass::getClassInfoInit() {
|
||||||
if (isInterface) {
|
if (isInterface) {
|
||||||
b.push_array(0, getNullValue(voidPtrPtr));
|
b.push_array(0, getNullValue(voidPtrPtr));
|
||||||
} else {
|
} else {
|
||||||
b.push_array(cd->vtbl.length, DtoBitCast(getVtblSymbol(), voidPtrPtr));
|
b.push_array(cd->vtbl.length, getVtblSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface[] interfaces
|
// Interface[] interfaces
|
||||||
|
@ -397,12 +396,12 @@ LLConstant *IrClass::getClassInfoInit() {
|
||||||
|
|
||||||
// void* destructor
|
// void* destructor
|
||||||
assert(!isInterface || !cd->tidtor);
|
assert(!isInterface || !cd->tidtor);
|
||||||
b.push_funcptr(cd->tidtor, Type::tvoidptr);
|
b.push_funcptr(cd->tidtor);
|
||||||
|
|
||||||
// void function(Object) classInvariant
|
// void function(Object) classInvariant
|
||||||
assert(!isInterface || !cd->inv);
|
assert(!isInterface || !cd->inv);
|
||||||
VarDeclaration *invVar = cinfo->fields[6];
|
VarDeclaration *invVar = cinfo->fields[6];
|
||||||
b.push_funcptr(cd->inv, invVar->type);
|
b.push_funcptr(cd->inv);
|
||||||
|
|
||||||
// ClassFlags m_flags
|
// ClassFlags m_flags
|
||||||
const auto flags = buildClassinfoFlags(cd);
|
const auto flags = buildClassinfoFlags(cd);
|
||||||
|
@ -430,7 +429,7 @@ LLConstant *IrClass::getClassInfoInit() {
|
||||||
defConstructor = nullptr;
|
defConstructor = nullptr;
|
||||||
}
|
}
|
||||||
assert(!isInterface || !defConstructor);
|
assert(!isInterface || !defConstructor);
|
||||||
b.push_funcptr(defConstructor, defConstructorVar->type);
|
b.push_funcptr(defConstructor);
|
||||||
|
|
||||||
// immutable(void)* m_RTInfo
|
// immutable(void)* m_RTInfo
|
||||||
if (cd->getRTInfo) {
|
if (cd->getRTInfo) {
|
||||||
|
@ -546,7 +545,7 @@ LLConstant *IrClass::getInterfaceVtblInit(BaseClass *b,
|
||||||
llvm::Constant *c = llvm::ConstantExpr::getGetElementPtr(
|
llvm::Constant *c = llvm::ConstantExpr::getGetElementPtr(
|
||||||
interfaceInfosZ->getValueType(), interfaceInfosZ, idxs, true);
|
interfaceInfosZ->getValueType(), interfaceInfosZ, idxs, true);
|
||||||
|
|
||||||
constants.push_back(DtoBitCast(c, voidPtrTy));
|
constants.push_back(c);
|
||||||
} else {
|
} else {
|
||||||
// use null if there are no TypeInfos
|
// use null if there are no TypeInfos
|
||||||
constants.push_back(llvm::Constant::getNullValue(voidPtrTy));
|
constants.push_back(llvm::Constant::getNullValue(voidPtrTy));
|
||||||
|
@ -579,7 +578,7 @@ LLConstant *IrClass::getInterfaceVtblInit(BaseClass *b,
|
||||||
if (fd->interfaceVirtual)
|
if (fd->interfaceVirtual)
|
||||||
thunkOffset -= fd->interfaceVirtual->offset;
|
thunkOffset -= fd->interfaceVirtual->offset;
|
||||||
if (thunkOffset == 0) {
|
if (thunkOffset == 0) {
|
||||||
constants.push_back(DtoBitCast(irFunc->getLLVMCallee(), voidPtrTy));
|
constants.push_back(irFunc->getLLVMCallee());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,10 +655,7 @@ LLConstant *IrClass::getInterfaceVtblInit(BaseClass *b,
|
||||||
? 0
|
? 0
|
||||||
: 1;
|
: 1;
|
||||||
LLValue *&thisArg = args[thisArgIndex];
|
LLValue *&thisArg = args[thisArgIndex];
|
||||||
LLType *targetThisType = thisArg->getType();
|
thisArg = DtoGEP1(getI8Type(), thisArg, DtoConstInt(-thunkOffset));
|
||||||
thisArg = DtoBitCast(thisArg, getVoidPtrType());
|
|
||||||
thisArg = DtoGEP1(LLType::getInt8Ty(gIR->context()), thisArg, DtoConstInt(-thunkOffset));
|
|
||||||
thisArg = DtoBitCast(thisArg, targetThisType);
|
|
||||||
|
|
||||||
// all calls that might be subject to inlining into a caller with debug
|
// all calls that might be subject to inlining into a caller with debug
|
||||||
// info should have debug info, too
|
// info should have debug info, too
|
||||||
|
@ -682,7 +678,7 @@ LLConstant *IrClass::getInterfaceVtblInit(BaseClass *b,
|
||||||
gIR->funcGenStates.pop_back();
|
gIR->funcGenStates.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
constants.push_back(DtoBitCast(thunk, voidPtrTy));
|
constants.push_back(thunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the vtbl constant
|
// build the vtbl constant
|
||||||
|
@ -734,8 +730,6 @@ LLConstant *IrClass::getClassInfoInterfaces() {
|
||||||
LLSmallVector<LLConstant *, 6> constants;
|
LLSmallVector<LLConstant *, 6> constants;
|
||||||
constants.reserve(cd->vtblInterfaces->length);
|
constants.reserve(cd->vtblInterfaces->length);
|
||||||
|
|
||||||
LLType *classinfo_type = DtoType(getClassInfoType());
|
|
||||||
LLType *voidptrptr_type = DtoType(pointerTo(pointerTo(Type::tvoid)));
|
|
||||||
LLStructType *interface_type =
|
LLStructType *interface_type =
|
||||||
isaStruct(DtoType(interfacesArrayType->nextOf()));
|
isaStruct(DtoType(interfacesArrayType->nextOf()));
|
||||||
assert(interface_type);
|
assert(interface_type);
|
||||||
|
@ -752,16 +746,14 @@ LLConstant *IrClass::getClassInfoInterfaces() {
|
||||||
|
|
||||||
// classinfo
|
// classinfo
|
||||||
LLConstant *ci = irinter->getClassInfoSymbol();
|
LLConstant *ci = irinter->getClassInfoSymbol();
|
||||||
ci = DtoBitCast(ci, classinfo_type);
|
|
||||||
|
|
||||||
// vtbl
|
// vtbl
|
||||||
LLConstant *vtb;
|
LLConstant *vtb;
|
||||||
// interface get a null
|
// interface get a null
|
||||||
if (cd->isInterfaceDeclaration()) {
|
if (cd->isInterfaceDeclaration()) {
|
||||||
vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(voidptrptr_type));
|
vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(getVoidPtrType()));
|
||||||
} else {
|
} else {
|
||||||
vtb = getInterfaceVtblSymbol(it, i);
|
vtb = getInterfaceVtblSymbol(it, i);
|
||||||
vtb = DtoBitCast(vtb, voidptrptr_type);
|
|
||||||
auto vtblSize = itc->getVtblType()->getNumContainedTypes();
|
auto vtblSize = itc->getVtblType()->getNumContainedTypes();
|
||||||
vtb = DtoConstSlice(DtoConstSize_t(vtblSize), vtb);
|
vtb = DtoConstSlice(DtoConstSize_t(vtblSize), vtb);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue