395 changes: 395 additions & 0 deletions clang/lib/Driver/ToolChains/FreeBSD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,395 @@
//===--- FreeBSD.cpp - FreeBSD ToolChain Implementations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "FreeBSD.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;

// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
switch (getToolChain().getArch()) {
default:
break;
case llvm::Triple::x86:
CmdArgs.push_back("--32");
break;
case llvm::Triple::ppc:
CmdArgs.push_back("-a32");
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());

CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());

if (getToolChain().getArch() == llvm::Triple::mips ||
getToolChain().getArch() == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
else
CmdArgs.push_back("-EL");

if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back(Args.MakeArgString("-G" + v));
A->claim();
}

AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);

if (ABI == arm::FloatABI::Hard)
CmdArgs.push_back("-mfpu=vfp");
else
CmdArgs.push_back("-mfpu=softvfp");

switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
CmdArgs.push_back("-meabi=5");
break;

default:
CmdArgs.push_back("-matpcs");
}
break;
}
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9: {
std::string CPU = getCPUName(Args, getToolChain().getTriple());
CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
}

Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());

const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const toolchains::FreeBSD &ToolChain =
static_cast<const toolchains::FreeBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
(Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
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));

if (IsPIE)
CmdArgs.push_back("-pie");

CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
CmdArgs.push_back("--hash-style=both");
}
}
CmdArgs.push_back("--enable-new-dtags");
}

// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct ld in the base system to link 32-bit code.
if (Arch == llvm::Triple::x86) {
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386_fbsd");
}

if (Arch == llvm::Triple::ppc) {
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_fbsd");
}

if (Arg *A = Args.getLastArg(options::OPT_G)) {
if (ToolChain.getArch() == llvm::Triple::mips ||
ToolChain.getArch() == llvm::Triple::mipsel ||
ToolChain.getArch() == llvm::Triple::mips64 ||
ToolChain.getArch() == llvm::Triple::mips64el) {
StringRef v = A->getValue();
CmdArgs.push_back(Args.MakeArgString("-G" + v));
A->claim();
}
}

if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
crt1 = "gcrt1.o";
else if (IsPIE)
crt1 = "Scrt1.o";
else
crt1 = "crt1.o";
}
if (crt1)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

const char *crtbegin = nullptr;
if (Args.hasArg(options::OPT_static))
crtbegin = "crtbeginT.o";
else if (Args.hasArg(options::OPT_shared) || IsPIE)
crtbegin = "crtbeginS.o";
else
crtbegin = "crtbegin.o";

CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}

Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
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())
AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);

bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, ToolChain, Args);
if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lgcc_p");
else
CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
} else if (Args.hasArg(options::OPT_pg)) {
CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("--no-as-needed");
}

if (Args.hasArg(options::OPT_pthread)) {
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lpthread_p");
else
CmdArgs.push_back("-lpthread");
}

if (Args.hasArg(options::OPT_pg)) {
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-lc");
else
CmdArgs.push_back("-lc_p");
CmdArgs.push_back("-lgcc_p");
} else {
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc");
}

if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
} else if (Args.hasArg(options::OPT_pg)) {
CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("--no-as-needed");
}
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || IsPIE)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}

ToolChain.addProfileRTLibs(Args, CmdArgs);

const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.

FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {

// When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
// back to '/usr/lib' if it doesn't exist.
if ((Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::ppc) &&
D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
else
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}

ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
if (getTriple().getOSMajorVersion() >= 10)
return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx;
}

void FreeBSD::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/c++/4.2", "", "",
"", "", DriverArgs, CC1Args);
}

void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
bool Profiling = Args.hasArg(options::OPT_pg);

switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
break;

case ToolChain::CST_Libstdcxx:
CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
break;
}
}

Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assembler(*this);
}

Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }

bool FreeBSD::UseSjLjExceptions(const ArgList &Args) const {
// FreeBSD uses SjLj exceptions on ARM oabi.
switch (getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
return false;

default:
return (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::thumb);
}
}

bool FreeBSD::HasNativeLLVMSupport() const { return true; }

bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }

SanitizerMask FreeBSD::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
getTriple().getArch() == llvm::Triple::mips64el;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Vptr;
if (IsX86_64 || IsMIPS64) {
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::Thread;
}
if (IsX86 || IsX86_64) {
Res |= SanitizerKind::SafeStack;
}
return Res;
}
86 changes: 86 additions & 0 deletions clang/lib/Driver/ToolChains/FreeBSD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//===--- FreeBSD.h - FreeBSD ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FREEBSD_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FREEBSD_H

#include "Gnu.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {

