[Driver] Add driver support for Fuchsia

Provide toolchain and tool support for Fuchsia operating system.
Fuchsia uses compiler-rt as the runtime library and libc++, libc++abi
and libunwind as the C++ standard library. lld is used as a default
linker.

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

llvm-svn: 283420
This commit is contained in:
Petr Hosek 2016-10-06 06:08:09 +00:00
parent e023d62e76
commit 62e1d23986
8 changed files with 359 additions and 0 deletions

View File

@ -823,6 +823,28 @@ public:
}
};
// Fuchsia Target
template<typename Target>
class FuchsiaTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("__Fuchsia__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
// Required by the libc++ locale support.
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
FuchsiaTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->MCountName = "__mcount";
}
};
// WebAssembly target
template <typename Target>
class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> {
@ -8271,6 +8293,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new LinuxTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
return new FuchsiaTargetInfo<AArch64leTargetInfo>(Triple, Opts);
default:
return new AArch64leTargetInfo(Triple, Opts);
}
@ -8639,6 +8663,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new HaikuTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
return new FuchsiaTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::PS4:
return new PS4OSTargetInfo<X86_64TargetInfo>(Triple, Opts);
default:

View File

@ -3075,6 +3075,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::NaCl:
TC = new toolchains::NaClToolChain(*this, Target, Args);
break;
case llvm::Triple::Fuchsia:
TC = new toolchains::Fuchsia(*this, Target, Args);
break;
case llvm::Triple::Solaris:
TC = new toolchains::Solaris(*this, Target, Args);
break;

View File

@ -4761,6 +4761,108 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
ToolChain::addProfileRTLibs(Args, CmdArgs);
}
/// 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");
// Use LLD by default.
DefaultLinker = "lld";
}
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(options::OPT_rtlib_EQ)) {
StringRef Value = A->getValue();
if (Value != "compiler-rt")
getDriver().Diag(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");
}
void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
addSystemInclude(DriverArgs, CC1Args,
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");
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,

View File

@ -1008,6 +1008,39 @@ private:
std::string NaClArmMacrosPath;
};
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;
}
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;
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;
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {

View File

@ -9493,6 +9493,7 @@ static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm_unreachable("unsupported OS");
case llvm::Triple::Win32:
case llvm::Triple::Linux:
case llvm::Triple::Fuchsia:
addClangRT(TC, Args, CmdArgs);
break;
}
@ -9979,6 +9980,112 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
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::filename(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);
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));
}
void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,

View File

@ -596,6 +596,21 @@ public:
};
} // end namespace nacltools
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
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {

View File

@ -0,0 +1,40 @@
// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \
// RUN: --sysroot=%S/platform 2>&1 | FileCheck %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
// CHECK: "-fuse-init-array"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
// CHECK: {{.*}}lld{{.*}}" "-flavor" "gnu"
// CHECK: "--sysroot=[[SYSROOT]]"
// CHECK: "-pie"
// CHECK: "--build-id"
// CHECK: "-dynamic-linker" "ld.so.1"
// CHECK: Scrt1.o
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]/lib"
// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
// CHECK-NOT: crtn.o
// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -rtlib=libgcc 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RTLIB
// CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc'
// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -static 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
// CHECK-STATIC: "-Bstatic"
// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lc"
// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -shared 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-SHARED
// CHECK-SHARED-NOT: "-pie"
// CHECK-SHARED: "-shared"
// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -r 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
// CHECK-RELOCATABLE-NOT: "-pie"
// CHECK-RELOCATABLE-NOT: "--build-id"
// CHECK-RELOCATABLE: "-r"

View File

@ -0,0 +1,33 @@
// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia \
// RUN: --sysroot=%S/platform 2>&1 | FileCheck %s
// CHECK: {{.*}}clang{{.*}}" "-cc1"
// CHECK: "-fuse-init-array"
// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
// CHECK: "-internal-isystem" "[[SYSROOT]]{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1"
// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
// CHECK: {{.*}}lld{{.*}}" "-flavor" "gnu"
// CHECK: "--sysroot=[[SYSROOT]]"
// CHECK: "-pie"
// CHECK: "--build-id"
// CHECK: "-dynamic-linker" "ld.so.1"
// CHECK: Scrt1.o
// CHECK-NOT: crti.o
// CHECK-NOT: crtbegin.o
// CHECK: "-L[[SYSROOT]]/lib"
// CHECK: "-lc++" "-lc++abi" "-lunwind" "-lm"
// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
// CHECK: "-lc"
// CHECK-NOT: crtend.o
// CHECK-NOT: crtn.o
// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -stdlib=libstdc++ 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STDLIB
// CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++'
// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
// CHECK-STATIC: "-Bstatic"
// CHECK-STATIC: "-lc++" "-lc++abi" "-lunwind"
// CHECK-STATIC: "-Bdynamic"
// CHECK-STATIC: "-lm"
// CHECK-STATIC: "-lc"