diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 29133f9ee8fc..de2cbc2a7580 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -578,6 +578,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, } case llvm::Triple::Haiku: return std::make_unique<HaikuX86_32TargetInfo>(Triple, Opts); + case llvm::Triple::Yggdrasil: + return std::make_unique<YggdrasilTargetInfo<X86_32TargetInfo>>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique<RTEMSX86_32TargetInfo>(Triple, Opts); case llvm::Triple::NaCl: @@ -638,6 +640,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, } case llvm::Triple::Haiku: return std::make_unique<HaikuTargetInfo<X86_64TargetInfo>>(Triple, Opts); + case llvm::Triple::Yggdrasil: + return std::make_unique<YggdrasilTargetInfo<X86_64TargetInfo>>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique<NaClTargetInfo<X86_64TargetInfo>>(Triple, Opts); case llvm::Triple::PS4: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 357c1965057c..d2a2ded87bb3 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -878,6 +878,23 @@ public: } }; +// Yggdrasil Target +template <typename Target> +class LLVM_LIBRARY_VISIBILITY YggdrasilTargetInfo : public OSTargetInfo<Target> { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + Builder.defineMacro("__yggdrasil__"); + this->PlatformName = "yggdrasil"; + } +public: + YggdrasilTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo<Target>(Triple, Opts) { + this->WIntType = TargetInfo::UnsignedInt; + this->MCountName = "__mcount"; + } +}; + // WebAssembly target template <typename Target> class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 32a4378ab499..42dcc9037620 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -85,6 +85,7 @@ add_clang_library(clangDriver ToolChains/PPCFreeBSD.cpp ToolChains/InterfaceStubs.cpp ToolChains/ZOS.cpp + ToolChains/Yggdrasil.cpp Types.cpp XRayArgs.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index ecae475f75da..18604cc8ed75 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -21,6 +21,7 @@ #include "ToolChains/DragonFly.h" #include "ToolChains/FreeBSD.h" #include "ToolChains/Fuchsia.h" +#include "ToolChains/Yggdrasil.h" #include "ToolChains/Gnu.h" #include "ToolChains/HIPAMD.h" #include "ToolChains/HIPSPV.h" @@ -6351,6 +6352,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Haiku: TC = std::make_unique<toolchains::Haiku>(*this, Target, Args); break; + case llvm::Triple::Yggdrasil: + TC = std::make_unique<toolchains::Yggdrasil>(*this, Target, Args); + break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: diff --git a/clang/lib/Driver/ToolChains/Yggdrasil.cpp b/clang/lib/Driver/ToolChains/Yggdrasil.cpp new file mode 100644 index 000000000000..83d728c37e77 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Yggdrasil.cpp @@ -0,0 +1,218 @@ +#include "Yggdrasil.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/MultilibBuilder.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/Option/ArgList.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" + +#include <iostream> + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +using tools::addMultilibFlag; + + +void yggdrasil::Linker::ConstructJob( + Compilation &C, + const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput +) const { + const toolchains::Yggdrasil &ToolChain = static_cast<const toolchains::Yggdrasil &>(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 (!D.SysRoot.empty()) { + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + } + + if (Args.hasArg(options::OPT_s)) { + CmdArgs.push_back("-s"); + } + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + } else if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-shared"); + } + + 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("crt0.o"))); + // } + // } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); + + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + + // if (D.isUsingLTO()) { + // assert(!Inputs.empty() && "Must have at least one input."); + // addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0], + // D.getLTOMode() == LTOK_Thin); + // } + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + // if (D.CCCIsCXX()) { + // if (ToolChain.ShouldLinkCXXStdlib(Args)) { + // ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + // CmdArgs.push_back("-lm"); + // CmdArgs.push_back("-lpthread"); + // } + // } + + // AddRunTimeLibs(ToolChain, D, CmdArgs, Args); + + if (!Args.hasArg(options::OPT_nolibc)) { + CmdArgs.push_back("-lc"); + } + } + + C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), + Exec, CmdArgs, Inputs, Output)); +} + +/// Yggdrasil - Yggdrasil OS tool chain which can call as(1) and ld(1) directly. + +Yggdrasil::Yggdrasil( + const Driver &D, + const llvm::Triple &Triple, + const ArgList &Args +): ToolChain(D, Triple, Args) { + getProgramPaths().push_back(getDriver().Dir); + + if (!D.SysRoot.empty()) { + SmallString<128> P(D.SysRoot); + llvm::sys::path::append(P, "lib"); + getFilePaths().push_back(std::string(P)); + } +} + +std::string Yggdrasil::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { + llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); + return Triple.str(); +} + +Tool *Yggdrasil::buildLinker() const { + return new tools::yggdrasil::Linker(*this); +} + +ToolChain::RuntimeLibType Yggdrasil::GetRuntimeLibType(const ArgList &Args) const { + return ToolChain::RLT_CompilerRT; +} + +ToolChain::UnwindLibType Yggdrasil::GetUnwindLibType(const ArgList &Args) const { + return ToolChain::UNW_None; +} + +ToolChain::CXXStdlibType Yggdrasil::GetCXXStdlibType(const ArgList &Args) const { + return ToolChain::CST_Libcxx; +} + +void Yggdrasil::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args, + Action::OffloadKind) const { + // if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, + // options::OPT_fno_use_init_array, true)) + // CC1Args.push_back("-fno-use-init-array"); + + // CC1Args.push_back("-mlong-double-64"); // for newlib + libc++ compat + + // CC1Args.push_back("-ffunction-sections"); // better to optimize binary sizes + // CC1Args.push_back("-fdata-sections"); +} + +void Yggdrasil::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; + } + + if (!D.SysRoot.empty()) { + SmallString<128> P(D.SysRoot); + llvm::sys::path::append(P, "include"); + addExternCSystemInclude(DriverArgs, CC1Args, P.str()); + } +} + +void Yggdrasil::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) { + return; + } + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: { + SmallString<128> P(getDriver().SysRoot); + llvm::sys::path::append(P, "include", "c++", "v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + break; + } + + default: + llvm_unreachable("invalid stdlib name"); + } +} + +void Yggdrasil::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + break; + + case ToolChain::CST_Libstdcxx: + llvm_unreachable("invalid stdlib name"); + } +} + +std::string Yggdrasil::getCompilerRTPath() const { + SmallString<128> Path(getDriver().SysRoot); + llvm::sys::path::append(Path, "lib", getOSLibName()); + return std::string(Path.str()); +} diff --git a/clang/lib/Driver/ToolChains/Yggdrasil.h b/clang/lib/Driver/ToolChains/Yggdrasil.h new file mode 100644 index 000000000000..81c9891ac1cc --- /dev/null +++ b/clang/lib/Driver/ToolChains/Yggdrasil.h @@ -0,0 +1,101 @@ +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_YGGDRASIL_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_YGGDRASIL_H + +#include "Gnu.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/MC/MCTargetOptions.h" + +namespace clang { +namespace driver { +namespace tools { +namespace yggdrasil { + +class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { +public: + Linker(const ToolChain &TC) : Tool("yggdrasil::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 yggdrasil +} // end tools + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY Yggdrasil : public ToolChain { +public: + Yggdrasil(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); + + bool HasNativeLLVMSupport() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } + bool IsMathErrnoDefault() const override { return false; } + bool useRelaxRelocations() const override { return true; } + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const { + return false; + } + llvm::ExceptionHandling GetExceptionModel(const llvm::opt::ArgList &Args) const override { + return llvm::ExceptionHandling::DwarfCFI; + } + bool isPICDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return false; } + bool isPICDefaultForced() const override { return false; } + + llvm::DebuggerKind getDefaultDebuggerTuning() const override { + return llvm::DebuggerKind::GDB; + } + + LangOptions::StackProtectorMode GetDefaultStackProtectorLevel(bool KernelOrKext) const override { + return LangOptions::SSPStrong; + } + std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, + types::ID InputType) const override; + + RuntimeLibType + GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; + UnwindLibType + GetUnwindLibType(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, + Action::OffloadKind DeviceOffloadKind) 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; + + const char *getDefaultLinker() const override { + return "ld.lld"; + } + + virtual std::string getCompilerRTPath() const override; + +protected: + Tool *buildLinker() const override; +}; + +} // end toolchains + +} // end driver +} // end clang + +#endif diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index d2126a03db90..63fb1124ff43 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -238,6 +238,7 @@ public: ShaderModel, // DirectX ShaderModel LiteOS, Serenity, + Yggdrasil, Vulkan, // Vulkan SPIR-V LastOSType = Vulkan }; diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 21d6c74b5956..be4f1180f750 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -292,6 +292,7 @@ StringRef Triple::getOSTypeName(OSType Kind) { case RTEMS: return "rtems"; case Solaris: return "solaris"; case Serenity: return "serenity"; + case Yggdrasil: return "yggdrasil"; case TvOS: return "tvos"; case UEFI: return "uefi"; case WASI: return "wasi"; @@ -686,6 +687,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("shadermodel", Triple::ShaderModel) .StartsWith("liteos", Triple::LiteOS) .StartsWith("serenity", Triple::Serenity) + .StartsWith("yggdrasil", Triple::Yggdrasil) .StartsWith("vulkan", Triple::Vulkan) .Default(Triple::UnknownOS); }