/// freebsd -- Directly call GNU Binutils assembler and linker
namespace freebsd {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
public:
Assembler(const ToolChain &TC)
: GnuTool("freebsd::Assembler", "assembler", TC) {}

bool hasIntegratedCPP() const override { return false; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("freebsd::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 freebsd
} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
public:
FreeBSD(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
bool HasNativeLLVMSupport() const override;

bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }

CXXStdlibType GetDefaultCXXStdlibType() const override;
void addLibStdCxxIncludePaths(
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 UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
unsigned GetDefaultDwarfVersion() const override { return 2; }
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
// FreeBSD defaults to standalone/full debug info.
bool GetDefaultStandaloneDebug() const override { return true; }

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FREEBSD_H
229 changes: 229 additions & 0 deletions clang/lib/Driver/ToolChains/Fuchsia.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
//===--- Fuchsia.cpp - Fuchsia ToolChain Implementations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Fuchsia.h"
#include "CommonArgs.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"

using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const toolchains::Fuchsia &ToolChain =
static_cast<const toolchains::Fuchsia &>(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);

const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
if (llvm::sys::path::stem(Exec).equals_lower("lld")) {
CmdArgs.push_back("-flavor");
CmdArgs.push_back("gnu");
}

if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))
CmdArgs.push_back("-pie");

if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");

if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");

if (Args.hasArg(options::OPT_r))
CmdArgs.push_back("-r");
else
CmdArgs.push_back("--build-id");

if (!Args.hasArg(options::OPT_static))
CmdArgs.push_back("--eh-frame-hdr");

if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bstatic");
else if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");

if (!Args.hasArg(options::OPT_static)) {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");

if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back(Args.MakeArgString(D.DyldPrefix + "ld.so.1"));
}
}

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
}
}

Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u);

ToolChain.AddFilePathLibArgs(Args, CmdArgs);

AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bdynamic");

if (D.CCCIsCXX()) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bstatic");
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bdynamic");
CmdArgs.push_back("-lm");
}

AddRunTimeLibs(ToolChain, D, CmdArgs, Args);

if (Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads))
CmdArgs.push_back("-lpthread");

if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("--wrap=pthread_create");

CmdArgs.push_back("-lc");
}

C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

/// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.

Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {

getFilePaths().push_back(D.SysRoot + "/lib");
getFilePaths().push_back(D.ResourceDir + "/lib/fuchsia");
}

Tool *Fuchsia::buildAssembler() const {
return new tools::gnutools::Assembler(*this);
}

Tool *Fuchsia::buildLinker() const {
return new tools::fuchsia::Linker(*this);
}

ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType(
const ArgList &Args) const {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
StringRef Value = A->getValue();
if (Value != "compiler-rt")
getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)
<< A->getAsString(Args);
}

return ToolChain::RLT_CompilerRT;
}

ToolChain::CXXStdlibType
Fuchsia::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value != "libc++")
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}

return ToolChain::CST_Libcxx;
}

void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array, true))
CC1Args.push_back("-fuse-init-array");
}

void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();

if (DriverArgs.hasArg(options::OPT_nostdinc))
return;

if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P);
}

if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;

// Check for configure-time C include directories.
StringRef CIncludeDirs(C_INCLUDE_DIRS);
if (CIncludeDirs != "") {
SmallVector<StringRef, 5> dirs;
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
StringRef Prefix =
llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
}

addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
}

std::string Fuchsia::findLibCxxIncludePath() const {
return getDriver().SysRoot + "/include/c++/v1";
}

void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
(void) GetCXXStdlibType(Args);
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}

SanitizerMask Fuchsia::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::SafeStack;
return Res;
}
79 changes: 79 additions & 0 deletions clang/lib/Driver/ToolChains/Fuchsia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===--- Fuchsia.h - Fuchsia ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FUCHSIA_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FUCHSIA_H

