dougk created this revision.
dougk added reviewers: jyknight, chandlerc.
dougk added a subscriber: cfe-commits.
Herald added a subscriber: jyknight.

Rename SHAVE toolchain to  Myriad toolchain.
Run the Myriad linker whenever the vendor [sic] is Myriad.
Also recognize RTEMS as the OS, and do something special for that.

(work-in-progress)

http://reviews.llvm.org/D12541

Files:
  lib/Driver/Driver.cpp
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h

Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -792,6 +792,17 @@
                     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", "ld", 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: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -9651,3 +9651,78 @@
   C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                           CmdArgs, Inputs));
 }
+
+void tools::SHAVE::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                                        const InputInfo &Output,
+                                        const InputInfoList &Inputs,
+                                        const ArgList &Args,
+                                        const char *LinkingOutput) const {
+  const auto &TC =
+      static_cast<const toolchains::MyriadToolChain &>(getToolChain());
+  const llvm::Triple &T = TC.getTriple();
+  ArgStringList CmdArgs;
+
+  SmallString<128> CrtObjDir;
+  TC.getCompilerSupportDir(CrtObjDir);
+
+  CmdArgs.push_back("-EL"); // Endianness = little
+
+  // The remaining logic is mostly like gnutools::Linker::ConstructJob,
+  // but we never pass through a --sysroot option and various other bits.
+  // For example, there are no sanitizers (yet) nor gold linker.
+
+  // Silence warning for "clang -g foo.o -o foo"
+  Args.ClaimAllArgs(options::OPT_g_Group);
+  // and for "clang -w foo.o -o foo". Other warning options are already
+  // handled somewhere else.
+  Args.ClaimAllArgs(options::OPT_w);
+  if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
+    CmdArgs.push_back("-s");
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  if (T.getOS() == llvm::Triple::RTEMS) {
+    SmallString<128> Path1(CrtObjDir), Path2(CrtObjDir);
+    llvm::sys::path::append(Path1, "crti.o");
+    llvm::sys::path::append(Path2, "crtbegin.o");
+    CmdArgs.push_back(Args.MakeArgString(Path1));
+    CmdArgs.push_back(Args.MakeArgString(Path2));
+  }
+
+  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+                            options::OPT_e, options::OPT_s, options::OPT_t,
+                            options::OPT_Z_Flag, options::OPT_r});
+
+  // The linker doesn't use these builtin paths unless directed to.
+  SmallString<128> LibDir;
+  TC.getBuiltinLibDir(LibDir);
+  CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibDir));
+  CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + CrtObjDir));
+
+  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+  if (T.getOS() == llvm::Triple::RTEMS) {
+    CmdArgs.push_back("--start-group");
+    CmdArgs.push_back("-lg");
+    CmdArgs.push_back("-lrtemscpu");
+    CmdArgs.push_back("-lrtemsbsp");
+    CmdArgs.push_back("--end-group");
+  }
+  CmdArgs.push_back("-lgcc");
+  if (C.getDriver().CCCIsCXX())
+    CmdArgs.push_back("-lstdc++");
+
+  if (T.getOS() == llvm::Triple::RTEMS) {
+    SmallString<128> Path1(CrtObjDir), Path2(CrtObjDir);
+    llvm::sys::path::append(Path1, "crtend.o");
+    llvm::sys::path::append(Path2, "crtn.o");
+    CmdArgs.push_back(Args.MakeArgString(Path1));
+    CmdArgs.push_back(Args.MakeArgString(Path2));
+  }
+
+  std::string Exec =
+      Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld"));
+  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
+                                          CmdArgs, Inputs));
+}
Index: lib/Driver/ToolChains.h
===================================================================
--- lib/Driver/ToolChains.h
+++ lib/Driver/ToolChains.h
@@ -101,7 +101,8 @@
   public:
     GCCInstallationDetector() : IsValid(false) {}
     void init(const Driver &D, const llvm::Triple &TargetTriple,
-              const llvm::opt::ArgList &Args);
+              const llvm::opt::ArgList &Args,
+              const ArrayRef<std::string> ExtraTripleAliases = {});
 
     /// \brief Check whether we detected a valid GCC install.
     bool isValid() const { return IsValid; }
@@ -910,21 +911,29 @@
                            llvm::opt::ArgStringList &CmdArgs) const override;
 };
 
-/// SHAVEToolChain - A tool chain using the compiler installed by the
-/// Movidius SDK into MV_TOOLS_DIR (which we assume will be copied to llvm's
-/// installation dir) to perform all subcommands.
-class LLVM_LIBRARY_VISIBILITY SHAVEToolChain : public Generic_GCC {
+/// MyriadToolChain - A tool chain using either clang or the external compiler
+/// installed by the Movidius SDK to perform all subcommands.
+class LLVM_LIBRARY_VISIBILITY MyriadToolChain : public Generic_GCC {
 public:
-  SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
-                 const llvm::opt::ArgList &Args);
-  ~SHAVEToolChain() override;
+  MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
+                  const llvm::opt::ArgList &Args);
+  ~MyriadToolChain() override;
 
   virtual Tool *SelectTool(const JobAction &JA) const override;
+  void getCompilerSupportDir(SmallString<128> &CrtFileDir) const;
+  void getBuiltinLibDir(SmallString<128> &CrtFileDir) const;
 
 protected:
   Tool *getTool(Action::ActionClass AC) const override;
   Tool *buildAssembler() const override;
   Tool *buildLinker() const override;
+  bool isShaveCompilation(const llvm::Triple &T) const {
+    // 'sparc' is wrong, but if you accidentally leave off an -EL flag,
+    // it should not imply performing a SHAVE compile.
+    // Or looked at another way - T might be the uncanonical triple.
+    return !(T.getArch() == llvm::Triple::sparcel ||
+             T.getArch() == llvm::Triple::sparc);
+  }
 
 private:
   mutable std::unique_ptr<Tool> Compiler;
Index: lib/Driver/ToolChains.cpp
===================================================================
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -1170,7 +1170,8 @@
 /// necessary because the driver doesn't store the final version of the target
 /// triple.
 void Generic_GCC::GCCInstallationDetector::init(
-    const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
+    const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args,
+    const ArrayRef<std::string> ExtraTripleAliases) {
   llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
                                          ? TargetTriple.get64BitArchVariant()
                                          : TargetTriple.get32BitArchVariant();
@@ -1220,6 +1221,8 @@
         continue;
       for (const StringRef Candidate : CandidateTripleAliases)
         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
+      for (const StringRef Candidate : ExtraTripleAliases)
+        ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
     }
     for (const StringRef Suffix : CandidateBiarchLibDirs) {
       const std::string LibDir = Prefix + Suffix.str();
@@ -3895,9 +3898,12 @@
   // We don't output any lib args. This is handled by xcc.
 }
 
-// SHAVEToolChain does not call Clang's C compiler.
-// We override SelectTool to avoid testing ShouldUseClangCompiler().
-Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const {
+// MyriadToolChain handles several triples:
+//  {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
+// We override SelectTool when the architecture is not sparc.
+Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
+  if (!isShaveCompilation(getTriple()))
+    return ToolChain::SelectTool(JA);
   switch (JA.getKind()) {
   case Action::CompileJobClass:
     if (!Compiler)
@@ -3912,28 +3918,53 @@
   }
 }
 
-SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
-                               const ArgList &Args)
-    : Generic_GCC(D, Triple, Args) {}
+MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
+                                 const ArgList &Args)
+    : Generic_GCC(D, Triple, Args) {
+  // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
+  // 'sparc-myriad--elf' (note the unkown "OS") as the canonical triple.
+  // This won't work to find gcc. Instead we hand the installation detector an
+  // extra triple, which is preferable to further hacks of the logic that at
+  // present is based solely on getArch(). In particular, it would be wrong to
+  // choose the myriad installation when targeting a non-myriad sparc install.
+  GCCInstallation.init(D, Triple, Args, {"sparc-myriad-elf"});
+}
 
-SHAVEToolChain::~SHAVEToolChain() {}
+MyriadToolChain::~MyriadToolChain() {}
 
-/// Following are methods necessary to avoid having moviClang be an abstract
-/// class.
+void MyriadToolChain::getCompilerSupportDir(SmallString<128> &Dir) const {
+  // This directory contains crt{i,n,begin,end}.o as well as libgcc.
+  // There are actually 4 choices: {le,be} x {fpu,nofpu}.
+  Dir = GCCInstallation.getInstallPath();
+  // We pick little-endian with fpu, which is just "le/".
+  llvm::sys::path::append(Dir, "le");
+}
+void MyriadToolChain::getBuiltinLibDir(SmallString<128> &Dir) const {
+  // This contains libc, libg (a superset of libc), libm, libstdc++, libssp.
+  // As above there are 4 choices, but we always pick "le/"
+  Dir = GCCInstallation.getParentLibPath();
+  llvm::sys::path::append(Dir, "../sparc-myriad-elf/lib/le");
+}
 
-Tool *SHAVEToolChain::getTool(Action::ActionClass AC) const {
+Tool *MyriadToolChain::getTool(Action::ActionClass AC) const {
+  if (!isShaveCompilation(getTriple()))
+    return ToolChain::getTool(AC);
   // SelectTool() must find a tool using the method in the superclass.
   // There's nothing we can do if that fails.
-  llvm_unreachable("SHAVEToolChain can't getTool");
+  llvm_unreachable("MyriadToolChain can't getTool");
 }
 
-Tool *SHAVEToolChain::buildLinker() const {
-  // SHAVEToolChain executables can not be linked except by the vendor tools.
-  llvm_unreachable("SHAVEToolChain can't buildLinker");
+Tool *MyriadToolChain::buildLinker() const {
+  // MyriadToolChain executables can not be linked except by the vendor tools.
+  // We run the so-called SHAVE linker even if there are no object files
+  // containing SHAVE executable code.
+  return new tools::SHAVE::Linker(*this);
 }
 
-Tool *SHAVEToolChain::buildAssembler() const {
+/// The Following method is necessary to avoid having moviClang be an abstract
+/// class.
+Tool *MyriadToolChain::buildAssembler() const {
   // This one you'd think should be reachable since we expose an
   // assembler to the driver, except not the way it expects.
-  llvm_unreachable("SHAVEToolChain can't buildAssembler");
+  llvm_unreachable("MyriadToolChain can't buildAssembler");
 }
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -2262,11 +2262,10 @@
       case llvm::Triple::xcore:
         TC = new toolchains::XCoreToolChain(*this, Target, Args);
         break;
-      case llvm::Triple::shave:
-        TC = new toolchains::SHAVEToolChain(*this, Target, Args);
-        break;
       default:
-        if (Target.isOSBinFormatELF())
+        if (Target.getVendor() == llvm::Triple::Myriad)
+          TC = new toolchains::MyriadToolChain(*this, Target, Args);
+        else if (Target.isOSBinFormatELF())
           TC = new toolchains::Generic_ELF(*this, Target, Args);
         else if (Target.isOSBinFormatMachO())
           TC = new toolchains::MachO(*this, Target, Args);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to