Backport fix for issue #2357 (#2366)

Improve robustness for TypeInfos of speculative types by only eliding
their TypeInfo definition, not the declaration of the LL global
altogether.

`DtoTypeInfoOf()` expects the LL global to be created and otherwise
fails with an assertion or segfault (e.g., issue #2357). So now only
linker errors should result in case the TypeInfo definition is missing.

Also normalize the calls to `DtoTypeInfoOf()` and revise the following
pointer bitcasts, as the LL type of forward-declared TypeInfo globals
may be opaque.
This commit is contained in:
kinke 2017-10-18 20:47:09 +02:00 committed by GitHub
parent fa5f318d3a
commit d1b30d627c
8 changed files with 38 additions and 44 deletions

View file

@ -23,11 +23,12 @@
#include "ir/irmodule.h"
// returns the keytype typeinfo
static LLValue *to_keyti(DValue *aa) {
static LLConstant *to_keyti(DValue *aa, LLType *targetType) {
// keyti param
assert(aa->type->toBasetype()->ty == Taarray);
TypeAArray *aatype = static_cast<TypeAArray *>(aa->type->toBasetype());
return DtoTypeInfoOf(aatype->index, false);
LLConstant *ti = DtoTypeInfoOf(aatype->index, /*base=*/false);
return DtoBitCast(ti, targetType);
}
////////////////////////////////////////////////////////////////////////////////
@ -58,14 +59,14 @@ DLValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key,
LLValue *ret;
if (lvalue) {
LLValue *rawAATI =
DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false);
DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), /*base=*/false);
LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1));
LLValue *valsize = DtoConstSize_t(getTypeAllocSize(DtoType(type)));
ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey,
"aa.index")
.getInstruction();
} else {
LLValue *keyti = DtoBitCast(to_keyti(aa), funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index")
.getInstruction();
}
@ -131,8 +132,7 @@ DValue *DtoAAIn(Loc &loc, Type *type, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0));
// keyti param
LLValue *keyti = to_keyti(aa);
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
// pkey param
LLValue *pkey = makeLValue(loc, key);
@ -177,8 +177,7 @@ DValue *DtoAARemove(Loc &loc, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0));
// keyti param
LLValue *keyti = to_keyti(aa);
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
// pkey param
LLValue *pkey = makeLValue(loc, key);

View file

@ -438,7 +438,7 @@ static LLConstant *build_offti_entry(ClassDeclaration *cd, VarDeclaration *vd) {
inits[0] = DtoConstSize_t(offset);
// TypeInfo ti;
inits[1] = DtoTypeInfoOf(vd->type, true);
inits[1] = DtoTypeInfoOf(vd->type);
// done
return llvm::ConstantStruct::get(inits);

View file

@ -89,15 +89,18 @@ public:
}
// Emit TypeInfo.
DtoTypeInfoOf(decl->type);
DtoTypeInfoOf(decl->type, /*base=*/false);
// Define __InterfaceZ.
// Declare __InterfaceZ.
IrAggr *ir = getIrAggr(decl);
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol();
// Only define if not speculative.
if (!isSpeculativeType(decl->type)) {
interfaceZ->setInitializer(ir->getClassInfoInit());
setLinkage(decl, interfaceZ);
}
}
}
//////////////////////////////////////////////////////////////////////////
@ -134,12 +137,11 @@ public:
IrAggr *ir = getIrAggr(decl);
auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
assert(initGlobal);
setLinkage(decl, initGlobal);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkage(decl, initGlobal);
// emit typeinfo
DtoTypeInfoOf(decl->type);
DtoTypeInfoOf(decl->type, /*base=*/false);
}
// Emit __xopEquals/__xopCmp/__xtoHash.
@ -186,19 +188,18 @@ public:
auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
assert(initGlobal);
setLinkage(lwc, initGlobal);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkage(lwc, initGlobal);
llvm::GlobalVariable *vtbl = ir->getVtblSymbol();
vtbl->setInitializer(ir->getVtblInit());
setLinkage(lwc, vtbl);
llvm::GlobalVariable *classZ = ir->getClassInfoSymbol();
if (!isSpeculativeType(decl->type)) {
classZ->setInitializer(ir->getClassInfoInit());
setLinkage(lwc, classZ);
// No need to do TypeInfo here, it is <name>__classZ for classes in D2.
}
}
}
@ -288,8 +289,8 @@ public:
// Set the initializer, swapping out the variable if the types do not
// match.
setLinkage(lwc, gvar);
irGlobal->value = irs->setGlobalVarInitializer(gvar, initVal);
setLinkage(lwc, gvar);
// Also set up the debug info.
irs->DBuilder.EmitGlobalVariable(gvar, decl);
@ -468,18 +469,14 @@ public:
//////////////////////////////////////////////////////////////////////////
void visit(TypeInfoDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) {
return;
}
if (!irs->dcomputetarget)
TypeInfoDeclaration_codegen(decl, irs);
}
//////////////////////////////////////////////////////////////////////////
void visit(TypeInfoClassDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) {
return;
}
if (!irs->dcomputetarget)
TypeInfoClassDeclaration_codegen(decl, irs);
}
};