#include "Gnu.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {
namespace fuchsia {
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("fuchsia::Linker", "ld.lld", 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 fuchsia
} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY Fuchsia : public Generic_ELF {
public:
Fuchsia(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

bool isPIEDefault() const override { return true; }
bool HasNativeLLVMSupport() const override { return true; }
bool IsIntegratedAssemblerDefault() const override { return true; }
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
return llvm::DebuggerKind::GDB;
}

SanitizerMask getSupportedSanitizers() const override;

RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
CXXStdlibType
GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;

void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
std::string findLibCxxIncludePath() const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;

const char *getDefaultLinker() const override {
return "lld";
}

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FUCHSIA_H
2,429 changes: 2,429 additions & 0 deletions clang/lib/Driver/ToolChains/Gnu.cpp

Large diffs are not rendered by default.

351 changes: 351 additions & 0 deletions clang/lib/Driver/ToolChains/Gnu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,351 @@
//===--- Gnu.h - Gnu Tool and ToolChain Implementations ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H

#include "Cuda.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include <set>

namespace clang {
namespace driver {

struct DetectedMultilibs {
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;

/// The primary multilib appropriate for the given flags.
Multilib SelectedMultilib;

/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
llvm::Optional<Multilib> BiarchSibling;
};

bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
StringRef Path, const llvm::opt::ArgList &Args,
DetectedMultilibs &Result);

namespace tools {

/// \brief Base class for all GNU tools that provide the same behavior when
/// it comes to response files support
class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
virtual void anchor();

public:
GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
: Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
};

/// Directly call GNU Binutils' assembler and linker.
namespace gnutools {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
public:
Assembler(const ToolChain &TC) : GnuTool("GNU::Assembler", "assembler", TC) {}

bool hasIntegratedCPP() const override { return false; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("GNU::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 gnutools

/// gcc - Generic GCC tool implementations.
namespace gcc {
class LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
public:
Common(const char *Name, const char *ShortName, const ToolChain &TC)
: GnuTool(Name, ShortName, TC) {}

// A gcc tool has an "integrated" assembler that it will call to produce an
// object. Let it use that assembler so that we don't have to deal with
// assembly syntax incompatibilities.
bool hasIntegratedAssembler() 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;

/// RenderExtraToolArgs - Render any arguments necessary to force
/// the particular tool mode.
virtual void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const = 0;
};

class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
public:
Preprocessor(const ToolChain &TC)
: Common("gcc::Preprocessor", "gcc preprocessor", TC) {}

bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedCPP() const override { return false; }

void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const override;
};

class LLVM_LIBRARY_VISIBILITY Compiler : public Common {
public:
Compiler(const ToolChain &TC) : Common("gcc::Compiler", "gcc frontend", TC) {}

bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedCPP() const override { return true; }

void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public Common {
public:
Linker(const ToolChain &TC) : Common("gcc::Linker", "linker (via gcc)", TC) {}

bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }

void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const override;
};
} // end namespace gcc
} // end namespace tools

namespace toolchains {

/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
public:
/// \brief Struct to store and manipulate GCC versions.
///
/// We rely on assumptions about the form and structure of GCC version
/// numbers: they consist of at most three '.'-separated components, and each
/// component is a non-negative integer except for the last component. For
/// the last component we are very flexible in order to tolerate release
/// candidates or 'x' wildcards.
///
/// Note that the ordering established among GCCVersions is based on the
/// preferred version string to use. For example we prefer versions without
/// a hard-coded patch number to those with a hard coded patch number.
///
/// Currently this doesn't provide any logic for textual suffixes to patches
/// in the way that (for example) Debian's version format does. If that ever
/// becomes necessary, it can be added.
struct GCCVersion {
/// \brief The unparsed text of the version.
std::string Text;

/// \brief The parsed major, minor, and patch numbers.
int Major, Minor, Patch;

/// \brief The text of the parsed major, and major+minor versions.
std::string MajorStr, MinorStr;

/// \brief Any textual suffix on the patch number.
std::string PatchSuffix;

static GCCVersion Parse(StringRef VersionText);
bool isOlderThan(int RHSMajor, int RHSMinor, int RHSPatch,
StringRef RHSPatchSuffix = StringRef()) const;
bool operator<(const GCCVersion &RHS) const {
return isOlderThan(RHS.Major, RHS.Minor, RHS.Patch, RHS.PatchSuffix);
}
bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
};

/// \brief This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
bool IsValid;
llvm::Triple GCCTriple;
const Driver &D;

// FIXME: These might be better as path objects.
std::string GCCInstallPath;
std::string GCCParentLibPath;

/// The primary multilib appropriate for the given flags.
Multilib SelectedMultilib;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
llvm::Optional<Multilib> BiarchSibling;

GCCVersion Version;

// We retain the list of install paths that were considered and rejected in
// order to print out detailed information in verbose mode.
std::set<std::string> CandidateGCCInstallPaths;

/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;

public:
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
ArrayRef<std::string> ExtraTripleAliases = None);

/// \brief Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }

/// \brief Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const { return GCCTriple; }

/// \brief Get the detected GCC installation path.
StringRef getInstallPath() const { return GCCInstallPath; }

/// \brief Get the detected GCC parent lib path.
StringRef getParentLibPath() const { return GCCParentLibPath; }

/// \brief Get the detected Multilib
const Multilib &getMultilib() const { return SelectedMultilib; }

/// \brief Get the whole MultilibSet
const MultilibSet &getMultilibs() const { return Multilibs; }

/// Get the biarch sibling multilib (if it exists).
/// \return true iff such a sibling exists
bool getBiarchSibling(Multilib &M) const;

/// \brief Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }

/// \brief Print information about the detected GCC installation.
void print(raw_ostream &OS) const;

private:
static void
CollectLibDirsAndTriples(const llvm::Triple &TargetTriple,
const llvm::Triple &BiarchTriple,
SmallVectorImpl<StringRef> &LibDirs,
SmallVectorImpl<StringRef> &TripleAliases,
SmallVectorImpl<StringRef> &BiarchLibDirs,
SmallVectorImpl<StringRef> &BiarchTripleAliases);

bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args,
StringRef Path,
bool NeedsBiarchSuffix = false);

void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
const llvm::opt::ArgList &Args,
const std::string &LibDir,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);

void scanLibDirForGCCTripleSolaris(const llvm::Triple &TargetArch,
const llvm::opt::ArgList &Args,
const std::string &LibDir,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);

bool ScanGentooGccConfig(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);
};

protected:
GCCInstallationDetector GCCInstallation;
CudaInstallationDetector CudaInstallation;

public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
~Generic_GCC() override;

void printVerboseInfo(raw_ostream &OS) const override;

bool IsUnwindTablesDefault() const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
bool IsIntegratedAssemblerDefault() const override;
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;

protected:
Tool *getTool(Action::ActionClass AC) const override;
Tool *buildAssembler() const override;
Tool *buildLinker() const override;

/// \name ToolChain Implementation Helper Functions
/// @{

/// \brief Check whether the target triple's architecture is 64-bits.
bool isTarget64Bit() const { return getTriple().isArch64Bit(); }

