mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 16:41:06 +03:00
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:
parent
fa5f318d3a
commit
d1b30d627c
8 changed files with 38 additions and 44 deletions
15
gen/aa.cpp
15
gen/aa.cpp
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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)};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue