https://github.com/Midar updated https://github.com/llvm/llvm-project/pull/191951
>From 14e0d9af04aef67ac8ba38dd936ccf6556add29d Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer <[email protected]> Date: Tue, 14 Apr 2026 00:18:28 -0500 Subject: [PATCH] Add support for MorphOS - Adds a MorphOS target - Adds toolchain for MorphOS - Adds -noixemul flag for MorphOS --- clang/include/clang/Basic/LangOptions.def | 2 + clang/include/clang/Options/Options.td | 7 + clang/lib/Basic/Targets.cpp | 2 + clang/lib/Basic/Targets/OSTargets.h | 32 ++++ clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 4 + clang/lib/Driver/ToolChains/Clang.cpp | 10 + clang/lib/Driver/ToolChains/MorphOS.cpp | 214 ++++++++++++++++++++++ clang/lib/Driver/ToolChains/MorphOS.h | 83 +++++++++ llvm/include/llvm/TargetParser/Triple.h | 5 + llvm/lib/TargetParser/Triple.cpp | 2 + 11 files changed, 362 insertions(+) create mode 100644 clang/lib/Driver/ToolChains/MorphOS.cpp create mode 100644 clang/lib/Driver/ToolChains/MorphOS.h diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 6bba142aaf428..a63eac0b5c0c4 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -530,6 +530,8 @@ LANGOPT(EnableLifetimeSafetyTUAnalysis, 1, 0, NotCompatible, "Lifetime safety at LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type") LANGOPT(Reflection , 1, 0, NotCompatible, "C++26 Reflection") +LANGOPT(NoIxemul, 1, 0, NotCompatible, "Do not use ixemul on MorphOS") + #undef LANGOPT #undef ENUM_LANGOPT #undef VALUE_LANGOPT diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index bffb3dfb27485..507d696d39ad0 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -10096,3 +10096,10 @@ def wasm_opt : Flag<["--"], "wasm-opt">, Group<m_Group>, HelpText<"Enable the wasm-opt optimizer (default)">, MarshallingInfoNegativeFlag<LangOpts<"NoWasmOpt">>; + +// Unfortunate naming to keep compatibility with GCC. +defm noixemul : BoolOption<"", "noixemul", + LangOpts<"NoIxemul">, DefaultFalse, + PosFlag<SetTrue, [], [ClangOption], "Do not use ixemul on MorphOS">, + NegFlag<SetFalse>, + BothFlags<[], [ClangOption, CC1Option]>>; diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index dc6ef6ed8f3f8..1eeafa71fdcd7 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -368,6 +368,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple, return std::make_unique<LinuxTargetInfo<PPC32TargetInfo>>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique<FreeBSDTargetInfo<PPC32TargetInfo>>(Triple, Opts); + case llvm::Triple::MorphOS: + return std::make_unique<MorphOSTargetInfo<PPC32TargetInfo>>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique<NetBSDTargetInfo<PPC32TargetInfo>>(Triple, Opts); case llvm::Triple::OpenBSD: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 16337d56f82c3..aee7f0fca3526 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -447,6 +447,38 @@ class LLVM_LIBRARY_VISIBILITY ManagarmTargetInfo : public OSTargetInfo<Target> { } }; +// MorphOS Target +template <typename Target> +class LLVM_LIBRARY_VISIBILITY MorphOSTargetInfo : public OSTargetInfo<Target> { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // MorphOS defines; list based off of gcc output + Builder.defineMacro("__MORPHOS__"); + Builder.defineMacro("__morphos__"); + Builder.defineMacro("__AMIGA__"); + Builder.defineMacro("__AMIGA"); + Builder.defineMacro("_AMIGA"); + Builder.defineMacro("AMIGA"); + Builder.defineMacro("__amigaos__"); + Builder.defineMacro("__amigaos"); + Builder.defineMacro("amigaos"); + if (Opts.NoIxemul) { + Builder.defineMacro("__libnix__"); + Builder.defineMacro("__libnix"); + Builder.defineMacro("libnix"); + } else { + Builder.defineMacro("__ixemul__"); + Builder.defineMacro("__ixemul"); + Builder.defineMacro("ixemul"); + } + } + +public: + MorphOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo<Target>(Triple, Opts) {} +}; + // NetBSD Target template <typename Target> class LLVM_LIBRARY_VISIBILITY NetBSDTargetInfo : public OSTargetInfo<Target> { diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index b8b10b351633f..cb09669d0a1a8 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -80,6 +80,7 @@ add_clang_library(clangDriver ToolChains/Managarm.cpp ToolChains/MipsLinux.cpp ToolChains/MinGW.cpp + ToolChains/MorphOS.cpp ToolChains/MSP430.cpp ToolChains/MSVC.cpp ToolChains/NetBSD.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index c41a8ded73b7b..a186d28cf48cd 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -37,6 +37,7 @@ #include "ToolChains/Managarm.h" #include "ToolChains/MinGW.h" #include "ToolChains/MipsLinux.h" +#include "ToolChains/MorphOS.h" #include "ToolChains/NetBSD.h" #include "ToolChains/OHOS.h" #include "ToolChains/OpenBSD.h" @@ -7152,6 +7153,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::ChipStar: TC = std::make_unique<toolchains::HIPSPVToolChain>(*this, Target, Args); break; + case llvm::Triple::MorphOS: + TC = std::make_unique<toolchains::MorphOS>(*this, Target, Args); + break; default: // Of these targets, Hexagon is the only one that might have // an OS of Linux, in which case it got handled above already. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f685abe9dad35..fd0376e651c4e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8071,6 +8071,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addOpenMPHostOffloadingArgs(C, JA, Args, CmdArgs); + if (TC.getTriple().isOSMorphOS()) { + Args.AddLastArg(CmdArgs, options::OPT_noixemul); + } else { + // Reject MorphOS-specific link options on other targets. + for (const Arg *A : Args.filtered(options::OPT_noixemul)) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << TripleStr; + } + } + if (Args.hasFlag(options::OPT_fdevirtualize_speculatively, options::OPT_fno_devirtualize_speculatively, /*Default value*/ false)) diff --git a/clang/lib/Driver/ToolChains/MorphOS.cpp b/clang/lib/Driver/ToolChains/MorphOS.cpp new file mode 100644 index 0000000000000..21fd12fc33649 --- /dev/null +++ b/clang/lib/Driver/ToolChains/MorphOS.cpp @@ -0,0 +1,214 @@ +//===--- MorphOS.cpp - MorphOS ToolChain Implementations --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MorphOS.h" +#include "clang/Config/config.h" +#include "clang/Driver/CommonArgs.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Options/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +void morphos::Assembler::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const auto &ToolChain = static_cast<const MorphOS &>(getToolChain()); + ArgStringList CmdArgs; + + claimNoWarnArgs(Args); + + 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((ToolChain.GetProgramPath("as"))); + C.addCommand(std::make_unique<Command>(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); +} + +void morphos::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const auto &ToolChain = static_cast<const MorphOS &>(getToolChain()); + const Driver &D = ToolChain.getDriver(); + ArgStringList CmdArgs; + // FIXME: Discover GCC instead of hard-coding the version. + const std::string GCCLibPath = D.SysRoot + "/lib/gcc-lib/ppc-morphos/15.1.0"; + const bool NoIxemul = Args.hasArg(options::OPT_noixemul); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + CmdArgs.push_back("--defsym"); + CmdArgs.push_back("__abox__=1"); + CmdArgs.push_back("-Qy"); + + CmdArgs.push_back("-Bstatic"); + if (NoIxemul) { + Args.ClaimAllArgs(options::OPT_noixemul); + CmdArgs.push_back("--flavor=libnix"); + } else { + CmdArgs.push_back("--flavor=ixemul"); + } + + assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { + if (NoIxemul) { + CmdArgs.push_back(Args.MakeArgString( + GCCLibPath + "/../../../../ppc-morphos/lib/libnix/crt0i.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/libnix/ecrti.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/libnix/crtbegin.o")); + } else { + CmdArgs.push_back(Args.MakeArgString( + GCCLibPath + "/../../../../ppc-morphos/lib/crt0i.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/ecrti.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/crtbegin.o")); + } + } + + CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath)); + CmdArgs.push_back( + Args.MakeArgString("-L" + GCCLibPath + "/../../../../ppc-morphos/lib")); + CmdArgs.push_back(Args.MakeArgString("-L" + D.SysRoot + "/lib")); + + Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, + options::OPT_s, options::OPT_t}); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, + options::OPT_r)) { + if (D.CCCIsCXX()) { + if (ToolChain.ShouldLinkCXXStdlib(Args)) + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lm"); + } + + // Silence warnings when linking C code with a C++ '-stdlib' argument. + Args.ClaimAllArgs(options::OPT_stdlib_EQ); + + CmdArgs.push_back("--start-group"); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-labox"); + CmdArgs.push_back("-laboxstubs"); + CmdArgs.push_back("-lsavl"); + CmdArgs.push_back("--end-group"); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { + if (NoIxemul) { + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/libnix/crtend.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/libnix/ecrtn.o")); + } else { + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/crtend.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "/ecrtn.o")); + } + } + + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + C.addCommand(std::make_unique<Command>(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); +} + +/// MorphOS - MorphOS tool chain which can call as(1) and ld(1) directly. + +MorphOS::MorphOS(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + if (!Args.hasArg(options::OPT_nostdlib)) { + getFilePaths().push_back(concat(getDriver().SysRoot, "/ppc-morphos/lib")); + } +} + +Tool *MorphOS::buildAssembler() const { + return new tools::morphos::Assembler(*this); +} + +Tool *MorphOS::buildLinker() const { return new tools::morphos::Linker(*this); } + +ToolChain::CXXStdlibType MorphOS::GetDefaultCXXStdlibType() const { + return ToolChain::CST_Libstdcxx; +} + +void MorphOS::AddClangSystemIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> Dir(D.ResourceDir); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } + + 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; + } + + if (DriverArgs.hasArg(options::OPT_noixemul)) { + addExternCSystemInclude(DriverArgs, CC1Args, + concat(D.SysRoot, "/includestd")); + } + addExternCSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot, "/include")); + addExternCSystemInclude(DriverArgs, CC1Args, + concat(D.SysRoot, "/usr/include")); + addExternCSystemInclude(DriverArgs, CC1Args, + concat(D.SysRoot, "/os-include")); +} + +void MorphOS::addLibStdCxxIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + // FIXME: Discover GCC instead of hard-coding the version. + addLibStdCXXIncludePaths( + concat(getDriver().SysRoot, + "/lib/gcc-lib/ppc-morphos/15.1.0/include/c++"), + "", "", DriverArgs, CC1Args); +} diff --git a/clang/lib/Driver/ToolChains/MorphOS.h b/clang/lib/Driver/ToolChains/MorphOS.h new file mode 100644 index 0000000000000..c58488ac36104 --- /dev/null +++ b/clang/lib/Driver/ToolChains/MorphOS.h @@ -0,0 +1,83 @@ +//===--- MorphOS.h - MorphOS ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MORPHOS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MORPHOS_H + +#include "Gnu.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace tools { + +/// Directly call GNU Binutils assembler and linker +namespace morphos { +class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool { +public: + Assembler(const ToolChain &TC) + : Tool("morphos::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 final : public Tool { +public: + Linker(const ToolChain &TC) : Tool("morphos::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 morphos +} // end namespace tools + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY MorphOS : public Generic_ELF { +public: + MorphOS(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool IsMathErrnoDefault() const override { return false; } + bool IsObjCNonFragileABIDefault() const override { return true; } + + CXXStdlibType GetDefaultCXXStdlibType() const 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; + + UnwindTableLevel + getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override { + return UnwindTableLevel::Asynchronous; + } + +protected: + Tool *buildAssembler() const override; + Tool *buildLinker() const override; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MORPHOS_H diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 7c5aa52a1bd04..538da08186b21 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -256,6 +256,7 @@ class Triple { ChipStar, Firmware, QURT, + MorphOS, LastOSType = QURT }; enum EnvironmentType { @@ -690,6 +691,10 @@ class Triple { return getOS() == Triple::ELFIAMCU; } + bool isOSMorphOS() const { + return getOS() == Triple::MorphOS; + } + bool isOSUnknown() const { return getOS() == Triple::UnknownOS; } bool isGNUEnvironment() const { diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 7a907808c0f34..82cc71989768c 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -315,6 +315,7 @@ StringRef Triple::getOSTypeName(OSType Kind) { case Managarm: return "managarm"; case Mesa3D: return "mesa3d"; + case MorphOS: return "morphos"; case NVCL: return "nvcl"; case NetBSD: return "netbsd"; case OpenBSD: return "openbsd"; @@ -724,6 +725,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("lv2", Triple::Lv2) .StartsWith("macos", Triple::MacOSX) .StartsWith("managarm", Triple::Managarm) + .StartsWith("morphos", Triple::MorphOS) .StartsWith("netbsd", Triple::NetBSD) .StartsWith("openbsd", Triple::OpenBSD) .StartsWith("solaris", Triple::Solaris) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
