Skip to content

Commit dd4d3d4

Browse files
committed
Emit struct & class TypeInfos incl. vtables into each referencing CU
1 parent 1c0accd commit dd4d3d4

9 files changed

+49
-60
lines changed

gen/classes.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void DtoResolveClass(ClassDeclaration *cd) {
5656
DtoType(cd->type);
5757

5858
// create IrAggr
59-
IrClass *irAggr = getIrAggr(cd, true);
59+
getIrAggr(cd, true);
6060

6161
// make sure all fields really get their ir field
6262
for (auto vd : cd->fields) {
@@ -67,11 +67,6 @@ void DtoResolveClass(ClassDeclaration *cd) {
6767
}
6868
getIrField(vd, true);
6969
}
70-
71-
// interface only emit typeinfo and classinfo
72-
if (cd->isInterfaceDeclaration()) {
73-
irAggr->initializeInterface();
74-
}
7570
}
7671

7772
////////////////////////////////////////////////////////////////////////////////

gen/functions.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,9 @@ void DtoDeclareFunction(FuncDeclaration *fdecl, const bool willDefine) {
566566
// Check if fdecl should be defined too for cross-module inlining.
567567
// If true, semantic is fully done for fdecl which is needed for some code
568568
// below (e.g. code that uses fdecl->vthis).
569-
bool defineAtEnd;
569+
bool defineAtEnd = false;
570570
bool defineAsAvailableExternally = false;
571571
if (willDefine) {
572-
defineAtEnd = false;
573572
} else if (DtoIsTemplateInstance(fdecl)) {
574573
if (fdecl->semanticRun < PASSsemantic3done) {
575574
assert(fdecl->functionSemantic3());

gen/rttibuilder.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ void RTTIBuilder::push_null_vp() { push(getNullValue(getVoidPtrType())); }
6464

6565
void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t)); }
6666

67-
void RTTIBuilder::push_classinfo(ClassDeclaration *cd) {
68-
push(getIrAggr(cd)->getClassInfoSymbol());
69-
}
70-
7167
void RTTIBuilder::push_string(const char *str) { push(DtoConstString(str)); }
7268

