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).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324438 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Saleem Abdulrasool 2018-02-07 01:46:46 +00:00
parent c1b9c07504
commit bcd5214fa1
8 changed files with 48 additions and 9 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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) {

View File

@ -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) {

View 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"}

View File

@ -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"}

View 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}}

View File

@ -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