Skip to content

Commit edc928b

Browse files
authored
Merge pull request #2647 from kinke/ifaceVtbl
[2.079] Only emit interface vtables in the declaring module
2 parents e4f424b + 2dea0e9 commit edc928b

File tree

11 files changed

+228
-168
lines changed

11 files changed

+228
-168
lines changed

gen/declarations.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ class CodegenVisitor : public Visitor {
9696
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol();
9797
// Only define if not speculative.
9898
if (!isSpeculativeType(decl->type)) {
99-
interfaceZ->setInitializer(ir->getClassInfoInit());
100-
setLinkage(decl, interfaceZ);
99+
defineGlobal(interfaceZ, ir->getClassInfoInit(), decl);
101100
}
102101
}
103102
}
@@ -186,21 +185,20 @@ class CodegenVisitor : public Visitor {
186185
}
187186

188187
IrAggr *ir = getIrAggr(decl);
189-
const auto lwc = DtoLinkage(decl);
190188

191189
auto &initZ = ir->getInitSymbol();
192190
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
193191
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
194-
setLinkage(lwc, initGlobal);
192+
setLinkage(decl, initGlobal);
195193

196194
llvm::GlobalVariable *vtbl = ir->getVtblSymbol();
197-
vtbl->setInitializer(ir->getVtblInit());
198-
setLinkage(lwc, vtbl);
195+
defineGlobal(vtbl, ir->getVtblInit(), decl);
196+
197+
ir->defineInterfaceVtbls();
199198

200199
llvm::GlobalVariable *classZ = ir->getClassInfoSymbol();
201200
if (!isSpeculativeType(decl->type)) {
202-
classZ->setInitializer(ir->getClassInfoInit());
203-
setLinkage(lwc, classZ);
201+
defineGlobal(classZ, ir->getClassInfoInit(), decl);
204202
}
205203
}
206204
}

gen/llvmhelpers.cpp

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -911,17 +911,12 @@ void DtoResolveVariable(VarDeclaration *vd) {
911911
// with a different type later, swap it out and replace any existing
912912
// uses with bitcasts to the previous type.
913913

914-
// We always start out with external linkage; any other type is set
915-
// when actually defining it in VarDeclaration::codegen.
916-
llvm::GlobalValue::LinkageTypes linkage =
917-
llvm::GlobalValue::ExternalLinkage;
918-
if (vd->llvmInternal == LLVMextern_weak) {
919-
linkage = llvm::GlobalValue::ExternalWeakLinkage;
920-
}
921-
922914
llvm::GlobalVariable *gvar =
923-
getOrCreateGlobal(vd->loc, gIR->module, DtoMemType(vd->type), isLLConst,
924-
linkage, nullptr, irMangle, vd->isThreadlocal());
915+
declareGlobal(vd->loc, gIR->module, DtoMemType(vd->type), irMangle,
916+
isLLConst, vd->isThreadlocal());
917+
if (vd->llvmInternal == LLVMextern_weak)
918+
gvar->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
919+
925920
auto varIr = getIrGlobal(vd);
926921
varIr->value = gvar;
927922

@@ -1751,19 +1746,32 @@ llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm) {
17511746
return LLConstantArray::get(at, vals);
17521747
}
17531748

