Hi chandlerc, jyknight,

Implement the ShaveToolChain::buildLinker() method instead of calling 
llvm_unreachable.
Lightly tested, but works ok on a few of the sample applications.

http://reviews.llvm.org/D10841

Files:
  include/clang/Driver/Options.td
  lib/Driver/ToolChains.cpp
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  test/Driver/shave-toolchain.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -80,6 +80,7 @@
 def m_arm_Features_Group  : OptionGroup<"<m arm features group>">, Group<m_Group>;
 def m_aarch64_Features_Group  : OptionGroup<"<m aarch64 features group>">, Group<m_Group>;
 def m_ppc_Features_Group  : OptionGroup<"<m ppc features group>">, Group<m_Group>;
+def m_shave_Features_Group  : OptionGroup<"<m shave features group>">, Group<m_Group>;
 def m_libc_Group          : OptionGroup<"<m libc group>">, Group<m_Group>;
 def u_Group               : OptionGroup<"<u group>">;
 
@@ -1756,6 +1757,8 @@
 def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
           AliasArgs<["v5"]>;
 
+def mprog_model_EQ : Joined<["-"], "mprog-model=">, Group<m_shave_Features_Group>;
+
 // These are legacy user-facing driver-level option spellings. They are always
 // aliases for options that are spelled using the more common Unix / GNU flag
 // style of double-dash and equals-joined flags.
