diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -394,7 +394,7 @@ def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>; def TargetMSP430 : TargetArch<["msp430"]>; def TargetM68k : TargetArch<["m68k"]>; -def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; +def TargetRISCV : TargetArch<["riscv32", "riscv64", "riscv32be", "riscv64be"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>; 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 @@ -426,6 +426,12 @@ return new RISCV64TargetInfo(Triple, Opts); } + case llvm::Triple::riscv32be: + return new RISCV32beTargetInfo(Triple, Opts); + + case llvm::Triple::riscv64be: + return new RISCV64beTargetInfo(Triple, Opts); + case llvm::Triple::sparc: switch (os) { case llvm::Triple::Linux: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -256,6 +256,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: break; } } @@ -491,6 +493,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: break; } } diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -101,14 +101,13 @@ return false; } }; -class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { +class LLVM_LIBRARY_VISIBILITY RISCV32BaseTargetInfo : public RISCVTargetInfo { public: - RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + RISCV32BaseTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : RISCVTargetInfo(Triple, Opts) { IntPtrType = SignedInt; PtrDiffType = SignedInt; SizeType = UnsignedInt; - resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128"); } bool setABI(const std::string &Name) override { @@ -131,13 +130,12 @@ MaxAtomicInlineWidth = 32; } }; -class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { +class LLVM_LIBRARY_VISIBILITY RISCV64BaseTargetInfo : public RISCVTargetInfo { public: - RISCV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + RISCV64BaseTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : RISCVTargetInfo(Triple, Opts) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = Int64Type = SignedLong; - resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n64-S128"); } bool setABI(const std::string &Name) override { @@ -160,6 +158,34 @@ MaxAtomicInlineWidth = 64; } }; +class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCV32BaseTargetInfo { +public: + RISCV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : RISCV32BaseTargetInfo(Triple, Opts) { + resetDataLayout("e-m:e-p:32:32-i64:64-n32-S128"); + } +}; +class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCV64BaseTargetInfo { +public: + RISCV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : RISCV64BaseTargetInfo(Triple, Opts) { + resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n64-S128"); + } +}; +class LLVM_LIBRARY_VISIBILITY RISCV32beTargetInfo : public RISCV32BaseTargetInfo { +public: + RISCV32beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : RISCV32BaseTargetInfo(Triple, Opts) { + resetDataLayout("E-m:e-p:32:32-i64:64-n32-S128"); + } +}; +class LLVM_LIBRARY_VISIBILITY RISCV64beTargetInfo : public RISCV64BaseTargetInfo { +public: + RISCV64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : RISCV64BaseTargetInfo(Triple, Opts) { + resetDataLayout("E-m:e-p:64:64-i64:64-i128:128-n64-S128"); + } +}; } // namespace targets } // namespace clang diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -121,7 +121,8 @@ MacroBuilder &Builder) const { Builder.defineMacro("__ELF__"); Builder.defineMacro("__riscv"); - bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; + bool Is64Bit = (getTriple().getArch() == llvm::Triple::riscv64 || + getTriple().getArch() == llvm::Triple::riscv64be); Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); StringRef CodeModel = getTargetOpts().CodeModel; unsigned FLen = ISAInfo->getFLen(); @@ -216,7 +217,8 @@ unsigned XLen = 32; - if (getTriple().getArch() == llvm::Triple::riscv64) { + if (getTriple().getArch() == llvm::Triple::riscv64 || + getTriple().getArch() == llvm::Triple::riscv64be) { Features["64bit"] = true; XLen = 64; } @@ -244,7 +246,8 @@ /// Return true if has this feature, need to sync with handleTargetFeatures. bool RISCVTargetInfo::hasFeature(StringRef Feature) const { - bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; + bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64 || + getTriple().getArch() == llvm::Triple::riscv64be; auto Result = llvm::StringSwitch>(Feature) .Case("riscv", true) .Case("riscv32", !Is64Bit) @@ -283,44 +286,44 @@ return true; } -bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { +bool RISCV32BaseTargetInfo::isValidCPUName(StringRef Name) const { return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), /*Is64Bit=*/false); } -void RISCV32TargetInfo::fillValidCPUList( +void RISCV32BaseTargetInfo::fillValidCPUList( SmallVectorImpl &Values) const { llvm::RISCV::fillValidCPUArchList(Values, false); } -bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { +bool RISCV32BaseTargetInfo::isValidTuneCPUName(StringRef Name) const { return llvm::RISCV::checkTuneCPUKind( llvm::RISCV::parseTuneCPUKind(Name, false), /*Is64Bit=*/false); } -void RISCV32TargetInfo::fillValidTuneCPUList( +void RISCV32BaseTargetInfo::fillValidTuneCPUList( SmallVectorImpl &Values) const { llvm::RISCV::fillValidTuneCPUArchList(Values, false); } -bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { +bool RISCV64BaseTargetInfo::isValidCPUName(StringRef Name) const { return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), /*Is64Bit=*/true); } -void RISCV64TargetInfo::fillValidCPUList( +void RISCV64BaseTargetInfo::fillValidCPUList( SmallVectorImpl &Values) const { llvm::RISCV::fillValidCPUArchList(Values, true); } -bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { +bool RISCV64BaseTargetInfo::isValidTuneCPUName(StringRef Name) const { return llvm::RISCV::checkTuneCPUKind( llvm::RISCV::parseTuneCPUKind(Name, true), /*Is64Bit=*/true); } -void RISCV64TargetInfo::fillValidTuneCPUList( +void RISCV64BaseTargetInfo::fillValidTuneCPUList( SmallVectorImpl &Values) const { llvm::RISCV::fillValidTuneCPUArchList(Values, true); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5431,6 +5431,8 @@ return CGF->EmitHexagonBuiltinExpr(BuiltinID, E); case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue); default: return nullptr; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -709,7 +709,8 @@ getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth); } - if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64) { + if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64 || + Arch == llvm::Triple::riscv32be || Arch == llvm::Triple::riscv64be) { StringRef ABIStr = Target.getABI(); llvm::LLVMContext &Ctx = TheModule.getContext(); getModule().addModuleFlag(llvm::Module::Error, "target-abi", @@ -945,6 +946,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: getModule().addModuleFlag(llvm::Module::Error, "SmallDataLimit", CodeGenOpts.SmallDataLimit); break; 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 @@ -11652,7 +11652,9 @@ return SetCGInfo(new MSP430TargetCodeGenInfo(Types)); case llvm::Triple::riscv32: - case llvm::Triple::riscv64: { + case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: { StringRef ABIStr = getTarget().getABI(); unsigned XLen = getTarget().getPointerWidth(0); unsigned ABIFLen = 0; 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 @@ -654,10 +654,17 @@ A = Args.getLastArg(options::OPT_march_EQ); if (A && Target.isRISCV()) { StringRef ArchName = A->getValue(); - if (ArchName.startswith_insensitive("rv32")) - Target.setArch(llvm::Triple::riscv32); - else if (ArchName.startswith_insensitive("rv64")) - Target.setArch(llvm::Triple::riscv64); + if (ArchName.startswith_insensitive("rv32")) { + if (Target.isLittleEndian()) + Target.setArch(llvm::Triple::riscv32); + else + Target.setArch(llvm::Triple::riscv32be); + } else if (ArchName.startswith_insensitive("rv64")) { + if (Target.isLittleEndian()) + Target.setArch(llvm::Triple::riscv64); + else + Target.setArch(llvm::Triple::riscv64be); + } } return Target; @@ -6043,6 +6050,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args)) TC = std::make_unique(*this, Target, Args); diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -51,7 +51,8 @@ const llvm::opt::ArgList &Args, const llvm::opt::Arg *A, StringRef Mcpu, std::vector &Features) { - bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64); + bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64 || + Triple.getArch() == llvm::Triple::riscv64be); llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu); if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) || !llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) { @@ -156,7 +157,9 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { assert((Triple.getArch() == llvm::Triple::riscv32 || - Triple.getArch() == llvm::Triple::riscv64) && + Triple.getArch() == llvm::Triple::riscv64 || + Triple.getArch() == llvm::Triple::riscv32be || + Triple.getArch() == llvm::Triple::riscv64be) && "Unexpected triple"); // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not @@ -205,7 +208,8 @@ // We deviate from GCC's defaults here: // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only. // - On all other OSs we use the double floating point calling convention. - if (Triple.getArch() == llvm::Triple::riscv32) { + if (Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv32be) { if (Triple.getOS() == llvm::Triple::UnknownOS) return "ilp32"; else @@ -221,7 +225,9 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args, const llvm::Triple &Triple) { assert((Triple.getArch() == llvm::Triple::riscv32 || - Triple.getArch() == llvm::Triple::riscv64) && + Triple.getArch() == llvm::Triple::riscv64 || + Triple.getArch() == llvm::Triple::riscv32be || + Triple.getArch() == llvm::Triple::riscv64be) && "Unexpected triple"); // GCC's logic around choosing a default `-march=` is complex. If GCC is not @@ -283,7 +289,8 @@ // We deviate from GCC's defaults here: // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac` // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`) - if (Triple.getArch() == llvm::Triple::riscv32) { + if (Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv32be) { if (Triple.getOS() == llvm::Triple::UnknownOS) return "rv32imac"; else diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -39,7 +39,8 @@ StringRef Arch = riscv::getRISCVArch(Args, TargetTriple); StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple); - if (TargetTriple.getArch() == llvm::Triple::riscv64) { + if (TargetTriple.getArch() == llvm::Triple::riscv64 || + TargetTriple.getArch() == llvm::Triple::riscv64be) { Multilib Imac = makeMultilib("").flag("+march=rv64imac").flag("+mabi=lp64"); Multilib Imafdc = makeMultilib("/rv64imafdc/lp64d") .flag("+march=rv64imafdc") @@ -57,7 +58,8 @@ Result.Multilibs = MultilibSet().Either(Imac, Imafdc); return Result.Multilibs.select(Flags, Result.SelectedMultilib); } - if (TargetTriple.getArch() == llvm::Triple::riscv32) { + if (TargetTriple.getArch() == llvm::Triple::riscv32 || + TargetTriple.getArch() == llvm::Triple::riscv32be) { Multilib Imac = makeMultilib("").flag("+march=rv32imac").flag("+mabi=ilp32"); Multilib I = @@ -141,7 +143,9 @@ static bool isRISCVBareMetal(const llvm::Triple &Triple) { if (Triple.getArch() != llvm::Triple::riscv32 && - Triple.getArch() != llvm::Triple::riscv64) + Triple.getArch() != llvm::Triple::riscv64 && + Triple.getArch() != llvm::Triple::riscv32be && + Triple.getArch() != llvm::Triple::riscv64be) return false; if (Triple.getVendor() != llvm::Triple::UnknownVendor) 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 @@ -351,6 +351,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: riscv::getRISCVTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::systemz: @@ -559,6 +561,8 @@ case llvm::Triple::ppc64le: case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: case llvm::Triple::amdgcn: case llvm::Triple::r600: case llvm::Triple::csky: @@ -1520,6 +1524,8 @@ case llvm::Triple::ppc64le: case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: case llvm::Triple::systemz: case llvm::Triple::xcore: return false; @@ -1815,6 +1821,8 @@ case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: AddRISCVTargetArgs(Args, CmdArgs); break; @@ -2169,7 +2177,8 @@ } } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ) .equals_insensitive("large") && - (Triple.getArch() == llvm::Triple::riscv64)) { + (Triple.getArch() == llvm::Triple::riscv64 || + Triple.getArch() == llvm::Triple::riscv64be)) { // Not support linker relaxation for RV64 with large code model. SmallDataLimit = "0"; if (Args.hasArg(options::OPT_G)) { @@ -7998,6 +8007,8 @@ case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: AddRISCVTargetArgs(Args, CmdArgs); break; } 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 @@ -425,6 +425,8 @@ return "ck810"; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); return ""; diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -230,6 +230,14 @@ CmdArgs.push_back("elf64lriscv"); CmdArgs.push_back("-X"); break; + case llvm::Triple::riscv32be: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32briscv"); + break; + case llvm::Triple::riscv64be: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64briscv"); + break; default: break; } 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 @@ -273,6 +273,10 @@ return "elf32lriscv"; case llvm::Triple::riscv64: return "elf64lriscv"; + case llvm::Triple::riscv32be: + return "elf32briscv"; + case llvm::Triple::riscv64be: + return "elf64briscv"; case llvm::Triple::sparc: case llvm::Triple::sparcel: return "elf32_sparc"; @@ -773,7 +777,9 @@ break; } case llvm::Triple::riscv32: - case llvm::Triple::riscv64: { + case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: { StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(ABIName.data()); @@ -1694,6 +1700,16 @@ "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(), "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()}); }); + MultilibSet RISCVMultilibsBe = + MultilibSet() + .Either(ArrayRef(Ms)) + .FilterOut(NonExistent) + .setFilePathsCallback([](const Multilib &M) { + return std::vector( + {M.gccSuffix(), + "/../../../../riscv64be-unknown-elf/lib" + M.gccSuffix(), + "/../../../../riscv32be-unknown-elf/lib" + M.gccSuffix()}); + }); Multilib::flags_list Flags; @@ -1710,8 +1726,15 @@ } } - if (RISCVMultilibs.select(Flags, Result.SelectedMultilib)) - Result.Multilibs = RISCVMultilibs; + if (TargetTriple.getArch() == llvm::Triple::riscv32 || + TargetTriple.getArch() == llvm::Triple::riscv64) { + if (RISCVMultilibs.select(Flags, Result.SelectedMultilib)) + Result.Multilibs = RISCVMultilibs; + } else { + // llvm::Triple::riscv32be or llvm::Triple::riscv64be + if (RISCVMultilibsBe.select(Flags, Result.SelectedMultilib)) + Result.Multilibs = RISCVMultilibsBe; + } } static void findRISCVMultilibs(const Driver &D, @@ -1735,7 +1758,8 @@ .FilterOut(NonExistent); Multilib::flags_list Flags; - bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64; + bool IsRV64 = (TargetTriple.getArch() == llvm::Triple::riscv64 || + TargetTriple.getArch() == llvm::Triple::riscv64be); StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple); addMultilibFlag(!IsRV64, "m32", Flags); @@ -2281,6 +2305,14 @@ static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu", "riscv64-linux-gnu", "riscv64-unknown-elf"}; + static const char *const RISCV32beLibDirs[] = {"/lib32", "/lib"}; + static const char *const RISCV32beTriples[] = {"riscv32be-unknown-linux-gnu", + "riscv32be-linux-gnu", + "riscv32be-unknown-elf"}; + static const char *const RISCV64beLibDirs[] = {"/lib64", "/lib"}; + static const char *const RISCV64beTriples[] = {"riscv64be-unknown-linux-gnu", + "riscv64be-linux-gnu", + "riscv64be-unknown-elf"}; static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", @@ -2544,6 +2576,18 @@ BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs)); BiarchTripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples)); break; + case llvm::Triple::riscv32be: + LibDirs.append(begin(RISCV32beLibDirs), end(RISCV32beLibDirs)); + TripleAliases.append(begin(RISCV32beTriples), end(RISCV32beTriples)); + BiarchLibDirs.append(begin(RISCV64beLibDirs), end(RISCV64beLibDirs)); + BiarchTripleAliases.append(begin(RISCV64beTriples), end(RISCV64beTriples)); + break; + case llvm::Triple::riscv64be: + LibDirs.append(begin(RISCV64beLibDirs), end(RISCV64beLibDirs)); + TripleAliases.append(begin(RISCV64beTriples), end(RISCV64beTriples)); + BiarchLibDirs.append(begin(RISCV32beLibDirs), end(RISCV32beLibDirs)); + BiarchTripleAliases.append(begin(RISCV32beTriples), end(RISCV32beTriples)); + break; case llvm::Triple::sparc: case llvm::Triple::sparcel: LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs)); @@ -2863,6 +2907,8 @@ case llvm::Triple::ppc64le: case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: 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 @@ -171,7 +171,8 @@ if (Triple.getArch() == llvm::Triple::x86_64 && Triple.isX32()) return "libx32"; - if (Triple.getArch() == llvm::Triple::riscv32) + if (Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv32be) return "lib32"; return Triple.isArch32Bit() ? "lib" : "lib64"; @@ -526,6 +527,18 @@ Loader = ("ld-linux-riscv64-" + ABIName + ".so.1").str(); break; } + case llvm::Triple::riscv32be: { + StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple); + LibDir = "lib"; + Loader = ("ld-linux-riscv32be-" + ABIName + ".so.1").str(); + break; + } + case llvm::Triple::riscv64be: { + StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple); + LibDir = "lib"; + Loader = ("ld-linux-riscv64be-" + ABIName + ".so.1").str(); + break; + } case llvm::Triple::sparc: case llvm::Triple::sparcel: LibDir = "lib"; @@ -735,7 +748,8 @@ getTriple().getArch() == llvm::Triple::thumb || getTriple().getArch() == llvm::Triple::armeb || getTriple().getArch() == llvm::Triple::thumbeb; - const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64; + const bool IsRISCV64 = (getTriple().getArch() == llvm::Triple::riscv64 || + getTriple().getArch() == llvm::Triple::riscv64be); const bool IsSystemZ = getTriple().getArch() == llvm::Triple::systemz; const bool IsHexagon = getTriple().getArch() == llvm::Triple::hexagon; SanitizerMask Res = ToolChain::getSupportedSanitizers(); diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -156,12 +156,15 @@ if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); - bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64; CmdArgs.push_back("-m"); - if (IsRV64) { + if (ToolChain.getArch() == llvm::Triple::riscv64) { CmdArgs.push_back("elf64lriscv"); - } else { + } else if (ToolChain.getArch() == llvm::Triple::riscv64be) { + CmdArgs.push_back("elf64briscv"); + } else if (ToolChain.getArch() == llvm::Triple::riscv32) { CmdArgs.push_back("elf32lriscv"); + } else { // llvm::Triple::riscv32be + CmdArgs.push_back("elf32briscv"); } CmdArgs.push_back("-X"); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1975,6 +1975,8 @@ return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall); } } @@ -4349,7 +4351,9 @@ // Check for 32-bit only builtins on a 64-bit target. const llvm::Triple &TT = TI.getTriple(); - if (TT.getArch() != llvm::Triple::riscv32 && isRISCV32Builtin(BuiltinID)) + if (TT.getArch() != llvm::Triple::riscv32 && + TT.getArch() != llvm::Triple::riscv32be && + isRISCV32Builtin(BuiltinID)) return Diag(TheCall->getCallee()->getBeginLoc(), diag::err_32_bit_builtin_64_bit_tgt); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7476,6 +7476,8 @@ break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: + case llvm::Triple::riscv32be: + case llvm::Triple::riscv64be: handleRISCVInterruptAttr(S, D, AL); break; default: diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -156,25 +156,46 @@ } void RISCV::writeGotHeader(uint8_t *buf) const { - if (config->is64) - write64le(buf, mainPart->dynamic->getVA()); - else - write32le(buf, mainPart->dynamic->getVA()); + if (config->is64) { + if (config->isLE) + write64le(buf, mainPart->dynamic->getVA()); + else + write64be(buf, mainPart->dynamic->getVA()); + } else { + if (config->isLE) + write32le(buf, mainPart->dynamic->getVA()); + else + write32be(buf, mainPart->dynamic->getVA()); + } } void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const { - if (config->is64) - write64le(buf, in.plt->getVA()); - else - write32le(buf, in.plt->getVA()); + if (config->is64) { + if (config->isLE) + write64le(buf, in.plt->getVA()); + else + write64be(buf, in.plt->getVA()); + } else { + if (config->isLE) + write32le(buf, in.plt->getVA()); + else + write32be(buf, in.plt->getVA()); + } } void RISCV::writeIgotPlt(uint8_t *buf, const Symbol &s) const { if (config->writeAddends) { - if (config->is64) - write64le(buf, s.getVA()); - else - write32le(buf, s.getVA()); + if (config->is64) { + if (config->isLE) + write64le(buf, s.getVA()); + else + write64be(buf, s.getVA()); + } else { + if (config->isLE) + write32le(buf, s.getVA()); + else + write32be(buf, s.getVA()); + } } } @@ -294,10 +315,16 @@ switch (rel.type) { case R_RISCV_32: - write32le(loc, val); + if (config->isLE) + write32le(loc, val); + else + write32be(loc, val); return; case R_RISCV_64: - write64le(loc, val); + if (config->isLE) + write64le(loc, val); + else + write64be(loc, val); return; case R_RISCV_RVC_BRANCH: { @@ -424,13 +451,22 @@ *loc += val; return; case R_RISCV_ADD16: - write16le(loc, read16le(loc) + val); + if (config->isLE) + write16le(loc, read16le(loc) + val); + else + write16be(loc, read16be(loc) + val); return; case R_RISCV_ADD32: - write32le(loc, read32le(loc) + val); + if (config->isLE) + write32le(loc, read32le(loc) + val); + else + write32be(loc, read32be(loc) + val); return; case R_RISCV_ADD64: - write64le(loc, read64le(loc) + val); + if (config->isLE) + write64le(loc, read64le(loc) + val); + else + write64be(loc, read64be(loc) + val); return; case R_RISCV_SUB6: *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f); @@ -439,13 +475,22 @@ *loc -= val; return; case R_RISCV_SUB16: - write16le(loc, read16le(loc) - val); + if (config->isLE) + write16le(loc, read16le(loc) - val); + else + write16be(loc, read16be(loc) - val); return; case R_RISCV_SUB32: - write32le(loc, read32le(loc) - val); + if (config->isLE) + write32le(loc, read32le(loc) - val); + else + write32be(loc, read32be(loc) - val); return; case R_RISCV_SUB64: - write64le(loc, read64le(loc) - val); + if (config->isLE) + write64le(loc, read64le(loc) - val); + else + write64be(loc, read64be(loc) - val); return; case R_RISCV_SET6: *loc = (*loc & 0xc0) | (val & 0x3f); @@ -458,14 +503,23 @@ return; case R_RISCV_SET32: case R_RISCV_32_PCREL: - write32le(loc, val); + if (config->isLE) + write32le(loc, val); + else + write32be(loc, val); return; case R_RISCV_TLS_DTPREL32: - write32le(loc, val - dtpOffset); + if (config->isLE) + write32le(loc, val - dtpOffset); + else + write32be(loc, val - dtpOffset); break; case R_RISCV_TLS_DTPREL64: - write64le(loc, val - dtpOffset); + if (config->isLE) + write64le(loc, val - dtpOffset); + else + write64be(loc, val - dtpOffset); break; case R_RISCV_RELAX: diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -899,7 +899,7 @@ if (sec.sh_type == SHT_RISCV_ATTRIBUTES && config->emachine == EM_RISCV) { RISCVAttributeParser attributes; ArrayRef contents = check(this->getObj().getSectionContents(sec)); - if (Error e = attributes.parse(contents, support::little)) { + if (Error e = attributes.parse(contents, config->endianness)) { auto *isec = make(*this, sec, name); warn(toString(isec) + ": " + llvm::toString(std::move(e))); } else { @@ -1540,6 +1540,8 @@ return EM_PPC64; case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: return EM_RISCV; case Triple::x86: return t.isOSIAMCU() ? EM_IAMCU : EM_386; diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -219,6 +219,10 @@ "riscv32"}, {eByteOrderLittle, 8, 2, 4, llvm::Triple::riscv64, ArchSpec::eCore_riscv64, "riscv64"}, + {eByteOrderBig, 4, 2, 4, llvm::Triple::riscv32be, ArchSpec::eCore_riscv32be, + "riscv32be"}, + {eByteOrderBig, 8, 2, 4, llvm::Triple::riscv64be, ArchSpec::eCore_riscv64be, + "riscv64be"}, {eByteOrderLittle, 4, 4, 4, llvm::Triple::UnknownArch, ArchSpec::eCore_uknownMach32, "unknown-mach-32"}, @@ -406,6 +410,10 @@ ArchSpec::eRISCVSubType_riscv32, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv32 {ArchSpec::eCore_riscv64, llvm::ELF::EM_RISCV, ArchSpec::eRISCVSubType_riscv64, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv64 + {ArchSpec::eCore_riscv32be, llvm::ELF::EM_RISCV, + ArchSpec::eRISCVSubType_riscv32be, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv32be + {ArchSpec::eCore_riscv64be, llvm::ELF::EM_RISCV, + ArchSpec::eRISCVSubType_riscv64be, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv64be }; static const ArchDefinition g_elf_arch_def = { diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -460,6 +460,10 @@ set(LLVM_NATIVE_ARCH RISCV) elseif (LLVM_NATIVE_ARCH MATCHES "riscv64") set(LLVM_NATIVE_ARCH RISCV) +elseif (LLVM_NATIVE_ARCH MATCHES "riscv32be") + set(LLVM_NATIVE_ARCH RISCV) +elseif (LLVM_NATIVE_ARCH MATCHES "riscv64be") + set(LLVM_NATIVE_ARCH RISCV) elseif (LLVM_NATIVE_ARCH STREQUAL "m68k") set(LLVM_NATIVE_ARCH M68k) else () diff --git a/llvm/cmake/config.guess b/llvm/cmake/config.guess --- a/llvm/cmake/config.guess +++ b/llvm/cmake/config.guess @@ -976,7 +976,7 @@ ppcle:Linux:*:*) echo powerpcle-unknown-linux-gnu exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) + riscv32:Linux:*:* | riscv64:Linux:*:* | riscv32be:Linux:*:* | riscv64be:Linux:*:*) LIBC=gnu eval $set_cc_for_build # Do not check for __GLIBC__ because uclibc defines it too diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -74,6 +74,8 @@ amdgcn, // AMDGCN: AMD GCN GPUs riscv32, // RISC-V (32-bit): riscv32 riscv64, // RISC-V (64-bit): riscv64 + riscv32be, // RISC-V (32-bit, big endian): riscv32be + riscv64be, // RISC-V (64-bit, big endian): riscv64be sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant @@ -861,7 +863,8 @@ /// Tests whether the target is RISC-V (32- and 64-bit). bool isRISCV() const { - return getArch() == Triple::riscv32 || getArch() == Triple::riscv64; + return getArch() == Triple::riscv32 || getArch() == Triple::riscv64 || + getArch() == Triple::riscv32be || getArch() == Triple::riscv64be; } /// Tests whether the target is 32-bit SPARC (little and big endian). diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -1201,7 +1201,7 @@ case ELF::EM_PPC: return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc"); case ELF::EM_RISCV: - return "elf32-littleriscv"; + return (IsLittleEndian ? "elf32-littleriscv" : "elf32-bigriscv"); case ELF::EM_CSKY: return "elf32-csky"; case ELF::EM_SPARC: @@ -1225,7 +1225,7 @@ case ELF::EM_PPC64: return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); case ELF::EM_RISCV: - return "elf64-littleriscv"; + return (IsLittleEndian ? "elf64-littleriscv" : "elf64-bigriscv"); case ELF::EM_S390: return "elf64-s390"; case ELF::EM_SPARCV9: @@ -1287,9 +1287,9 @@ case ELF::EM_RISCV: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: - return Triple::riscv32; + return IsLittleEndian ? Triple::riscv32 : Triple::riscv32be; case ELF::ELFCLASS64: - return Triple::riscv64; + return IsLittleEndian ? Triple::riscv64 : Triple::riscv64be; default: report_fatal_error("Invalid ELFCLASS!"); } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -255,6 +255,8 @@ break; case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp @@ -86,6 +86,8 @@ return; case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: link_ELF_riscv(std::move(G), std::move(Ctx)); return; case Triple::x86_64: diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -551,14 +551,26 @@ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), (*ELFObj)->makeTriple()) .buildGraph(); - } else { - assert((*ELFObj)->getArch() == Triple::riscv32 && - "Invalid triple for RISCV ELF object file"); + } else if ((*ELFObj)->getArch() == Triple::riscv64be) { + auto &ELFObjFile = cast>(**ELFObj); + return ELFLinkGraphBuilder_riscv( + (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), + (*ELFObj)->makeTriple()) + .buildGraph(); + } else if ((*ELFObj)->getArch() == Triple::riscv32) { auto &ELFObjFile = cast>(**ELFObj); return ELFLinkGraphBuilder_riscv( (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), (*ELFObj)->makeTriple()) .buildGraph(); + } else { + assert((*ELFObj)->getArch() == Triple::riscv32be && + "Invalid triple for RISCV ELF object file"); + auto &ELFObjFile = cast>(**ELFObj); + return ELFLinkGraphBuilder_riscv( + (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), + (*ELFObj)->makeTriple()) + .buildGraph(); } } diff --git a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp --- a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp @@ -261,6 +261,7 @@ return CreateWithABI(EPC); case Triple::riscv64: + case Triple::riscv64be: return CreateWithABI(EPC); case Triple::x86_64: diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -152,7 +152,8 @@ return CCMgrT::Create(ES, ErrorHandlerAddress); } - case Triple::riscv64: { + case Triple::riscv64: + case Triple::riscv64be: { typedef orc::LocalJITCompileCallbackManager CCMgrT; return CCMgrT::Create(ES, ErrorHandlerAddress); } @@ -212,6 +213,7 @@ }; case Triple::riscv64: + case Triple::riscv64be: return []() { return std::make_unique< orc::LocalIndirectStubsManager>(); diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp --- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp @@ -132,6 +132,7 @@ return LocalLazyCallThroughManager::Create(ES, ErrorHandlerAddr); case Triple::riscv64: + case Triple::riscv64be: return LocalLazyCallThroughManager::Create(ES, ErrorHandlerAddr); diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -724,6 +724,7 @@ case Triple::amdgcn: return {supportsAmdgpu, resolveAmdgpu}; case Triple::riscv64: + case Triple::riscv64be: return {supportsRISCV, resolveRISCV}; default: return {nullptr, nullptr}; @@ -757,6 +758,7 @@ case Triple::hexagon: return {supportsHexagon, resolveHexagon}; case Triple::riscv32: + case Triple::riscv32be: return {supportsRISCV, resolveRISCV}; case Triple::csky: return {supportsCSKY, resolveCSKY}; @@ -798,7 +800,9 @@ Addend = getELFAddend(R); // RISCV relocations use both LocData and Addend. if (Obj->getArch() != Triple::riscv32 && - Obj->getArch() != Triple::riscv64) + Obj->getArch() != Triple::riscv64 && + Obj->getArch() != Triple::riscv32be && + Obj->getArch() != Triple::riscv64be) LocData = 0; } } diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -64,6 +64,8 @@ case renderscript64: return "renderscript64"; case riscv32: return "riscv32"; case riscv64: return "riscv64"; + case riscv32be: return "riscv32be"; + case riscv64be: return "riscv64be"; case shave: return "shave"; case sparc: return "sparc"; case sparcel: return "sparcel"; @@ -163,7 +165,9 @@ case wasm64: return "wasm"; case riscv32: - case riscv64: return "riscv"; + case riscv64: + case riscv32be: + case riscv64be: return "riscv"; case ve: return "ve"; case csky: return "csky"; @@ -333,6 +337,8 @@ .Case("amdgcn", amdgcn) .Case("riscv32", riscv32) .Case("riscv64", riscv64) + .Case("riscv32be", riscv32be) + .Case("riscv64be", riscv64be) .Case("hexagon", hexagon) .Case("sparc", sparc) .Case("sparcel", sparcel) @@ -477,6 +483,8 @@ .Case("amdgcn", Triple::amdgcn) .Case("riscv32", Triple::riscv32) .Case("riscv64", Triple::riscv64) + .Case("riscv32be", Triple::riscv32be) + .Case("riscv64be", Triple::riscv64be) .Case("hexagon", Triple::hexagon) .Cases("s390x", "systemz", Triple::systemz) .Case("sparc", Triple::sparc) @@ -824,6 +832,8 @@ case Triple::renderscript64: case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: case Triple::shave: case Triple::sparc: case Triple::sparcel: @@ -1399,6 +1409,7 @@ case llvm::Triple::r600: case llvm::Triple::renderscript32: case llvm::Triple::riscv32: + case llvm::Triple::riscv32be: case llvm::Triple::shave: case llvm::Triple::sparc: case llvm::Triple::sparcel: @@ -1429,6 +1440,7 @@ case llvm::Triple::ppc64le: case llvm::Triple::renderscript64: case llvm::Triple::riscv64: + case llvm::Triple::riscv64be: case llvm::Triple::sparcv9: case llvm::Triple::spir64: case llvm::Triple::spirv64: @@ -1489,6 +1501,7 @@ case Triple::r600: case Triple::renderscript32: case Triple::riscv32: + case Triple::riscv32be: case Triple::shave: case Triple::sparc: case Triple::sparcel: @@ -1521,6 +1534,7 @@ case Triple::ppc64le: T.setArch(Triple::ppcle); break; case Triple::renderscript64: T.setArch(Triple::renderscript32); break; case Triple::riscv64: T.setArch(Triple::riscv32); break; + case Triple::riscv64be: T.setArch(Triple::riscv32be); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; case Triple::spir64: T.setArch(Triple::spir); break; case Triple::spirv64: @@ -1570,6 +1584,7 @@ case Triple::ppc64le: case Triple::renderscript64: case Triple::riscv64: + case Triple::riscv64be: case Triple::sparcv9: case Triple::spir64: case Triple::spirv64: @@ -1598,6 +1613,7 @@ case Triple::ppcle: T.setArch(Triple::ppc64le); break; case Triple::renderscript32: T.setArch(Triple::renderscript64); break; case Triple::riscv32: T.setArch(Triple::riscv64); break; + case Triple::riscv32be: T.setArch(Triple::riscv64be); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; case Triple::spir: T.setArch(Triple::spir64); break; case Triple::spirv32: @@ -1637,8 +1653,6 @@ case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: - case Triple::riscv32: - case Triple::riscv64: case Triple::shave: case Triple::spir64: case Triple::spir: @@ -1671,6 +1685,9 @@ case Triple::ppc64le: T.setArch(Triple::ppc64); break; case Triple::sparcel: T.setArch(Triple::sparc); break; case Triple::tcele: T.setArch(Triple::tce); break; + case Triple::riscv32: T.setArch(Triple::riscv32be); break; + case Triple::riscv64: T.setArch(Triple::riscv64be); break; + default: llvm_unreachable("getBigEndianArchVariant: unknown triple."); } @@ -1708,6 +1725,8 @@ case Triple::ppc64: T.setArch(Triple::ppc64le); break; case Triple::sparc: T.setArch(Triple::sparcel); break; case Triple::tce: T.setArch(Triple::tcele); break; + case Triple::riscv32be: T.setArch(Triple::riscv32); break; + case Triple::riscv64be: T.setArch(Triple::riscv64); break; default: llvm_unreachable("getLittleEndianArchVariant: unknown triple."); } diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2792,4 +2792,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() { RegisterMCAsmParser X(getTheRISCV32Target()); RegisterMCAsmParser Y(getTheRISCV64Target()); + RegisterMCAsmParser A(getTheRISCV32beTarget()); + RegisterMCAsmParser B(getTheRISCV64beTarget()); } diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -56,6 +56,10 @@ createRISCVDisassembler); TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(), createRISCVDisassembler); + TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(), + createRISCVDisassembler); + TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(), + createRISCVDisassembler); } static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -29,9 +29,9 @@ const MCTargetOptions &TargetOptions; public: - RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, + RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, bool IsLittleEndian, const MCTargetOptions &Options) - : MCAsmBackend(support::little), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), + : MCAsmBackend(IsLittleEndian ? support::little : support::big), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) { RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits()); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -251,7 +251,7 @@ OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc); Offset = OS.tell(); Fixup = {RISCV::fixup_riscv_add_16, RISCV::fixup_riscv_sub_16}; - support::endian::write(OS, 0, support::little); + support::endian::write(OS, 0, Endian); } const MCBinaryExpr &MBE = cast(AddrDelta); @@ -313,15 +313,15 @@ AddFixups(0, {RISCV::fixup_riscv_set_6b, RISCV::fixup_riscv_sub_6b}); } else if (isUInt<8>(Value)) { OS << uint8_t(dwarf::DW_CFA_advance_loc1); - support::endian::write(OS, 0, support::little); + support::endian::write(OS, 0, Endian); AddFixups(1, {RISCV::fixup_riscv_set_8, RISCV::fixup_riscv_sub_8}); } else if (isUInt<16>(Value)) { OS << uint8_t(dwarf::DW_CFA_advance_loc2); - support::endian::write(OS, 0, support::little); + support::endian::write(OS, 0, Endian); AddFixups(1, {RISCV::fixup_riscv_set_16, RISCV::fixup_riscv_sub_16}); } else if (isUInt<32>(Value)) { OS << uint8_t(dwarf::DW_CFA_advance_loc4); - support::endian::write(OS, 0, support::little); + support::endian::write(OS, 0, Endian); AddFixups(1, {RISCV::fixup_riscv_set_32, RISCV::fixup_riscv_sub_32}); } else { llvm_unreachable("unsupported CFA encoding"); @@ -546,6 +546,58 @@ return true; } +/// isDataFixup - Is this a data fixup kind? Data should +/// be swapped for big endian cores. +static bool isDataFixup(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + case FK_Data_6b: + case FK_Data_2: + case FK_Data_4: + case FK_Data_8: + case RISCV::fixup_riscv_set_8: + case RISCV::fixup_riscv_add_8: + case RISCV::fixup_riscv_sub_8: + case RISCV::fixup_riscv_set_16: + case RISCV::fixup_riscv_add_16: + case RISCV::fixup_riscv_sub_16: + case RISCV::fixup_riscv_set_32: + case RISCV::fixup_riscv_add_32: + case RISCV::fixup_riscv_sub_32: + case RISCV::fixup_riscv_add_64: + case RISCV::fixup_riscv_sub_64: + case RISCV::fixup_riscv_set_6b: + case RISCV::fixup_riscv_sub_6b: + return true; + + case RISCV::fixup_riscv_hi20: + case RISCV::fixup_riscv_lo12_i: + case RISCV::fixup_riscv_lo12_s: + case RISCV::fixup_riscv_pcrel_hi20: + case RISCV::fixup_riscv_pcrel_lo12_i: + case RISCV::fixup_riscv_pcrel_lo12_s: + case RISCV::fixup_riscv_got_hi20: + case RISCV::fixup_riscv_tprel_hi20: + case RISCV::fixup_riscv_tprel_lo12_i: + case RISCV::fixup_riscv_tprel_lo12_s: + case RISCV::fixup_riscv_tprel_add: + case RISCV::fixup_riscv_tls_got_hi20: + case RISCV::fixup_riscv_tls_gd_hi20: + case RISCV::fixup_riscv_jal: + case RISCV::fixup_riscv_branch: + case RISCV::fixup_riscv_call: + case RISCV::fixup_riscv_call_plt: + case RISCV::fixup_riscv_relax: + case RISCV::fixup_riscv_align: + case RISCV::fixup_riscv_rvc_jump: + case RISCV::fixup_riscv_rvc_branch: + return false; + } +} + void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, @@ -571,8 +623,12 @@ // For each byte of the fragment that the fixup touches, mask in the // bits from the fixup value. + + // For big endian cores, data fixup should be swapped. + bool swapValue = (Endian == support::big) && isDataFixup(Kind); for (unsigned i = 0; i != NumBytes; ++i) { - Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + unsigned Idx = swapValue ? (NumBytes - 1 - i) : i; + Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); } } @@ -643,5 +699,5 @@ const MCTargetOptions &Options) { const Triple &TT = STI.getTargetTriple(); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); - return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options); + return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), TT.isLittleEndian(), Options); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -20,6 +20,9 @@ void RISCVMCAsmInfo::anchor() {} RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) { + if (TT.getArch() == Triple::riscv32be || TT.getArch() == Triple::riscv64be) + IsLittleEndian = false; + CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; CommentString = "#"; AlignmentIsInBytes = false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -161,7 +161,8 @@ } // end anonymous namespace extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() { - for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) { + for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target(), + &getTheRISCV32beTarget(), &getTheRISCV64beTarget()}) { TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo); TargetRegistry::RegisterMCObjectFileInfo(*T, createRISCVMCObjectFileInfo); TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo); diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -211,4 +211,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() { RegisterAsmPrinter X(getTheRISCV32Target()); RegisterAsmPrinter Y(getTheRISCV64Target()); + RegisterAsmPrinter A(getTheRISCV32beTarget()); + RegisterAsmPrinter B(getTheRISCV64beTarget()); } diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -45,6 +45,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { RegisterTargetMachine X(getTheRISCV32Target()); RegisterTargetMachine Y(getTheRISCV64Target()); + RegisterTargetMachine A(getTheRISCV32beTarget()); + RegisterTargetMachine B(getTheRISCV64beTarget()); auto *PR = PassRegistry::getPassRegistry(); initializeGlobalISel(*PR); initializeRISCVMakeCompressibleOptPass(*PR); @@ -56,10 +58,18 @@ } static StringRef computeDataLayout(const Triple &TT) { - if (TT.isArch64Bit()) - return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; + if (TT.isArch64Bit()) { + if (TT.isLittleEndian()) + return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; + else + return "E-m:e-p:64:64-i64:64-i128:128-n64-S128"; + } assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported"); - return "e-m:e-p:32:32-i64:64-n32-S128"; + + if (TT.isLittleEndian()) + return "e-m:e-p:32:32-i64:64-n32-S128"; + + return "E-m:e-p:32:32-i64:64-n32-S128"; } static Reloc::Model getEffectiveRelocModel(const Triple &TT, @@ -246,7 +256,8 @@ void RISCVPassConfig::addMachineSSAOptimization() { TargetPassConfig::addMachineSSAOptimization(); - if (TM->getTargetTriple().getArch() == Triple::riscv64) + if (TM->getTargetTriple().getArch() == Triple::riscv64 || + TM->getTargetTriple().getArch() == Triple::riscv64be) addPass(createRISCVSExtWRemovalPass()); } diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h --- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h +++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h @@ -15,6 +15,8 @@ Target &getTheRISCV32Target(); Target &getTheRISCV64Target(); +Target &getTheRISCV32beTarget(); +Target &getTheRISCV64beTarget(); } // namespace llvm diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp --- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp +++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp @@ -20,9 +20,23 @@ return TheRISCV64Target; } +Target &llvm::getTheRISCV32beTarget() { + static Target TheRISCV32beTarget; + return TheRISCV32beTarget; +} + +Target &llvm::getTheRISCV64beTarget() { + static Target TheRISCV64beTarget; + return TheRISCV64beTarget; +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetInfo() { RegisterTarget X(getTheRISCV32Target(), "riscv32", "32-bit RISC-V", "RISCV"); RegisterTarget Y(getTheRISCV64Target(), "riscv64", "64-bit RISC-V", "RISCV"); + RegisterTarget A(getTheRISCV32beTarget(), "riscv32be", + "32-bit big endian RISC-V", "RISCV"); + RegisterTarget B(getTheRISCV64beTarget(), "riscv64be", + "64-bit big endian RISC-V", "RISCV"); } diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -479,7 +479,8 @@ bool IsMIPS64 = TargetTriple.isMIPS64(); bool IsArmOrThumb = TargetTriple.isARM() || TargetTriple.isThumb(); bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64; - bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64; + bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64 || + TargetTriple.getArch() == Triple::riscv64be; bool IsWindows = TargetTriple.isOSWindows(); bool IsFuchsia = TargetTriple.isOSFuchsia(); bool IsEmscripten = TargetTriple.isOSEmscripten(); diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -301,6 +301,8 @@ // RISC-V {"elf32-littleriscv", {ELF::EM_RISCV, false, true}}, {"elf64-littleriscv", {ELF::EM_RISCV, true, true}}, + {"elf32-bigriscv", {ELF::EM_RISCV, false, false}}, + {"elf64-bigriscv", {ELF::EM_RISCV, true, false}}, // PowerPC {"elf32-powerpc", {ELF::EM_PPC, false, false}}, {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -186,10 +186,10 @@ } TEST(ELFObjectFileTest, MachineTestForRISCV) { - std::array Formats = {"elf32-littleriscv", "elf32-littleriscv", - "elf64-littleriscv", "elf64-littleriscv"}; - std::array Archs = {Triple::riscv32, Triple::riscv32, - Triple::riscv64, Triple::riscv64}; + std::array Formats = {"elf32-littleriscv", "elf32-bigriscv", + "elf64-littleriscv", "elf64-bigriscv"}; + std::array Archs = {Triple::riscv32, Triple::riscv32be, + Triple::riscv64, Triple::riscv64be}; size_t I = 0; for (const DataForTest &D : generateData(ELF::EM_RISCV)) { checkFormatAndArch(D, Formats[I], Archs[I]);