diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2014-06-29 06:11:14 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2014-06-29 06:11:14 +0000 |
commit | a4a474b859c8560d9f451a951acb6a477d2d08b6 (patch) | |
tree | 560a9e3ad9905dfcdc23a7329d0f005cbe017acc /clang/lib/Driver | |
parent | 7206a52522bbf7a3d8ddee9d19f9562ef06434a9 (diff) | |
download | bcm5719-llvm-a4a474b859c8560d9f451a951acb6a477d2d08b6.tar.gz bcm5719-llvm-a4a474b859c8560d9f451a951acb6a477d2d08b6.zip |
Driver: add a cygwin linker tool
This adds a linker tool for the Windows cygwin environment. This linker
invocation is significantly different from the generic ld invocation. It
requires additional parameters as well as does not accept some normal
parameters. This should fix self-hosting on Cygwin.
llvm-svn: 211995
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.h | 8 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 166 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.h | 18 |
5 files changed, 206 insertions, 0 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index a18312a84fa..7ef19ce60fa 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2023,6 +2023,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = new toolchains::Generic_GCC(*this, Target, Args); break; + case llvm::Triple::Cygnus: + TC = new toolchains::Cygwin(*this, Target, Args); + break; case llvm::Triple::MSVC: case llvm::Triple::UnknownEnvironment: TC = new toolchains::Windows(*this, Target, Args); diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index c01f0326a04..4efc9a10782 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -3476,6 +3476,17 @@ Tool *DragonFly::buildLinker() const { return new tools::dragonfly::Link(*this); } +/// Cygwin toolchain +Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Generic_GCC(D, Triple, Args) { + ToolChain::path_list &LibPaths = getFilePaths(); + LibPaths.push_back("/usr/lib"); +} + +Tool *Cygwin::buildLinker() const { + return new tools::cygwin::Link(*this); +} /// XCore tool chain XCore::XCore(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index 8931aec7899..66d7eef53ad 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -744,6 +744,14 @@ protected: Tool *buildAssembler() const override; }; +class LLVM_LIBRARY_VISIBILITY Cygwin : public Generic_GCC { +public: + Cygwin(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + +protected: + Tool *buildLinker() const override; +}; class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain { public: diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 06c681091d0..24d4bf90a9b 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -7315,6 +7315,172 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void cygwin::Link::AddLibGCC(const ArgList &Args, ArgStringList &CmdArgs) const { + if (Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_static_libgcc)) { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lgcc_eh"); + } else { + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("-lgcc"); + } +} + +void cygwin::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &Args, + const char *LinkingOutput) const { + static const char *WrappedSymbols[] = { + "_Znwj", + "_Znaj", + "_ZdlPv", + "_ZdaPv", + "_ZnwjRKSt9nothrow_t", + "_ZnajRKSt9nothrow_t", + "_ZdlPvRKSt9nothrow_t", + "_ZdaPvRKSt9nothrow_t", + }; + + const auto &ToolChain = getToolChain(); + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + // FIXME: -mwindows should pass --subsystem windows + // FIXME: -mconsole should pass --subsystem console + + // FIXME: this can be disabled via -mno-use-libstdc-wrappers + for (const auto &Symbol : WrappedSymbols) { + CmdArgs.push_back("--wrap"); + CmdArgs.push_back(Symbol); + } + + if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--shared"); + else if (Args.hasArg(options::OPT_mdll)) + CmdArgs.push_back("--dll"); + + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("-Bstatic"); + else + CmdArgs.push_back("-Bdynamic"); + + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back("--enable-auto-image-base"); + + CmdArgs.push_back("-e"); + CmdArgs.push_back("__cygwin_dll_entry@12"); + } + + CmdArgs.push_back("--dll-search-prefix=cyg"); + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("--export-all-symbols"); + + if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back("--large-address-aware"); + CmdArgs.push_back("--tsaware"); + } + + if (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + Args.AddAllArgs(CmdArgs, options::OPT_e); + // FIXME: add -N, -n flags + Args.AddLastArg(CmdArgs, options::OPT_r); + Args.AddLastArg(CmdArgs, options::OPT_s); + Args.AddLastArg(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_u_Group); + Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("gcrt0.o"))); + } + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + + // FIXME: support mudflap: wrap the following: + // -fmudflap || -fmudflapth: + // static const char *WrappedStaticSymbols[] = { + // "malloc", "free", "calloc", "realloc", "mmap", "mmap64", "munmap", + // "alloca", + // }; + // -fmudflapth: + // static const char *WrappedStaticSymbols[] = { + // "pthread_create", + // }; + // -fmudflap || -fmudflapth: + // static const char *WrappedSymbols[] = { + // "main", + // }; + + for (const auto &Path : ToolChain.getFilePaths()) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + // FIXME: support -freopen, -ftree-parallelize-loops=* + // FIXME: support itm (-fgnu-tm) + // FIXME: support mudflap (-fmudflap || -fmudflapth) ? -export-dynamic : "" + + if (Args.hasArg(options::OPT_fsplit_stack)) + CmdArgs.push_back("--wrap=pthread_create"); + + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_fprofile_generate) || + Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back("-lgcov"); + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + // FIXME: support asan, tsan + + if (Args.hasArg(options::OPT_fstack_protector) || + Args.hasArg(options::OPT_fstack_protector_all)) { + CmdArgs.push_back("-lssp_nonshared"); + CmdArgs.push_back("-lssp"); + } + + AddLibGCC(Args, CmdArgs); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lgmon"); + CmdArgs.push_back("-lcygwin"); + // FIXME: -mwindows: -lgdi32 -lcomdlg32 + CmdArgs.push_back("-ladvapi32"); + CmdArgs.push_back("-lshell32"); + CmdArgs.push_back("-luser32"); + CmdArgs.push_back("-lkernel32"); + AddLibGCC(Args, CmdArgs); + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); + } + } + + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index c4e6d6c8298..708715e4fd1 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -457,6 +457,24 @@ namespace gnutools { const char *LinkingOutput) const override; }; } + +namespace cygwin { +class LLVM_LIBRARY_VISIBILITY Link : public Tool { +public: + Link(const ToolChain &TC) : Tool("cygwin::Link", "linker", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &Args, + const char *LinkingOutput) const override; +private: + void AddLibGCC(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) const; +}; +} + /// minix -- Directly call GNU Binutils assembler and linker namespace minix { class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { |