Support #pragma comment(lib, "name") in the frontend for ELF
This adds the frontend support required to support the use of the comment pragma to enable auto linking on ELFish targets. This is a generic ELF extension supported by LLVM. We need to change the handling for the "dependentlib" in order to accommodate the previously discussed encoding for the dependent library descriptor. Without the custom handling of the PCK_Lib directive, the -l prefixed option would be encoded into the resulting object (which is treated as a frontend error). llvm-svn: 324438
This commit is contained in:
@@ -2725,3 +2725,11 @@ The ``#pragma clang section`` directive obeys the following rules:
|
||||
* The decision about which section-kind applies to each global is taken in the back-end.
|
||||
Once the section-kind is known, appropriate section name, as specified by the user using
|
||||
``#pragma clang section`` directive, is applied to that global.
|
||||
|
||||
Specifying Linker Options on ELF Targets
|
||||
========================================
|
||||
|
||||
The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets.
|
||||
The second parameter is the library name (without the traditional Unix prefix of
|
||||
``lib``). This allows you to provide an implicit link of dependent libraries.
|
||||
|
||||
|
||||
@@ -1411,6 +1411,12 @@ void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) {
|
||||
LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
|
||||
}
|
||||
|
||||
void CodeGenModule::AddELFLibDirective(StringRef Lib) {
|
||||
auto &C = getLLVMContext();
|
||||
LinkerOptionsMetadata.push_back(llvm::MDNode::get(
|
||||
C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)}));
|
||||
}
|
||||
|
||||
void CodeGenModule::AddDependentLib(StringRef Lib) {
|
||||
llvm::SmallString<24> Opt;
|
||||
getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
|
||||
@@ -4329,7 +4335,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
AppendLinkerOptions(PCD->getArg());
|
||||
break;
|
||||
case PCK_Lib:
|
||||
AddDependentLib(PCD->getArg());
|
||||
if (getTarget().getTriple().isOSBinFormatELF() &&
|
||||
!getTarget().getTriple().isPS4())
|
||||
AddELFLibDirective(PCD->getArg());
|
||||
else
|
||||
AddDependentLib(PCD->getArg());
|
||||
break;
|
||||
case PCK_Compiler:
|
||||
case PCK_ExeStr:
|
||||
|
||||
@@ -1094,6 +1094,8 @@ public:
|
||||
/// value.
|
||||
void AddDependentLib(StringRef Lib);
|
||||
|
||||
void AddELFLibDirective(StringRef Lib);
|
||||
|
||||
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
|
||||
|
||||
void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) {
|
||||
|
||||
@@ -295,7 +295,8 @@ void Parser::initializePragmaHandlers() {
|
||||
OpenMPHandler.reset(new PragmaNoOpenMPHandler());
|
||||
PP.AddPragmaHandler(OpenMPHandler.get());
|
||||
|
||||
if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
|
||||
if (getLangOpts().MicrosoftExt ||
|
||||
getTargetInfo().getTriple().isOSBinFormatELF()) {
|
||||
MSCommentHandler.reset(new PragmaCommentHandler(Actions));
|
||||
PP.AddPragmaHandler(MSCommentHandler.get());
|
||||
}
|
||||
@@ -377,7 +378,8 @@ void Parser::resetPragmaHandlers() {
|
||||
PP.RemovePragmaHandler(OpenMPHandler.get());
|
||||
OpenMPHandler.reset();
|
||||
|
||||
if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
|
||||
if (getLangOpts().MicrosoftExt ||
|
||||
getTargetInfo().getTriple().isOSBinFormatELF()) {
|
||||
PP.RemovePragmaHandler(MSCommentHandler.get());
|
||||
MSCommentHandler.reset();
|
||||
}
|
||||
@@ -2449,6 +2451,12 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
|
||||
return;
|
||||
}
|
||||
|
||||
if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
|
||||
<< II->getName();
|
||||
return;
|
||||
}
|
||||
|
||||
// On PS4, issue a warning about any pragma comments other than
|
||||
// #pragma comment lib.
|
||||
if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
|
||||
|
||||
7
clang/test/CodeGen/elf-linker-options.c
Normal file
7
clang/test/CodeGen/elf-linker-options.c
Normal file
@@ -0,0 +1,7 @@
|
||||
// RUN: %clang_cc1 -triple i686---elf -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
#pragma comment(lib, "alpha")
|
||||
|
||||
// CHECK: !llvm.linker.options = !{[[NODE:![0-9]+]]}
|
||||
// CHECK: [[NODE]] = !{!"lib", !"alpha"}
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
// CHECK: ![[bar]] = !{!" /bar=2"}
|
||||
// CHECK: ![[foo]] = !{!" /foo=\22foo bar\22"}
|
||||
|
||||
// LINUX: !{!"-lmsvcrt.lib"}
|
||||
// LINUX: !{!"-lkernel32"}
|
||||
// LINUX: !{!"-lUSER32.LIB"}
|
||||
// LINUX: !{!" /bar=2"}
|
||||
// LINUX: !{!"lib", !"msvcrt.lib"}
|
||||
// LINUX: !{!"lib", !"kernel32"}
|
||||
// LINUX: !{!"lib", !"USER32.LIB"}
|
||||
|
||||
// PS4: !{!"\01msvcrt.lib"}
|
||||
// PS4: !{!"\01kernel32"}
|
||||
|
||||
5
clang/test/Preprocessor/pragma-comment-linux.c
Normal file
5
clang/test/Preprocessor/pragma-comment-linux.c
Normal file
@@ -0,0 +1,5 @@
|
||||
// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s -Wunknown-pragmas
|
||||
|
||||
#pragma comment(linker, "")
|
||||
// expected-warning@-1 {{'#pragma comment linker' ignored}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas
|
||||
// RUN: not %clang_cc1 %s -fms-extensions -E | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple i686-unknown-windows-msvc %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas
|
||||
// RUN: not %clang_cc1 -triple i686-unknown-windows-msvc %s -fms-extensions -E | FileCheck %s
|
||||
// REQUIRES: non-ps4-sdk
|
||||
|
||||
// rdar://6495941
|
||||
|
||||
Reference in New Issue
Block a user