Skip to content

Commit 02c3866

Browse files
committed
[RISCV] Add big-endian support to RISC-V backend
Initial big-endian RISC-V support: - Add riscv32be/riscv64be target triples - Implement BE-aware codegen patterns - Handle endianness in load/store operations - Add BE target feature and subtarget info
1 parent cd10ded commit 02c3866

File tree

21 files changed

+144
-41
lines changed

21 files changed

+144
-41
lines changed

clang/test/Driver/frame-pointer-elim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
// RUN: FileCheck --check-prefix=KEEP-ALL %s
161161
// RUN: %clang -### --target=riscv64-linux-android -O1 -S %s 2>&1 | \
162162
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
163-
// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
163+
// RUN: %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \
164164
// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
165165

166166
// On ARM backend bare metal targets, frame pointer is omitted

llvm/cmake/config.guess

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ EOF
10031003
ppcle:Linux:*:*)
10041004
echo powerpcle-unknown-linux-gnu
10051005
exit ;;
1006-
riscv32:Linux:*:* | riscv64:Linux:*:*)
1006+
riscv32:Linux:*:* | riscv64:Linux:*:* | riscv32be:Linux:*:* | riscv64be:Linux:*:*)
10071007
LIBC=gnu
10081008
eval $set_cc_for_build
10091009
# Do not check for __GLIBC__ because uclibc defines it too

llvm/include/llvm/Object/ELFObjectFile.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
13121312
case ELF::EM_PPC:
13131313
return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc");
13141314
case ELF::EM_RISCV:
1315-
return "elf32-littleriscv";
1315+
return (IsLittleEndian ? "elf32-littleriscv" : "elf32-bigriscv");
13161316
case ELF::EM_CSKY:
13171317
return "elf32-csky";
13181318
case ELF::EM_SPARC:
@@ -1338,7 +1338,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
13381338
case ELF::EM_PPC64:
13391339
return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc");
13401340
case ELF::EM_RISCV:
1341-
return "elf64-littleriscv";
1341+
return (IsLittleEndian ? "elf64-littleriscv" : "elf64-bigriscv");
13421342
case ELF::EM_S390:
13431343
return "elf64-s390";
13441344
case ELF::EM_SPARCV9:
@@ -1400,9 +1400,9 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
14001400
case ELF::EM_RISCV:
14011401
switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
14021402
case ELF::ELFCLASS32:
1403-
return Triple::riscv32;
1403+
return IsLittleEndian ? Triple::riscv32 : Triple::riscv32be;
14041404
case ELF::ELFCLASS64:
1405-
return Triple::riscv64;
1405+
return IsLittleEndian ? Triple::riscv64 : Triple::riscv64be;
14061406
default:
14071407
report_fatal_error("Invalid ELFCLASS!");
14081408
}

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class Triple {
7676
amdgcn, // AMDGCN: AMD GCN GPUs
7777
riscv32, // RISC-V (32-bit): riscv32
7878
riscv64, // RISC-V (64-bit): riscv64
79+
riscv32be, // RISC-V (32-bit, big endian): riscv32be
80+
riscv64be, // RISC-V (64-bit, big endian): riscv64be
7981
sparc, // Sparc: sparc
8082
sparcv9, // Sparcv9: Sparcv9
8183
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
@@ -1069,10 +1071,14 @@ class Triple {
10691071
}
10701072

10711073
/// Tests whether the target is 32-bit RISC-V.
1072-
bool isRISCV32() const { return getArch() == Triple::riscv32; }
1074+
bool isRISCV32() const {
1075+
return getArch() == Triple::riscv32 || getArch() == Triple::riscv32be;
1076+
}
10731077

10741078
/// Tests whether the target is 64-bit RISC-V.
1075-
bool isRISCV64() const { return getArch() == Triple::riscv64; }
1079+
bool isRISCV64() const {
1080+
return getArch() == Triple::riscv64 || getArch() == Triple::riscv64be;
1081+
}
10761082

10771083
/// Tests whether the target is RISC-V (32- and 64-bit).
10781084
bool isRISCV() const { return isRISCV32() || isRISCV64(); }

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
248248
break;
249249
case Triple::riscv32:
250250
case Triple::riscv64:
251+
case Triple::riscv32be:
252+
case Triple::riscv64be:
251253
LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
252254
PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
253255
dwarf::DW_EH_PE_sdata4;

llvm/lib/Object/RelocationResolver.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@ getRelocationResolver(const ObjectFile &Obj) {
812812
case Triple::amdgcn:
813813
return {supportsAmdgpu, resolveAmdgpu};
814814
case Triple::riscv64:
815+
case Triple::riscv64be:
815816
return {supportsRISCV, resolveRISCV};
816817
default:
817818
if (isAMDGPU(Obj))
@@ -851,6 +852,7 @@ getRelocationResolver(const ObjectFile &Obj) {
851852
case Triple::r600:
852853
return {supportsAmdgpu, resolveAmdgpu};
853854
case Triple::riscv32:
855+
case Triple::riscv32be:
854856
return {supportsRISCV, resolveRISCV};
855857
case Triple::csky:
856858
return {supportsCSKY, resolveCSKY};
@@ -897,7 +899,9 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
897899
if (Obj->getArch() != Triple::loongarch32 &&
898900
Obj->getArch() != Triple::loongarch64 &&
899901
Obj->getArch() != Triple::riscv32 &&
900-
Obj->getArch() != Triple::riscv64)
902+
Obj->getArch() != Triple::riscv64 &&
903+
Obj->getArch() != Triple::riscv32be &&
904+
Obj->getArch() != Triple::riscv64be)
901905
LocData = 0;
902906
}
903907
}

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4031,4 +4031,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
40314031
LLVMInitializeRISCVAsmParser() {
40324032
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
40334033
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
4034+
RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
4035+
RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
40344036
}

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ LLVMInitializeRISCVDisassembler() {
7272
createRISCVDisassembler);
7373
TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
7474
createRISCVDisassembler);
75+
TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(),
76+
createRISCVDisassembler);
77+
TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(),
78+
createRISCVDisassembler);
7579
}
7680

