Skip superfluous IR pointer bitcasts, now that they are always opaque

This commit is contained in:
Martin Kinkelin 2024-05-19 17:59:21 +02:00
parent ee9f3a142c
commit d140f2a283
28 changed files with 182 additions and 399 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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() {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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() {

View file

@ -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())

View file

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

View file

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

View file

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

View file

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

View file

@ -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() {

View file

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

View file

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

View file

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

View file

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

View file

@ -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),

View file

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

View file

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

View file

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

View file

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

View file

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