/// \brief Check whether the target triple's architecture is 32-bits.
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }

// FIXME: This should be final, but the Solaris tool chain does weird
// things we can't easily represent.
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

virtual std::string findLibCxxIncludePath() const;
virtual void
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;

bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
StringRef GCCMultiarchTriple,
StringRef TargetMultiarchTriple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;

/// @}

private:
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocess;
mutable std::unique_ptr<tools::gcc::Compiler> Compile;
};

class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
virtual void anchor();

public:
Generic_ELF(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: Generic_GCC(D, Triple, Args) {}

void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
33 changes: 33 additions & 0 deletions clang/lib/Driver/ToolChains/Haiku.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===--- Haiku.cpp - Haiku ToolChain Implementations ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Haiku.h"
#include "CommonArgs.h"

using namespace clang::driver;
using namespace clang::driver::toolchains;;
using namespace clang;
using namespace llvm::opt;

/// Haiku - Haiku tool chain which can call as(1) and ld(1) directly.

Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {

}

std::string Haiku::findLibCxxIncludePath() const {
return getDriver().SysRoot + "/system/develop/headers/c++/v1";
}

void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addLibStdCXXIncludePaths(getDriver().SysRoot, "/system/develop/headers/c++",
getTriple().str(), "", "", "", DriverArgs, CC1Args);
}
40 changes: 40 additions & 0 deletions clang/lib/Driver/ToolChains/Haiku.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===--- Haiku.h - Haiku ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HAIKU_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HAIKU_H

#include "Gnu.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY Haiku : public Generic_ELF {
public:
Haiku(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

bool isPIEDefault() const override {
return getTriple().getArch() == llvm::Triple::x86_64;
}

std::string findLibCxxIncludePath() const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HAIKU_H
457 changes: 457 additions & 0 deletions clang/lib/Driver/ToolChains/Hexagon.cpp

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions clang/lib/Driver/ToolChains/Hexagon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//===--- Hexagon.h - Hexagon ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HEXAGON_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HEXAGON_H

#include "Linux.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {
namespace hexagon {
// For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile
// and Compile.
// We simply use "clang -cc1" for those actions.
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
public:
Assembler(const ToolChain &TC)
: GnuTool("hexagon::Assembler", "hexagon-as", TC) {}

bool hasIntegratedCPP() const override { return false; }

void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const;
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("hexagon::Linker", "hexagon-ld", TC) {}

bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }

virtual void RenderExtraToolArgs(const JobAction &JA,
llvm::opt::ArgStringList &CmdArgs) const;
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 hexagon.
} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
protected:
GCCVersion GCCLibAndIncVersion;
Tool *buildAssembler() const override;
Tool *buildLinker() const override;

public:
HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
~HexagonToolChain() override;

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;

StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
bool IsIntegratedAssemblerDefault() const override {
return true;
}

std::string getHexagonTargetDir(
const std::string &InstalledDir,
const SmallVectorImpl<std::string> &PrefixDirs) const;
void getHexagonLibraryPaths(const llvm::opt::ArgList &Args,
ToolChain::path_list &LibPaths) const;

static const StringRef GetDefaultCPU();
static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);

static Optional<unsigned> getSmallDataThreshold(
const llvm::opt::ArgList &Args);
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HEXAGON_H
39 changes: 39 additions & 0 deletions clang/lib/Driver/ToolChains/Lanai.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===--- Lanai.h - Lanai ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LANAI_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LANAI_H

#include "Gnu.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY LanaiToolChain : public Generic_ELF {
public:
LanaiToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: Generic_ELF(D, Triple, Args) {}

// No support for finding a C++ standard library yet.
std::string findLibCxxIncludePath() const override { return ""; }
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}

bool IsIntegratedAssemblerDefault() const override { return true; }
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LANAI_H
898 changes: 898 additions & 0 deletions clang/lib/Driver/ToolChains/Linux.cpp

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions clang/lib/Driver/ToolChains/Linux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//===--- Linux.h - Linux ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LINUX_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LINUX_H

#include "Gnu.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
public:
Linux(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

bool HasNativeLLVMSupport() const override;

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
std::string findLibCxxIncludePath() const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
bool isPIEDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
virtual std::string computeSysRoot() const;

virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;

std::vector<std::string> ExtraOpts;

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LINUX_H
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
//
//===----------------------------------------------------------------------===//

#include "ToolChains.h"
#include "Tools.h"
#include "Darwin.h"
#include "MSVC.h"
#include "CommonArgs.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
Expand Down Expand Up @@ -44,9 +46,348 @@

using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

// Try to find Exe from a Visual Studio distribution. This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
// from clang itself to prevent clang from falling back to itself.
static std::string FindVisualStudioExecutable(const ToolChain &TC,
const char *Exe,
const char *ClangProgramPath) {
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
std::string visualStudioBinDir;
if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath,
visualStudioBinDir)) {
SmallString<128> FilePath(visualStudioBinDir);
llvm::sys::path::append(FilePath, Exe);
if (llvm::sys::fs::can_execute(FilePath.c_str()))
return FilePath.str();
}

return Exe;
}

void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
const ToolChain &TC = getToolChain();

