Split up getOrCreateGlobal() in {declare,define}Global()

Making it obvious which of the two operations is performed, reducing
call args and making sure a global isn't defined multiple times via
`defineGlobal()`.

The only [intended] functional change is in gen/trycatchfinally.cpp,
where I inserted a check for an existing __cpp_type_info_ptr global when
emitting a catch for C++ exceptions.
This commit is contained in:
Martin 2018-04-07 19:25:54 +02:00
parent e4f424bf63
commit f38a7972a5
9 changed files with 133 additions and 120 deletions

View file

@ -911,17 +911,12 @@ void DtoResolveVariable(VarDeclaration *vd) {
// with a different type later, swap it out and replace any existing
// uses with bitcasts to the previous type.
// We always start out with external linkage; any other type is set
// when actually defining it in VarDeclaration::codegen.
llvm::GlobalValue::LinkageTypes linkage =
llvm::GlobalValue::ExternalLinkage;
if (vd->llvmInternal == LLVMextern_weak) {
linkage = llvm::GlobalValue::ExternalWeakLinkage;
}
llvm::GlobalVariable *gvar =
getOrCreateGlobal(vd->loc, gIR->module, DtoMemType(vd->type), isLLConst,
linkage, nullptr, irMangle, vd->isThreadlocal());
declareGlobal(vd->loc, gIR->module, DtoMemType(vd->type), irMangle,
isLLConst, vd->isThreadlocal());
if (vd->llvmInternal == LLVMextern_weak)
gvar->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
auto varIr = getIrGlobal(vd);
varIr->value = gvar;
@ -1751,19 +1746,20 @@ llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm) {
return LLConstantArray::get(at, vals);
}
llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type, bool isConstant,
llvm::GlobalValue::LinkageTypes linkage,
llvm::Constant *init,
llvm::StringRef name,
bool isThreadLocal) {
llvm::GlobalVariable *existing = module.getGlobalVariable(name, true);
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type,
llvm::StringRef mangledName,
bool isConstant, bool isThreadLocal) {
llvm::GlobalVariable *existing =
module.getGlobalVariable(mangledName, /*AllowInternal=*/true);
if (existing) {
if (existing->getType()->getElementType() != type) {
if (existing->getType()->getElementType() != type ||
existing->isConstant() != isConstant ||
existing->isThreadLocal() != isThreadLocal) {
error(loc,
"Global variable type does not match previous declaration with "
"same mangled name: `%s`",
name.str().c_str());
mangledName.str().c_str());
fatal();
}
return existing;
@ -1772,14 +1768,36 @@ llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
// Use a command line option for the thread model.
// On PPC there is only local-exec available - in this case just ignore the
// command line.
const llvm::GlobalVariable::ThreadLocalMode tlsModel =
const auto tlsModel =
isThreadLocal
? (global.params.targetTriple->getArch() == llvm::Triple::ppc
? llvm::GlobalVariable::LocalExecTLSModel
: clThreadModel.getValue())
: llvm::GlobalVariable::NotThreadLocal;
return new llvm::GlobalVariable(module, type, isConstant, linkage, init, name,
nullptr, tlsModel);
return new llvm::GlobalVariable(module, type, isConstant,
llvm::GlobalValue::ExternalLinkage, nullptr,
mangledName, nullptr, tlsModel);
}
void defineGlobal(llvm::GlobalVariable *global, llvm::Constant *init,
llvm::GlobalValue::LinkageTypes linkage) {
assert(global->isDeclaration() && "Global variable already defined");
assert(init);
global->setInitializer(init);
global->setLinkage(linkage);
}
llvm::GlobalVariable *defineGlobal(const Loc &loc, llvm::Module &module,
llvm::StringRef mangledName,
llvm::Constant *init,
llvm::GlobalValue::LinkageTypes linkage,
bool isConstant, bool isThreadLocal) {
assert(init);
auto global = declareGlobal(loc, module, init->getType(), mangledName,
isConstant, isThreadLocal);
defineGlobal(global, init, linkage);
return global;
}
FuncDeclaration *getParentFunc(Dsymbol *sym) {

View file

@ -245,19 +245,30 @@ stringLiteralCacheForType(Type *charType);
llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
/// Tries to create an LLVM global with the given properties. If a variable with
/// the same mangled name already exists, checks if the types match and returns
/// it instead.
/// Tries to declare an LLVM global. If a variable with the same mangled name
/// already exists, checks if the types match and returns it instead.
///
/// Necessary to support multiple declarations with the same mangled name, as
/// can be the case due to pragma(mangle).
llvm::GlobalVariable *getOrCreateGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type, bool isConstant,
llvm::GlobalValue::LinkageTypes linkage,
llvm::Constant *init,
llvm::StringRef name,
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type,
llvm::StringRef mangledName,
bool isConstant,
bool isThreadLocal = false);
/// Defines an existing LLVM global, i.e., sets the initial value and finalizes
/// its linkage.
/// Asserts that a global isn't defined multiple times this way.
void defineGlobal(llvm::GlobalVariable *global, llvm::Constant *init,
llvm::GlobalValue::LinkageTypes linkage);
/// Declares (if not already declared) & defines an LLVM global.
llvm::GlobalVariable *defineGlobal(const Loc &loc, llvm::Module &module,
llvm::StringRef mangledName,
llvm::Constant *init,
llvm::GlobalValue::LinkageTypes linkage,
bool isConstant, bool isThreadLocal = false);
FuncDeclaration *getParentFunc(Dsymbol *sym);
void Declaration_codegen(Dsymbol *decl);

View file

@ -169,18 +169,15 @@ LLFunction *build_module_reference_and_ctor(const char *moduleMangle,
// create the ModuleReference node for this module
const auto thismrefIRMangle = getIRMangledModuleRefSymbolName(moduleMangle);
Loc loc;
LLGlobalVariable *thismref = getOrCreateGlobal(
loc, gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage,
thismrefinit, thismrefIRMangle);
LLGlobalVariable *thismref =
defineGlobal(Loc(), gIR->module, thismrefIRMangle, thismrefinit,
LLGlobalValue::InternalLinkage, false);
// make sure _Dmodule_ref is declared
const auto mrefIRMangle = getIRMangledVarName("_Dmodule_ref", LINKc);
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
if (!mref) {
mref = new LLGlobalVariable(gIR->module, modulerefPtrTy, false,
LLGlobalValue::ExternalLinkage, nullptr,
mrefIRMangle);
mref = declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false);
}
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));
@ -218,9 +215,9 @@ llvm::Function *buildGetTLSAnchor() {
// Create a dummmy TLS global private to this module.
const auto one =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(gIR->context()), 1);
const auto anchor = getOrCreateGlobal(
Loc(), gIR->module, one->getType(), false,
llvm::GlobalValue::LinkOnceODRLinkage, one, "ldc.tls_anchor", true);
const auto anchor = defineGlobal(Loc(), gIR->module, "ldc.tls_anchor", one,
llvm::GlobalValue::LinkOnceODRLinkage, false,
/*isThreadLocal=*/true);
anchor->setVisibility(llvm::GlobalValue::HiddenVisibility);
anchor->setAlignment(16);
@ -358,11 +355,11 @@ void emitModuleRefToSection(RegistryStyle style, std::string moduleMangle,
const auto thismrefIRMangle =
getIRMangledModuleRefSymbolName(moduleMangle.c_str());
auto thismref = new llvm::GlobalVariable(
gIR->module, moduleInfoPtrTy,
false, // FIXME: mRelocModel != llvm::Reloc::PIC_
auto thismref = defineGlobal(Loc(), gIR->module, thismrefIRMangle,
DtoBitCast(thisModuleInfo, moduleInfoPtrTy),
llvm::GlobalValue::LinkOnceODRLinkage,
DtoBitCast(thisModuleInfo, moduleInfoPtrTy), thismrefIRMangle);
false // FIXME: mRelocModel != llvm::Reloc::PIC_
);
thismref->setSection(sectionName);
gIR->usedArray.push_back(thismref);
@ -382,22 +379,19 @@ void emitModuleRefToSection(RegistryStyle style, std::string moduleMangle,
const auto magicEndSymbolName = (style == RegistryStyle::sectionDarwin)
? "\1section$end$__DATA$.minfo"
: "__stop___minfo";
auto minfoBeg = new llvm::GlobalVariable(gIR->module, moduleInfoPtrTy, false,
llvm::GlobalValue::ExternalLinkage,
nullptr, magicBeginSymbolName);
auto minfoEnd = new llvm::GlobalVariable(gIR->module, moduleInfoPtrTy, false,
llvm::GlobalValue::ExternalLinkage,
nullptr, magicEndSymbolName);
auto minfoBeg = declareGlobal(Loc(), gIR->module, moduleInfoPtrTy,
magicBeginSymbolName, false);
auto minfoEnd = declareGlobal(Loc(), gIR->module, moduleInfoPtrTy,
magicEndSymbolName, false);
minfoBeg->setVisibility(llvm::GlobalValue::HiddenVisibility);
minfoEnd->setVisibility(llvm::GlobalValue::HiddenVisibility);
// Build the ctor to invoke _d_dso_registry.
// This is the DSO slot for use by the druntime implementation.
auto dsoSlot =
new llvm::GlobalVariable(gIR->module, getVoidPtrType(), false,
llvm::GlobalValue::LinkOnceODRLinkage,
getNullPtr(getVoidPtrType()), "ldc.dso_slot");
auto dsoSlot = defineGlobal(Loc(), gIR->module, "ldc.dso_slot",
getNullPtr(getVoidPtrType()),
llvm::GlobalValue::LinkOnceODRLinkage, false);
dsoSlot->setVisibility(llvm::GlobalValue::HiddenVisibility);
// 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,
// problems. This would mean that it is no longer safe to link D objects
// directly using e.g. "g++ dcode.o cppcode.o", though.
auto dsoInitialized = new llvm::GlobalVariable(
gIR->module, llvm::Type::getInt8Ty(gIR->context()), false,
llvm::GlobalValue::LinkOnceODRLinkage,
auto dsoInitialized = defineGlobal(
Loc(), gIR->module, "ldc.dso_initialized",
llvm::ConstantInt::get(llvm::Type::getInt8Ty(gIR->context()), 0),
"ldc.dso_initialized");
llvm::GlobalValue::LinkOnceODRLinkage, false);
dsoInitialized->setVisibility(llvm::GlobalValue::HiddenVisibility);
// There is no reason for this cast to void*, other than that removing it
@ -505,7 +498,7 @@ void addCoverageAnalysis(Module *m) {
llvm::ConstantAggregateZero *zeroinitializer =
llvm::ConstantAggregateZero::get(type);
m->d_cover_valid = new llvm::GlobalVariable(
gIR->module, type, true, LLGlobalValue::InternalLinkage,
gIR->module, type, /*isConstant=*/true, LLGlobalValue::InternalLinkage,
zeroinitializer, "_d_cover_valid");
LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)};
d_cover_valid_slice =

View file

@ -165,9 +165,8 @@ llvm::StructType *getTypeDescriptorType(IRState &irs,
llvm::GlobalVariable *getTypeDescriptor(IRState &irs, ClassDeclaration *cd) {
if (cd->isCPPclass()) {
const char *name = Target::cppTypeInfoMangle(cd);
return getOrCreateGlobal(
cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true,
LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name);
return declareGlobal(cd->loc, irs.module, getVoidPtrType(), name,
/*isConstant=*/true);
}
auto classInfoPtr = getIrAggr(cd, true)->getClassInfoSymbol();
@ -188,10 +187,9 @@ llvm::GlobalVariable *getTypeDescriptor(IRState &irs, ClassDeclaration *cd) {
llvm::ConstantDataArray::getString(gIR->context(), TypeNameString)};
llvm::StructType *TypeDescriptorType =
getTypeDescriptorType(irs, classInfoPtr, TypeNameString);
Var = new llvm::GlobalVariable(
gIR->module, TypeDescriptorType, /*Constant=*/false,
LLGlobalVariable::InternalLinkage, // getLinkageForRTTI(Type),
llvm::ConstantStruct::get(TypeDescriptorType, Fields), TypeDescName);
Var = defineGlobal(cd->loc, gIR->module, TypeDescName,
llvm::ConstantStruct::get(TypeDescriptorType, Fields),
LLGlobalVariable::InternalLinkage, false);
return Var;
}

View file

@ -161,18 +161,22 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
LLGlobalVariable *ci;
if (p.cd->isCPPclass()) {
const char *name = Target::cppTypeInfoMangle(p.cd);
auto cpp_ti = getOrCreateGlobal(
p.cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true,
LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name);
// Wrap std::type_info pointers inside a __cpp_type_info_ptr class
// instance so that the personality routine may differentiate C++ catch
// clauses from D ones.
OutBuffer wrapperMangleBuf;
wrapperMangleBuf.writestring("_D");
mangleToBuffer(p.cd, &wrapperMangleBuf);
wrapperMangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
const auto wrapperMangle =
getIRMangledVarName(wrapperMangleBuf.peekString(), LINKd);
// Wrap std::type_info pointers inside a __cpp_type_info_ptr class instance so that
// the personality routine may differentiate C++ catch clauses from D ones.
OutBuffer mangleBuf;
mangleBuf.writestring("_D");
mangleToBuffer(p.cd, &mangleBuf);
mangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
const auto wrapperMangle = getIRMangledVarName(mangleBuf.peekString(), LINKd);
ci = irs.module.getGlobalVariable(wrapperMangle);
if (!ci) {
const char *name = Target::cppTypeInfoMangle(p.cd);
auto cpp_ti =
declareGlobal(p.cd->loc, irs.module, getVoidPtrType(), name,
/*isConstant=*/true);
const auto cppTypeInfoPtrType = getCppTypeInfoPtrType();
RTTIBuilder b(cppTypeInfoPtrType);
@ -183,9 +187,10 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
->getMemoryLLType());
auto wrapperInit = b.get_constant(wrapperType);
ci = getOrCreateGlobal(
p.cd->loc, irs.module, wrapperType, /*isConstant=*/true,
LLGlobalValue::LinkOnceODRLinkage, wrapperInit, wrapperMangle);
ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit,
LLGlobalValue::LinkOnceODRLinkage,
/*isConstant=*/true);
}
} else {
ci = getIrAggr(p.cd)->getClassInfoSymbol();
}

