Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ class CodegenVisitor : public Visitor {
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol();
// Only define if not speculative.
if (!isSpeculativeType(decl->type)) {
interfaceZ->setInitializer(ir->getClassInfoInit());
setLinkage(decl, interfaceZ);
defineGlobal(interfaceZ, ir->getClassInfoInit(), decl);
}
}
}
Expand Down Expand Up @@ -186,21 +185,20 @@ class CodegenVisitor : public Visitor {
}

IrAggr *ir = getIrAggr(decl);
const auto lwc = DtoLinkage(decl);

auto &initZ = ir->getInitSymbol();
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkage(lwc, initGlobal);
setLinkage(decl, initGlobal);

llvm::GlobalVariable *vtbl = ir->getVtblSymbol();
vtbl->setInitializer(ir->getVtblInit());
setLinkage(lwc, vtbl);
defineGlobal(vtbl, ir->getVtblInit(), decl);

ir->defineInterfaceVtbls();

llvm::GlobalVariable *classZ = ir->getClassInfoSymbol();
if (!isSpeculativeType(decl->type)) {
classZ->setInitializer(ir->getClassInfoInit());
setLinkage(lwc, classZ);
defineGlobal(classZ, ir->getClassInfoInit(), decl);
}
}
}
Expand Down
76 changes: 54 additions & 22 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -1751,19 +1746,32 @@ 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);
static std::string llvmTypeToString(llvm::Type *type) {
std::string result;
llvm::raw_string_ostream stream(result);
stream << *type;
stream.flush();
return result;
}

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) {
const auto existingType = existing->getType()->getElementType();
if (existingType != type || existing->isConstant() != isConstant ||
existing->isThreadLocal() != isThreadLocal) {
const auto existingTypeName = llvmTypeToString(existingType);
const auto newTypeName = llvmTypeToString(type);
error(loc,
"Global variable type does not match previous declaration with "
"same mangled name: `%s`",
name.str().c_str());
mangledName.str().c_str());
errorSupplemental(loc, "Previous IR type: %s", existingTypeName.c_str());
errorSupplemental(loc, "New IR type: %s", newTypeName.c_str());
fatal();
}
return existing;
Expand All @@ -1772,14 +1780,38 @@ 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,
Dsymbol *symbolForLinkage) {
assert(global->isDeclaration() && "Global variable already defined");
assert(init);
global->setInitializer(init);
if (symbolForLinkage)
setLinkage(symbolForLinkage, global);
}

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, nullptr);
global->setLinkage(linkage);
return global;
}

FuncDeclaration *getParentFunc(Dsymbol *sym) {
Expand Down
29 changes: 20 additions & 9 deletions gen/llvmhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,29 @@ 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,
bool isThreadLocal = false);
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,
Dsymbol *symbolForLinkage);

/// 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);

Expand Down
53 changes: 23 additions & 30 deletions gen/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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_
llvm::GlobalValue::LinkOnceODRLinkage,
DtoBitCast(thisModuleInfo, moduleInfoPtrTy), thismrefIRMangle);
auto thismref = defineGlobal(Loc(), gIR->module, thismrefIRMangle,
DtoBitCast(thisModuleInfo, moduleInfoPtrTy),
llvm::GlobalValue::LinkOnceODRLinkage,
false // FIXME: mRelocModel != llvm::Reloc::PIC_
);
thismref->setSection(sectionName);
gIR->usedArray.push_back(thismref);

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Expand Down
16 changes: 9 additions & 7 deletions gen/ms-cxx-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -188,10 +187,13 @@ 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);

const LinkageWithCOMDAT lwc = {LLGlobalVariable::LinkOnceODRLinkage, true};
Var = defineGlobal(cd->loc, gIR->module, TypeDescName,
llvm::ConstantStruct::get(TypeDescriptorType, Fields),
lwc.first, /*isConstant=*/true);
setLinkage(lwc, Var);

return Var;
}

Expand Down
55 changes: 30 additions & 25 deletions gen/trycatchfinally.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,31 +161,36 @@ 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 mangleBuf;
mangleBuf.writestring("_D");
mangleToBuffer(p.cd, &mangleBuf);
mangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
const auto wrapperMangle = getIRMangledVarName(mangleBuf.peekString(), LINKd);

const auto cppTypeInfoPtrType = getCppTypeInfoPtrType();
RTTIBuilder b(cppTypeInfoPtrType);
b.push(cpp_ti);

auto wrapperType = llvm::cast<llvm::StructType>(
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype)
->getMemoryLLType());
auto wrapperInit = b.get_constant(wrapperType);

ci = getOrCreateGlobal(
p.cd->loc, irs.module, wrapperType, /*isConstant=*/true,
LLGlobalValue::LinkOnceODRLinkage, wrapperInit, wrapperMangle);
// 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);

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);
b.push(cpp_ti);

auto wrapperType = llvm::cast<llvm::StructType>(
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype)
->getMemoryLLType());
auto wrapperInit = b.get_constant(wrapperType);

ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit,
LLGlobalValue::LinkOnceODRLinkage,
/*isConstant=*/true);
}
} else {
ci = getIrAggr(p.cd)->getClassInfoSymbol();
}
Expand Down
Loading