assert((Output.isFilename() || Output.isNothing()) && "invalid output");
if (Output.isFilename())
CmdArgs.push_back(
Args.MakeArgString(std::string("-out:") + Output.getFilename()));

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
!C.getDriver().IsCLMode())
CmdArgs.push_back("-defaultlib:libcmt");

if (!llvm::sys::Process::GetEnv("LIB")) {
// If the VC environment hasn't been configured (perhaps because the user
// did not run vcvarsall), try to build a consistent link environment. If
// the environment variable is set however, assume the user knows what
// they're doing.
std::string VisualStudioDir;
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
SmallString<128> LibDir(VisualStudioDir);
llvm::sys::path::append(LibDir, "VC", "lib");
switch (MSVC.getArch()) {
case llvm::Triple::x86:
// x86 just puts the libraries directly in lib
break;
case llvm::Triple::x86_64:
llvm::sys::path::append(LibDir, "amd64");
break;
case llvm::Triple::arm:
llvm::sys::path::append(LibDir, "arm");
break;
default:
break;
}
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));

if (MSVC.useUniversalCRT(VisualStudioDir)) {
std::string UniversalCRTLibPath;
if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
UniversalCRTLibPath));
}
}

std::string WindowsSdkLibPath;
if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}

if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));

CmdArgs.push_back("-nologo");

if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
options::OPT__SLASH_Zd))
CmdArgs.push_back("-debug");

bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
options::OPT_shared);
if (DLL) {
CmdArgs.push_back(Args.MakeArgString("-dll"));

SmallString<128> ImplibName(Output.getFilename());
llvm::sys::path::replace_extension(ImplibName, "lib");
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}

if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
if (TC.getSanitizerArgs().needsSharedAsanRt() ||
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
CmdArgs.push_back(Args.MakeArgString(
TC.getArch() == llvm::Triple::x86
? "-include:___asan_seh_interceptor"
: "-include:__asan_seh_interceptor"));
// Make sure the linker consider all object files from the dynamic runtime
// thunk.
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
} else if (DLL) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
} else {
for (const auto &Lib : {"asan", "asan_cxx"}) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
// Make sure the linker consider all object files from the static lib.
// This is necessary because instrumented dlls need access to all the
// interface exported by the static lib in the main executable.
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
TC.getCompilerRT(Args, Lib)));
}
}
}

Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);

if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
CmdArgs.push_back("-nodefaultlib:vcomp.lib");
CmdArgs.push_back("-nodefaultlib:vcompd.lib");
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
TC.getDriver().Dir + "/../lib"));
switch (TC.getDriver().getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
CmdArgs.push_back("-defaultlib:libomp.lib");
break;
case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-defaultlib:libiomp5md.lib");
break;
case Driver::OMPRT_GOMP:
break;
case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
}
}

// Add compiler-rt lib in case if it was explicitly
// specified as an argument for --rtlib option.
if (!Args.hasArg(options::OPT_nostdlib)) {
AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
}

// Add filenames, libraries, and other linker inputs.
for (const auto &Input : Inputs) {
if (Input.isFilename()) {
CmdArgs.push_back(Input.getFilename());
continue;
}

const Arg &A = Input.getInputArg();

// Render -l options differently for the MSVC linker.
if (A.getOption().matches(options::OPT_l)) {
StringRef Lib = A.getValue();
const char *LinkLibArg;
if (Lib.endswith(".lib"))
LinkLibArg = Args.MakeArgString(Lib);
else
LinkLibArg = Args.MakeArgString(Lib + ".lib");
CmdArgs.push_back(LinkLibArg);
continue;
}

// Otherwise, this is some other kind of linker input option like -Wl, -z,
// or -L. Render it, even if MSVC doesn't understand it.
A.renderAsInput(Args, CmdArgs);
}

TC.addProfileRTLibs(Args, CmdArgs);

// We need to special case some linker paths. In the case of lld, we need to
// translate 'lld' into 'lld-link', and in the case of the regular msvc
// linker, we need to use a special search algorithm.
llvm::SmallString<128> linkPath;
StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
if (Linker.equals_lower("lld"))
Linker = "lld-link";

if (Linker.equals_lower("link")) {
// If we're using the MSVC linker, it's not sufficient to just use link
// from the program PATH, because other environments like GnuWin32 install
// their own link.exe which may come first.
linkPath = FindVisualStudioExecutable(TC, "link.exe",
C.getDriver().getClangProgramPath());
} else {
linkPath = Linker;
llvm::sys::path::replace_extension(linkPath, "exe");
linkPath = TC.GetProgramPath(linkPath.c_str());
}

const char *Exec = Args.MakeArgString(linkPath);
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}

std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
Compilation &C, const JobAction &JA, const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
CmdArgs.push_back("/nologo");
CmdArgs.push_back("/c"); // Compile only.
CmdArgs.push_back("/W0"); // No warnings.

// The goal is to be able to invoke this tool correctly based on
// any flag accepted by clang-cl.

// These are spelled the same way in clang and cl.exe,.
Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});