View file

@ -64,7 +64,7 @@ void RTTIBuilder::push_null(Type *T) { push(getNullValue(DtoType(T))); }
void RTTIBuilder::push_null_vp() { push(getNullValue(getVoidPtrType())); }
void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t, true)); }
void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t)); }
void RTTIBuilder::push_classinfo(ClassDeclaration *cd) {
push(getIrAggr(cd)->getClassInfoSymbol());

View file

@ -68,11 +68,8 @@ public:
}
if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) {
LLType *vartype = DtoType(e->type);
result = DtoTypeInfoOf(ti->tinfo, false);
if (result->getType() != getPtrToType(vartype)) {
result = llvm::ConstantExpr::getBitCast(result, vartype);
}
result = DtoBitCast(result, DtoType(e->type));
return;
}
@ -707,6 +704,7 @@ public:
TypeInfoDeclaration_codegen(tid, p);
}
result = llvm::cast<llvm::GlobalVariable>(getIrGlobal(tid)->value);
result = DtoBitCast(result, DtoType(e->type));
}
//////////////////////////////////////////////////////////////////////////////

View file

@ -2447,7 +2447,7 @@ public:
getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX");
LLFunctionType *funcTy = func->getFunctionType();
LLValue *aaTypeInfo =
DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype)),
DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype), /*base=*/false),
DtoType(Type::typeinfoassociativearray->type));
LLConstant *idxs[2] = {DtoConstUint(0), DtoConstUint(0)};

View file

@ -482,7 +482,7 @@ public:
LLType *tiTy = DtoType(Type::dtypeinfo->type);
for (auto arg : *tu->arguments) {
arrInits.push_back(DtoTypeInfoOf(arg->type, true));
arrInits.push_back(DtoTypeInfoOf(arg->type));
}
// build array
@ -619,12 +619,12 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) {
emitTypeMetadata(decl);
// this is a declaration of a builtin __initZ var
if (builtinTypeInfo(decl->tinfo)) {
// check if the definition can be elided
if (isSpeculativeType(decl->tinfo) || builtinTypeInfo(decl->tinfo)) {
return;
}
// define custom typedef
// define the TypeInfo global
LLVMDefineVisitor v;
decl->accept(&v);
}

View file

@ -15,11 +15,11 @@ struct S
{
}
// CHECK: @{{.*}}classvarC14TypeInfo_Class{{\"?}} = thread_local global %object.TypeInfo_Class* @{{.*}}1C7__ClassZ
// CHECK: _D{{.*}}classvarC14TypeInfo_Class{{\"?}} = thread_local global %object.TypeInfo_Class* {{.*}}1C7__ClassZ
auto classvar = typeid(C);
// CHECK: @{{.*}}interfacevarC18TypeInfo_Interface{{\"?}} = thread_local global %"typeid({{.*}}.I)"* @{{.*}}_D{{[0-9]+}}TypeInfo_C{{.*}}1I6__initZ
// CHECK: _D{{.*}}interfacevarC18TypeInfo_Interface{{\"?}} = thread_local global %object.TypeInfo_Interface* {{.*}}TypeInfo_C{{.*}}1I6__initZ
auto interfacevar = typeid(I);
// CHECK: @{{.*}}structvarC15TypeInfo_Struct{{\"?}} = thread_local global %"typeid({{.*}}S)"* @{{.*}}_D{{[0-9]+}}TypeInfo_S{{.*}}1S6__initZ
// CHECK: _D{{.*}}structvarC15TypeInfo_Struct{{\"?}} = thread_local global %object.TypeInfo_Struct* {{.*}}TypeInfo_S{{.*}}1S6__initZ
auto structvar = typeid(S);