Index: lib/Driver/ToolChains.cpp
===================================================================
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -3729,8 +3729,7 @@
 }
 
 Tool *SHAVEToolChain::buildLinker() const {
-  // SHAVEToolChain executables can not be linked except by the vendor tools.
-  llvm_unreachable("SHAVEToolChain can't buildLinker");
+  return new tools::SHAVE::Linker(*this);
 }
 
 Tool *SHAVEToolChain::buildAssembler() const {
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -9091,3 +9091,175 @@
   C.addCommand(
       llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
 }
+
+void tools::SHAVE::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                                        const InputInfo &Output,
+                                        const InputInfoList &Inputs,
+                                        const ArgList &Args,
+                                        const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  // Directory structure is:
+  //   <path_to_mdk_root>
+  //       mdk
+  //       tools             <-- $MV_TOOLS_DIR is this
+  //         <version#>
+  //            linux64
+  //            ...
+
+  const char *ToolsRoot = ::getenv("MV_TOOLS_DIR");
+  // The version is numbered 'n.n.n.n' for arbitrary values that are opaque
+  // as far as clang is concerned.
+  std::string ToolsVersion;
+  // The "Host" directory contains both host tools and target libraries
+  // even though target-only stuff is bitwise identical across
+  // the the 3 possible host toolchains {linux32 | linux64 | win32}.
+  std::string ToolsHostDir;
+  // The "Common" directory has target-only stuff in it such as "crt0.o".
+  std::string ToolsCommonDir;
+
+  if (ToolsRoot) {
+    // Detecting which version of the tools are installed is patterned after
+    // GCCInstallationDetector::ScanLibDirForGCCTriple and other places.
+    // It is assumed that multiple versions will not co-exist side-by-side,
+    // or rather if they do, that picking any is ok.
+    SmallString<128> DirNative;
+    std::error_code EC;
+    llvm::sys::path::native(ToolsRoot, DirNative);
+    for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd;
+         Dir != DirEnd && !EC; Dir.increment(EC)) {
+      // Look for a subdirectory of ToolsDir that has within it
+      // a directory named 'common'.
+      SmallString<128> CommonDir(Dir->path());
+      llvm::sys::path::append(CommonDir, "common");
+      if (llvm::sys::fs::exists(CommonDir)) {
+        ToolsCommonDir = CommonDir.str();
+        ToolsVersion = llvm::sys::path::filename(Dir->path());
+        break;
+      }
+    }
+  }
+  if (ToolsCommonDir.empty()) {
+    ToolsRoot = "/usr/local/myriad/tools";
+    ToolsVersion = "00.50.62.5";
+    ToolsCommonDir = "/usr/local/mdk/tools/" + ToolsVersion + "/common";
+  }
+  llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
+  const char *HostSubdir = "linux64";
+  if (HostTriple.isOSWindows())
+    HostSubdir = "win32";
+  else if (HostTriple.getArch() == llvm::Triple::x86)
+    HostSubdir = "linux32";
+  SmallString<128> HostDir(ToolsRoot);
+  llvm::sys::path::append(HostDir, ToolsVersion, HostSubdir);
+
+  SmallString<127> GnuToolsRoot(ToolsHostDir);
+  llvm::sys::path::append(GnuToolsRoot, "sparc-myriad-elf-4.8.2");
+
+  CmdArgs.push_back("-EL"); // Endianness = little
+  CmdArgs.push_back("-O9"); // Optimization
+  CmdArgs.push_back("--gc-sections");
+  CmdArgs.push_back("-warn-common");
+
+  static const char *LibDirs[] = {"lib/gcc/sparc-myriad-elf/4.8.2/le",
+                                  "sparc-myriad-elf/lib/le"};
+  for (const auto &Dir : LibDirs) {
+    SmallString<128> FullPath(GnuToolsRoot);
+    llvm::sys::path::append(FullPath, Dir);
+    CmdArgs.push_back("-L");
+    CmdArgs.push_back(Args.MakeArgString(FullPath));
+  }
+
+  SmallString<127> CommonDir(ToolsRoot);
+  llvm::sys::path::append(CommonDir, "../mdk/common");
+
+  SmallString<128> LinkerScriptDir(CommonDir);
+  llvm::sys::path::append(LinkerScriptDir, "scripts/ld/myriad2collection");
+  CmdArgs.push_back("-L");
+  CmdArgs.push_back(Args.MakeArgString(LinkerScriptDir));
+
+  SmallString<128> MainLinkerScript(LinkerScriptDir);
+  llvm::sys::path::append(MainLinkerScript,
+                          "myriad2_default_memory_map_elf.ldscript");
+  CmdArgs.push_back("-T");
+  CmdArgs.push_back(Args.MakeArgString(MainLinkerScript));
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  enum ProgrammingModel { Bare, OneLeon, BothLeons, RTEMS } ProgrammingModel;
+  Arg *Arg = Args.getLastArg(options::OPT_mprog_model_EQ);
+  if (Arg) {
+    std::string Value = Arg->getValue(0);
+    // FIXME: Instead of "Fell off the end of a string-switch"
+    // print something like "unsupported programming model".
+    ProgrammingModel = llvm::StringSwitch<enum ProgrammingModel>(Value)
+                           .Case("bare", Bare)
+                           .Case("oneleon", OneLeon)
+                           .Case("bothleons", BothLeons)
+                           .Case("rtems", RTEMS);
+  }
+
+  if (ProgrammingModel != Bare) {
+    static const char *StartFiles[] = {"crti.o", "crtbegin.o"};
+    for (const auto &File : StartFiles) {
+      SmallString<128> FullPath(GnuToolsRoot);
+      llvm::sys::path::append(FullPath, "lib/gcc/sparc-myriad-elf/4.8.2/le",
+                              File);
+      CmdArgs.push_back(Args.MakeArgString(FullPath));
+    }
+  }
+
+  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+  CmdArgs.push_back("--start-group");
+  if (ProgrammingModel == Bare) {
+    CmdArgs.push_back("-lgcc");
+    CmdArgs.push_back("-lc");
+  } else {
+    static const char *RTEMSStaticLibs[] = {"librtemsbsp.a", "librtemscpu.a"};
+    static const char *CStaticLibs[] = {"libc.a", "libssp.a",
+                                        "libssp_nonshared.a"};
+    static const char *GCCStaticLibs[] = {"libgcc.a"};
+    for (const auto &File : RTEMSStaticLibs) {
+      SmallString<128> FullPath(ToolsCommonDir);
+      llvm::sys::path::append(FullPath, "rtems/prebuilt/lib", File);
+      CmdArgs.push_back(Args.MakeArgString(FullPath));
+    }
+    for (const auto &File : CStaticLibs) {
+      SmallString<128> FullPath(ToolsHostDir);
+      llvm::sys::path::append(
+          FullPath, "sparc-myriad-elf-4.8.2/sparc-myriad-elf/lib/le", File);
+      CmdArgs.push_back(Args.MakeArgString(FullPath));
+    }
+    for (const auto &File : GCCStaticLibs) {
+      SmallString<128> FullPath(GnuToolsRoot);
+      llvm::sys::path::append(FullPath, "lib/gcc/sparc-myriad-elf/4.8.2/le",
+                              File);
+      CmdArgs.push_back(Args.MakeArgString(FullPath));
+    }
+  }
+
+  if (C.getDriver().CCCIsCXX()) {
+    CmdArgs.push_back("-lstdc++");
+    CmdArgs.push_back("-lsupc++");
+  }
+
+  CmdArgs.push_back("--end-group");
+
+  if (ProgrammingModel != Bare) {
+    static const char *EndFiles[] = {"crtend.o", "crtn.o"};
+    for (const auto &File : EndFiles) {
+      SmallString<128> FullPath(GnuToolsRoot);
+      llvm::sys::path::append(FullPath, "lib/gcc/sparc-myriad-elf/4.8.2/le",
+                              File);
+      CmdArgs.push_back(Args.MakeArgString(FullPath));
+    }
+  }
+
+  SmallString<128> LinkerExec(GnuToolsRoot);
+  llvm::sys::path::append(LinkerExec, "bin/sparc-myriad-elf-ld");
+
+  C.addCommand(llvm::make_unique<Command>(
+      JA, *this, Args.MakeArgString(LinkerExec), CmdArgs));
+}
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -758,6 +758,20 @@
                     const llvm::opt::ArgList &TCArgs,
                     const char *LinkingOutput) const override;
 };
+
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+  Linker(const ToolChain &TC) : GnuTool("shave::Linker", "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 &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+
 } // end namespace SHAVE
 
 } // end namespace tools
Index: test/Driver/shave-toolchain.cpp
===================================================================
--- /dev/null
+++ test/Driver/shave-toolchain.cpp
@@ -0,0 +1,4 @@
+// RUN: %clangxx %s -### -target shave 2>&1 | FileCheck %s
+// CHECK: moviCompile
+// CHECK: moviAsm
+// CHECK: "-lstdc++" "-lsupc++"
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to