// Optimization level.
if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
: "/Oi-");
if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
if (A->getOption().getID() == options::OPT_O0) {
CmdArgs.push_back("/Od");
} else {
CmdArgs.push_back("/Og");

StringRef OptLevel = A->getValue();
if (OptLevel == "s" || OptLevel == "z")
CmdArgs.push_back("/Os");
else
CmdArgs.push_back("/Ot");

CmdArgs.push_back("/Ob2");
}
}
if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
options::OPT_fno_omit_frame_pointer))
CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
? "/Oy"
: "/Oy-");
if (!Args.hasArg(options::OPT_fwritable_strings))
CmdArgs.push_back("/GF");

// Flags for which clang-cl has an alias.
// FIXME: How can we ensure this stays in sync with relevant clang-cl options?

if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
/*default=*/false))
CmdArgs.push_back("/GR-");

if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
/*default=*/false))
CmdArgs.push_back("/GS-");

if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
options::OPT_fno_function_sections))
CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
? "/Gy"
: "/Gy-");
if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
options::OPT_fno_data_sections))
CmdArgs.push_back(
A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
if (Args.hasArg(options::OPT_fsyntax_only))
CmdArgs.push_back("/Zs");
if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
options::OPT__SLASH_Z7))
CmdArgs.push_back("/Z7");

std::vector<std::string> Includes =
Args.getAllArgValues(options::OPT_include);
for (const auto &Include : Includes)
CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));

// Flags that can simply be passed through.
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);

// The order of these flags is relevant, so pick the last one.
if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
A->render(Args, CmdArgs);

// Use MSVC's default threadsafe statics behaviour unless there was a flag.
if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
options::OPT_fno_threadsafe_statics)) {
CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
? "/Zc:threadSafeInit"
: "/Zc:threadSafeInit-");
}

// Pass through all unknown arguments so that the fallback command can see
// them too.
Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);

// Input filename.
assert(Inputs.size() == 1);
const InputInfo &II = Inputs[0];
assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);

// Output filename.
assert(Output.getType() == types::TY_Object);
const char *Fo =
Args.MakeArgString(std::string("/Fo") + Output.getFilename());
CmdArgs.push_back(Fo);

const Driver &D = getToolChain().getDriver();
std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
D.getClangProgramPath());
return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs);
}

MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
Expand Down
133 changes: 133 additions & 0 deletions clang/lib/Driver/ToolChains/MSVC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//===--- MSVC.h - MSVC ToolChain Implementations ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H

#include "Cuda.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {

/// Visual studio tools.
namespace visualstudio {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC)
: Tool("visualstudio::Linker", "linker", TC, RF_Full,
llvm::sys::WEM_UTF16) {}

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;
};

class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
public:
Compiler(const ToolChain &TC)
: Tool("visualstudio::Compiler", "compiler", TC, RF_Full,
llvm::sys::WEM_UTF16) {}

bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
bool isLinkJob() const override { return false; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;

std::unique_ptr<Command> GetCommand(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace visualstudio

} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
public:
MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;

bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault() const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

bool getWindowsSDKDir(std::string &path, int &major,
std::string &windowsSDKIncludeVersion,
std::string &windowsSDKLibVersion) const;
bool getWindowsSDKLibraryPath(std::string &path) const;
/// \brief Check if Universal CRT should be used if available
bool useUniversalCRT(std::string &visualStudioDir) const;
bool getUniversalCRTSdkDir(std::string &path, std::string &ucrtVersion) const;
bool getUniversalCRTLibraryPath(std::string &path) const;
bool getVisualStudioInstallDir(std::string &path) const;
bool getVisualStudioBinariesFolder(const char *clangProgramPath,
std::string &path) const;
VersionTuple
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;

std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
SanitizerMask getSupportedSanitizers() const override;

void printVerboseInfo(raw_ostream &OS) const override;

protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const std::string &folder,
const Twine &subfolder1,
const Twine &subfolder2 = "",
const Twine &subfolder3 = "") const;

Tool *buildLinker() const override;
Tool *buildAssembler() const override;
private:
VersionTuple getMSVCVersionFromTriple() const;
VersionTuple getMSVCVersionFromExe() const;

CudaInstallationDetector CudaInstallation;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
471 changes: 471 additions & 0 deletions clang/lib/Driver/ToolChains/MinGW.cpp

Large diffs are not rendered by default.

102 changes: 102 additions & 0 deletions clang/lib/Driver/ToolChains/MinGW.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===--- MinGW.h - MinGW ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINGW_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINGW_H

#include "Cuda.h"
#include "Gnu.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {

/// MinGW -- Directly call GNU Binutils assembler and linker
namespace MinGW {
class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC) : Tool("MinGW::Assemble", "assembler", TC) {}

bool hasIntegratedCPP() const override { return false; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC) : Tool("MinGW::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;

private:
void AddLibGCC(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
};
} // end namespace MinGW
} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
public:
MinGW(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault() const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
bool UseSEHExceptions() const;

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

void printVerboseInfo(raw_ostream &OS) const override;

protected:
Tool *getTool(Action::ActionClass AC) const override;
Tool *buildLinker() const override;
Tool *buildAssembler() const override;

private:
CudaInstallationDetector CudaInstallation;

std::string Base;
std::string GccLibDir;
std::string Ver;
std::string Arch;
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;
mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
void findGccLibDir();
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINGW_H
109 changes: 109 additions & 0 deletions clang/lib/Driver/ToolChains/Minix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//===--- Minix.cpp - Minix ToolChain Implementations ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Minix.h"
#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"

using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;

void tools::minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;

Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());

