diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -86,6 +86,7 @@ Targets/WebAssembly.cpp Targets/X86.cpp Targets/XCore.cpp + Targets/VE.cpp TokenKinds.cpp Version.cpp Warnings.cpp diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -33,6 +33,7 @@ #include "Targets/Sparc.h" #include "Targets/SystemZ.h" #include "Targets/TCE.h" +#include "Targets/VE.h" #include "Targets/WebAssembly.h" #include "Targets/X86.h" #include "Targets/XCore.h" @@ -608,6 +609,9 @@ return new LinuxTargetInfo(Triple, Opts); case llvm::Triple::renderscript64: return new LinuxTargetInfo(Triple, Opts); + + case llvm::Triple::ve: + return new LinuxTargetInfo(Triple, Opts); } } } // namespace targets diff --git a/clang/lib/Basic/Targets/VE.h b/clang/lib/Basic/Targets/VE.h new file mode 100644 --- /dev/null +++ b/clang/lib/Basic/Targets/VE.h @@ -0,0 +1,155 @@ +//===--- VE.h - Declare VE target feature support ---------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares VE TargetInfo objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_VE_H +#define LLVM_CLANG_LIB_BASIC_TARGETS_VE_H + +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Compiler.h" + +namespace clang { +namespace targets { + +class LLVM_LIBRARY_VISIBILITY VETargetInfo : public TargetInfo { + +public: + VETargetInfo(const llvm::Triple &Triple, const TargetOptions &) + : TargetInfo(Triple) { + NoAsmVariants = true; + LongDoubleWidth = 128; + LongDoubleAlign = 128; + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + DoubleAlign = LongLongAlign = 64; + SuitableAlign = 64; + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + SizeType = UnsignedLong; + PtrDiffType = SignedLong; + IntPtrType = SignedLong; + IntMaxType = SignedLong; + Int64Type = SignedLong; + RegParmMax = 8; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + + WCharType = UnsignedInt; + WIntType = UnsignedInt; + UseZeroLengthBitfieldAlignment = true; + resetDataLayout("e-m:e-i64:64-n32:64-S64"); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; + + bool hasSjLjLowering() const override { return true; } + + ArrayRef getTargetBuiltins() const override; + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::VoidPtrBuiltinVaList; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_X86RegCall: + return CCCR_OK; + } + } + + const char *getClobbers() const override { return ""; } + + ArrayRef getGCCRegNames() const override { + static const char *const GCCRegNames[] = { + // Regular registers + "sx0", "sx1", "sx2", "sx3", "sx4", "sx5", "sx6", "sx7", + "sx8", "sx9", "sx10", "sx11", "sx12", "sx13", "sx14", "sx15", + "sx16", "sx17", "sx18", "sx19", "sx20", "sx21", "sx22", "sx23", + "sx24", "sx25", "sx26", "sx27", "sx28", "sx29", "sx30", "sx31", + "sx32", "sx33", "sx34", "sx35", "sx36", "sx37", "sx38", "sx39", + "sx40", "sx41", "sx42", "sx43", "sx44", "sx45", "sx46", "sx47", + "sx48", "sx49", "sx50", "sx51", "sx52", "sx53", "sx54", "sx55", + "sx56", "sx57", "sx58", "sx59", "sx60", "sx61", "sx62", "sx63", + // Vector registers + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + "v32", "v33", "v34", "v35", "v36", "v37", "v38", "v39", + "v40", "v41", "v42", "v43", "v44", "v45", "v46", "v47", + "v48", "v49", "v50", "v51", "v52", "v53", "v54", "v55", + "v56", "v57", "v58", "v59", "v60", "v61", "v62", "v63", + // Special registers + "vl", "vixr", "ucc", "psw", "sar", "pmmr", + "pmcr0", "pmcr1", "pmcr2", "pmcr3", + "pmc0", "pmc1", "pmc2", "pmc3", "pmc4", "pmc5", "pmc6", "pmc7", + "pmc8", "pmc9", "pmc10", "pmc11", "pmc12", "pmc13", "pmc14", + }; + return llvm::makeArrayRef(GCCRegNames); + } + + ArrayRef getGCCRegAliases() const override { + static const TargetInfo::GCCRegAlias GCCRegAliases[] = { + {{"s0"}, "sx0"}, {{"s1"}, "sx1"}, + {{"s2"}, "sx2"}, {{"s3"}, "sx3"}, + {{"s4"}, "sx4"}, {{"s5"}, "sx5"}, + {{"s6"}, "sx6"}, {{"s7"}, "sx7"}, + {{"s8", "sl"}, "sx8"}, {{"s9", "fp"}, "sx9"}, + {{"s10", "lr"}, "sx10"}, {{"s11", "sp"}, "sx11"}, + {{"s12", "outer"}, "sx12"}, {{"s13"}, "sx13"}, + {{"s14", "tp"}, "sx14"}, {{"s15", "got"}, "sx15"}, + {{"s16", "plt"}, "sx16"}, {{"s17", "info"}, "sx17"}, + {{"s18"}, "sx18"}, {{"s19"}, "sx19"}, + {{"s20"}, "sx20"}, {{"s21"}, "sx21"}, + {{"s22"}, "sx22"}, {{"s23"}, "sx23"}, + {{"s24"}, "sx24"}, {{"s25"}, "sx25"}, + {{"s26"}, "sx26"}, {{"s27"}, "sx27"}, + {{"s28"}, "sx28"}, {{"s29"}, "sx29"}, + {{"s30"}, "sx30"}, {{"s31"}, "sx31"}, + {{"s32"}, "sx32"}, {{"s33"}, "sx33"}, + {{"s34"}, "sx34"}, {{"s35"}, "sx35"}, + {{"s36"}, "sx36"}, {{"s37"}, "sx37"}, + {{"s38"}, "sx38"}, {{"s39"}, "sx39"}, + {{"s40"}, "sx40"}, {{"s41"}, "sx41"}, + {{"s42"}, "sx42"}, {{"s43"}, "sx43"}, + {{"s44"}, "sx44"}, {{"s45"}, "sx45"}, + {{"s46"}, "sx46"}, {{"s47"}, "sx47"}, + {{"s48"}, "sx48"}, {{"s49"}, "sx49"}, + {{"s50"}, "sx50"}, {{"s51"}, "sx51"}, + {{"s52"}, "sx52"}, {{"s53"}, "sx53"}, + {{"s54"}, "sx54"}, {{"s55"}, "sx55"}, + {{"s56"}, "sx56"}, {{"s57"}, "sx57"}, + {{"s58"}, "sx58"}, {{"s59"}, "sx59"}, + {{"s60"}, "sx60"}, {{"s61"}, "sx61"}, + {{"s62"}, "sx62"}, {{"s63"}, "sx63"}, + {{"vix"}, "vixr"}, {{"usrcc"}, "ucc"}, + }; + return llvm::makeArrayRef(GCCRegAliases); + } + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { + return false; + } + + int getEHDataRegisterNumber(unsigned RegNo) const override { + // S0 = ExceptionPointerRegister, S1 = ExceptionSelectorRegister + return (RegNo < 2) ? RegNo : -1; + } + + bool allowsLargerPreferedTypeAlignment() const override { return false; } +}; +} // namespace targets +} // namespace clang +#endif // LLVM_CLANG_LIB_BASIC_TARGETS_VE_H diff --git a/clang/lib/Basic/Targets/VE.cpp b/clang/lib/Basic/Targets/VE.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Basic/Targets/VE.cpp @@ -0,0 +1,39 @@ +//===--- VE.cpp - Implement VE target feature support ---------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements VE TargetInfo objects. +// +//===----------------------------------------------------------------------===// + +#include "VE.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" + +using namespace clang; +using namespace clang::targets; + +void VETargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("_LP64", "1"); + Builder.defineMacro("unix", "1"); + Builder.defineMacro("__unix__", "1"); + Builder.defineMacro("__linux__", "1"); + Builder.defineMacro("__ve", "1"); + Builder.defineMacro("__ve__", "1"); + Builder.defineMacro("__STDC_HOSTED__", "1"); + Builder.defineMacro("__STDC__", "1"); + Builder.defineMacro("__NEC__", "1"); + // FIXME: define __FAST_MATH__ 1 if -ffast-math is enabled + // FIXME: define __OPTIMIZE__ n if -On is enabled + // FIXME: define __VECTOR__ n 1 if automatic vectorization is enabled +} + +ArrayRef VETargetInfo::getTargetBuiltins() const { + return None; +} diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -9763,6 +9763,46 @@ }; } // namespace +//===----------------------------------------------------------------------===// +// VE ABI Implementation. +// Copied from SPARC V8 ABI. +// +// Ensures that complex values are passed in registers. +// +namespace { +class VEABIInfo : public DefaultABIInfo { +public: + VEABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + +private: + ABIArgInfo classifyReturnType(QualType RetTy) const; + void computeInfo(CGFunctionInfo &FI) const override; +}; +} // end anonymous namespace + +ABIArgInfo VEABIInfo::classifyReturnType(QualType Ty) const { + if (Ty->isAnyComplexType()) { + return ABIArgInfo::getDirect(); + } else { + return DefaultABIInfo::classifyReturnType(Ty); + } +} + +void VEABIInfo::computeInfo(CGFunctionInfo &FI) const { + + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &Arg : FI.arguments()) + Arg.info = classifyArgumentType(Arg.type); +} + +namespace { +class VETargetCodeGenInfo : public TargetCodeGenInfo { +public: + VETargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(new VEABIInfo(CGT)) {} +}; +} // end anonymous namespace + //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// @@ -9950,6 +9990,8 @@ case llvm::Triple::spir: case llvm::Triple::spir64: return SetCGInfo(new SPIRTargetCodeGenInfo(Types)); + case llvm::Triple::ve: + return SetCGInfo(new VETargetCodeGenInfo(Types)); } } diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -31,6 +31,7 @@ ToolChains/Arch/Sparc.cpp ToolChains/Arch/SystemZ.cpp ToolChains/Arch/X86.cpp + ToolChains/Arch/VE.cpp ToolChains/AIX.cpp ToolChains/Ananas.cpp ToolChains/AMDGPU.cpp @@ -70,6 +71,7 @@ ToolChains/XCore.cpp ToolChains/PPCLinux.cpp ToolChains/InterfaceStubs.cpp + ToolChains/VE.cpp Types.cpp XRayArgs.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -45,6 +45,7 @@ #include "ToolChains/TCE.h" #include "ToolChains/WebAssembly.h" #include "ToolChains/XCore.h" +#include "ToolChains/VE.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -4823,17 +4824,19 @@ case llvm::Triple::Linux: case llvm::Triple::ELFIAMCU: if (Target.getArch() == llvm::Triple::hexagon) - TC = std::make_unique(*this, Target, - Args); + TC = + std::make_unique(*this, Target, Args); + else if (Target.getArch() == llvm::Triple::ve) + TC = std::make_unique(*this, Target, Args); else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) && !Target.hasEnvironment()) TC = std::make_unique(*this, Target, - Args); + Args); else if (Target.getArch() == llvm::Triple::ppc || Target.getArch() == llvm::Triple::ppc64 || Target.getArch() == llvm::Triple::ppc64le) TC = std::make_unique(*this, Target, - Args); + Args); else TC = std::make_unique(*this, Target, Args); break; @@ -4924,6 +4927,9 @@ case llvm::Triple::riscv64: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::ve: + TC = std::make_unique(*this, Target, Args); + break; default: if (Target.getVendor() == llvm::Triple::Myriad) TC = std::make_unique(*this, Target, diff --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/VE.h @@ -0,0 +1,41 @@ +//===--- VE.h - VE-specific Tool Helpers ------------------------*- 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_ARCH_VE_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H + +#include "clang/Driver/Driver.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" +#include +#include + +namespace clang { +namespace driver { +namespace tools { +namespace ve { + +enum class FloatABI { + Invalid, + Soft, + Hard, +}; + +FloatABI getVEFloatABI(const Driver &D, const llvm::opt::ArgList &Args); + +void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, + std::vector &Features); +const char *getVEAsmModeForCPU(llvm::StringRef Name, + const llvm::Triple &Triple); + +} // end namespace ve +} // end namespace target +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H diff --git a/clang/lib/Driver/ToolChains/Arch/VE.cpp b/clang/lib/Driver/ToolChains/Arch/VE.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/VE.cpp @@ -0,0 +1,67 @@ +//===--- VE.cpp - Tools 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 "VE.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/ArgList.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +const char *ve::getVEAsmModeForCPU(StringRef Name, + const llvm::Triple &Triple) { + return llvm::StringSwitch(Name) + .Default(""); +} + +ve::FloatABI ve::getVEFloatABI(const Driver &D, + const ArgList &Args) { + ve::FloatABI ABI = ve::FloatABI::Invalid; + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_msoft_float, + options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { + if (A->getOption().matches(clang::driver::options::OPT_msoft_float)) + ABI = ve::FloatABI::Soft; + else if (A->getOption().matches(options::OPT_mhard_float)) + ABI = ve::FloatABI::Hard; + else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", ve::FloatABI::Soft) + .Case("hard", ve::FloatABI::Hard) + .Default(ve::FloatABI::Invalid); + if (ABI == ve::FloatABI::Invalid && + !StringRef(A->getValue()).empty()) { + D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = ve::FloatABI::Hard; + } + } + } + + // If unspecified, choose the default based on the platform. + // Only the hard-float ABI on VE is standardized, and it is the + // default. GCC also supports a nonstandard soft-float ABI mode, also + // implemented in LLVM. However as this is not standard we set the default + // to be hard-float. + if (ABI == ve::FloatABI::Invalid) { + ABI = ve::FloatABI::Hard; + } + + return ABI; +} + +void ve::getVETargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features) { + ve::FloatABI FloatABI = ve::getVEFloatABI(D, Args); + if (FloatABI == ve::FloatABI::Soft) + Features.push_back("+soft-float"); +} diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -73,6 +73,8 @@ llvm::opt::ArgStringList &CmdArgs) const; void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + void AddVETargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile }; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -15,6 +15,7 @@ #include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "Arch/VE.h" #include "AMDGPU.h" #include "CommonArgs.h" #include "Hexagon.h" @@ -368,6 +369,9 @@ break; case llvm::Triple::msp430: msp430::getMSP430TargetFeatures(D, Args, Features); + break; + case llvm::Triple::ve: + ve::getVETargetFeatures(D, Args, Features); } // Find the last of each feature. @@ -1675,6 +1679,10 @@ case llvm::Triple::wasm64: AddWebAssemblyTargetArgs(Args, CmdArgs); break; + + case llvm::Triple::ve: + AddVETargetArgs(Args, CmdArgs); + break; } } @@ -2112,6 +2120,24 @@ } } +void Clang::AddVETargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + ve::FloatABI FloatABI = + ve::getVEFloatABI(getToolChain().getDriver(), Args); + + if (FloatABI == ve::FloatABI::Soft) { + // Floating point operations and argument passing are soft. + CmdArgs.push_back("-msoft-float"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("soft"); + } else { + // Floating point operations and argument passing are hard. + assert(FloatABI == ve::FloatABI::Hard && "Invalid float abi!"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("hard"); + } +} + void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, StringRef Target, const InputInfo &Output, const InputInfo &Input, const ArgList &Args) const { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -489,8 +489,11 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { + // Enable -frtlib-add-rpath by default for the case of VE. + const bool IsVE = TC.getTriple().isVE(); + bool DefaultValue = IsVE; if (!Args.hasFlag(options::OPT_frtlib_add_rpath, - options::OPT_fno_rtlib_add_rpath, false)) + options::OPT_fno_rtlib_add_rpath, DefaultValue)) return; std::string CandidateRPath = TC.getArchSpecificLibPath(); diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -304,6 +304,8 @@ if (T.getEnvironment() == llvm::Triple::GNUX32) return "elf32_x86_64"; return "elf_x86_64"; + case llvm::Triple::ve: + return "elf64ve"; default: return nullptr; } @@ -355,6 +357,8 @@ const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool isAndroid = ToolChain.getTriple().isAndroid(); const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU(); + const bool IsVE = ToolChain.getTriple().isVE(); + const bool IsMusl = ToolChain.getTriple().isMusl(); const bool IsPIE = getPIE(Args, ToolChain); const bool IsStaticPIE = getStaticPIE(Args, ToolChain); const bool IsStatic = getStatic(Args); @@ -475,6 +479,11 @@ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); } + if (IsVE) { + CmdArgs.push_back("-z"); + CmdArgs.push_back("max-page-size=0x4000000"); + } + if (IsIAMCU) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); else if (HasCRTBeginEndFiles) { @@ -570,7 +579,7 @@ AddRunTimeLibs(ToolChain, D, CmdArgs, Args); - if (WantPthread && !isAndroid) + if (WantPthread && !isAndroid && !(IsVE && IsMusl)) CmdArgs.push_back("-lpthread"); if (Args.hasArg(options::OPT_fsplit_stack)) @@ -646,6 +655,7 @@ llvm::Reloc::Model RelocationModel; unsigned PICLevel; bool IsPIE; + const char *DefaultAssembler = "as"; std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(getToolChain(), Args); @@ -866,6 +876,8 @@ CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); break; } + case llvm::Triple::ve: + DefaultAssembler = "nas"; } for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ, @@ -890,7 +902,8 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler)); C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); // Handle the debug info splitting at object creation time if we're diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -518,6 +518,7 @@ if (Triple.isMusl()) { std::string ArchName; + std::string Path = "/lib/"; bool IsArm = false; switch (Arch) { @@ -531,6 +532,10 @@ ArchName = "armeb"; IsArm = true; break; + case llvm::Triple::ve: + Path = "/opt/nec/ve/musl/lib/"; + ArchName = "ve"; + break; default: ArchName = Triple.getArchName().str(); } @@ -539,7 +544,7 @@ tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)) ArchName += "hf"; - return "/lib/ld-musl-" + ArchName + ".so.1"; + return Path + "ld-musl-" + ArchName + ".so.1"; } std::string LibDir; @@ -638,6 +643,9 @@ Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2"; break; } + case llvm::Triple::ve: + return "/opt/nec/ve/lib/ld-linux-ve.so.1"; + break; } if (Distro == Distro::Exherbo && diff --git a/clang/lib/Driver/ToolChains/VE.h b/clang/lib/Driver/ToolChains/VE.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/VE.h @@ -0,0 +1,66 @@ +//===--- VE.h - VE 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_VE_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H + +#include "Linux.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY VEToolChain : public Linux { +public: + VEToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + +protected: + Tool *buildAssembler() const override; + Tool *buildLinker() const override; + +public: + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; + bool SupportsProfiling() const override; + bool hasBlocksRuntime() const override; + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void + addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) 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; + + llvm::ExceptionHandling + GetExceptionModel(const llvm::opt::ArgList &Args) const override; + + CXXStdlibType + GetCXXStdlibType(const llvm::opt::ArgList &Args) const override { + return ToolChain::CST_Libcxx; + } + + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + + const char *getDefaultLinker() const override { return "nld"; } +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H diff --git a/clang/lib/Driver/ToolChains/VE.cpp b/clang/lib/Driver/ToolChains/VE.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/VE.cpp @@ -0,0 +1,151 @@ +//===--- VE.cpp - VE 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 "VE.h" +#include "CommonArgs.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include // ::getenv + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +/// VE tool chain +VEToolChain::VEToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Linux(D, Triple, Args) { + getProgramPaths().push_back("/opt/nec/ve/bin"); + // ProgramPaths are found via 'PATH' environment variable. + + // default file paths are: + // ${RESOURCEDIR}/lib/linux/ve (== getArchSpecificLibPath) + // /lib/../lib64 + // /usr/lib/../lib64 + // ${BINPATH}/../lib + // /lib + // /usr/lib + // + // These are OK for host, but no go for VE. So, defines them all + // from scratch here. + getFilePaths().clear(); + getFilePaths().push_back(getArchSpecificLibPath()); + if (getTriple().isMusl()) + getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/musl/lib"); + else + getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib"); +} + +Tool *VEToolChain::buildAssembler() const { + return new tools::gnutools::Assembler(*this); +} + +Tool *VEToolChain::buildLinker() const { + return new tools::gnutools::Linker(*this); +} + +bool VEToolChain::isPICDefault() const { return false; } + +bool VEToolChain::isPIEDefault() const { return false; } + +bool VEToolChain::isPICDefaultForced() const { return false; } + +bool VEToolChain::SupportsProfiling() const { return false; } + +bool VEToolChain::hasBlocksRuntime() const { return false; } + +void VEToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) + return; + + if (DriverArgs.hasArg(options::OPT_nobuiltininc) && + DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(getDriver().ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { + if (const char *cl_include_dir = getenv("NCC_C_INCLUDE_PATH")) { + SmallVector Dirs; + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; + StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr)); + ArrayRef DirVec(Dirs); + addSystemIncludes(DriverArgs, CC1Args, DirVec); + } else { + if (getTriple().isMusl()) + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/opt/nec/ve/musl/include"); + else + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/opt/nec/ve/include"); + } + } +} + +void VEToolChain::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args, + Action::OffloadKind) const { + CC1Args.push_back("-nostdsysteminc"); + bool UseInitArrayDefault = true; + if (DriverArgs.hasFlag(options::OPT_fuse_init_array, + options::OPT_fno_use_init_array, UseInitArrayDefault)) + CC1Args.push_back("-fuse-init-array"); +} + +void VEToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) || + DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + if (const char *cl_include_dir = getenv("NCC_CPLUS_INCLUDE_PATH")) { + SmallVector Dirs; + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; + StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr)); + ArrayRef DirVec(Dirs); + addSystemIncludes(DriverArgs, CC1Args, DirVec); + } else { + SmallString<128> P(getDriver().ResourceDir); + llvm::sys::path::append(P, "include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P); + } +} + +void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) && + "Only -lc++ (aka libxx) is supported in this toolchain."); + + tools::addArchSpecificRPath(*this, Args, CmdArgs); + + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); + // libc++ requires -lpthread under glibc environment + // libunwind requires -ldl under glibc environment + if (!getTriple().isMusl()) { + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + } +} + +llvm::ExceptionHandling +VEToolChain::GetExceptionModel(const ArgList &Args) const { + // VE uses SjLj exceptions. + return llvm::ExceptionHandling::SjLj; +} diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2980,7 +2980,8 @@ Arch != llvm::Triple::x86; emitError |= (DefaultCC == LangOptions::DCC_VectorCall || DefaultCC == LangOptions::DCC_RegCall) && - !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); + !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || + Arch == llvm::Triple::ve); if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple();