mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 15:40:55 +03:00
Map export
visibility to LLVM DLL storage classes
Compatible with DMD, but restricted to Windows and functions only. `export` functions with bodies get the dllexport attribute and will be exported if the containing object is pulled in when linking. Body-less `export` functions get the dllimport attribute and will be accessed via an import table indirection, set up at runtime by the OS. This is a temporary solution, the proper fix is a pending DMD PR, after which LDC will need to be adapted.
This commit is contained in:
parent
8a2a6c1e7f
commit
67d5fe5624
6 changed files with 60 additions and 1 deletions
|
@ -356,6 +356,7 @@ public:
|
||||||
setLinkage(lwc, newGvar);
|
setLinkage(lwc, newGvar);
|
||||||
|
|
||||||
newGvar->setAlignment(gvar->getAlignment());
|
newGvar->setAlignment(gvar->getAlignment());
|
||||||
|
newGvar->setDLLStorageClass(gvar->getDLLStorageClass());
|
||||||
applyVarDeclUDAs(decl, newGvar);
|
applyVarDeclUDAs(decl, newGvar);
|
||||||
newGvar->takeName(gvar);
|
newGvar->takeName(gvar);
|
||||||
|
|
||||||
|
@ -368,6 +369,8 @@ public:
|
||||||
irGlobal->value = newGvar;
|
irGlobal->value = newGvar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!gvar->hasDLLImportStorageClass());
|
||||||
|
|
||||||
// Now, set the initializer.
|
// Now, set the initializer.
|
||||||
assert(!irGlobal->constInit);
|
assert(!irGlobal->constInit);
|
||||||
irGlobal->constInit = initVal;
|
irGlobal->constInit = initVal;
|
||||||
|
|
|
@ -538,6 +538,12 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
|
||||||
|
|
||||||
func->setCallingConv(gABI->callingConv(func->getFunctionType(), link, fdecl));
|
func->setCallingConv(gABI->callingConv(func->getFunctionType(), link, fdecl));
|
||||||
|
|
||||||
|
if (global.params.isWindows && fdecl->isExport()) {
|
||||||
|
func->setDLLStorageClass(fdecl->isImportedSymbol()
|
||||||
|
? LLGlobalValue::DLLImportStorageClass
|
||||||
|
: LLGlobalValue::DLLExportStorageClass);
|
||||||
|
}
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "func = " << *func << std::endl;
|
IF_LOG Logger::cout() << "func = " << *func << std::endl;
|
||||||
|
|
||||||
// add func to IRFunc
|
// add func to IRFunc
|
||||||
|
@ -906,11 +912,12 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
|
|
||||||
const auto f = static_cast<TypeFunction *>(fd->type->toBasetype());
|
const auto f = static_cast<TypeFunction *>(fd->type->toBasetype());
|
||||||
IrFuncTy &irFty = irFunc->irFty;
|
IrFuncTy &irFty = irFunc->irFty;
|
||||||
llvm::Function *func = irFunc->func;;
|
llvm::Function *func = irFunc->func;
|
||||||
|
|
||||||
const auto lwc = lowerFuncLinkage(fd);
|
const auto lwc = lowerFuncLinkage(fd);
|
||||||
if (linkageAvailableExternally) {
|
if (linkageAvailableExternally) {
|
||||||
func->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
|
func->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
|
||||||
|
func->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
|
||||||
// Assert that we are not overriding a linkage type that disallows inlining
|
// Assert that we are not overriding a linkage type that disallows inlining
|
||||||
assert(lwc.first != llvm::GlobalValue::WeakAnyLinkage &&
|
assert(lwc.first != llvm::GlobalValue::WeakAnyLinkage &&
|
||||||
lwc.first != llvm::GlobalValue::ExternalWeakLinkage &&
|
lwc.first != llvm::GlobalValue::ExternalWeakLinkage &&
|
||||||
|
@ -919,6 +926,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
setLinkage(lwc, func);
|
setLinkage(lwc, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!func->hasDLLImportStorageClass());
|
||||||
|
|
||||||
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
// On x86_64, always set 'uwtable' for System V ABI compatibility.
|
||||||
// TODO: Find a better place for this.
|
// TODO: Find a better place for this.
|
||||||
// TODO: Is this required for Win64 as well?
|
// TODO: Is this required for Win64 as well?
|
||||||
|
|
|
@ -851,6 +851,14 @@ void DtoResolveVariable(VarDeclaration *vd) {
|
||||||
// as well).
|
// as well).
|
||||||
gvar->setAlignment(DtoAlignment(vd));
|
gvar->setAlignment(DtoAlignment(vd));
|
||||||
|
|
||||||
|
/* TODO: set DLL storage class when `export` is fixed (an attribute)
|
||||||
|
if (global.params.isWindows && vd->isExport()) {
|
||||||
|
auto c = vd->isImportedSymbol() ? LLGlobalValue::DLLImportStorageClass
|
||||||
|
: LLGlobalValue::DLLExportStorageClass;
|
||||||
|
gvar->setDLLStorageClass(c);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
applyVarDeclUDAs(vd, gvar);
|
applyVarDeclUDAs(vd, gvar);
|
||||||
|
|
||||||
IF_LOG Logger::cout() << *gvar << '\n';
|
IF_LOG Logger::cout() << *gvar << '\n';
|
||||||
|
|
19
tests/codegen/export.d
Normal file
19
tests/codegen/export.d
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// RUN: %ldc -output-ll -of=%t.ll %s
|
||||||
|
// RUN: FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// REQUIRES: Windows
|
||||||
|
|
||||||
|
export
|
||||||
|
{
|
||||||
|
// CHECK-DAG: define dllexport {{.*}}_D6export11exportedFooFZv
|
||||||
|
void exportedFoo() {}
|
||||||
|
|
||||||
|
// CHECK-DAG: declare dllimport {{.*}}_D6export11importedFooFZv
|
||||||
|
void importedFoo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar()
|
||||||
|
{
|
||||||
|
exportedFoo();
|
||||||
|
importedFoo();
|
||||||
|
}
|
19
tests/codegen/export_crossModuleInlining.d
Normal file
19
tests/codegen/export_crossModuleInlining.d
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Make sure exported functions can be cross-module inlined without exporting the local function copy.
|
||||||
|
|
||||||
|
// REQUIRES: atleast_llvm307
|
||||||
|
|
||||||
|
// RUN: %ldc -O -release -enable-cross-module-inlining -output-ll -of=%t.ll -I%S/inputs %s
|
||||||
|
// RUN: FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
import export2;
|
||||||
|
|
||||||
|
// CHECK-NOT: _D7export23fooFZi
|
||||||
|
|
||||||
|
// CHECK: define {{.*}}_D26export_crossModuleInlining3barFZi
|
||||||
|
int bar()
|
||||||
|
{
|
||||||
|
// CHECK-NEXT: ret i32 666
|
||||||
|
return foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-NOT: _D7export23fooFZi
|
1
tests/codegen/inputs/export2.d
Normal file
1
tests/codegen/inputs/export2.d
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export int foo() { return 666; }
|
Loading…
Add table
Add a link
Reference in a new issue