Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: Make -fvisibility=public export all defined symbols and import external data #3703

Merged
merged 11 commits into from
May 21, 2021
Merged
4 changes: 4 additions & 0 deletions dmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ version (IN_LLVM)
bool outputSourceLocations; // if true, output line tables.

bool linkonceTemplates; // -linkonce-templates

// Windows-specific:
bool dllexport; // dllexport ~all defined symbols?
bool dllimport; // dllimport data symbols not defined in any root module?
} // IN_LLVM
}

Expand Down
4 changes: 4 additions & 0 deletions dmd/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,10 @@ struct Param
bool outputSourceLocations; // if true, output line tables.

bool linkonceTemplates; // -linkonce-templates

// Windows-specific:
bool dllexport; // dllexport ~all defined symbols?
bool dllimport; // dllimport data symbols not defined in any root module?
#endif
};

Expand Down
16 changes: 10 additions & 6 deletions driver/cl_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,16 @@ static cl::opt<bool, true>
createSharedLib("shared", cl::desc("Create shared library (DLL)"),
cl::ZeroOrMore, cl::location(global.params.dll));

cl::opt<unsigned char> defaultToHiddenVisibility(
"fvisibility", cl::ZeroOrMore,
cl::desc("Default visibility of symbols (not relevant for Windows)"),
cl::values(clEnumValN(0, "default", "Export all symbols"),
clEnumValN(1, "hidden",
"Only export symbols marked with 'export'")));
cl::opt<SymbolVisibility> symbolVisibility(
"fvisibility", cl::ZeroOrMore, cl::desc("Default visibility of symbols"),
cl::init(SymbolVisibility::default_),
cl::values(
clEnumValN(
SymbolVisibility::default_, "default",
"Hidden for Windows targets without -shared, otherwise public"),
clEnumValN(SymbolVisibility::hidden, "hidden",
"Only export symbols marked with 'export'"),
clEnumValN(SymbolVisibility::public_, "public", "Export all symbols")));

static cl::opt<bool, true> verbose("v", cl::desc("Verbose"), cl::ZeroOrMore,
cl::location(global.params.verbose));
Expand Down
3 changes: 2 additions & 1 deletion driver/cl_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ extern cl::opt<std::string> mTargetTriple;
extern cl::opt<std::string> mABI;
extern FloatABI::Type floatABI;
extern cl::opt<bool> disableLinkerStripDead;
extern cl::opt<unsigned char> defaultToHiddenVisibility;
enum class SymbolVisibility { default_, hidden, public_ };
extern cl::opt<SymbolVisibility> symbolVisibility;
extern cl::opt<bool> noPLT;
extern cl::opt<bool> useDIP25;

Expand Down
12 changes: 12 additions & 0 deletions driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,18 @@ int cppmain() {
global.params.symdebug = 1;
}

if (global.params.targetTriple->isOSWindows()) {
const auto v = opts::symbolVisibility.getValue();
global.params.dllexport =
v == opts::SymbolVisibility::public_ ||
// default with -shared
(v == opts::SymbolVisibility::default_ && global.params.dll);
global.params.dllimport =
v == opts::SymbolVisibility::public_ ||
// enforced when linking against shared default libs
linkAgainstSharedDefaultLibs();
}

// allocate the target abi
gABI = TargetABI::getTarget();

Expand Down
17 changes: 4 additions & 13 deletions gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,12 +667,6 @@ void DtoDeclareFunction(FuncDeclaration *fdecl, const bool willDefine) {

func->setCallingConv(gABI->callingConv(link, f, fdecl));

if (global.params.targetTriple->isOSWindows() && fdecl->isExport()) {
func->setDLLStorageClass(fdecl->isImportedSymbol()
? LLGlobalValue::DLLImportStorageClass
: LLGlobalValue::DLLExportStorageClass);
}

IF_LOG Logger::cout() << "func = " << *func << std::endl;

// add func to IRFunc
Expand Down Expand Up @@ -1029,9 +1023,10 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
assert(func);
if (!linkageAvailableExternally &&
(func->getLinkage() == llvm::GlobalValue::AvailableExternallyLinkage)) {
// Fix linkage
// Fix linkage and visibility
const auto lwc = lowerFuncLinkage(fd);
setLinkage(lwc, func);
setVisibility(fd, func);
}
return;
}
Expand Down Expand Up @@ -1151,10 +1146,6 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
return;
}

if (opts::defaultToHiddenVisibility && !fd->isExport()) {
func->setVisibility(LLGlobalValue::HiddenVisibility);
}

// if this function is naked, we take over right away! no standard processing!
if (fd->naked) {
DtoDefineNakedFunction(fd);
Expand Down Expand Up @@ -1191,10 +1182,9 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
lwc.first != llvm::GlobalValue::LinkOnceAnyLinkage);
} else {
setLinkage(lwc, func);
setVisibility(fd, func);
}

assert(!func->hasDLLImportStorageClass());

// function attributes
if (gABI->needsUnwindTables()) {
func->addFnAttr(LLAttribute::UWTable);
Expand Down Expand Up @@ -1383,6 +1373,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
}

