Skip to content

Commit 2d6aa04

Browse files
committed
[RISCV] Add initial assembler/MC layer support for big-endian
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) - Handle BE targets in AddressSanitizer This provides the foundation for BE support but does not yet include: - Codegen patterns for BE - Load/store instruction handling - BE-specific subtarget features
1 parent ded255e commit 2d6aa04

File tree

13 files changed

+93
-26
lines changed

13 files changed

+93
-26
lines changed

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/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

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

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4053,4 +4053,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
40534053
LLVMInitializeRISCVAsmParser() {
40544054
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
40554055
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
4056+
RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
4057+
RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
40564058
}

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

@@ -370,7 +372,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCFragment &F,
370372
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
371373
Offset = OS.tell();
372374
Fixup = RISCV::getRelocPairForSize(2);
373-
support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
375+
support::endian::write<uint16_t>(OS, 0, Endian);
374376
}
375377

376378
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
@@ -426,15 +428,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const {
426428
AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
427429
} else if (isUInt<8>(Value)) {
428430
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
429-
support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
431+
support::endian::write<uint8_t>(OS, 0, Endian);
430432
AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
431433
} else if (isUInt<16>(Value)) {
432434
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
433-
support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
435+
support::endian::write<uint16_t>(OS, 0, Endian);
434436
AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
435437
} else if (isUInt<32>(Value)) {
436438
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
437-
support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
439+
support::endian::write<uint32_t>(OS, 0, Endian);
438440
AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
439441
} else {
440442
llvm_unreachable("unsupported CFA encoding");
@@ -880,6 +882,34 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
880882
return false;
881883
}
882884

885+
// Data should be swapped for big endian cores.
886+
static bool isDataFixup(unsigned Kind) {
887+
switch (Kind) {
888+
default:
889+
llvm_unreachable("Unknown fixup kind!");
890+
891+
case FK_Data_1:
892+
case FK_Data_2:
893+
case FK_Data_4:
894+
case FK_Data_8:
895+
return true;
896+
897+
case RISCV::fixup_riscv_hi20:
898+
case RISCV::fixup_riscv_lo12_i:
899+
case RISCV::fixup_riscv_lo12_s:
900+
case RISCV::fixup_riscv_pcrel_hi20:
901+
case RISCV::fixup_riscv_pcrel_lo12_i:
902+
case RISCV::fixup_riscv_pcrel_lo12_s:
903+
case RISCV::fixup_riscv_jal:
904+
case RISCV::fixup_riscv_branch:
905+
case RISCV::fixup_riscv_call:
906+
case RISCV::fixup_riscv_call_plt:
907+
case RISCV::fixup_riscv_rvc_jump:
908+
case RISCV::fixup_riscv_rvc_branch:
909+
return false;
910+
}
911+
}
912+
883913
void RISCVAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
884914
const MCValue &Target,
885915
MutableArrayRef<char> Data, uint64_t Value,
@@ -905,8 +935,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
905935

906936
// For each byte of the fragment that the fixup touches, mask in the
907937
// bits from the fixup value.
938+
// For big endian cores, data fixup should be swapped.
939+
bool SwapValue = (Endian == llvm::endianness::big) && isDataFixup(Kind);
908940
for (unsigned i = 0; i != NumBytes; ++i) {
909-
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
941+
unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
942+
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
910943
}
911944
}
912945

@@ -921,5 +954,6 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
921954
const MCTargetOptions &Options) {
922955
const Triple &TT = STI.getTargetTriple();
923956
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
924-
return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
957+
return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), TT.isLittleEndian(),
958+
Options);
925959
}

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

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

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

4141
std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ using namespace llvm;
2121
void RISCVMCAsmInfo::anchor() {}
2222

2323
RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
24+
IsLittleEndian = TT.isLittleEndian();
2425
CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4;
2526
CommentString = "#";
2627
AlignmentIsInBytes = false;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
376376

377377
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
378378
LLVMInitializeRISCVTargetMC() {
379-
for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) {
379+
for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target(),
380+
&getTheRISCV32beTarget(), &getTheRISCV64beTarget()}) {
380381
TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo);
381382
TargetRegistry::RegisterMCObjectFileInfo(*T, createRISCVMCObjectFileInfo);
382383
TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo);

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,8 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
611611
LLVMInitializeRISCVAsmPrinter() {
612612
RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
613613
RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
614+
RegisterAsmPrinter<RISCVAsmPrinter> A(getTheRISCV32beTarget());
615+
RegisterAsmPrinter<RISCVAsmPrinter> B(getTheRISCV64beTarget());
614616
}
615617

616618
void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ static cl::opt<bool>
117117
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
118118
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
119119
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
120+
RegisterTargetMachine<RISCVTargetMachine> A(getTheRISCV32beTarget());
121+
RegisterTargetMachine<RISCVTargetMachine> B(getTheRISCV64beTarget());
120122
auto *PR = PassRegistry::getPassRegistry();
121123
initializeGlobalISel(*PR);
122124
initializeRISCVO0PreLegalizerCombinerPass(*PR);
@@ -150,21 +152,23 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
150152
initializeRISCVAsmPrinterPass(*PR);
151153
}
152154

153-
static StringRef computeDataLayout(const Triple &TT,
154-
const TargetOptions &Options) {
155-
StringRef ABIName = Options.MCOptions.getABIName();
156-
if (TT.isArch64Bit()) {
157-
if (ABIName == "lp64e")
158-
return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64";
155+
static std::string computeDataLayout(const Triple &TT,
156+
const TargetOptions &Opts) {
157+
const bool IsLittle = TT.isLittleEndian();
158+
StringRef ABI = Opts.MCOptions.getABIName();
159+
std::string DL;
159160

160-
return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
161+
if (TT.isArch64Bit()) {
162+
DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:64:64-i64:64-i128:128-n32:64-" +
163+
(ABI == "lp64e" ? "S64" : "S128"))
164+
.str();
165+
} else {
166+
assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
167+
DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:32:32-i64:64-n32-" +
168+
(ABI == "ilp32e" ? "S32" : "S128"))
169+
.str();
161170
}
162-
assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
163-
164-
if (ABIName == "ilp32e")
165-
return "e-m:e-p:32:32-i64:64-n32-S32";
166-
167-
return "e-m:e-p:32:32-i64:64-n32-S128";
171+
return DL;
168172
}
169173

170174
static Reloc::Model getEffectiveRelocModel(const Triple &TT,

0 commit comments

Comments
 (0)