const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;

if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}

Args.AddAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_e});

AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);

getToolChain().addProfileRTLibs(Args, CmdArgs);

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lCompilerRT-Generic");
CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
}

const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

/// Minix - Minix tool chain which can call as(1) and ld(1) directly.

toolchains::Minix::Minix(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}

Tool *toolchains::Minix::buildAssembler() const {
return new tools::minix::Assembler(*this);
}

Tool *toolchains::Minix::buildLinker() const {
return new tools::minix::Linker(*this);
}
66 changes: 66 additions & 0 deletions clang/lib/Driver/ToolChains/Minix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===--- Minix.h - Minix ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H

#include "Gnu.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
public:
Assembler(const ToolChain &TC)
: GnuTool("minix::Assembler", "assembler", TC) {}

bool hasIntegratedCPP() const override { return false; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};

class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("minix::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 minix
} // end namespace tools

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
public:
Minix(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H
128 changes: 128 additions & 0 deletions clang/lib/Driver/ToolChains/Mips.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//===--- Mips.cpp - Mips ToolChain Implementations --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Mips.h"
#include "Arch/Mips.h"
#include "CommonArgs.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

/// Mips Toolchain
MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args)
: Linux(D, Triple, Args) {
// Select the correct multilib according to the given arguments.
DetectedMultilibs Result;
findMIPSMultilibs(D, Triple, "", Args, Result);
Multilibs = Result.Multilibs;
SelectedMultilib = Result.SelectedMultilib;

// Find out the library suffix based on the ABI.
LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple);
getFilePaths().clear();
getFilePaths().push_back(computeSysRoot() + "/usr/lib" + LibSuffix);
}

void MipsLLVMToolChain::AddClangSystemIncludeArgs(
const ArgList &DriverArgs, ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
return;

const Driver &D = getDriver();

if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P);
}

if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;

const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
for (const auto &Path : Callback(SelectedMultilib))
addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
D.getInstalledDir() + Path);
}
}

Tool *MipsLLVMToolChain::buildLinker() const {
return new tools::gnutools::Linker(*this);
}

std::string MipsLLVMToolChain::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot + SelectedMultilib.osSuffix();

const std::string InstalledDir(getDriver().getInstalledDir());
std::string SysRootPath =
InstalledDir + "/../sysroot" + SelectedMultilib.osSuffix();
if (llvm::sys::fs::exists(SysRootPath))
return SysRootPath;

return std::string();
}

ToolChain::CXXStdlibType
MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const {
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
if (A) {
StringRef Value = A->getValue();
if (Value != "libc++")
getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}

return ToolChain::CST_Libcxx;
}

std::string MipsLLVMToolChain::findLibCxxIncludePath() const {
if (const auto &Callback = Multilibs.includeDirsCallback()) {
for (std::string Path : Callback(SelectedMultilib)) {
Path = getDriver().getInstalledDir() + Path + "/c++/v1";
if (llvm::sys::fs::exists(Path)) {
return Path;
}
}
}
return "";
}

void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) &&
"Only -lc++ (aka libxx) is suported in this toolchain.");

CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}

std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args,
StringRef Component,
bool Shared) const {
SmallString<128> Path(getDriver().ResourceDir);
llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix,
getOS());
llvm::sys::path::append(Path, Twine("libclang_rt." + Component + "-" +
"mips" + (Shared ? ".so" : ".a")));
return Path.str();
}
62 changes: 62 additions & 0 deletions clang/lib/Driver/ToolChains/Mips.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===--- Mips.h - Mips ToolChain Implementations ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MIPS_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MIPS_H

#include "Linux.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY MipsLLVMToolChain : public Linux {
protected:
Tool *buildLinker() const override;

public:
MipsLLVMToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;

std::string findLibCxxIncludePath() const override;

void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;

std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
bool Shared = false) const override;

std::string computeSysRoot() const override;

RuntimeLibType GetDefaultRuntimeLibType() const override {
return GCCInstallation.isValid() ? RuntimeLibType::RLT_Libgcc
: RuntimeLibType::RLT_CompilerRT;
}

const char *getDefaultLinker() const override {
return "lld";
}

private:
Multilib SelectedMultilib;
std::string LibSuffix;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MIPS_H
286 changes: 286 additions & 0 deletions clang/lib/Driver/ToolChains/Myriad.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
//===--- Myriad.cpp - Myriad ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Myriad.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"

using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

using tools::addPathIfExists;

void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
assert(Inputs.size() == 1);
const InputInfo &II = Inputs[0];
assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX ||
II.getType() == types::TY_PP_CXX);

if (JA.getKind() == Action::PreprocessJobClass) {
Args.ClaimAllArgs();
CmdArgs.push_back("-E");
} else {
assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
CmdArgs.push_back("-S");
CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
}
CmdArgs.push_back("-DMYRIAD2");