1754-
llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
1755-
llvm::Type *type, bool isConstant,
1756-
llvm::GlobalValue::LinkageTypes linkage,
1757-
llvm::Constant *init,
1758-
llvm::StringRef name,
1759-
bool isThreadLocal) {
1760-
llvm::GlobalVariable *existing = module.getGlobalVariable(name, true);
1749+
static std::string llvmTypeToString(llvm::Type *type) {
1750+
std::string result;
1751+
llvm::raw_string_ostream stream(result);
1752+
stream << *type;
1753+
stream.flush();
1754+
return result;
1755+
}
1756+
1757+
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
1758+
llvm::Type *type,
1759+
llvm::StringRef mangledName,
1760+
bool isConstant, bool isThreadLocal) {
1761+
llvm::GlobalVariable *existing =
1762+
module.getGlobalVariable(mangledName, /*AllowInternal=*/true);
17611763
if (existing) {
1762-
if (existing->getType()->getElementType() != type) {
1764+
const auto existingType = existing->getType()->getElementType();
1765+
if (existingType != type || existing->isConstant() != isConstant ||
1766+
existing->isThreadLocal() != isThreadLocal) {
1767+
const auto existingTypeName = llvmTypeToString(existingType);
1768+
const auto newTypeName = llvmTypeToString(type);
17631769
error(loc,
17641770
"Global variable type does not match previous declaration with "
17651771
"same mangled name: `%s`",
1766-
name.str().c_str());
1772+
mangledName.str().c_str());
1773+
errorSupplemental(loc, "Previous IR type: %s", existingTypeName.c_str());
1774+
errorSupplemental(loc, "New IR type: %s", newTypeName.c_str());
17671775
fatal();
17681776
}
17691777
return existing;
@@ -1772,14 +1780,38 @@ llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
17721780
// Use a command line option for the thread model.
17731781
// On PPC there is only local-exec available - in this case just ignore the
17741782
// command line.
1775-
const llvm::GlobalVariable::ThreadLocalMode tlsModel =
1783+
const auto tlsModel =
17761784
isThreadLocal
17771785
? (global.params.targetTriple->getArch() == llvm::Triple::ppc
17781786
? llvm::GlobalVariable::LocalExecTLSModel
17791787
: clThreadModel.getValue())
17801788
: llvm::GlobalVariable::NotThreadLocal;
1781-
return new llvm::GlobalVariable(module, type, isConstant, linkage, init, name,
1782-
nullptr, tlsModel);
1789+
1790+
return new llvm::GlobalVariable(module, type, isConstant,
1791+
llvm::GlobalValue::ExternalLinkage, nullptr,
1792+
mangledName, nullptr, tlsModel);
1793+
}
1794+
1795+
void defineGlobal(llvm::GlobalVariable *global, llvm::Constant *init,
1796+
Dsymbol *symbolForLinkage) {
1797+
assert(global->isDeclaration() && "Global variable already defined");
1798+
assert(init);
1799+
global->setInitializer(init);
1800+
if (symbolForLinkage)
1801+
setLinkage(symbolForLinkage, global);
1802+
}
1803+
1804+
llvm::GlobalVariable *defineGlobal(const Loc &loc, llvm::Module &module,
1805+
llvm::StringRef mangledName,
1806+
llvm::Constant *init,
1807+
llvm::GlobalValue::LinkageTypes linkage,
1808+
bool isConstant, bool isThreadLocal) {
1809+
assert(init);
1810+
auto global = declareGlobal(loc, module, init->getType(), mangledName,
1811+
isConstant, isThreadLocal);
1812+
defineGlobal(global, init, nullptr);
1813+
global->setLinkage(linkage);
1814+
return global;
17831815
}
17841816

17851817
FuncDeclaration *getParentFunc(Dsymbol *sym) {

gen/llvmhelpers.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,18 +245,29 @@ stringLiteralCacheForType(Type *charType);
245245

246246
llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
247247

248-
/// Tries to create an LLVM global with the given properties. If a variable with
249-
/// the same mangled name already exists, checks if the types match and returns
250-
/// it instead.
248+
/// Tries to declare an LLVM global. If a variable with the same mangled name
249+
/// already exists, checks if the types match and returns it instead.
251250
///
252251
/// Necessary to support multiple declarations with the same mangled name, as
253252
/// can be the case due to pragma(mangle).
254-
llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
255-
llvm::Type *type, bool isConstant,
256-
llvm::GlobalValue::LinkageTypes linkage,
257-
llvm::Constant *init,
258-
llvm::StringRef name,
259-
bool isThreadLocal = false);
253+
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
254+
llvm::Type *type,
255+
llvm::StringRef mangledName,
256+
bool isConstant,
257+
bool isThreadLocal = false);
258+
259+
/// Defines an existing LLVM global, i.e., sets the initial value and finalizes
260+
/// its linkage.
261+
/// Asserts that a global isn't defined multiple times this way.
262+
void defineGlobal(llvm::GlobalVariable *global, llvm::Constant *init,
263+
Dsymbol *symbolForLinkage);
264+
265+
/// Declares (if not already declared) & defines an LLVM global.
266+
llvm::GlobalVariable *defineGlobal(const Loc &loc, llvm::Module &module,
267+
llvm::StringRef mangledName,
268+
llvm::Constant *init,
269+
llvm::GlobalValue::LinkageTypes linkage,
270+
bool isConstant, bool isThreadLocal = false);
260271