View file

@ -624,18 +624,11 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) {
}
const auto irMangle = getIRMangledVarName(mangled, LINKd);
LLGlobalVariable *gvar = gIR->module.getGlobalVariable(irMangle);
if (gvar) {
assert(gvar->getType()->getContainedType(0)->isStructTy());
} else {
LLType *type = DtoType(decl->type)->getPointerElementType();
// Create the symbol. We need to keep it mutable as the type is not declared
// as immutable on the D side, and e.g. synchronized() can be used on the
// implicit monitor.
gvar =
new LLGlobalVariable(gIR->module, type, false,
LLGlobalValue::ExternalLinkage, nullptr, irMangle);
}
// Declare the symbol. We need to keep it mutable as the type is not
// declared as immutable on the D side, and e.g. synchronized() can be used
// on the implicit monitor.
auto gvar = declareGlobal(decl->loc, gIR->module, type, irMangle, false);
IrGlobal *irg = getIrGlobal(decl, true);
irg->value = gvar;

View file

@ -49,9 +49,8 @@ LLConstant *&IrAggr::getInitSymbol() {
// create the initZ symbol
const auto irMangle = getIRMangledInitSymbolName(aggrdecl);
auto initGlobal =
getOrCreateGlobal(aggrdecl->loc, gIR->module, getLLStructType(), true,
llvm::GlobalValue::ExternalLinkage, nullptr, irMangle);
auto initGlobal = declareGlobal(aggrdecl->loc, gIR->module, getLLStructType(),
irMangle, /*isConstant=*/true);
initGlobal->setAlignment(DtoAlignment(type));
init = initGlobal;

View file

@ -51,9 +51,8 @@ LLGlobalVariable *IrAggr::getVtblSymbol() {
LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType();
vtbl =
getOrCreateGlobal(aggrdecl->loc, gIR->module, vtblTy, true,
llvm::GlobalValue::ExternalLinkage, nullptr, irMangle);
vtbl = declareGlobal(aggrdecl->loc, gIR->module, vtblTy, irMangle,
/*isConstant=*/true);
return vtbl;
}
@ -77,9 +76,8 @@ LLGlobalVariable *IrAggr::getClassInfoSymbol() {
assert(tc && "invalid ClassInfo type");
// classinfos cannot be constants since they're used as locks for synchronized
classInfo = getOrCreateGlobal(
aggrdecl->loc, gIR->module, tc->getMemoryLLType(), false,
llvm::GlobalValue::ExternalLinkage, nullptr, irMangle);
classInfo = declareGlobal(aggrdecl->loc, gIR->module, tc->getMemoryLLType(),
irMangle, false);
// Generate some metadata on this ClassInfo if it's for a class.
ClassDeclaration *classdecl = aggrdecl->isClassDeclaration();
@ -139,11 +137,8 @@ LLGlobalVariable *IrAggr::getInterfaceArraySymbol() {
LLArrayType *array_type = llvm::ArrayType::get(InterfaceTy, n);
// We keep the global as external for now and only consider template linkage
// if we emit the initializer later.
classInterfacesArray =
getOrCreateGlobal(cd->loc, gIR->module, array_type, true,
llvm::GlobalValue::ExternalLinkage, nullptr, irMangle);
classInterfacesArray = declareGlobal(cd->loc, gIR->module, array_type,
irMangle, /*isConstant=*/true);
return classInterfacesArray;
}
@ -457,8 +452,8 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
const auto lwc = DtoLinkage(cd);
LLGlobalVariable *GV =
getOrCreateGlobal(cd->loc, gIR->module, vtbl_constant->getType(), true,
lwc.first, vtbl_constant, irMangle);
defineGlobal(cd->loc, gIR->module, irMangle, vtbl_constant,
lwc.first, /*isConstant=*/true);
setLinkage(lwc, GV);
// insert into the vtbl map

View file

@ -11,6 +11,7 @@
#include "module.h"
#include "gen/llvm.h"
#include "gen/irstate.h"
#include "gen/llvmhelpers.h"
#include "gen/mangling.h"
#include "gen/tollvm.h"
#include "ir/irdsymbol.h"
@ -25,9 +26,9 @@ llvm::GlobalVariable *IrModule::moduleInfoSymbol() {
const auto irMangle = getIRMangledModuleInfoSymbolName(M);
moduleInfoVar = new llvm::GlobalVariable(
gIR->module, llvm::StructType::create(gIR->context()), false,
llvm::GlobalValue::ExternalLinkage, nullptr, irMangle);
moduleInfoVar =
declareGlobal(Loc(), gIR->module,
llvm::StructType::create(gIR->context()), irMangle, false);
return moduleInfoVar;
}