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" #include "ir/irmodule.h"
// returns the keytype typeinfo // returns the keytype typeinfo
static LLValue *to_keyti(DValue *aa) { static LLConstant *to_keyti(DValue *aa, LLType *targetType) {
// keyti param // keyti param
assert(aa->type->toBasetype()->ty == Taarray); assert(aa->type->toBasetype()->ty == Taarray);
TypeAArray *aatype = static_cast<TypeAArray *>(aa->type->toBasetype()); 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; LLValue *ret;
if (lvalue) { if (lvalue) {
LLValue *rawAATI = LLValue *rawAATI =
DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false); DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), /*base=*/false);
LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1)); 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, castedAATI, valsize, pkey,
"aa.index") "aa.index")
.getInstruction(); .getInstruction();
} else { } 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") ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index")
.getInstruction(); .getInstruction();
} }
@ -131,8 +132,7 @@ DValue *DtoAAIn(Loc &loc, Type *type, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0)); aaval = DtoBitCast(aaval, funcTy->getParamType(0));
// keyti param // keyti param
LLValue *keyti = to_keyti(aa); LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
// pkey param // pkey param
LLValue *pkey = makeLValue(loc, key); LLValue *pkey = makeLValue(loc, key);
@ -177,8 +177,7 @@ DValue *DtoAARemove(Loc &loc, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0)); aaval = DtoBitCast(aaval, funcTy->getParamType(0));
// keyti param // keyti param
LLValue *keyti = to_keyti(aa); LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
// pkey param // pkey param
LLValue *pkey = makeLValue(loc, key); 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); inits[0] = DtoConstSize_t(offset);
// TypeInfo ti; // TypeInfo ti;
inits[1] = DtoTypeInfoOf(vd->type, true); inits[1] = DtoTypeInfoOf(vd->type);
// done // done
return llvm::ConstantStruct::get(inits); return llvm::ConstantStruct::get(inits);

View file

@ -89,13 +89,16 @@ public:
} }
// Emit TypeInfo. // Emit TypeInfo.
DtoTypeInfoOf(decl->type); DtoTypeInfoOf(decl->type, /*base=*/false);
// Define __InterfaceZ. // Declare __InterfaceZ.
IrAggr *ir = getIrAggr(decl); IrAggr *ir = getIrAggr(decl);
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol(); llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol();
interfaceZ->setInitializer(ir->getClassInfoInit()); // Only define if not speculative.
setLinkage(decl, interfaceZ); if (!isSpeculativeType(decl->type)) {
interfaceZ->setInitializer(ir->getClassInfoInit());
setLinkage(decl, interfaceZ);
}
} }
} }
@ -134,12 +137,11 @@ public:
IrAggr *ir = getIrAggr(decl); IrAggr *ir = getIrAggr(decl);
auto &initZ = ir->getInitSymbol(); auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ); auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
assert(initGlobal);
setLinkage(decl, initGlobal);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit()); initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkage(decl, initGlobal);
// emit typeinfo // emit typeinfo
DtoTypeInfoOf(decl->type); DtoTypeInfoOf(decl->type, /*base=*/false);
} }
// Emit __xopEquals/__xopCmp/__xtoHash. // Emit __xopEquals/__xopCmp/__xtoHash.
@ -186,19 +188,18 @@ public:
auto &initZ = ir->getInitSymbol(); auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ); auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
assert(initGlobal);
setLinkage(lwc, initGlobal);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit()); initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkage(lwc, initGlobal);
llvm::GlobalVariable *vtbl = ir->getVtblSymbol(); llvm::GlobalVariable *vtbl = ir->getVtblSymbol();
vtbl->setInitializer(ir->getVtblInit()); vtbl->setInitializer(ir->getVtblInit());
setLinkage(lwc, vtbl); setLinkage(lwc, vtbl);
llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); llvm::GlobalVariable *classZ = ir->getClassInfoSymbol();
classZ->setInitializer(ir->getClassInfoInit()); if (!isSpeculativeType(decl->type)) {
setLinkage(lwc, classZ); 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 // Set the initializer, swapping out the variable if the types do not
// match. // match.
setLinkage(lwc, gvar);
irGlobal->value = irs->setGlobalVarInitializer(gvar, initVal); irGlobal->value = irs->setGlobalVarInitializer(gvar, initVal);
setLinkage(lwc, gvar);
// Also set up the debug info. // Also set up the debug info.
irs->DBuilder.EmitGlobalVariable(gvar, decl); irs->DBuilder.EmitGlobalVariable(gvar, decl);
@ -468,19 +469,15 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void visit(TypeInfoDeclaration *decl) LLVM_OVERRIDE { void visit(TypeInfoDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) { if (!irs->dcomputetarget)
return; TypeInfoDeclaration_codegen(decl, irs);
}
TypeInfoDeclaration_codegen(decl, irs);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void visit(TypeInfoClassDeclaration *decl) LLVM_OVERRIDE { void visit(TypeInfoClassDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) { if (!irs->dcomputetarget)
return; TypeInfoClassDeclaration_codegen(decl, irs);
}
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_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) { void RTTIBuilder::push_classinfo(ClassDeclaration *cd) {
push(getIrAggr(cd)->getClassInfoSymbol()); push(getIrAggr(cd)->getClassInfoSymbol());

View file

@ -68,11 +68,8 @@ public:
} }
if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) { if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) {
LLType *vartype = DtoType(e->type);
result = DtoTypeInfoOf(ti->tinfo, false); result = DtoTypeInfoOf(ti->tinfo, false);
if (result->getType() != getPtrToType(vartype)) { result = DtoBitCast(result, DtoType(e->type));
result = llvm::ConstantExpr::getBitCast(result, vartype);
}
return; return;
} }
@ -707,6 +704,7 @@ public:
TypeInfoDeclaration_codegen(tid, p); TypeInfoDeclaration_codegen(tid, p);
} }
result = llvm::cast<llvm::GlobalVariable>(getIrGlobal(tid)->value); 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"); getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX");
LLFunctionType *funcTy = func->getFunctionType(); LLFunctionType *funcTy = func->getFunctionType();
LLValue *aaTypeInfo = LLValue *aaTypeInfo =
DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype)), DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype), /*base=*/false),
DtoType(Type::typeinfoassociativearray->type)); DtoType(Type::typeinfoassociativearray->type));
LLConstant *idxs[2] = {DtoConstUint(0), DtoConstUint(0)}; LLConstant *idxs[2] = {DtoConstUint(0), DtoConstUint(0)};

View file

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