diff options
author | Reid Kleckner <reid@kleckner.net> | 2013-05-08 13:44:39 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2013-05-08 13:44:39 +0000 |
commit | e43f0fea153bd67e39f085d92d9e12ada915bb99 (patch) | |
tree | 6e125ab241ac35e231eb1aca174c107b03fd2347 /clang/lib/CodeGen | |
parent | 7bbd7aa7fe63f9df9e4d30355180cfcf0785973c (diff) | |
download | bcm5719-llvm-e43f0fea153bd67e39f085d92d9e12ada915bb99.tar.gz bcm5719-llvm-e43f0fea153bd67e39f085d92d9e12ada915bb99.zip |
Forward #pragma comment(lib/linker) through as flags metadata
Summary:
Most of this change is wiring the pragma all the way through from the
lexer, parser, and sema to codegen. I considered adding a Decl AST node
for this, but it seemed too heavyweight.
Mach-O already uses a metadata flag called "Linker Options" to do this
kind of auto-linking. This change follows that pattern.
LLVM knows how to forward the "Linker Options" metadata into the COFF
.drectve section where these flags belong. ELF support is not
implemented, but possible.
This is related to auto-linking, which is http://llvm.org/PR13016.
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D723
llvm-svn: 181426
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CodeGenAction.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 45 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/ModuleBuilder.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 32 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.h | 6 |
6 files changed, 92 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 679cfeb6ed3..9570076574c 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -179,6 +179,14 @@ namespace clang { Gen->HandleVTable(RD, DefinitionRequired); } + virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) { + Gen->HandleLinkerOptionPragma(Opts); + } + + virtual void HandleDependentLibrary(llvm::StringRef Opts) { + Gen->HandleDependentLibrary(Opts); + } + static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, unsigned LocCookie) { SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0b03a3c4b67..1da4e87c0a5 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -186,7 +186,8 @@ void CodeGenModule::Release() { EmitStaticExternCAliases(); EmitLLVMUsed(); - if (CodeGenOpts.Autolink && Context.getLangOpts().Modules) { + if (CodeGenOpts.Autolink && + (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) { EmitModuleLinkOptions(); } @@ -762,31 +763,41 @@ void CodeGenModule::EmitLLVMUsed() { GV->setSection("llvm.metadata"); } +void CodeGenModule::AppendLinkerOptions(StringRef Opts) { + llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opts); + LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); +} + +void CodeGenModule::AddDependentLib(StringRef Lib) { + llvm::SmallString<24> Opt; + getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt); + llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt); + LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); +} + /// \brief Add link options implied by the given module, including modules /// it depends on, using a postorder walk. -static void addLinkOptionsPostorder(llvm::LLVMContext &Context, +static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, SmallVectorImpl<llvm::Value *> &Metadata, llvm::SmallPtrSet<Module *, 16> &Visited) { // Import this module's parent. if (Mod->Parent && Visited.insert(Mod->Parent)) { - addLinkOptionsPostorder(Context, Mod->Parent, Metadata, Visited); + addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited); } // Import this module's dependencies. for (unsigned I = Mod->Imports.size(); I > 0; --I) { if (Visited.insert(Mod->Imports[I-1])) - addLinkOptionsPostorder(Context, Mod->Imports[I-1], Metadata, Visited); + addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited); } // Add linker options to link against the libraries/frameworks // described by this module. + llvm::LLVMContext &Context = CGM.getLLVMContext(); for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) { - // FIXME: -lfoo is Unix-centric and -framework Foo is Darwin-centric. - // We need to know more about the linker to know how to encode these - // options propertly. - - // Link against a framework. + // Link against a framework. Frameworks are currently Darwin only, so we + // don't to ask TargetCodeGenInfo for the spelling of the linker option. if (Mod->LinkLibraries[I-1].IsFramework) { llvm::Value *Args[2] = { llvm::MDString::get(Context, "-framework"), @@ -798,9 +809,10 @@ static void addLinkOptionsPostorder(llvm::LLVMContext &Context, } // Link against a library. - llvm::Value *OptString - = llvm::MDString::get(Context, - "-l" + Mod->LinkLibraries[I-1].Library); + llvm::SmallString<24> Opt; + CGM.getTargetCodeGenInfo().getDependentLibraryOption( + Mod->LinkLibraries[I-1].Library, Opt); + llvm::Value *OptString = llvm::MDString::get(Context, Opt); Metadata.push_back(llvm::MDNode::get(Context, OptString)); } } @@ -852,20 +864,23 @@ void CodeGenModule::EmitModuleLinkOptions() { } // Add link options for all of the imported modules in reverse topological - // order. + // order. We don't do anything to try to order import link flags with respect + // to linker options inserted by things like #pragma comment(). SmallVector<llvm::Value *, 16> MetadataArgs; Visited.clear(); for (llvm::SetVector<clang::Module *>::iterator M = LinkModules.begin(), MEnd = LinkModules.end(); M != MEnd; ++M) { if (Visited.insert(*M)) - addLinkOptionsPostorder(getLLVMContext(), *M, MetadataArgs, Visited); + addLinkOptionsPostorder(*this, *M, MetadataArgs, Visited); } std::reverse(MetadataArgs.begin(), MetadataArgs.end()); + LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end()); // Add the linker options metadata flag. getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options", - llvm::MDNode::get(getLLVMContext(), MetadataArgs)); + llvm::MDNode::get(getLLVMContext(), + LinkerOptionsMetadata)); } void CodeGenModule::EmitDeferred() { diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 91138c607c3..1d6c7e98e5c 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -355,6 +355,9 @@ class CodeGenModule : public CodeGenTypeCache { /// \brief The complete set of modules that has been imported. llvm::SetVector<clang::Module *> ImportedModules; + /// \brief A vector of metadata strings. + SmallVector<llvm::Value *, 16> LinkerOptionsMetadata; + /// @name Cache for Objective-C runtime types /// @{ @@ -906,6 +909,12 @@ public: void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired); + /// \brief Appends Opts to the "Linker Options" metadata value. + void AppendLinkerOptions(StringRef Opts); + + /// \brief Appends a dependent lib to the "Linker Options" metadata value. + void AddDependentLib(StringRef Lib); + llvm::GlobalVariable::LinkageTypes getFunctionLinkage(const FunctionDecl *FD); diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 69e5b323045..56067a47bbd 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -115,6 +116,14 @@ namespace { Builder->EmitVTable(RD, DefinitionRequired); } + + virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) { + Builder->AppendLinkerOptions(Opts); + } + + virtual void HandleDependentLibrary(llvm::StringRef Lib) { + Builder->AddDependentLib(Lib); + } }; } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 32b27b3172a..45fc475e341 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -143,6 +143,16 @@ bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args, return false; } +void +TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib, + llvm::SmallString<24> &Opt) const { + // This assumes the user is passing a library name like "rt" instead of a + // filename like "librt.a/so", and that they don't care whether it's static or + // dynamic. + Opt = "-l"; + Opt += Lib; +} + static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); /// isEmptyField - Return true iff a the field is "empty", that is it @@ -1256,6 +1266,18 @@ public: }; +class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo { +public: + WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned RegParms) + : X86_32TargetCodeGenInfo(CGT, false, true, true, RegParms) {} + + void getDependentLibraryOption(llvm::StringRef Lib, + llvm::SmallString<24> &Opt) const { + Opt = "/DEFAULTLIB:"; + Opt += Lib; + } +}; + class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) @@ -1274,6 +1296,12 @@ public: AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16); return false; } + + void getDependentLibraryOption(llvm::StringRef Lib, + llvm::SmallString<24> &Opt) const { + Opt = "/DEFAULTLIB:"; + Opt += Lib; + } }; } @@ -5173,8 +5201,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::Win32: return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, false, true, true, - CodeGenOpts.NumRegisterParameters)); + new WinX86_32TargetCodeGenInfo(Types, + CodeGenOpts.NumRegisterParameters)); default: return *(TheTargetCodeGenInfo = diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index bb50ce69e31..dee7fd8dd40 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -18,6 +18,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" namespace llvm { class GlobalValue; @@ -167,6 +168,11 @@ namespace clang { /// that unprototyped calls to varargs functions still succeed. virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args, const FunctionNoProtoType *fnType) const; + + /// Gets the linker options necessary to link a dependent library on this + /// platform. + virtual void getDependentLibraryOption(llvm::StringRef Lib, + llvm::SmallString<24> &Opt) const; }; } |