261272
FuncDeclaration *getParentFunc(Dsymbol *sym);
262273

gen/modules.cpp

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,15 @@ LLFunction *build_module_reference_and_ctor(const char *moduleMangle,
169169

170170
// create the ModuleReference node for this module
171171
const auto thismrefIRMangle = getIRMangledModuleRefSymbolName(moduleMangle);
172-
Loc loc;
173-
LLGlobalVariable *thismref = getOrCreateGlobal(
174-
loc, gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage,
175-
thismrefinit, thismrefIRMangle);
172+
LLGlobalVariable *thismref =
173+
defineGlobal(Loc(), gIR->module, thismrefIRMangle, thismrefinit,
174+
LLGlobalValue::InternalLinkage, false);
176175
// make sure _Dmodule_ref is declared
177176
const auto mrefIRMangle = getIRMangledVarName("_Dmodule_ref", LINKc);
178177
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
179178
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
180179
if (!mref) {
181-
mref = new LLGlobalVariable(gIR->module, modulerefPtrTy, false,
182-
LLGlobalValue::ExternalLinkage, nullptr,
183-
mrefIRMangle);
180+
mref = declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false);
184181
}
185182
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
186183

@@ -218,9 +215,9 @@ llvm::Function *buildGetTLSAnchor() {
218215
// Create a dummmy TLS global private to this module.
219216
const auto one =
220217
llvm::ConstantInt::get(llvm::Type::getInt8Ty(gIR->context()), 1);
221-
const auto anchor = getOrCreateGlobal(
222-
Loc(), gIR->module, one->getType(), false,
223-
llvm::GlobalValue::LinkOnceODRLinkage, one, "ldc.tls_anchor", true);
218+
const auto anchor = defineGlobal(Loc(), gIR->module, "ldc.tls_anchor", one,
219+
llvm::GlobalValue::LinkOnceODRLinkage, false,
220+
/*isThreadLocal=*/true);
224221
anchor->setVisibility(llvm::GlobalValue::HiddenVisibility);
225222
anchor->setAlignment(16);
226223

@@ -358,11 +355,11 @@ void emitModuleRefToSection(RegistryStyle style, std::string moduleMangle,
358355

359356
const auto thismrefIRMangle =
360357
getIRMangledModuleRefSymbolName(moduleMangle.c_str());
361-
auto thismref = new llvm::GlobalVariable(
362-
gIR->module, moduleInfoPtrTy,
363-
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
364-
llvm::GlobalValue::LinkOnceODRLinkage,
365-
DtoBitCast(thisModuleInfo, moduleInfoPtrTy), thismrefIRMangle);
358+
auto thismref = defineGlobal(Loc(), gIR->module, thismrefIRMangle,
359+
DtoBitCast(thisModuleInfo, moduleInfoPtrTy),
360+
llvm::GlobalValue::LinkOnceODRLinkage,
361+
false // FIXME: mRelocModel != llvm::Reloc::PIC_
362+
);
366363
thismref->setSection(sectionName);
367364
gIR->usedArray.push_back(thismref);
368365

@@ -382,22 +379,19 @@ void emitModuleRefToSection(RegistryStyle style, std::string moduleMangle,
382379
const auto magicEndSymbolName = (style == RegistryStyle::sectionDarwin)
383380
? "\1section$end$__DATA$.minfo"
384381
: "__stop___minfo";
385-
auto minfoBeg = new llvm::GlobalVariable(gIR->module, moduleInfoPtrTy, false,
386-
llvm::GlobalValue::ExternalLinkage,
387-
nullptr, magicBeginSymbolName);
388-
auto minfoEnd = new llvm::GlobalVariable(gIR->module, moduleInfoPtrTy, false,
389-
llvm::GlobalValue::ExternalLinkage,
390-
nullptr, magicEndSymbolName);
382+
auto minfoBeg = declareGlobal(Loc(), gIR->module, moduleInfoPtrTy,
383+
magicBeginSymbolName, false);
384+
auto minfoEnd = declareGlobal(Loc(), gIR->module, moduleInfoPtrTy,
385+
magicEndSymbolName, false);
391386
minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility);
392387
minfoEnd->setVisibility(llvm::GlobalValue::HiddenVisibility);
393388

394389
// Build the ctor to invoke _d_dso_registry.
395390

396391
// This is the DSO slot for use by the druntime implementation.
397-
auto dsoSlot =
398-
new llvm::GlobalVariable(gIR->module, getVoidPtrType(), false,
399-
llvm::GlobalValue::LinkOnceODRLinkage,
400-
getNullPtr(getVoidPtrType()), "ldc.dso_slot");
392+
auto dsoSlot = defineGlobal(Loc(), gIR->module, "ldc.dso_slot",
393+
getNullPtr(getVoidPtrType()),
394+
llvm::GlobalValue::LinkOnceODRLinkage, false);
401395
dsoSlot->setVisibility(llvm::GlobalValue::HiddenVisibility);
402396

403397
// Okay, so the theory is easy: We want to have one global constructor and
@@ -429,11 +423,10 @@ void emitModuleRefToSection(RegistryStyle style, std::string moduleMangle,
429423
// problems. This would mean that it is no longer safe to link D objects
430424
// directly using e.g. "g++ dcode.o cppcode.o", though.
431425

432-
auto dsoInitialized = new llvm::GlobalVariable(
433-
gIR->module, llvm::Type::getInt8Ty(gIR->context()), false,
434-
llvm::GlobalValue::LinkOnceODRLinkage,
426+
auto dsoInitialized = defineGlobal(
427+
Loc(), gIR->module, "ldc.dso_initialized",
435428
llvm::ConstantInt::get(llvm::Type::getInt8Ty(gIR->context()), 0),
436-
"ldc.dso_initialized");
429+
llvm::GlobalValue::LinkOnceODRLinkage, false);
437430
dsoInitialized->setVisibility(llvm::GlobalValue::HiddenVisibility);
438431

439432
// There is no reason for this cast to void*, other than that removing it
@@ -505,7 +498,7 @@ void addCoverageAnalysis(Module *m) {
505498
llvm::ConstantAggregateZero *zeroinitializer =
506499
llvm::ConstantAggregateZero::get(type);
507500
m->d_cover_valid = new llvm::GlobalVariable(
508-
gIR->module, type, true, LLGlobalValue::InternalLinkage,
501+
gIR->module, type, /*isConstant=*/true, LLGlobalValue::InternalLinkage,
509502
zeroinitializer, "_d_cover_valid");
510503
LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)};
511504
d_cover_valid_slice =

gen/ms-cxx-helper.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,8 @@ llvm::StructType *getTypeDescriptorType(IRState &irs,
165165
llvm::GlobalVariable *getTypeDescriptor(IRState &irs, ClassDeclaration *cd) {
166166
if (cd->isCPPclass()) {
167167
const char *name = Target::cppTypeInfoMangle(cd);
168-
return getOrCreateGlobal(
169-
cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true,
170-
LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name);
168+
return declareGlobal(cd->loc, irs.module, getVoidPtrType(), name,
169+
/*isConstant=*/true);
171170
}
172171

173172
auto classInfoPtr = getIrAggr(cd, true)->getClassInfoSymbol();
@@ -188,10 +187,13 @@ llvm::GlobalVariable *getTypeDescriptor(IRState &irs, ClassDeclaration *cd) {
188187
llvm::ConstantDataArray::getString(gIR->context(), TypeNameString)};
189188
llvm::StructType *TypeDescriptorType =
190189
getTypeDescriptorType(irs, classInfoPtr, TypeNameString);
191-
Var = new llvm::GlobalVariable(
192-
gIR->module, TypeDescriptorType, /*Constant=*/false,
193-
LLGlobalVariable::InternalLinkage, // getLinkageForRTTI(Type),
194-
llvm::ConstantStruct::get(TypeDescriptorType, Fields), TypeDescName);
190+
191+
const LinkageWithCOMDAT lwc = {LLGlobalVariable::LinkOnceODRLinkage, true};
192+
Var = defineGlobal(cd->loc, gIR->module, TypeDescName,
193+
llvm::ConstantStruct::get(TypeDescriptorType, Fields),
194+
lwc.first, /*isConstant=*/true);
195+
setLinkage(lwc, Var);
196+
195197
return Var;
196198
}
197199

gen/trycatchfinally.cpp

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -161,31 +161,36 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
161161

162162
LLGlobalVariable *ci;
163163
if (p.cd->isCPPclass()) {
164-
const char *name = Target::cppTypeInfoMangle(p.cd);
165-
auto cpp_ti = getOrCreateGlobal(
166-
p.cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true,
167-
LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name);
168-
169-
// Wrap std::type_info pointers inside a __cpp_type_info_ptr class instance so that
170-
// the personality routine may differentiate C++ catch clauses from D ones.
171-
OutBuffer mangleBuf;
172-
mangleBuf.writestring("_D");
173-
mangleToBuffer(p.cd, &mangleBuf);
174-
mangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
175-
const auto wrapperMangle = getIRMangledVarName(mangleBuf.peekString(), LINKd);
176-
177-
const auto cppTypeInfoPtrType = getCppTypeInfoPtrType();
178-
RTTIBuilder b(cppTypeInfoPtrType);
179-
b.push(cpp_ti);
180-
181-
auto wrapperType = llvm::cast<llvm::StructType>(
182-
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype)
183-
->getMemoryLLType());
184-
auto wrapperInit = b.get_constant(wrapperType);
185-
186-
ci = getOrCreateGlobal(
187-
p.cd->loc, irs.module, wrapperType, /*isConstant=*/true,
188-
LLGlobalValue::LinkOnceODRLinkage, wrapperInit, wrapperMangle);
164+
// Wrap std::type_info pointers inside a __cpp_type_info_ptr class
165+
// instance so that the personality routine may differentiate C++ catch
166+
// clauses from D ones.
167+
OutBuffer wrapperMangleBuf;
168+
wrapperMangleBuf.writestring("_D");
169+
mangleToBuffer(p.cd, &wrapperMangleBuf);
170+
wrapperMangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
171+
const auto wrapperMangle =
172+
getIRMangledVarName(wrapperMangleBuf.peekString(), LINKd);
173+
174+
ci = irs.module.getGlobalVariable(wrapperMangle);
175+
if (!ci) {
176+
const char *name = Target::cppTypeInfoMangle(p.cd);
177+
auto cpp_ti =
178+
declareGlobal(p.cd->loc, irs.module, getVoidPtrType(), name,
179+
/*isConstant=*/true);
180+
181+
const auto cppTypeInfoPtrType = getCppTypeInfoPtrType();
182+
RTTIBuilder b(cppTypeInfoPtrType);
183+
b.push(cpp_ti);
184+
185+
auto wrapperType = llvm::cast<llvm::StructType>(
186+
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype)
187+
->getMemoryLLType());
188+
auto wrapperInit = b.get_constant(wrapperType);
189+
190+
ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit,
191+
LLGlobalValue::LinkOnceODRLinkage,
192+
/*isConstant=*/true);
193+
}
189194
} else {
190195
ci = getIrAggr(p.cd)->getClassInfoSymbol();
191196
}

0 commit comments

Comments
 (0)