r211995 - Driver: add a cygwin linker tool

Saleem Abdulrasool compnerd at compnerd.org
Sat Jun 28 23:11:16 PDT 2014


Author: compnerd
Date: Sun Jun 29 01:11:14 2014
New Revision: 211995

URL: http://llvm.org/viewvc/llvm-project?rev=211995&view=rev
Log:
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.

Added:
    cfe/trunk/test/Driver/cygwin-link.c
Modified:
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/Driver/Driver.cpp
    cfe/trunk/lib/Driver/ToolChains.cpp
    cfe/trunk/lib/Driver/ToolChains.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Driver/Tools.h

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Sun Jun 29 01:11:14 2014
@@ -1019,6 +1019,7 @@ def masm_EQ : Joined<["-"], "masm=">, Gr
 def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
 def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>;
 def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>;
+def mdll : Joined<["-"], "mdll">, Group<m_Group>, Flags<[DriverOption]>;
 def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group<m_Group>;
 def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>;
 def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>;

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Sun Jun 29 01:11:14 2014
@@ -2023,6 +2023,9 @@ const ToolChain &Driver::getToolChain(co
         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);

Modified: cfe/trunk/lib/Driver/ToolChains.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains.cpp Sun Jun 29 01:11:14 2014
@@ -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,

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Sun Jun 29 01:11:14 2014
@@ -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:

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Sun Jun 29 01:11:14 2014
@@ -7315,6 +7315,172 @@ void gnutools::Link::ConstructJob(Compil
   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 at 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,

Modified: cfe/trunk/lib/Driver/Tools.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.h?rev=211995&r1=211994&r2=211995&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.h (original)
+++ cfe/trunk/lib/Driver/Tools.h Sun Jun 29 01:11:14 2014
@@ -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  {

Added: cfe/trunk/test/Driver/cygwin-link.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cygwin-link.c?rev=211995&view=auto
==============================================================================
--- cfe/trunk/test/Driver/cygwin-link.c (added)
+++ cfe/trunk/test/Driver/cygwin-link.c Sun Jun 29 01:11:14 2014
@@ -0,0 +1,48 @@
+// RUN: %clang -### -target i686-windows-cygnus %s 2>&1 \
+// RUN:     | FileCheck %s -check-prefix CHECK-EXE -check-prefix CHECK
+
+// RUN: %clang -shared -### -target i686-windows-cygnus %s 2>&1 \
+// RUN:     | FileCheck %s -check-prefix CHECK-SHARED -check-prefix CHECK
+
+// RUN: %clang -static -### -target i686-windows-cygnus %s 2>&1 \
+// RUN:     | FileCheck %s -check-prefix CHECK-STATIC -check-prefix CHECK
+
+// CHECK: "{{.*}}ld"
+// CHECK: "--wrap" "_Znwj"
+// CHECK: "--wrap" "_Znaj"
+// CHECK: "--wrap" "_ZdlPv"
+// CHECK: "--wrap" "_ZdaPv"
+// CHECK: "--wrap" "_ZnwjRKSt9nothrow_t"
+// CHECK: "--wrap" "_ZnajRKSt9nothrow_t"
+// CHECK: "--wrap" "_ZdlPvRKSt9nothrow_t"
+// CHECK: "--wrap" "_ZdaPvRKSt9nothrow_t"
+// CHECK-SHARED: "--shared"
+// CHECK-STATIC: "-Bstatic"
+// CHECK-DYNAMIC: "-Bdynamic"
+// CHECK-EXE: "-Bdynamic"
+// CHECK-SHARED: "--enable-auto-image-base"
+// CHECK-SHARED: "-e" "__cygwin_dll_entry at 12"
+// CHECK: "--dll-search-prefix=cyg"
+// CHECK-EXE: "--large-address-aware"
+// CHECK-STATIC: "--large-address-aware"
+// CHECK-EXE: "--tsaware"
+// CHECK-STATIC: "--tsaware"
+// CHECK: .o"
+// CHECK-EXE: crt0.o"
+// CHECK-STATIC: crt0.o"
+// CHECK: crtbegin.o"
+// CHECK: "-L/usr/lib"
+// CHECK: "-o"
+// CHECK-EXE: "-lgcc_s"
+// CHECK: "-lgcc"
+// CHECK-STATIC: "-lgcc_eh"
+// CHECK: "-lcygwin"
+// CHECK: "-ladvapi32"
+// CHECK: "-lshell32"
+// CHECK: "-luser32"
+// CHECK: "-lkernel32"
+// CHECK-EXE: "-lgcc_s"
+// CHECK: "-lgcc"
+// CHECK-STATIC: "-lgcc_eh"
+// CHECK: crtend.o"
+





More information about the cfe-commits mailing list