mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 23:50:43 +03:00
Allow multiple declarations to share the same mangled name/LLVM global.
This is necessary to enable aliasing compiler-generated symbols with pragma(mangle, …). Note that globals for internal use are still directly created.
This commit is contained in:
parent
0305d3bce2
commit
acd508945a
9 changed files with 63 additions and 34 deletions
|
@ -605,7 +605,8 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT)
|
|||
name.append("__OffsetTypeInfos");
|
||||
|
||||
// create symbol
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
|
||||
llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, *gIR->module, arrTy,
|
||||
true,DtoInternalLinkage(cd),arrInit,name);
|
||||
ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
|
||||
|
||||
return DtoConstSlice(size, ptr);
|
||||
|
|
|
@ -98,23 +98,6 @@ void TupleDeclaration::codegen(Ir* p)
|
|||
|
||||
/* ================================================================== */
|
||||
|
||||
static llvm::GlobalVariable* createGlobal(llvm::Type* type, bool isConst,
|
||||
llvm::GlobalValue::LinkageTypes linkage, llvm::StringRef name,
|
||||
bool isThreadLocal)
|
||||
{
|
||||
#if LDC_LLVM_VER >= 302
|
||||
// FIXME: clang uses a command line option for the thread model
|
||||
const llvm::GlobalVariable::ThreadLocalMode tlsModel =
|
||||
isThreadLocal ? llvm::GlobalVariable::GeneralDynamicTLSModel
|
||||
: llvm::GlobalVariable::NotThreadLocal;
|
||||
return new llvm::GlobalVariable(*gIR->module, type, isConst, linkage,
|
||||
NULL, name, 0, tlsModel);
|
||||
#else
|
||||
return new llvm::GlobalVariable(*gIR->module, type, isConst, linkage,
|
||||
NULL, name, 0, isThreadLocal);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VarDeclaration::codegen(Ir* p)
|
||||
{
|
||||
Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars());
|
||||
|
@ -171,8 +154,9 @@ void VarDeclaration::codegen(Ir* p)
|
|||
// this->ir.irGlobal->value!), and in case we also do an initializer
|
||||
// with a different type later, swap it out and replace any existing
|
||||
// uses with bitcasts to the previous type.
|
||||
llvm::GlobalVariable* gvar = createGlobal(i1ToI8(DtoType(type)), isLLConst,
|
||||
llLinkage, llName, isThreadlocal());
|
||||
llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module,
|
||||
i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName,
|
||||
isThreadlocal());
|
||||
this->ir.irGlobal->value = gvar;
|
||||
|
||||
// Check if we are defining or just declaring the global in this module.
|
||||
|
@ -184,8 +168,8 @@ void VarDeclaration::codegen(Ir* p)
|
|||
// In case of type mismatch, swap out the variable.
|
||||
if (initVal->getType() != gvar->getType()->getElementType())
|
||||
{
|
||||
llvm::GlobalVariable* newGvar = createGlobal(
|
||||
initVal->getType(), isLLConst, llLinkage,
|
||||
llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc,
|
||||
*gIR->module, initVal->getType(), isLLConst, llLinkage, 0,
|
||||
"", // We take on the name of the old global below.
|
||||
isThreadlocal());
|
||||
|
||||
|
|
|
@ -2024,3 +2024,32 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl)
|
|||
|
||||
llvm_unreachable("Taking constant address not implemented.");
|
||||
}
|
||||
|
||||
llvm::GlobalVariable* getOrCreateGlobal(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);
|
||||
if (existing)
|
||||
{
|
||||
if (existing->getType()->getElementType() != type)
|
||||
{
|
||||
error(loc, "Global variable type does not match previous "
|
||||
"declaration with same mangled name: %s", name.str().c_str());
|
||||
fatal();
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
#if LDC_LLVM_VER >= 302
|
||||
// FIXME: clang uses a command line option for the thread model
|
||||
const llvm::GlobalVariable::ThreadLocalMode tlsModel =
|
||||
isThreadLocal ? llvm::GlobalVariable::GeneralDynamicTLSModel
|
||||
: llvm::GlobalVariable::NotThreadLocal;
|
||||
return new llvm::GlobalVariable(module, type, isConstant, linkage,
|
||||
init, name, 0, tlsModel);
|
||||
#else
|
||||
return new llvm::GlobalVariable(module, type, isConstant, linkage,
|
||||
init, name, 0, isThreadLocal);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -226,4 +226,16 @@ LLConstant* toConstantArray(LLType* ct, LLArrayType* at, T* str, size_t len, boo
|
|||
return LLConstantArray::get(at, vals);
|
||||
}
|
||||
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Necessary to support multiple declarations with the same mangled name, as
|
||||
/// can be the case due to pragma(mangle).
|
||||
llvm::GlobalVariable* getOrCreateGlobal(Loc loc, llvm::Module& module,
|
||||
llvm::Type* type, bool isConstant, llvm::GlobalValue::LinkageTypes linkage,
|
||||
llvm::Constant* init, llvm::StringRef name, bool isThreadLocal = false);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -178,8 +178,9 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
|
|||
std::string thismrefname = "_D";
|
||||
thismrefname += gIR->dmodule->mangle();
|
||||
thismrefname += "11__moduleRefZ";
|
||||
LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname);
|
||||
|
||||
LLGlobalVariable* thismref = getOrCreateGlobal(Loc(), *gIR->module,
|
||||
modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
|
||||
thismrefname);
|
||||
// make sure _Dmodule_ref is declared
|
||||
LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
|
||||
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
|
||||
|
@ -341,7 +342,8 @@ llvm::GlobalVariable* Module::moduleInfoSymbol()
|
|||
|
||||
// declare global
|
||||
// flags will be modified at runtime so can't make it constant
|
||||
moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);
|
||||
moduleInfoVar = getOrCreateGlobal(loc, *gIR->module, moduleInfoType,
|
||||
false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);
|
||||
|
||||
return moduleInfoVar;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma
|
|||
std::string initname(mangle_sym->mangle());
|
||||
initname.append(".rtti.voidarr.data");
|
||||
|
||||
LLGlobalVariable* G = new llvm::GlobalVariable(
|
||||
LLGlobalVariable* G = new LLGlobalVariable(
|
||||
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
||||
G->setAlignment(valtype->alignsize());
|
||||
|
||||
|
@ -105,7 +105,7 @@ void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, D
|
|||
initname.append(tmpStr);
|
||||
initname.append(".data");
|
||||
|
||||
LLGlobalVariable* G = new llvm::GlobalVariable(
|
||||
LLGlobalVariable* G = new LLGlobalVariable(
|
||||
*gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname);
|
||||
G->setAlignment(valtype->alignsize());
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "root.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/llvm.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/irtype.h"
|
||||
|
@ -121,7 +122,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char*
|
|||
}
|
||||
|
||||
LLPointerType* t = g->getType();
|
||||
return new LLGlobalVariable(*target, t->getElementType(), g->isConstant(),
|
||||
return getOrCreateGlobal(Loc(), *target, t->getElementType(), g->isConstant(),
|
||||
g->getLinkage(), NULL, g->getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ LLGlobalVariable * IrAggr::getInitSymbol()
|
|||
|
||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||
|
||||
init = new llvm::GlobalVariable(
|
||||
init = getOrCreateGlobal(aggrdecl->loc,
|
||||
*gIR->module, init_type, true, _linkage, NULL, initname);
|
||||
|
||||
// set alignment
|
||||
|
|
|
@ -56,7 +56,7 @@ LLGlobalVariable * IrAggr::getVtblSymbol()
|
|||
|
||||
LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
|
||||
|
||||
vtbl = new llvm::GlobalVariable(
|
||||
vtbl = getOrCreateGlobal(aggrdecl->loc,
|
||||
*gIR->module, vtblTy, true, _linkage, NULL, initname);
|
||||
|
||||
return vtbl;
|
||||
|
@ -86,7 +86,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol()
|
|||
assert(tc && "invalid ClassInfo type");
|
||||
|
||||
// classinfos cannot be constants since they're used as locks for synchronized
|
||||
classInfo = new llvm::GlobalVariable(
|
||||
classInfo = getOrCreateGlobal(aggrdecl->loc,
|
||||
*gIR->module, tc->getMemoryLLType(), false, _linkage, NULL, initname);
|
||||
|
||||
// Generate some metadata on this ClassInfo if it's for a class.
|
||||
|
@ -138,7 +138,7 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol()
|
|||
name.append("16__interfaceInfosZ");
|
||||
|
||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||
classInterfacesArray = new llvm::GlobalVariable(*gIR->module,
|
||||
classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
|
||||
array_type, true, _linkage, NULL, name);
|
||||
|
||||
return classInterfacesArray;
|
||||
|
@ -335,7 +335,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance
|
|||
mangle.append(b->base->mangle());
|
||||
mangle.append("6__vtblZ");
|
||||
|
||||
llvm::GlobalVariable* GV = new llvm::GlobalVariable(
|
||||
llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
|
||||
*gIR->module,
|
||||
vtbl_constant->getType(),
|
||||
true,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue