mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 09:00:33 +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"
|
#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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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)};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue