Add AVR target and toolchain to Clang

Summary:
Authored by Senthil Kumar Selvaraj

This patch adds barebones support in Clang for the (experimental) AVR target. It uses the integrated assembler for assembly, and the GNU linker for linking, as lld doesn't know about the target yet.

The DataLayout string is the same as the one in AVRTargetMachine.cpp. The alignment specs look wrong to me, as it's an 8 bit target and all types only need 8 bit alignment. Clang failed with a datalayout mismatch error when I tried to change it, so I left it that way for now.

Reviewers: rsmith, dylanmckay, cfe-commits, rengolin

Subscribers: rengolin, jroelofs, wdng

Differential Revision: https://reviews.llvm.org/D27123

llvm-svn: 291082
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 7bd43ac..15f830d 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3764,6 +3764,9 @@
       case llvm::Triple::wasm64:
         TC = new toolchains::WebAssembly(*this, Target, Args);
         break;
+      case llvm::Triple::avr:
+        TC = new toolchains::AVRToolChain(*this, Target, Args);
+        break;
       default:
         if (Target.getVendor() == llvm::Triple::Myriad)
           TC = new toolchains::MyriadToolChain(*this, Target, Args);
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp
index 968b0cb..f15baa8 100644
--- a/clang/lib/Driver/ToolChains.cpp
+++ b/clang/lib/Driver/ToolChains.cpp
@@ -5318,3 +5318,12 @@
     Res |= SanitizerKind::SafeStack;
   return Res;
 }
+
+/// AVR Toolchain
+AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
+                           const ArgList &Args)
+  : Generic_ELF(D, Triple, Args) { }
+Tool *AVRToolChain::buildLinker() const {
+  return new tools::AVR::Linker(*this);
+}
+// End AVR
diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h
index 7dab089..e687222 100644
--- a/clang/lib/Driver/ToolChains.h
+++ b/clang/lib/Driver/ToolChains.h
@@ -1349,6 +1349,16 @@
   SanitizerMask getSupportedSanitizers() const override;
 };
 
+class LLVM_LIBRARY_VISIBILITY AVRToolChain : public Generic_ELF {
+protected:
+  Tool *buildLinker() const override;
+public:
+  AVRToolChain(const Driver &D, const llvm::Triple &Triple,
+               const llvm::opt::ArgList &Args);
+  bool IsIntegratedAssemblerDefault() const override { return true; }
+};
+
+
 } // end namespace toolchains
 } // end namespace driver
 } // end namespace clang
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index ea5ad7d..62ac95a 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -12191,3 +12191,19 @@
   const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
   C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
 }
+
+void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                               const InputInfo &Output,
+                               const InputInfoList &Inputs,
+                               const ArgList &Args,
+                               const char *LinkingOutput) const {
+
+  std::string Linker = getToolChain().GetProgramPath(getShortName());
+  ArgStringList CmdArgs;
+  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
+                                          CmdArgs, Inputs));
+}
+// AVR tools end.
diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h
index 98dcf84..9d5b892 100644
--- a/clang/lib/Driver/Tools.h
+++ b/clang/lib/Driver/Tools.h
@@ -990,6 +990,19 @@
 
 }  // end namespace NVPTX
 
+namespace AVR {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+  Linker(const ToolChain &TC) : GnuTool("AVR::Linker", "avr-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 AVR
+
 } // end namespace tools
 } // end namespace driver
 } // end namespace clang