7369
void RTTIBuilder::push_null_void_array() {

gen/rttibuilder.h

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class RTTIBuilder {
4646
void push_size_as_vp(uint64_t s);
4747
void push_string(const char *str);
4848
void push_typeinfo(Type *t);
49-
void push_classinfo(ClassDeclaration *cd);
5049

5150
/// pushes the function pointer or a null void* if it cannot.
5251
void push_funcptr(FuncDeclaration *fd, Type *castto = nullptr);

gen/typinf.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ class DefineVisitor : public Visitor {
299299
RTTIBuilder b(getInterfaceTypeInfoType());
300300

301301
// TypeInfo base
302-
b.push_classinfo(tc->sym);
302+
b.push_typeinfo(tc);
303303

304304
// finish
305305
b.finalize(gvar);
@@ -503,10 +503,10 @@ LLGlobalVariable *DtoResolveTypeInfo(TypeInfoDeclaration *tid) {
503503
assert(!gIR->dcomputetarget);
504504

505505
if (!tid->ir->isResolved()) {
506-
tid->ir->setResolved();
507-
508506
DeclareOrDefineVisitor v;
509507
tid->accept(&v);
508+
509+
tid->ir->setResolved();
510510
}
511511

512512
return llvm::cast<LLGlobalVariable>(getIrValue(tid));

ir/iraggr.cpp

+7-15
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,9 @@ IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) {
174174
}
175175
}
176176

177-
// Add the initializers for the member fields. While we are traversing the
178-
// class hierarchy, use the opportunity to populate interfacesWithVtbls if
179-
// we haven't done so previously (due to e.g. ClassReferenceExp, we can
180-
// have multiple initializer constants for a single class).
181-
addFieldInitializers(constants, explicitInitializers, aggrdecl, offset,
182-
irClass && irClass->interfacesWithVtbls.empty());
177+
// Add the initializers for the member fields.
178+
unsigned dummy = 0;
179+
addFieldInitializers(constants, explicitInitializers, aggrdecl, offset, dummy);
183180

184181
// tail padding?
185182
const size_t structsize = aggrdecl->size(Loc());
@@ -218,12 +215,11 @@ IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) {
218215
void IrAggr::addFieldInitializers(
219216
llvm::SmallVectorImpl<llvm::Constant *> &constants,
220217
const VarInitMap &explicitInitializers, AggregateDeclaration *decl,
221-
unsigned &offset, bool populateInterfacesWithVtbls) {
222-
218+
unsigned &offset, unsigned &interfaceVtblIndex) {
223219
if (ClassDeclaration *cd = decl->isClassDeclaration()) {
224220
if (cd->baseClass) {
225221
addFieldInitializers(constants, explicitInitializers, cd->baseClass,
226-
offset, populateInterfacesWithVtbls);
222+
offset, interfaceVtblIndex);
227223
}
228224

229225
// has interface vtbls?
@@ -237,14 +233,10 @@ void IrAggr::addFieldInitializers(
237233
}
238234

239235
IrClass *irClass = static_cast<IrClass *>(this);
240-
size_t inter_idx = irClass->interfacesWithVtbls.size();
241236
for (auto bc : *cd->vtblInterfaces) {
242-
constants.push_back(irClass->getInterfaceVtblSymbol(bc, inter_idx));
237+
constants.push_back(irClass->getInterfaceVtblSymbol(bc, interfaceVtblIndex));
243238
offset += target.ptrsize;
244-
inter_idx++;
245-
246-
if (populateInterfacesWithVtbls)
247-
irClass->interfacesWithVtbls.push_back(bc);
239+
++interfaceVtblIndex;
248240
}
249241
}
250242
}

ir/iraggr.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class IrAggr {
103103
void addFieldInitializers(llvm::SmallVectorImpl<llvm::Constant *> &constants,
104104
const VarInitMap &explicitInitializers,
105105
AggregateDeclaration *decl, unsigned &offset,
106-
bool populateInterfacesWithVtbls);
106+
unsigned &interfaceVtblIndex);
107107
};
108108

