From 1900e229c00d5626eb0a65cd932cf4231b6061b4 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Thu, 26 Mar 2015 11:13:44 +0000 Subject: [PATCH] Let Clang invoke CloudABI's linker. Now that CloudABI's target information and header search logic for Clang has been submitted, the only thing that remains to be done is adding support for CloudABI's linker. CloudABI uses Binutils ld, although there is some work to use lld instead. This means that this code is largely based on what we use on FreeBSD. There are some exceptions, however: - Only static linking is performed. CloudABI does not support any dynamically linked executables. - CloudABI uses compiler-rt, libc++ and libc++abi unconditionally. Link in these libraries instead of using libgcc_s, libstdc++, etc. - We must ensure that the .eh_frame_hdr is present to make C++ exceptions work properly. Differential Revision: http://reviews.llvm.org/D8250 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233269 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Driver.cpp | 3 ++ lib/Driver/ToolChains.cpp | 30 +++++++++++++++++ lib/Driver/ToolChains.h | 25 ++++++++++++++ lib/Driver/Tools.cpp | 70 +++++++++++++++++++++++++++++++++++++++ lib/Driver/Tools.h | 16 +++++++++ test/Driver/cloudabi.c | 3 ++ test/Driver/cloudabi.cpp | 3 ++ 7 files changed, 150 insertions(+) create mode 100644 test/Driver/cloudabi.c create mode 100644 test/Driver/cloudabi.cpp diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index c619c8caa9..0e99c5882a 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2030,6 +2030,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, ToolChain *&TC = ToolChains[Target.str()]; if (!TC) { switch (Target.getOS()) { + case llvm::Triple::CloudABI: + TC = new toolchains::CloudABI(*this, Target, Args); + break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index bc647d1ef0..9606df6b5a 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -2340,6 +2340,36 @@ bool TCEToolChain::isPICDefaultForced() const { return false; } +// CloudABI - CloudABI tool chain which can call ld(1) directly. + +CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + SmallString<128> P(getDriver().Dir); + llvm::sys::path::append(P, "..", getTriple().str(), "lib"); + getFilePaths().push_back(P.str()); +} + +void CloudABI::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) && + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + SmallString<128> P(getDriver().Dir); + llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); +} + +void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); +} + +Tool *CloudABI::buildLinker() const { return new tools::cloudabi::Link(*this); } + /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 2bf707ef65..ebd23d1857 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -512,6 +512,31 @@ public: llvm::opt::ArgStringList &CC1Args) const override; }; +class LLVM_LIBRARY_VISIBILITY CloudABI : public Generic_ELF { +public: + CloudABI(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + bool HasNativeLLVMSupport() const override { return true; } + + bool IsMathErrnoDefault() const override { return false; } + bool IsObjCNonFragileABIDefault() const override { return true; } + + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) + const override { + return ToolChain::CST_Libcxx; + } + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + + bool isPIEDefault() const override { return false; } + +protected: + Tool *buildLinker() const override; +}; + class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC { public: Solaris(const Driver &D, const llvm::Triple &Triple, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 72a7749310..874484d35d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -5725,6 +5725,76 @@ const char *Clang::getDependencyFileName(const ArgList &Args, return Args.MakeArgString(Res + ".d"); } +void cloudabi::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const ToolChain &ToolChain = getToolChain(); + const Driver &D = ToolChain.getDriver(); + 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); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + // CloudABI only supports static linkage. + CmdArgs.push_back("-Bstatic"); + CmdArgs.push_back("--eh-frame-hdr"); + CmdArgs.push_back("--gc-sections"); + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_s); + Args.AddAllArgs(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); + Args.AddAllArgs(CmdArgs, options::OPT_r); + + if (D.IsUsingLTO(ToolChain, Args)) + AddGoldPlugin(ToolChain, Args, CmdArgs); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (D.CCCIsCXX()) + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lcompiler_rt"); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); + + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs)); +} + void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 93a19fb595..5161557970 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -248,6 +248,22 @@ namespace ppc { bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value); } + /// cloudabi -- Directly call GNU Binutils linker +namespace cloudabi { +class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { +public: + Link(const ToolChain &TC) : GnuTool("cloudabi::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 &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace cloudabi + namespace darwin { llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); diff --git a/test/Driver/cloudabi.c b/test/Driver/cloudabi.c new file mode 100644 index 0000000000..91c9e192e5 --- /dev/null +++ b/test/Driver/cloudabi.c @@ -0,0 +1,3 @@ +// RUN: %clang %s -### -target x86_64-unknown-cloudabi 2>&1 | FileCheck %s +// CHECK: "-cc1" "-triple" "x86_64-unknown-cloudabi" +// CHECK: "-Bstatic" "--eh-frame-hdr" "--gc-sections" "-o" "a.out" "crt0.o" "crtbegin.o" "{{.*}}" "{{.*}}" "-lc" "-lcompiler_rt" "crtend.o" diff --git a/test/Driver/cloudabi.cpp b/test/Driver/cloudabi.cpp new file mode 100644 index 0000000000..8db3d85cb1 --- /dev/null +++ b/test/Driver/cloudabi.cpp @@ -0,0 +1,3 @@ +// RUN: %clangxx %s -### -target x86_64-unknown-cloudabi 2>&1 | FileCheck %s +// CHECK: "-cc1" "-triple" "x86_64-unknown-cloudabi" +// CHECK: "-Bstatic" "--eh-frame-hdr" "--gc-sections" "-o" "a.out" "crt0.o" "crtbegin.o" "{{.*}}" "{{.*}}" "-lc++" "-lc++abi" "-lunwind" "-lc" "-lcompiler_rt" "crtend.o" -- 2.40.0