-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[RISCV] Add initial assembler/MC layer support for big-endian #146534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-clang-driver Author: Djordje Todorovic (djtodoro) ChangesInitial big-endian RISC-V support:
Patch is 27.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146534.diff 21 Files Affected:
diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c
index f64ff6efc7261..416afce81050a 100644
--- a/clang/test/Driver/frame-pointer-elim.c
+++ b/clang/test/Driver/frame-pointer-elim.c
@@ -160,7 +160,7 @@
// RUN: FileCheck --check-prefix=KEEP-ALL %s
// RUN: %clang -### --target=riscv64-linux-android -O1 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
-// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
+// RUN: %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// On ARM backend bare metal targets, frame pointer is omitted
diff --git a/llvm/cmake/config.guess b/llvm/cmake/config.guess
index 96cc554f181ab..27b55bd166edc 100644
--- a/llvm/cmake/config.guess
+++ b/llvm/cmake/config.guess
@@ -1003,7 +1003,7 @@ EOF
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/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 103686884e705..a3aa0d9c137a2 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -1312,7 +1312,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
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:
@@ -1338,7 +1338,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
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:
@@ -1400,9 +1400,9 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
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/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index cbf85b2ff74f5..c28838e41ded0 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -76,6 +76,8 @@ class Triple {
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
@@ -1069,10 +1071,14 @@ class Triple {
}
/// Tests whether the target is 32-bit RISC-V.
- bool isRISCV32() const { return getArch() == Triple::riscv32; }
+ bool isRISCV32() const {
+ return getArch() == Triple::riscv32 || getArch() == Triple::riscv32be;
+ }
/// Tests whether the target is 64-bit RISC-V.
- bool isRISCV64() const { return getArch() == Triple::riscv64; }
+ bool isRISCV64() const {
+ return getArch() == Triple::riscv64 || getArch() == Triple::riscv64be;
+ }
/// Tests whether the target is RISC-V (32- and 64-bit).
bool isRISCV() const { return isRISCV32() || isRISCV64(); }
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 5454cd475f5ed..6c99bd030ec96 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -248,6 +248,8 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
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/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp
index b6318bbe3ab74..d81899334b2b1 100644
--- a/llvm/lib/Object/RelocationResolver.cpp
+++ b/llvm/lib/Object/RelocationResolver.cpp
@@ -812,6 +812,7 @@ getRelocationResolver(const ObjectFile &Obj) {
case Triple::amdgcn:
return {supportsAmdgpu, resolveAmdgpu};
case Triple::riscv64:
+ case Triple::riscv64be:
return {supportsRISCV, resolveRISCV};
default:
if (isAMDGPU(Obj))
@@ -851,6 +852,7 @@ getRelocationResolver(const ObjectFile &Obj) {
case Triple::r600:
return {supportsAmdgpu, resolveAmdgpu};
case Triple::riscv32:
+ case Triple::riscv32be:
return {supportsRISCV, resolveRISCV};
case Triple::csky:
return {supportsCSKY, resolveCSKY};
@@ -897,7 +899,9 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
if (Obj->getArch() != Triple::loongarch32 &&
Obj->getArch() != Triple::loongarch64 &&
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/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index bb0f9df2032fd..890067e270998 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -4031,4 +4031,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmParser() {
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
+ RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
+ RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
}
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 27e04c0cb1f8b..1efc7a896552d 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -72,6 +72,10 @@ LLVMInitializeRISCVDisassembler() {
createRISCVDisassembler);
TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(),
+ createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(),
+ createRISCVDisassembler);
}
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 75ef861d58a1c..7719ab4d95d16 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -33,9 +33,11 @@ static cl::opt<bool> ULEB128Reloc(
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
- bool Is64Bit, const MCTargetOptions &Options)
- : MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI),
- Is64Bit(Is64Bit), TargetOptions(Options) {
+ bool Is64Bit, bool IsLittleEndian,
+ const MCTargetOptions &Options)
+ : MCAsmBackend(IsLittleEndian ? llvm::endianness::little
+ : llvm::endianness::big),
+ STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
}
@@ -313,7 +315,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
Offset = OS.tell();
Fixup = RISCV::getRelocPairForSize(2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
}
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
@@ -370,15 +372,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
} else if (isUInt<8>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
- support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint8_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
} else if (isUInt<16>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
} else if (isUInt<32>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint32_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
} else {
llvm_unreachable("unsupported CFA encoding");
@@ -815,6 +817,34 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
return false;
}
+// 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_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ 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_jal:
+ case RISCV::fixup_riscv_branch:
+ case RISCV::fixup_riscv_call:
+ case RISCV::fixup_riscv_call_plt:
+ case RISCV::fixup_riscv_rvc_jump:
+ case RISCV::fixup_riscv_rvc_branch:
+ return false;
+ }
+}
+
void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
@@ -839,8 +869,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
// 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 == llvm::endianness::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);
}
}
@@ -905,5 +938,6 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
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/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index 91efd44547509..9c03c7aaa98e2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -36,7 +36,7 @@ class RISCVAsmBackend : public MCAsmBackend {
public:
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
- const MCTargetOptions &Options);
+ bool IsLittleEndian, const MCTargetOptions &Options);
~RISCVAsmBackend() override = default;
// Return Size with extra Nop Bytes for alignment directive in code section.
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 090d331d99cab..77f65d814ce7a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -21,6 +21,7 @@ using namespace llvm;
void RISCVMCAsmInfo::anchor() {}
RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
+ IsLittleEndian = TT.isLittleEndian();
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
index f66c2d5f99cb3..88e564580dc5e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -334,7 +334,8 @@ static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
extern "C" LLVM_ABI 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
index b078b9268c984..02a6cbdb9f80d 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -615,6 +615,8 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmPrinter() {
RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
+ RegisterAsmPrinter<RISCVAsmPrinter> A(getTheRISCV32beTarget());
+ RegisterAsmPrinter<RISCVAsmPrinter> B(getTheRISCV64beTarget());
}
void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index b43b915d0ad4f..32177fe06e889 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -122,6 +122,8 @@ static cl::opt<bool>
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
+ RegisterTargetMachine<RISCVTargetMachine> A(getTheRISCV32beTarget());
+ RegisterTargetMachine<RISCVTargetMachine> B(getTheRISCV64beTarget());
auto *PR = PassRegistry::getPassRegistry();
initializeGlobalISel(*PR);
initializeRISCVO0PreLegalizerCombinerPass(*PR);
@@ -155,21 +157,23 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVAsmPrinterPass(*PR);
}
-static StringRef computeDataLayout(const Triple &TT,
- const TargetOptions &Options) {
- StringRef ABIName = Options.MCOptions.getABIName();
- if (TT.isArch64Bit()) {
- if (ABIName == "lp64e")
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64";
+static std::string computeDataLayout(const Triple &TT,
+ const TargetOptions &Opts) {
+ const bool IsLittle = TT.isLittleEndian();
+ StringRef ABI = Opts.MCOptions.getABIName();
+ std::string DL;
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
+ if (TT.isArch64Bit()) {
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:64:64-i64:64-i128:128-n32:64-" +
+ (ABI == "lp64e" ? "S64" : "S128"))
+ .str();
+ } else {
+ assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:32:32-i64:64-n32-" +
+ (ABI == "ilp32e" ? "S32" : "S128"))
+ .str();
}
- assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
-
- if (ABIName == "ilp32e")
- return "e-m:e-p:32:32-i64:64-n32-S32";
-
- return "e-m:e-p:32:32-i64:64-n32-S128";
+ return DL;
}
static Reloc::Model getEffectiveRelocModel(const Triple &TT,
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
index fc0965d263a8a..7b0afe46971a3 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
@@ -21,10 +21,24 @@ Target &llvm::getTheRISCV64Target() {
return TheRISCV64Target;
}
+Target &llvm::getTheRISCV32beTarget() {
+ static Target TheRISCV32beTarget;
+ return TheRISCV32beTarget;
+}
+
+Target &llvm::getTheRISCV64beTarget() {
+ static Target TheRISCV64beTarget;
+ return TheRISCV64beTarget;
+}
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVTargetInfo() {
RegisterTarget<Triple::riscv32, /*HasJIT=*/true> X(
getTheRISCV32Target(), "riscv32", "32-bit RISC-V", "RISCV");
RegisterTarget<Triple::riscv64, /*HasJIT=*/true> Y(
getTheRISCV64Target(), "riscv64", "64-bit RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv32be> A(getTheRISCV32beTarget(), "riscv32be",
+ "32-bit big endian RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv64be> B(getTheRISCV64beTarget(), "riscv64be",
+ "64-bit big endian RISC-V", "RISCV");
}
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
index ed00a01fa1a2a..9b9fd2cca2fd0 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
@@ -15,6 +15,8 @@ class Target;
Target &getTheRISCV32Target();
Target &getTheRISCV64Target();
+Target &getTheRISCV32beTarget();
+Target &getTheRISCV64beTarget();
} // namespace llvm
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index a348640d75f26..47d6150a04365 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -63,6 +63,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
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";
@@ -237,7 +239,9 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
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";
@@ -452,6 +456,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("amdgcn", amdgcn)
.Case("riscv32", riscv32)
.Case("riscv64", riscv64)
+ .Case("riscv32be", riscv32be)
+ .Case("riscv64be", riscv64be)
.Case("hexagon", hexagon)
.Case("sparc", sparc)
.Case("sparcel", sparcel)
@@ -598,6 +604,8 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("amdgcn", Triple::amdgcn)
.Case("riscv32", Triple::riscv32)
.Case("riscv64", Triple::riscv64)
+ .Case("riscv32be", Triple::riscv32be)
+ ...
[truncated]
|
@llvm/pr-subscribers-backend-risc-v Author: Djordje Todorovic (djtodoro) ChangesInitial big-endian RISC-V support:
Patch is 27.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146534.diff 21 Files Affected:
diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c
index f64ff6efc7261..416afce81050a 100644
--- a/clang/test/Driver/frame-pointer-elim.c
+++ b/clang/test/Driver/frame-pointer-elim.c
@@ -160,7 +160,7 @@
// RUN: FileCheck --check-prefix=KEEP-ALL %s
// RUN: %clang -### --target=riscv64-linux-android -O1 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
-// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
+// RUN: %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
// On ARM backend bare metal targets, frame pointer is omitted
diff --git a/llvm/cmake/config.guess b/llvm/cmake/config.guess
index 96cc554f181ab..27b55bd166edc 100644
--- a/llvm/cmake/config.guess
+++ b/llvm/cmake/config.guess
@@ -1003,7 +1003,7 @@ EOF
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/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 103686884e705..a3aa0d9c137a2 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -1312,7 +1312,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
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:
@@ -1338,7 +1338,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
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:
@@ -1400,9 +1400,9 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
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/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index cbf85b2ff74f5..c28838e41ded0 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -76,6 +76,8 @@ class Triple {
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
@@ -1069,10 +1071,14 @@ class Triple {
}
/// Tests whether the target is 32-bit RISC-V.
- bool isRISCV32() const { return getArch() == Triple::riscv32; }
+ bool isRISCV32() const {
+ return getArch() == Triple::riscv32 || getArch() == Triple::riscv32be;
+ }
/// Tests whether the target is 64-bit RISC-V.
- bool isRISCV64() const { return getArch() == Triple::riscv64; }
+ bool isRISCV64() const {
+ return getArch() == Triple::riscv64 || getArch() == Triple::riscv64be;
+ }
/// Tests whether the target is RISC-V (32- and 64-bit).
bool isRISCV() const { return isRISCV32() || isRISCV64(); }
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 5454cd475f5ed..6c99bd030ec96 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -248,6 +248,8 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
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/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp
index b6318bbe3ab74..d81899334b2b1 100644
--- a/llvm/lib/Object/RelocationResolver.cpp
+++ b/llvm/lib/Object/RelocationResolver.cpp
@@ -812,6 +812,7 @@ getRelocationResolver(const ObjectFile &Obj) {
case Triple::amdgcn:
return {supportsAmdgpu, resolveAmdgpu};
case Triple::riscv64:
+ case Triple::riscv64be:
return {supportsRISCV, resolveRISCV};
default:
if (isAMDGPU(Obj))
@@ -851,6 +852,7 @@ getRelocationResolver(const ObjectFile &Obj) {
case Triple::r600:
return {supportsAmdgpu, resolveAmdgpu};
case Triple::riscv32:
+ case Triple::riscv32be:
return {supportsRISCV, resolveRISCV};
case Triple::csky:
return {supportsCSKY, resolveCSKY};
@@ -897,7 +899,9 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
if (Obj->getArch() != Triple::loongarch32 &&
Obj->getArch() != Triple::loongarch64 &&
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/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index bb0f9df2032fd..890067e270998 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -4031,4 +4031,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmParser() {
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
+ RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
+ RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
}
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 27e04c0cb1f8b..1efc7a896552d 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -72,6 +72,10 @@ LLVMInitializeRISCVDisassembler() {
createRISCVDisassembler);
TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(),
+ createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(),
+ createRISCVDisassembler);
}
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 75ef861d58a1c..7719ab4d95d16 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -33,9 +33,11 @@ static cl::opt<bool> ULEB128Reloc(
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
- bool Is64Bit, const MCTargetOptions &Options)
- : MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI),
- Is64Bit(Is64Bit), TargetOptions(Options) {
+ bool Is64Bit, bool IsLittleEndian,
+ const MCTargetOptions &Options)
+ : MCAsmBackend(IsLittleEndian ? llvm::endianness::little
+ : llvm::endianness::big),
+ STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
}
@@ -313,7 +315,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
Offset = OS.tell();
Fixup = RISCV::getRelocPairForSize(2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
}
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
@@ -370,15 +372,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
} else if (isUInt<8>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
- support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint8_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
} else if (isUInt<16>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
} else if (isUInt<32>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint32_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
} else {
llvm_unreachable("unsupported CFA encoding");
@@ -815,6 +817,34 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
return false;
}
+// 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_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ 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_jal:
+ case RISCV::fixup_riscv_branch:
+ case RISCV::fixup_riscv_call:
+ case RISCV::fixup_riscv_call_plt:
+ case RISCV::fixup_riscv_rvc_jump:
+ case RISCV::fixup_riscv_rvc_branch:
+ return false;
+ }
+}
+
void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
@@ -839,8 +869,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
// 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 == llvm::endianness::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);
}
}
@@ -905,5 +938,6 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
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/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index 91efd44547509..9c03c7aaa98e2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -36,7 +36,7 @@ class RISCVAsmBackend : public MCAsmBackend {
public:
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
- const MCTargetOptions &Options);
+ bool IsLittleEndian, const MCTargetOptions &Options);
~RISCVAsmBackend() override = default;
// Return Size with extra Nop Bytes for alignment directive in code section.
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 090d331d99cab..77f65d814ce7a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -21,6 +21,7 @@ using namespace llvm;
void RISCVMCAsmInfo::anchor() {}
RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
+ IsLittleEndian = TT.isLittleEndian();
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
index f66c2d5f99cb3..88e564580dc5e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -334,7 +334,8 @@ static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
extern "C" LLVM_ABI 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
index b078b9268c984..02a6cbdb9f80d 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -615,6 +615,8 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmPrinter() {
RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
+ RegisterAsmPrinter<RISCVAsmPrinter> A(getTheRISCV32beTarget());
+ RegisterAsmPrinter<RISCVAsmPrinter> B(getTheRISCV64beTarget());
}
void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index b43b915d0ad4f..32177fe06e889 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -122,6 +122,8 @@ static cl::opt<bool>
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
+ RegisterTargetMachine<RISCVTargetMachine> A(getTheRISCV32beTarget());
+ RegisterTargetMachine<RISCVTargetMachine> B(getTheRISCV64beTarget());
auto *PR = PassRegistry::getPassRegistry();
initializeGlobalISel(*PR);
initializeRISCVO0PreLegalizerCombinerPass(*PR);
@@ -155,21 +157,23 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVAsmPrinterPass(*PR);
}
-static StringRef computeDataLayout(const Triple &TT,
- const TargetOptions &Options) {
- StringRef ABIName = Options.MCOptions.getABIName();
- if (TT.isArch64Bit()) {
- if (ABIName == "lp64e")
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64";
+static std::string computeDataLayout(const Triple &TT,
+ const TargetOptions &Opts) {
+ const bool IsLittle = TT.isLittleEndian();
+ StringRef ABI = Opts.MCOptions.getABIName();
+ std::string DL;
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
+ if (TT.isArch64Bit()) {
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:64:64-i64:64-i128:128-n32:64-" +
+ (ABI == "lp64e" ? "S64" : "S128"))
+ .str();
+ } else {
+ assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:32:32-i64:64-n32-" +
+ (ABI == "ilp32e" ? "S32" : "S128"))
+ .str();
}
- assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
-
- if (ABIName == "ilp32e")
- return "e-m:e-p:32:32-i64:64-n32-S32";
-
- return "e-m:e-p:32:32-i64:64-n32-S128";
+ return DL;
}
static Reloc::Model getEffectiveRelocModel(const Triple &TT,
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
index fc0965d263a8a..7b0afe46971a3 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
@@ -21,10 +21,24 @@ Target &llvm::getTheRISCV64Target() {
return TheRISCV64Target;
}
+Target &llvm::getTheRISCV32beTarget() {
+ static Target TheRISCV32beTarget;
+ return TheRISCV32beTarget;
+}
+
+Target &llvm::getTheRISCV64beTarget() {
+ static Target TheRISCV64beTarget;
+ return TheRISCV64beTarget;
+}
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVTargetInfo() {
RegisterTarget<Triple::riscv32, /*HasJIT=*/true> X(
getTheRISCV32Target(), "riscv32", "32-bit RISC-V", "RISCV");
RegisterTarget<Triple::riscv64, /*HasJIT=*/true> Y(
getTheRISCV64Target(), "riscv64", "64-bit RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv32be> A(getTheRISCV32beTarget(), "riscv32be",
+ "32-bit big endian RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv64be> B(getTheRISCV64beTarget(), "riscv64be",
+ "64-bit big endian RISC-V", "RISCV");
}
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
index ed00a01fa1a2a..9b9fd2cca2fd0 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
@@ -15,6 +15,8 @@ class Target;
Target &getTheRISCV32Target();
Target &getTheRISCV64Target();
+Target &getTheRISCV32beTarget();
+Target &getTheRISCV64beTarget();
} // namespace llvm
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index a348640d75f26..47d6150a04365 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -63,6 +63,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
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";
@@ -237,7 +239,9 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
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";
@@ -452,6 +456,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("amdgcn", amdgcn)
.Case("riscv32", riscv32)
.Case("riscv64", riscv64)
+ .Case("riscv32be", riscv32be)
+ .Case("riscv64be", riscv64be)
.Case("hexagon", hexagon)
.Case("sparc", sparc)
.Case("sparcel", sparcel)
@@ -598,6 +604,8 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("amdgcn", Triple::amdgcn)
.Case("riscv32", Triple::riscv32)
.Case("riscv64", Triple::riscv64)
+ .Case("riscv32be", Triple::riscv32be)
+ ...
[truncated]
|
Support for Basically, this brings into life the https://reviews.llvm.org/D128612. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
A PR in psABI repo is here: riscv-non-isa/riscv-elf-psabi-doc#470. |
This seems to only implement the first bullet point in your commit message, and assembler/relocation/fixup support, right? Please update the PR description. I presume there will be follow-ups for the codegen/load-store support, plus subtarget info. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
llvm-objcopy and libObject changes look fine to me. If you split the llvm-objcopy changes into a separate PR, I'd be happy to approve directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are we going to verify the correctness? Does qemu support big-endian riscv64?
Good question. We have an initial support for it developed internally inside MIPS, for both qemu and Linux kernel, but team from Codethink is trying to upstream similar effort already, so please check it here https://gitlab.com/CodethinkLabs/riscv_bigendian. I am not sure how we merged Big Endian support for RISC-V in GNU GCC, but we should have agreed on convention first I think (effort initiated at riscv-non-isa/riscv-elf-psabi-doc#470.) |
What is your intention here around the LLVM 21 release cycle, knowing this is a big feature and we are ~2 weeks from the branch date |
Hey @lenary, thanks for mentioning that. I agree it is a big feature, so no need to rush to include it in the release. |
Done as #146913. |
89eca90
to
2d6aa04
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code mostly looks right, but it's going to need tests 😄
llvm/cmake/config.guess
Outdated
@@ -1003,7 +1003,7 @@ EOF | |||
ppcle:Linux:*:*) | |||
echo powerpcle-unknown-linux-gnu | |||
exit ;; | |||
riscv32:Linux:*:* | riscv64:Linux:*:*) | |||
riscv32:Linux:*:* | riscv64:Linux:*:* | riscv32be:Linux:*:* | riscv64be:Linux:*:*) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a separate change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I will remove it from this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
if (TT.isArch64Bit()) { | ||
Ret += (ABI == "lp64e") ? "-S64" : "-S128"; | ||
} else { | ||
Ret += (ABI == "ilp32e") ? "-S32" : "-S128"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These still have redundant parentheses. But why not:
if (TT.isArch64Bit()) { | |
Ret += (ABI == "lp64e") ? "-S64" : "-S128"; | |
} else { | |
Ret += (ABI == "ilp32e") ? "-S32" : "-S128"; | |
} | |
if (ABI == "ilp32e") { | |
Ret += "-S32"; | |
} else if (ABI == "lp64e") { | |
Ret += "-S64"; | |
} else { | |
Ret += "-S128"; | |
} |
(with optional asserts about 64-bit-ness for the E ABIs if you want)
Do we need to gate this behind -menable-experimental-extensions (or an equivalent given it's not really an extension)? There is no ABI specification for it yet and I would be concerned about future incompatibility. GCC implements an ABI but IIRC there were concerns about whether it was actually a sensible ABI or organically came into being, possibly around things like structs passed in register pairs? |
See the thread starting at riscv-non-isa/riscv-elf-psabi-doc#265 (comment) |
Hmm, the
|
Thanks a lot for providing this! I guess these problems should be addressed within riscv-non-isa/riscv-elf-psabi-doc#470. |
@@ -0,0 +1,60 @@ | |||
# RUN: llvm-mc -filetype=obj -triple=riscv32be < %s \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%s
instead of < %s
@@ -0,0 +1,60 @@ | |||
# RUN: llvm-mc -filetype=obj -triple=riscv32be < %s \ | |||
# RUN: | llvm-objdump --no-print-imm-hex -M no-aliases -d - \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test inline relocations with llvm-objdump -dr -
. It's important to test the encoding for at least a few insns, so you should omit --no-print-imm-hex
The early RISC-V fixup/relocation tests are probably not the best model to follow.
For new fixup/relocation tests. Prefer test/MC/RISCV/Relocations/
.
See LoongArch/Relocations/fixups.s for an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @MaskRay!
case FK_Data_8: | ||
return true; | ||
|
||
case RISCV::fixup_riscv_hi20: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete all fixup_riscv_*
cases - these are all instruction kinds.
If we ever have fixups for data relocations, we could add them like FK_Data_8 in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, it makes sense.
Is this OK to go as is now? |
@@ -247,6 +247,8 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, | |||
break; | |||
case Triple::riscv32: | |||
case Triple::riscv64: | |||
case Triple::riscv32be: | |||
case Triple::riscv64be: | |||
LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a CodeGen/RISCV test to cover it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. But, I will drop this from this PR, and leave it for the upcoming/codegen change.
Description:
While this might be on the roadmap, I don't see it in the patch. |
Ah, we decided to leave it for the other upcoming changes, and I removed it from the PR as well as from commit message. Just removed it from PR description as well. |
@MaskRay Thanks! |
Any other comment? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this as is.
I agree for the need for some kind of "experimental" warning, but I think that's better to come from clang, probably in RISCVTargetInfo::handleTargetFeatures
- where we also have things like the +experimental
feature so it can be disabled if need be.
I think this is safe to land as there have been no changes to clang, clang assumes little-endian for RISC-V, and most users will be using clang rather than e.g. llvm-mc
.
@@ -2341,6 +2341,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, | |||
|
|||
getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI); | |||
|
|||
// RISC-V instructions are always little-endian, even on BE systems. | |||
bool ForceLE = getContext().getTargetTriple().isRISCV(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a follow-up, this should probably be turned into some kind of target-independent hook, as AArch64 is also little-endian instructions always, but little/big-endian data. This does not need to be in the current PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, noted, I agree.
It does make sense. I will address it along with
Yes, I agree. @lenary Thanks a lot! |
This patch adds basic assembler and MC layer infrastructure for RISC-V big-endian targets (riscv32be/riscv64be): - Register big-endian targets in RISCVTargetMachine - Add big-endian data layout strings - Implement endianness-aware fixup application in assembler backend - Add byte swapping for data fixups on BE cores - Update MC layer components (AsmInfo, MCTargetDesc, Disassembler, AsmParser) This provides the foundation for BE support but does not yet include: - Codegen patterns for BE - Load/store instruction handling - BE-specific subtarget features
- Drop change in llvm/cmake/config.guess - Align computeDataLayout with X86 and ARM
967d436
to
7b766e8
Compare
This patch adds basic assembler and MC layer infrastructure for
RISC-V big-endian targets (riscv32be/riscv64be):
- Register big-endian targets in RISCVTargetMachine
- Add big-endian data layout strings
- Implement endianness-aware fixup application in assembler
backend
- Add byte swapping for data fixups on BE cores
- Update MC layer components (AsmInfo, MCTargetDesc, Disassembler,
AsmParser)
This provides the foundation for BE support but does not yet include:
- Codegen patterns for BE
- Load/store instruction handling
- BE-specific subtarget features