From c0b9ba4ca2aed8789697adee2dfa4992a7403f1c Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 14 Oct 2017 17:10:52 +0200 Subject: [PATCH] Skip TypeInfo definitions for -betterC And improve robustness for TypeInfos of speculative types by only eliding their TypeInfo definition, not the declaration of the LL global altogether. Handle `-betterC` exactly the same way; don't touch ClassInfos as -betterC doesn't support classes [yet]. `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. --- gen/aa.cpp | 15 +++++++-------- gen/classes.cpp | 2 +- gen/declarations.cpp | 24 ++++++++++-------------- gen/rttibuilder.cpp | 2 +- gen/toconstelem.cpp | 6 ++---- gen/toir.cpp | 2 +- gen/typinf.cpp | 9 +++++---- tests/codegen/static_typeid_gh1540.d | 4 ++-- 8 files changed, 29 insertions(+), 35 deletions(-) diff --git a/gen/aa.cpp b/gen/aa.cpp index 11c6aa91944..4a25698646e 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -24,11 +24,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(aa->type->toBasetype()); - return DtoTypeInfoOf(aatype->index, false); + LLConstant *ti = DtoTypeInfoOf(aatype->index, /*base=*/false); + return DtoBitCast(ti, targetType); } //////////////////////////////////////////////////////////////////////////////// @@ -59,14 +60,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(); } @@ -125,8 +126,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); @@ -171,8 +171,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); diff --git a/gen/classes.cpp b/gen/classes.cpp index a6522da228a..298b4a9a66b 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -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); diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 515a596bfeb..56cfa85a6cd 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -89,12 +89,13 @@ class CodegenVisitor : public Visitor { } // Emit TypeInfo. - DtoTypeInfoOf(decl->type); + DtoTypeInfoOf(decl->type, /*base=*/false); // Define __InterfaceZ. IrAggr *ir = getIrAggr(decl); llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol(); - interfaceZ->setInitializer(ir->getClassInfoInit()); + if (!isSpeculativeType(decl->type)) + interfaceZ->setInitializer(ir->getClassInfoInit()); setLinkage(decl, interfaceZ); } } @@ -139,7 +140,7 @@ class CodegenVisitor : public Visitor { initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit()); // emit typeinfo - DtoTypeInfoOf(decl->type); + DtoTypeInfoOf(decl->type, /*base=*/false); } // Emit __xopEquals/__xopCmp/__xtoHash. @@ -195,10 +196,9 @@ class CodegenVisitor : public Visitor { setLinkage(lwc, vtbl); llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); - classZ->setInitializer(ir->getClassInfoInit()); + if (!isSpeculativeType(decl->type)) + classZ->setInitializer(ir->getClassInfoInit()); setLinkage(lwc, classZ); - - // No need to do TypeInfo here, it is __classZ for classes in D2. } } @@ -468,19 +468,15 @@ class CodegenVisitor : public Visitor { ////////////////////////////////////////////////////////////////////////// void visit(TypeInfoDeclaration *decl) LLVM_OVERRIDE { - if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) { - return; - } - TypeInfoDeclaration_codegen(decl, irs); + if (!irs->dcomputetarget) + TypeInfoDeclaration_codegen(decl, irs); } ////////////////////////////////////////////////////////////////////////// void visit(TypeInfoClassDeclaration *decl) LLVM_OVERRIDE { - if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) { - return; - } - TypeInfoClassDeclaration_codegen(decl, irs); + if (!irs->dcomputetarget) + TypeInfoClassDeclaration_codegen(decl, irs); } }; diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index e9048eb77ed..da90491d2a6 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -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()); diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp index b4c051f6a8d..db9ecab2275 100644 --- a/gen/toconstelem.cpp +++ b/gen/toconstelem.cpp @@ -68,11 +68,8 @@ class ToConstElemVisitor : public Visitor { } 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; } @@ -699,6 +696,7 @@ class ToConstElemVisitor : public Visitor { } result = DtoTypeInfoOf(t, false); + result = DtoBitCast(result, DtoType(e->type)); } ////////////////////////////////////////////////////////////////////////////// diff --git a/gen/toir.cpp b/gen/toir.cpp index 08a44198742..36ffd4a871d 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2454,7 +2454,7 @@ class ToElemVisitor : public Visitor { getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX"); LLFunctionType *funcTy = func->getFunctionType(); LLValue *aaTypeInfo = - DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype)), + DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype), false), DtoType(Type::typeinfoassociativearray->type)); LLConstant *idxs[2] = {DtoConstUint(0), DtoConstUint(0)}; diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 2208f9eed19..3cf12a576f4 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -481,7 +481,7 @@ class LLVMDefineVisitor : public Visitor { 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 @@ -617,12 +617,13 @@ 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 (global.params.betterC || isSpeculativeType(decl->tinfo) || + builtinTypeInfo(decl->tinfo)) { return; } - // define custom typedef + // define the TypeInfo global LLVMDefineVisitor v; decl->accept(&v); } diff --git a/tests/codegen/static_typeid_gh1540.d b/tests/codegen/static_typeid_gh1540.d index 3ead419d99a..04cfed98dc8 100644 --- a/tests/codegen/static_typeid_gh1540.d +++ b/tests/codegen/static_typeid_gh1540.d @@ -18,8 +18,8 @@ struct S // CHECK: @{{.*}}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: @{{.*}}interfacevarC18TypeInfo_Interface = thread_local global %object.TypeInfo_Interface* {{.*}}@_D{{[0-9]+}}TypeInfo_C{{.*}}1I6__initZ auto interfacevar = typeid(I); -// CHECK: @{{.*}}structvarC15TypeInfo_Struct = thread_local global %"typeid({{.*}}S)"* @_D{{[0-9]+}}TypeInfo_S{{.*}}1S6__initZ +// CHECK: @{{.*}}structvarC15TypeInfo_Struct = thread_local global %object.TypeInfo_Struct* {{.*}}@_D{{[0-9]+}}TypeInfo_S{{.*}}1S6__initZ auto structvar = typeid(S);