7781
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ static cl::opt<bool> ULEB128Reloc(
3333
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
3434

3535
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
36-
bool Is64Bit, const MCTargetOptions &Options)
37-
: MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI),
38-
Is64Bit(Is64Bit), TargetOptions(Options) {
36+
bool Is64Bit, bool IsLittleEndian,
37+
const MCTargetOptions &Options)
38+
: MCAsmBackend(IsLittleEndian ? llvm::endianness::little
39+
: llvm::endianness::big),
40+
STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
3941
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
4042
}
4143

@@ -313,7 +315,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
313315
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
314316
Offset = OS.tell();
315317
Fixup = RISCV::getRelocPairForSize(2);
316-
support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
318+
support::endian::write<uint16_t>(OS, 0, Endian);
317319
}
318320

319321
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
@@ -370,15 +372,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
370372
AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
371373
} else if (isUInt<8>(Value)) {
372374
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
373-
support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
375+
support::endian::write<uint8_t>(OS, 0, Endian);
374376
AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
375377
} else if (isUInt<16>(Value)) {
376378
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
377-
support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
379+
support::endian::write<uint16_t>(OS, 0, Endian);
378380
AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
379381
} else if (isUInt<32>(Value)) {
380382
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
381-
support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
383+
support::endian::write<uint32_t>(OS, 0, Endian);
382384
AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
383385
} else {
384386
llvm_unreachable("unsupported CFA encoding");
@@ -815,6 +817,34 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
815817
return false;
816818
}
817819

820+
// Data should be swapped for big endian cores.
821+
static bool isDataFixup(unsigned Kind) {
822+
switch (Kind) {
823+
default:
824+
llvm_unreachable("Unknown fixup kind!");
825+
826+
case FK_Data_1:
827+
case FK_Data_2:
828+
case FK_Data_4:
829+
case FK_Data_8:
830+
return true;
831+
832+
case RISCV::fixup_riscv_hi20:
833+
case RISCV::fixup_riscv_lo12_i:
834+
case RISCV::fixup_riscv_lo12_s:
835+
case RISCV::fixup_riscv_pcrel_hi20:
836+
case RISCV::fixup_riscv_pcrel_lo12_i:
837+
case RISCV::fixup_riscv_pcrel_lo12_s:
838+
case RISCV::fixup_riscv_jal:
839+
case RISCV::fixup_riscv_branch:
840+
case RISCV::fixup_riscv_call:
841+
case RISCV::fixup_riscv_call_plt:
842+
case RISCV::fixup_riscv_rvc_jump:
843+
case RISCV::fixup_riscv_rvc_branch:
844+
return false;
845+
}
846+
}
847+
818848
void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
819849
const MCValue &Target,
820850
MutableArrayRef<char> Data, uint64_t Value,
@@ -839,8 +869,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
839869

840870
// For each byte of the fragment that the fixup touches, mask in the
841871
// bits from the fixup value.
872+
// For big endian cores, data fixup should be swapped.
873+
bool SwapValue = (Endian == llvm::endianness::big) && isDataFixup(Kind);
842874
for (unsigned i = 0; i != NumBytes; ++i) {
843-
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
875+
unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
876+
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
844877
}
845878
}
846879

@@ -905,5 +938,6 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
905938
const MCTargetOptions &Options) {
906939
const Triple &TT = STI.getTargetTriple();
907940
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
908-
return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
941+
return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), TT.isLittleEndian(),
942+
Options);
909943
}

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class RISCVAsmBackend : public MCAsmBackend {
3636

3737
public:
3838
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
39-
const MCTargetOptions &Options);
39+
bool IsLittleEndian, const MCTargetOptions &Options);
4040
~RISCVAsmBackend() override = default;
4141

4242
// Return Size with extra Nop Bytes for alignment directive in code section.

0 commit comments

Comments
 (0)