109109
/// Represents a struct.
@@ -122,7 +122,7 @@ class IrStruct : public IrAggr {
122122
/// Represents a class/interface.
123123
class IrClass : public IrAggr {
124124
public:
125-
explicit IrClass(ClassDeclaration *cd) : IrAggr(cd) {}
125+
explicit IrClass(ClassDeclaration *cd);
126126

127127
/// Creates the __ClassZ/__InterfaceZ symbol lazily.
128128
llvm::GlobalVariable *getClassInfoSymbol(bool define = false);
@@ -133,9 +133,6 @@ class IrClass : public IrAggr {
133133
/// Defines all interface vtbls.
134134
void defineInterfaceVtbls();
135135

136-
/// Initialize interface.
137-
void initializeInterface();
138-
139136
private:
140137
/// Vtbl global.
141138
llvm::GlobalVariable *vtbl = nullptr;
@@ -157,6 +154,8 @@ class IrClass : public IrAggr {
157154
/// Corresponds to the Interface instances needed to be output.
158155
std::vector<BaseClass *> interfacesWithVtbls;
159156

157+
void addInterfaceVtbls(ClassDeclaration *cd);
158+
160159
/// Builds the __ClassZ/__InterfaceZ initializer constant lazily.
161160
llvm::Constant *getClassInfoInit();
162161

ir/irclass.cpp

+29-23
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@
4141

4242
//////////////////////////////////////////////////////////////////////////////
4343

44+
IrClass::IrClass(ClassDeclaration *cd) : IrAggr(cd) {
45+
addInterfaceVtbls(cd);
46+
47+
assert(interfacesWithVtbls.size() ==
48+
stripModifiers(type)->ctype->isClass()->getNumInterfaceVtbls() &&
49+
"inconsistent number of interface vtables in this class");
50+
}
51+
52+
void IrClass::addInterfaceVtbls(ClassDeclaration *cd) {
53+
if (cd->baseClass && !cd->isInterfaceDeclaration()) {
54+
addInterfaceVtbls(cd->baseClass);
55+
}
56+
57+
if (cd->vtblInterfaces) {
58+
for (auto bc : *cd->vtblInterfaces) {
59+
interfacesWithVtbls.push_back(bc);
60+
}
61+
}
62+
}
63+
64+
//////////////////////////////////////////////////////////////////////////////
65+
4466
LLGlobalVariable *IrClass::getVtblSymbol(bool define) {
4567
if (!vtbl) {
4668
const auto irMangle = getIRMangledVTableSymbolName(aggrdecl);
@@ -108,12 +130,15 @@ LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) {
108130
node->addOperand(llvm::MDNode::get(
109131
gIR->context(), llvm::makeArrayRef(mdVals, CD_NumFields)));
110132
}
133+
134+
if (!define && DtoIsTemplateInstance(aggrdecl))
135+
define = true;
111136
}
112137

113138
if (define) {
114139
auto init = getClassInfoInit();
115140
if (!typeInfo->hasInitializer())
116-
defineGlobal(typeInfo, init, aggrdecl, true);
141+
defineGlobal(typeInfo, init, aggrdecl);
117142
}
118143

119144
return typeInfo;
@@ -361,7 +386,7 @@ LLConstant *IrClass::getClassInfoInit() {
361386
// TypeInfo_Class base
362387
assert(!isInterface || !cd->baseClass);
363388
if (cd->baseClass) {
364-
b.push_classinfo(cd->baseClass);
389+
b.push_typeinfo(cd->baseClass->type);
365390
} else {
366391
b.push_null(cinfoType);
367392
}
@@ -711,9 +736,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
711736
if (cd->isInterfaceDeclaration()) {
712737
vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(voidptrptr_type));
713738
} else {
714-
auto itv = interfaceVtblMap.find({it->sym, i});
715-
assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
716-
vtb = itv->second;
739+
vtb = getInterfaceVtblSymbol(it, i);
717740
vtb = DtoBitCast(vtb, voidptrptr_type);
718741
auto vtblSize = itc->getVtblType()->getNumContainedTypes();
719742
vtb = DtoConstSlice(DtoConstSize_t(vtblSize), vtb);
@@ -735,7 +758,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
735758
// create and apply initializer
736759
LLConstant *arr = LLConstantArray::get(array_type, constants);
737760
auto ciarr = getInterfaceArraySymbol();
738-
defineGlobal(ciarr, arr, cd, true);
761+
defineGlobal(ciarr, arr, cd);
739762

740763
// return null, only baseclass provide interfaces
741764
if (cd->vtblInterfaces->length == 0) {
@@ -753,20 +776,3 @@ LLConstant *IrClass::getClassInfoInterfaces() {
753776
// return as a slice
754777
return DtoConstSlice(DtoConstSize_t(cd->vtblInterfaces->length), ptr);
755778
}
756-
757-
//////////////////////////////////////////////////////////////////////////////
758-
759-
void IrClass::initializeInterface() {
760-
InterfaceDeclaration *base = aggrdecl->isInterfaceDeclaration();
761-
assert(base && "not interface");
762-
763-
// has interface vtbls?
764-
if (!base->vtblInterfaces) {
765-
return;
766-
}
767-
768-
for (auto bc : *base->vtblInterfaces) {
769-
// add to the interface list
770-
interfacesWithVtbls.push_back(bc);
771-
}
772-
}

ir/irstruct.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ LLGlobalVariable* IrStruct::getTypeInfoSymbol(bool define) {
5252
getTypeInfoStructMemType(), irMangle, false);
5353

5454
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
55+
56+
if (!define && DtoIsTemplateInstance(aggrdecl))
57+
define = true;
5558
}
5659

5760
if (define) {
5861
auto init = getTypeInfoInit();
5962
if (!typeInfo->hasInitializer())
60-
defineGlobal(typeInfo, init, aggrdecl, true);
63+
defineGlobal(typeInfo, init, aggrdecl);
6164
}
6265

6366
return typeInfo;

0 commit comments

Comments
 (0)