From c38baa7d958d6de986f71f9838d495f2c626e469 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Fri, 25 Jan 2019 13:16:49 +0100 Subject: [PATCH 1/2] Enable pragma(LDC_extern_weak) on function declarations. --- gen/functions.cpp | 9 ++++++--- gen/pragma.cpp | 10 +++++++++- tests/codegen/pragma_LDC_extern_weak.d | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 tests/codegen/pragma_LDC_extern_weak.d diff --git a/gen/functions.cpp b/gen/functions.cpp index a89a6f681b9..dbf0ef90061 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -551,9 +551,12 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) { LLFunction *func = vafunc ? vafunc : gIR->module.getFunction(irMangle); if (!func) { // All function declarations are "external" - any other linkage type - // is set when actually defining the function. - func = LLFunction::Create(functype, llvm::GlobalValue::ExternalLinkage, - irMangle, &gIR->module); + // is set when actually defining the function, except extern_weak. + auto linkage = llvm::GlobalValue::ExternalLinkage; + // Apply pragma(LDC_extern_weak) + if (fdecl->llvmInternal == LLVMextern_weak) + linkage = llvm::GlobalValue::ExternalWeakLinkage; + func = LLFunction::Create(functype, linkage, irMangle, &gIR->module); } else if (func->getFunctionType() != functype) { const auto existingTypeString = llvmTypeToString(func->getFunctionType()); const auto newTypeString = llvmTypeToString(functype); diff --git a/gen/pragma.cpp b/gen/pragma.cpp index 1975be5c77f..9e43ce8361e 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -499,7 +499,7 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, } case LLVMextern_weak: { - const int count = applyVariablePragma(s, [=](VarDeclaration *vd) { + int count = applyVariablePragma(s, [=](VarDeclaration *vd) { if (!vd->isDataseg() || !(vd->storage_class & STCextern)) { error(s->loc, "`%s` requires storage class `extern`", ident->toChars()); fatal(); @@ -516,6 +516,14 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, } vd->llvmInternal = llvm_internal; }); + count += applyFunctionPragma(s, [=](FuncDeclaration *fd) { + if (fd->fbody) { + error(s->loc, "`%s` cannot be applied to function definitions", ident->toChars()); + fatal(); + } + fd->llvmInternal = llvm_internal; + }); + if (count == 0) { error(s->loc, "the `%s` pragma doesn't affect any variable declarations", ident->toChars()); diff --git a/tests/codegen/pragma_LDC_extern_weak.d b/tests/codegen/pragma_LDC_extern_weak.d new file mode 100644 index 00000000000..a6456a91c30 --- /dev/null +++ b/tests/codegen/pragma_LDC_extern_weak.d @@ -0,0 +1,21 @@ +// Test pragma(LDC_extern_weak) on function declarations. + +// RUN: %ldc -d-version=DECLARATION -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll --check-prefix=DECLARATION +// RUN: not %ldc -d-version=DEFINITION %s 2>&1 | FileCheck %s --check-prefix=DEFINITION + +version(DECLARATION) +{ +// DECLARATION: declare{{.*}} extern_weak {{.*}}weakreffunction +pragma(LDC_extern_weak) extern(C) void weakreffunction(); +} + +version(DEFINITION) +{ +// DEFINITION: Error: `LDC_extern_weak` cannot be applied to function definitions +pragma(LDC_extern_weak) extern(C) void weakreffunction() {}; +} + +void foo() +{ + auto a = &weakreffunction; +} From 31c301b94f7d8596401fb33a89190049a031c783 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Fri, 25 Jan 2019 17:14:01 +0100 Subject: [PATCH 2/2] fixup --- gen/pragma.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gen/pragma.cpp b/gen/pragma.cpp index 9e43ce8361e..e376aa9c3a7 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -525,7 +525,9 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, }); if (count == 0) { - error(s->loc, "the `%s` pragma doesn't affect any variable declarations", + error(s->loc, + "the `%s` pragma doesn't affect any variable or function " + "declarations", ident->toChars()); fatal(); }