From 0b21467e6102cbad5b7652c06abac42be4cf0a04 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Mon, 11 Nov 2024 23:18:27 +0200 Subject: [PATCH 1/2] alnyan/yggdrasil: Yggdrasil target support --- clang/lib/Basic/Targets.cpp | 6 + clang/lib/Basic/Targets/OSTargets.h | 19 ++ clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 4 + clang/lib/Driver/ToolChains/Yggdrasil.cpp | 255 +++++++++++++++++++++ clang/lib/Driver/ToolChains/Yggdrasil.h | 98 ++++++++ compiler-rt/lib/builtins/cpu_model/x86.c | 3 + libcxx/include/__locale | 4 +- libcxx/include/ios | 4 + libcxx/src/atomic.cpp | 12 + libcxx/src/locale.cpp | 2 +- llvm/cmake/modules/HandleLLVMOptions.cmake | 2 +- llvm/include/llvm/TargetParser/Triple.h | 1 + llvm/lib/TargetParser/Triple.cpp | 2 + 14 files changed, 409 insertions(+), 4 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/Yggdrasil.cpp create mode 100644 clang/lib/Driver/ToolChains/Yggdrasil.h diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 29133f9ee8fc..b116c06e86bc 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -142,6 +142,8 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, return std::make_unique(Triple, Opts); switch (os) { + case llvm::Triple::Yggdrasil: + return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); @@ -578,6 +580,8 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, } case llvm::Triple::Haiku: return std::make_unique(Triple, Opts); + case llvm::Triple::Yggdrasil: + return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique(Triple, Opts); case llvm::Triple::NaCl: @@ -638,6 +642,8 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, } case llvm::Triple::Haiku: return std::make_unique>(Triple, Opts); + case llvm::Triple::Yggdrasil: + return std::make_unique>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); case llvm::Triple::PS4: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 357c1965057c..339eb218f830 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -878,6 +878,25 @@ public: } }; +// Yggdrasil Target +template +class LLVM_LIBRARY_VISIBILITY YggdrasilTargetInfo : public OSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + Builder.defineMacro("__yggdrasil__"); + Builder.defineMacro("__FLOAT128__"); + this->PlatformName = "yggdrasil"; + } +public: + YggdrasilTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo(Triple, Opts) { + this->WIntType = TargetInfo::UnsignedInt; + this->MCountName = "__mcount"; + this->HasFloat128 = true; + } +}; + // WebAssembly target template 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(*this, Target, Args); break; + case llvm::Triple::Yggdrasil: + TC = std::make_unique(*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..d45945abbd99 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Yggdrasil.cpp @@ -0,0 +1,255 @@ +#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 + +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(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()); + + CmdArgs.push_back("-z"); + CmdArgs.push_back("max-page-size=4096"); + + CmdArgs.push_back("--eh-frame-hdr"); + + if (!Args.hasArg(options::OPT_shared) && + !Args.hasArg(options::OPT_static) && + !Args.hasArg(options::OPT_r)) { + CmdArgs.push_back("-pie"); + } + + if (Args.hasArg(options::OPT_r)) { + CmdArgs.push_back("-r"); + } else { + CmdArgs.push_back("--build-id"); + CmdArgs.push_back("--hash-style=gnu"); + } + + 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("--dynamic-linker=/libexec/dyn-loader"); + } + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, options::OPT_r)) { + 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); + // } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); + + if (!Args.hasArg(options::OPT_nolibc)) { + CmdArgs.push_back("-lygglibc"); + } + + if (D.CCCIsCXX()) { + if (ToolChain.ShouldLinkCXXStdlib(Args)) { + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + // CmdArgs.push_back("-lm"); + // CmdArgs.push_back("-lpthread"); + } + } + } + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + + C.addCommand(std::make_unique(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::RuntimeLibType Yggdrasil::GetDefaultRuntimeLibType() const { + return ToolChain::RLT_CompilerRT; +} + +ToolChain::CXXStdlibType Yggdrasil::GetDefaultCXXStdlibType() const { + return ToolChain::CST_Libcxx; +} + +ToolChain::UnwindLibType Yggdrasil::GetUnwindLibType(const ArgList &Args) const { + return ToolChain::UNW_None; +} + +ToolChain::CXXStdlibType Yggdrasil::GetCXXStdlibType(const ArgList &Args) const { + return ToolChain::CST_Libcxx; +} + +ToolChain::UnwindTableLevel Yggdrasil::getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const { + return ToolChain::UnwindTableLevel::None; +} + +void Yggdrasil::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args, + Action::OffloadKind) const { + if (getArch() == llvm::Triple::x86) { + CC1Args.push_back("-mstack-alignment=16"); + } + // 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..985bbc06ce27 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Yggdrasil.h @@ -0,0 +1,98 @@ +#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; } + UnwindTableLevel getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override; + RuntimeLibType GetDefaultRuntimeLibType() const override; + CXXStdlibType GetDefaultCXXStdlibType() const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const { + return true; + } + 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/compiler-rt/lib/builtins/cpu_model/x86.c b/compiler-rt/lib/builtins/cpu_model/x86.c index b1c4abd9d11d..05939e079f66 100644 --- a/compiler-rt/lib/builtins/cpu_model/x86.c +++ b/compiler-rt/lib/builtins/cpu_model/x86.c @@ -1157,8 +1157,11 @@ int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) { unsigned Vendor; unsigned Model, Family; unsigned Features[(CPU_FEATURE_MAX + 31) / 32] = {0}; +// TODO static_assert is not defined +#if !defined(__yggdrasil__) static_assert(sizeof(Features) / sizeof(Features[0]) == 4, ""); static_assert(sizeof(__cpu_features2) / sizeof(__cpu_features2[0]) == 3, ""); +#endif // This function needs to run just once. if (__cpu_model.__cpu_vendor) diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 4b382764b446..dd047eaceae0 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -314,7 +314,7 @@ public: # else static const mask __regex_word = 1 << 10; # endif // defined(__BIONIC__) -#elif defined(__GLIBC__) +#elif defined(__GLIBC__) || defined(__yggdrasil__) typedef unsigned short mask; static const mask space = _ISspace; static const mask print = _ISprint; @@ -326,7 +326,7 @@ public: static const mask punct = _ISpunct; static const mask xdigit = _ISxdigit; static const mask blank = _ISblank; -# if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN) +# if !defined(__yggdrasil__) && (defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN)) static const mask __regex_word = static_cast(_ISbit(15)); # else static const mask __regex_word = 0x80; diff --git a/libcxx/include/ios b/libcxx/include/ios index d8a3643c7ad5..b13c474a72af 100644 --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -244,7 +244,11 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +#if defined(__yggdrasil__) +typedef ssize_t streamsize; +#else typedef ptrdiff_t streamsize; +#endif class _LIBCPP_EXPORTED_FROM_ABI ios_base { public: diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp index ae062155661e..3906f8d1f589 100644 --- a/libcxx/src/atomic.cpp +++ b/libcxx/src/atomic.cpp @@ -101,6 +101,18 @@ static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const vo _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), UMTX_OP_WAKE, __notify_one ? 1 : INT_MAX, NULL, NULL); } +#elif defined(__yggdrasil__) + +static void __libcpp_platform_wait_on_address( + __cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val +) {} + +static void __libcpp_platform_wake_by_address( + __cxx_atomic_contention_t const volatile*, + bool +) {} + #else // <- Add other operating systems here // Baseline is just a timed backoff diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index 4efdc63c0966..86a08de694de 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -985,7 +985,7 @@ const ctype::mask* ctype::classic_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_b; # elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) return __pctype_func(); -# elif defined(__EMSCRIPTEN__) +# elif defined(__EMSCRIPTEN__) || defined(__yggdrasil__) return *__ctype_b_loc(); # elif defined(_NEWLIB_VERSION) // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index 5ca580fbb59c..1fed40a04091 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -217,7 +217,7 @@ elseif(FUCHSIA OR UNIX) else() set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic" OR CMAKE_SYSTEM_NAME STREQUAL "yggdrasil") set(LLVM_ON_WIN32 0) set(LLVM_ON_UNIX 0) set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) 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); } -- 2.48.1