diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 48eb338d7c2..dd56637d6d0 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -506,8 +506,19 @@ class DeclareOrDefineVisitor : public Visitor { auto cd = decl->tinfo->isTypeClass()->sym; DtoResolveClass(cd); + auto irclass = getIrAggr(cd, true); IrGlobal *irg = getIrGlobal(decl, true); - irg->value = getIrAggr(cd)->getClassInfoSymbol(); + + auto ti = irclass->getClassInfoSymbol(); + irg->value = ti; + + // check if the definition can be elided + if (irclass->suppressTypeInfo()) { + return; + } + + irclass->getClassInfoSymbol(true); + ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override } // Build all other TypeInfos. diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index 86d6c78d5f9..12d2703ff01 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -24,6 +24,7 @@ #include "gen/mangling.h" #include "gen/pragma.h" #include "gen/tollvm.h" +#include "gen/linkage.h" #include "ir/irdsymbol.h" #include "ir/irtypeclass.h" #include "ir/irtypestruct.h" @@ -102,9 +103,9 @@ LLGlobalVariable *IrAggr::getInitSymbol(bool define) { if (define) { auto initConstant = getDefaultInit(); - if (!init->hasInitializer()) { + if (!init->hasInitializer()) init = gIR->setGlobalVarInitializer(init, initConstant, aggrdecl); - } + init->setLinkage(TYPEINFO_LINKAGE_TYPE); // override } return init; diff --git a/ir/irclass.cpp b/ir/irclass.cpp index 7e51208c66b..0286cbcc504 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -29,6 +29,7 @@ #include "gen/runtime.h" #include "gen/tollvm.h" #include "gen/typinf.h" +#include "gen/linkage.h" #include "ir/iraggr.h" #include "ir/irdsymbol.h" #include "ir/irfunction.h" @@ -89,8 +90,10 @@ LLGlobalVariable *IrClass::getVtblSymbol(bool define) { if (define) { auto init = getVtblInit(); // might define vtbl - if (!vtbl->hasInitializer()) + if (!vtbl->hasInitializer()) { defineGlobal(vtbl, init, aggrdecl); + vtbl->setLinkage(TYPEINFO_LINKAGE_TYPE); // override + } } return vtbl; @@ -140,8 +143,10 @@ LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) { if (define) { auto init = getClassInfoInit(); - if (!typeInfo->hasInitializer()) + if (!typeInfo->hasInitializer()) { defineGlobal(typeInfo, init, aggrdecl); + typeInfo->setLinkage(TYPEINFO_LINKAGE_TYPE); // override + } } return typeInfo; @@ -367,7 +372,7 @@ LLConstant *IrClass::getClassInfoInit() { if (isInterface) { b.push_null_void_array(); } else { - b.push_void_array(cd->size(Loc()), getInitSymbol()); + b.push_void_array(cd->size(Loc()), getInitSymbol(true)); } // string name @@ -381,7 +386,7 @@ LLConstant *IrClass::getClassInfoInit() { if (isInterface) { b.push_array(0, getNullPtr()); } else { - b.push_array(cd->vtbl.length, getVtblSymbol()); + b.push_array(cd->vtbl.length, getVtblSymbol(true)); // override } // Interface[] interfaces @@ -391,7 +396,9 @@ LLConstant *IrClass::getClassInfoInit() { assert(!isInterface || !cd->baseClass); if (cd->baseClass) { DtoResolveClass(cd->baseClass); - b.push(getIrAggr(cd->baseClass)->getClassInfoSymbol()); + auto ti = getIrAggr(cd->baseClass)->getClassInfoSymbol(true); + ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override + b.push(ti); } else { b.push_null(cinfoType); } @@ -743,7 +750,7 @@ LLConstant *IrClass::getClassInfoInterfaces() { assert(itc && "null interface IrTypeClass"); // classinfo - LLConstant *ci = irinter->getClassInfoSymbol(); + LLConstant *ci = irinter->getClassInfoSymbol(true); // vtbl LLConstant *vtb; @@ -772,6 +779,7 @@ LLConstant *IrClass::getClassInfoInterfaces() { LLConstant *arr = LLConstantArray::get(array_type, constants); auto ciarr = getInterfaceArraySymbol(); defineGlobal(ciarr, arr, cd); + ciarr->setLinkage(TYPEINFO_LINKAGE_TYPE); // override // return null, only baseclass provide interfaces if (cd->vtblInterfaces->length == 0) { diff --git a/tests/codegen/pragma_no_typeinfo.d b/tests/codegen/pragma_no_typeinfo.d index e0c94cb7528..6229047d0e1 100644 --- a/tests/codegen/pragma_no_typeinfo.d +++ b/tests/codegen/pragma_no_typeinfo.d @@ -10,10 +10,10 @@ struct StructWithTypeInfo {} // force emission auto ti = typeid(StructWithTypeInfo); -// CHECK: _D18pragma_no_typeinfo17ClassWithTypeInfo7__ClassZ = global %object.TypeInfo_Class +// CHECK: _D18pragma_no_typeinfo17ClassWithTypeInfo7__ClassZ = linkonce_odr global %object.TypeInfo_Class class ClassWithTypeInfo {} -// CHECK: _D18pragma_no_typeinfo21InterfaceWithTypeInfo11__InterfaceZ = global %object.TypeInfo_Class +// CHECK: _D18pragma_no_typeinfo21InterfaceWithTypeInfo11__InterfaceZ = linkonce_odr global %object.TypeInfo_Class interface InterfaceWithTypeInfo {} diff --git a/tests/codegen/static_typeid_gh1540.d b/tests/codegen/static_typeid_gh1540.d index 55b4fb2a31b..ee0d1518aab 100644 --- a/tests/codegen/static_typeid_gh1540.d +++ b/tests/codegen/static_typeid_gh1540.d @@ -15,7 +15,7 @@ struct S { } -// CHECK-DAG: _D{{.*}}1C7__ClassZ{{\"?}} = global %object.TypeInfo_Class +// CHECK-DAG: _D{{.*}}1C7__ClassZ{{\"?}} = linkonce_odr global %object.TypeInfo_Class // CHECK-DAG: _D{{.*}}classvarC14TypeInfo_Class{{\"?}} = thread_local global ptr {{.*}}1C7__ClassZ auto classvar = typeid(C); diff --git a/tests/linking/inputs/typeinfo_on_demand2.d b/tests/linking/inputs/typeinfo_on_demand2.d new file mode 100644 index 00000000000..1cc8d2ef01d --- /dev/null +++ b/tests/linking/inputs/typeinfo_on_demand2.d @@ -0,0 +1,13 @@ +module inputs.typeinfo_on_demand2; + +extern(C++) class MyClass : MyInterface1 { + void method() {} +} + +extern(C++) interface MyInterface1 { + void method(); +} + +extern(C++) interface MyInterface2 { + void method(); +} \ No newline at end of file diff --git a/tests/linking/typeinfo_on_demand.d b/tests/linking/typeinfo_on_demand.d new file mode 100644 index 00000000000..6927d66acab --- /dev/null +++ b/tests/linking/typeinfo_on_demand.d @@ -0,0 +1,15 @@ +// Tests that TypeInfo is generated per CU to enable on demand usage + +// RUN: %ldc -of%t_lib%obj -betterC -c %S/inputs/typeinfo_on_demand2.d +// RUN: %ldc -I%S %t_lib%obj -run %s + +import inputs.typeinfo_on_demand2; + +void main() { + MyChildClass mcc = new MyChildClass; + mcc.method(); +} + +extern(C++) class MyChildClass : MyClass, MyInterface2 { + override void method() {} +} \ No newline at end of file