diff options
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; }; } |