// Append all -I, -iquote, -isystem paths, defines/undefines,
// 'f' flags, optimize flags, and warning options.
// These are spelled the same way in clang and moviCompile.
Args.AddAllArgsExcept(
CmdArgs,
{options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
options::OPT_D, options::OPT_U, options::OPT_f_Group,
options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ},
{options::OPT_fno_split_dwarf_inlining});
Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.

// If we're producing a dependency file, and assembly is the final action,
// then the name of the target in the dependency file should be the '.o'
// file, not the '.s' file produced by this step. For example, instead of
// /tmp/mumble.s: mumble.c .../someheader.h
// the filename on the lefthand side should be "mumble.o"
if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) &&
C.getActions().size() == 1 &&
C.getActions()[0]->getKind() == Action::AssembleJobClass) {
Arg *A = Args.getLastArg(options::OPT_o);
if (A) {
CmdArgs.push_back("-MT");
CmdArgs.push_back(Args.MakeArgString(A->getValue()));
}
}

CmdArgs.push_back(II.getFilename());
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs));
}

void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;

assert(Inputs.size() == 1);
const InputInfo &II = Inputs[0];
assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
assert(Output.getType() == types::TY_Object);

CmdArgs.push_back("-no6thSlotCompression");
const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
if (CPUArg)
CmdArgs.push_back(
Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
CmdArgs.push_back("-noSPrefixing");
CmdArgs.push_back("-a"); // Mystery option.
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
A->claim();
CmdArgs.push_back(
Args.MakeArgString(std::string("-i:") + A->getValue(0)));
}
CmdArgs.push_back("-elf"); // Output format.
CmdArgs.push_back(II.getFilename());
CmdArgs.push_back(
Args.MakeArgString(std::string("-o:") + Output.getFilename()));

std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs));
}

void tools::Myriad::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;
bool UseStartfiles =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
bool UseDefaultLibs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
// Silence warning if the args contain both -nostdlib and -stdlib=.
Args.getLastArg(options::OPT_stdlib_EQ);

if (T.getArch() == llvm::Triple::sparc)
CmdArgs.push_back("-EB");
else // SHAVE assumes little-endian, and sparcel is expressly so.
CmdArgs.push_back("-EL");

// 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.

// Eat some arguments that may be present but have no effect.
Args.ClaimAllArgs(options::OPT_g_Group);
Args.ClaimAllArgs(options::OPT_w);
Args.ClaimAllArgs(options::OPT_static_libgcc);

if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
CmdArgs.push_back("-s");

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

if (UseStartfiles) {
// If you want startfiles, it means you want the builtin crti and crtbegin,
// but not crt0. Myriad link commands provide their own crt0.o as needed.
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
}

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});

TC.AddFilePathLibArgs(Args, CmdArgs);

bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);

if (UseDefaultLibs) {
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(TC, CmdArgs);
if (C.getDriver().CCCIsCXX()) {
if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
} else
CmdArgs.push_back("-lstdc++");
}
if (T.getOS() == llvm::Triple::RTEMS) {
CmdArgs.push_back("--start-group");
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
// You must provide your own "-L" option to enable finding these.
CmdArgs.push_back("-lrtemscpu");
CmdArgs.push_back("-lrtemsbsp");
CmdArgs.push_back("--end-group");
} else {
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc");
}
}
if (UseStartfiles) {
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
}

std::string Exec =
Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs));
}

MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
// If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
// 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
// This won't work to find gcc. Instead we give 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.
switch (Triple.getArch()) {
default:
D.Diag(clang::diag::err_target_unsupported_arch)
<< Triple.getArchName() << "myriad";
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::shave:
GCCInstallation.init(Triple, Args, {"sparc-myriad-elf"});
}

if (GCCInstallation.isValid()) {
// This directory contains crt{i,n,begin,end}.o as well as libgcc.
// These files are tied to a particular version of gcc.
SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
addPathIfExists(D, CompilerSupportDir, getFilePaths());
}
// libstd++ and libc++ must both be found in this one place.
addPathIfExists(D, D.Dir + "/../sparc-myriad-elf/lib", getFilePaths());
}

MyriadToolChain::~MyriadToolChain() {}

void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
}

std::string MyriadToolChain::findLibCxxIncludePath() const {
std::string Path(getDriver().getInstalledDir());
return Path + "/../include/c++/v1";
}

void MyriadToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
StringRef LibDir = GCCInstallation.getParentLibPath();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
addLibStdCXXIncludePaths(
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
"", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
}

// MyriadToolChain handles several triples:
// {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
// The inherited method works fine if not targeting the SHAVE.
if (!isShaveCompilation(getTriple()))
return ToolChain::SelectTool(JA);
switch (JA.getKind()) {
case Action::PreprocessJobClass:
case Action::CompileJobClass:
if (!Compiler)
Compiler.reset(new tools::SHAVE::Compiler(*this));
return Compiler.get();
case Action::AssembleJobClass:
if (!Assembler)
Assembler.reset(new tools::SHAVE::Assembler(*this));
return Assembler.get();
default:
return ToolChain::getTool(JA.getKind());
}
}

Tool *MyriadToolChain::buildLinker() const {
return new tools::Myriad::Linker(*this);
}

SanitizerMask MyriadToolChain::getSupportedSanitizers() const {
return SanitizerKind::Address;
}
Loading