if (func->getLinkage() == LLGlobalValue::WeakAnyLinkage &&
!func->hasDLLExportStorageClass() &&
global.params.targetTriple->isWindowsMSVCEnvironment()) {
emulateWeakAnyLinkageForMSVC(func, fd->linkage);
}
Expand Down
19 changes: 13 additions & 6 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,8 @@ std::string llvmTypeToString(llvm::Type *type) {
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type,
llvm::StringRef mangledName,
bool isConstant, bool isThreadLocal) {
bool isConstant, bool isThreadLocal,
bool useDLLImport) {
// No TLS support for WebAssembly and AVR; spare users from having to add
// __gshared everywhere.
const auto arch = global.params.targetTriple->getArch();
Expand Down Expand Up @@ -1714,9 +1715,14 @@ llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
: clThreadModel.getValue())
: llvm::GlobalVariable::NotThreadLocal;

return new llvm::GlobalVariable(module, type, isConstant,
llvm::GlobalValue::ExternalLinkage, nullptr,
mangledName, nullptr, tlsModel);
auto gvar = new llvm::GlobalVariable(module, type, isConstant,
llvm::GlobalValue::ExternalLinkage,
nullptr, mangledName, nullptr, tlsModel);

if (useDLLImport && global.params.targetTriple->isOSWindows())
gvar->setDLLStorageClass(LLGlobalValue::DLLImportStorageClass);

return gvar;
}

void defineGlobal(llvm::GlobalVariable *global, llvm::Constant *init,
Expand All @@ -1734,8 +1740,9 @@ llvm::GlobalVariable *defineGlobal(const Loc &loc, llvm::Module &module,
llvm::GlobalValue::LinkageTypes linkage,
bool isConstant, bool isThreadLocal) {
assert(init);
auto global = declareGlobal(loc, module, init->getType(), mangledName,
isConstant, isThreadLocal);
auto global =
declareGlobal(loc, module, init->getType(), mangledName, isConstant,
isThreadLocal, /*useDLLImport*/ false);
defineGlobal(global, init, nullptr);
global->setLinkage(linkage);
return global;
Expand Down
4 changes: 2 additions & 2 deletions gen/llvmhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ llvm::Constant *buildStringLiteralConstant(StringExp *se, bool zeroTerm);
llvm::GlobalVariable *declareGlobal(const Loc &loc, llvm::Module &module,
llvm::Type *type,
llvm::StringRef mangledName,
bool isConstant,
bool isThreadLocal = false);
bool isConstant, bool isThreadLocal,
bool useDLLImport);

/// Defines an existing LLVM global, i.e., sets the initial value and finalizes
/// its linkage and visibility.
Expand Down
3 changes: 3 additions & 0 deletions gen/moduleinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,5 +312,8 @@ llvm::GlobalVariable *genModuleInfo(Module *m) {
LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
b.finalize(moduleInfoSym);
setLinkage({LLGlobalValue::ExternalLinkage, needsCOMDAT()}, moduleInfoSym);
if (global.params.dllexport) {
moduleInfoSym->setDLLStorageClass(LLGlobalValue::DLLExportStorageClass);
}
return moduleInfoSym;
}
5 changes: 3 additions & 2 deletions gen/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ RegistryStyle getModuleRegistryStyle() {
LLGlobalVariable *declareDSOGlobal(llvm::StringRef mangledName, LLType *type,
bool isThreadLocal = false) {
auto global = declareGlobal(Loc(), gIR->module, type, mangledName, false,
isThreadLocal);
isThreadLocal, false);
global->setVisibility(LLGlobalValue::HiddenVisibility);
return global;
}
Expand Down Expand Up @@ -190,7 +190,8 @@ LLFunction *build_module_reference_and_ctor(const char *moduleMangle,
LLConstant *mref = gIR->module.getNamedGlobal(mrefIRMangle);
LLType *modulerefPtrTy = getPtrToType(modulerefTy);
if (!mref) {
mref = declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle, false);
mref = declareGlobal(Loc(), gIR->module, modulerefPtrTy, mrefIRMangle,
false, false, global.params.dllimport);
}
mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));

Expand Down
3 changes: 2 additions & 1 deletion gen/ms-cxx-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ llvm::GlobalVariable *getTypeDescriptor(IRState &irs, ClassDeclaration *cd) {
if (cd->isCPPclass()) {
const char *name = target.cpp.typeInfoMangle(cd);
return declareGlobal(cd->loc, irs.module, getVoidPtrType(), name,
/*isConstant=*/true);
/*isConstant*/ true, false,
/*useDLLImport*/ cd->isExport());
}

llvm::GlobalVariable *&Var = irs.TypeDescriptorMap[cd];
Expand Down
4 changes: 2 additions & 2 deletions gen/naked.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ void DtoDefineNakedFunction(FuncDeclaration *fd) {
gIR->module.appendModuleInlineAsm(asmstr.str());
asmstr.str("");

if (global.params.targetTriple->isWindowsMSVCEnvironment() &&
fd->isExport()) {
if (global.params.dllexport ||
(global.params.targetTriple->isOSWindows() && fd->isExport())) {
// Embed a linker switch telling the MS linker to export the naked function.
// This mimics the effect of the dllexport attribute for regular functions.
const auto linkerSwitch = std::string("/EXPORT:") + mangle;
Expand Down
4 changes: 4 additions & 0 deletions gen/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,10 @@ bool ldc_optimize_module(llvm::Module *M) {

addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel());

if (global.params.dllimport) {
mpm.add(createDLLImportRelocationPass());
}

// Run per-function passes.
fpm.doInitialization();
for (auto &F : *M) {
Expand Down
Loading