diff options
Diffstat (limited to 'backend/lib/Target/RISCV')
| -rw-r--r-- | backend/lib/Target/RISCV/CMakeLists.txt | 18 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCV.rccdesc | 195 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVAsmBackend.cpp | 382 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp | 984 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp | 112 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVObjectFile.cpp | 148 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVTargetConstant.cpp | 169 |
7 files changed, 1983 insertions, 25 deletions
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt index 646e856..55578a2 100644 --- a/backend/lib/Target/RISCV/CMakeLists.txt +++ b/backend/lib/Target/RISCV/CMakeLists.txt @@ -53,6 +53,9 @@ add_library( RISCVAssemblyPrinter.cpp RISCVFrameLowering.cpp RISCVInstPrinter.cpp + RISCVAsmBackend.cpp + RISCVMCCodeEmitter.cpp + RISCVObjectFile.cpp RISCVMCTargetLowering.cpp RISCVMachineCombiner.cpp RISCVMachineMemoryFolding.cpp @@ -61,6 +64,7 @@ add_library( RISCVRegisterAllocation.cpp RISCVScheduling.cpp RISCVTarget.cpp + RISCVTargetConstant.cpp "${RCCBackendRISCVGeneratedRegisterHeader}" "${RCCBackendRISCVGeneratedInstructionHeader}" "${RCCBackendRISCVGeneratedTables}" @@ -114,6 +118,9 @@ rcc_backend_register_format_files( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVFrameLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstPrinter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVAsmBackend.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCCodeEmitter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVObjectFile.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCTargetLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineCombiner.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineMemoryFolding.cpp" @@ -122,12 +129,19 @@ rcc_backend_register_format_files( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVRegisterAllocation.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVScheduling.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTarget.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTargetConstant.cpp" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCodeGen.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCallLowering.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVInstPrinter.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVAsmBackend.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVFixupKinds.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVMCCodeEmitter.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVObjectFile.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVMCTargetLowering.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTarget.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTargetConstant.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTargetRelocationKinds.h" ) rcc_backend_register_tidy_files( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVBranchInfo.cpp" @@ -136,6 +150,9 @@ rcc_backend_register_tidy_files( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVFrameLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstPrinter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVAsmBackend.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCCodeEmitter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVObjectFile.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCTargetLowering.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineCombiner.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineMemoryFolding.cpp" @@ -144,4 +161,5 @@ rcc_backend_register_tidy_files( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVRegisterAllocation.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVScheduling.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTarget.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTargetConstant.cpp" ) diff --git a/backend/lib/Target/RISCV/RISCV.rccdesc b/backend/lib/Target/RISCV/RISCV.rccdesc index dce984c..237e294 100644 --- a/backend/lib/Target/RISCV/RISCV.rccdesc +++ b/backend/lib/Target/RISCV/RISCV.rccdesc @@ -375,6 +375,7 @@ instructions: symbol: LUI name: LUI assembly_mnemonic: lui + encoding: 5175 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: SIMM20, name: IMM } @@ -388,6 +389,7 @@ instructions: symbol: AUIPC name: AUIPC assembly_mnemonic: auipc + encoding: 5143 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate, basic_block, global_symbol, external_symbol, mc_symbol], immediate_predicate: SIMM20, allowed_target_flags: 3, name: IMM } @@ -401,6 +403,7 @@ instructions: symbol: ADDI name: ADDI assembly_mnemonic: addi + encoding: 1344531 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -415,6 +418,7 @@ instructions: symbol: SRLI name: SRLI assembly_mnemonic: srli + encoding: 1365011 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -429,6 +433,7 @@ instructions: symbol: SRAI name: SRAI assembly_mnemonic: srai + encoding: 1075106835 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -443,6 +448,7 @@ instructions: symbol: ADDIW name: ADDIW assembly_mnemonic: addiw + encoding: 1344539 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -457,6 +463,7 @@ instructions: symbol: SLLIW name: SLLIW assembly_mnemonic: slliw + encoding: 1348635 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -471,6 +478,7 @@ instructions: symbol: SRLIW name: SRLIW assembly_mnemonic: srliw + encoding: 1365019 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -485,6 +493,7 @@ instructions: symbol: SRAIW name: SRAIW assembly_mnemonic: sraiw + encoding: 1075106843 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -499,6 +508,7 @@ instructions: symbol: SLL name: SLL assembly_mnemonic: sll + encoding: 10785843 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -513,6 +523,7 @@ instructions: symbol: SLT name: SLT assembly_mnemonic: slt + encoding: 10789939 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -527,6 +538,7 @@ instructions: symbol: SLTU name: SLTU assembly_mnemonic: sltu + encoding: 10794035 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -541,6 +553,7 @@ instructions: symbol: XOR name: XOR assembly_mnemonic: xor + encoding: 10798131 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -555,6 +568,7 @@ instructions: symbol: SRL name: SRL assembly_mnemonic: srl + encoding: 10802227 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -569,6 +583,7 @@ instructions: symbol: SRA name: SRA assembly_mnemonic: sra + encoding: 1084544051 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -583,6 +598,7 @@ instructions: symbol: OR name: OR assembly_mnemonic: or + encoding: 10806323 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -597,6 +613,7 @@ instructions: symbol: AND name: AND assembly_mnemonic: and + encoding: 10810419 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -611,6 +628,7 @@ instructions: symbol: ADDW name: ADDW assembly_mnemonic: addw + encoding: 10781755 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -625,6 +643,7 @@ instructions: symbol: SUBW name: SUBW assembly_mnemonic: subw + encoding: 1084523579 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -639,6 +658,7 @@ instructions: symbol: SLLW name: SLLW assembly_mnemonic: sllw + encoding: 10785851 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -653,6 +673,7 @@ instructions: symbol: SRLW name: SRLW assembly_mnemonic: srlw + encoding: 10802235 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -667,6 +688,7 @@ instructions: symbol: SRAW name: SRAW assembly_mnemonic: sraw + encoding: 1084544059 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -681,6 +703,7 @@ instructions: symbol: LB name: LB assembly_mnemonic: lb + encoding: 8684547 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -696,6 +719,7 @@ instructions: symbol: LH name: LH assembly_mnemonic: lh + encoding: 8688643 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -711,6 +735,7 @@ instructions: symbol: LW name: LW assembly_mnemonic: lw + encoding: 8692739 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -726,6 +751,7 @@ instructions: symbol: LBU name: LBU assembly_mnemonic: lbu + encoding: 8700931 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -741,6 +767,7 @@ instructions: symbol: LHU name: LHU assembly_mnemonic: lhu + encoding: 8705027 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -756,6 +783,7 @@ instructions: symbol: LWU name: LWU assembly_mnemonic: lwu + encoding: 8709123 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -771,6 +799,7 @@ instructions: symbol: SB name: SB assembly_mnemonic: sb + encoding: 10781731 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -786,6 +815,7 @@ instructions: symbol: SH name: SH assembly_mnemonic: sh + encoding: 10785827 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -801,6 +831,7 @@ instructions: symbol: SW name: SW assembly_mnemonic: sw + encoding: 10789923 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -816,6 +847,7 @@ instructions: symbol: BLT name: BLT assembly_mnemonic: blt + encoding: 9715811 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -830,6 +862,7 @@ instructions: symbol: BGE name: BGE assembly_mnemonic: bge + encoding: 9719907 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -844,6 +877,7 @@ instructions: symbol: BLTU name: BLTU assembly_mnemonic: bltu + encoding: 9724003 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -858,6 +892,7 @@ instructions: symbol: BGEU name: BGEU assembly_mnemonic: bgeu + encoding: 9728099 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -872,6 +907,7 @@ instructions: symbol: JALR name: JALR assembly_mnemonic: jalr + encoding: 1344615 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -886,6 +922,7 @@ instructions: symbol: FENCE name: FENCE assembly_mnemonic: fence + encoding: 15 operands: - { kinds: [immediate], immediate_predicate: UIMM4, name: PRED } - { kinds: [immediate], immediate_predicate: UIMM4, name: SUCC } @@ -899,6 +936,7 @@ instructions: symbol: FENCE_I name: FENCE_I assembly_mnemonic: fence.i + encoding: 4111 operands: [] num_explicit_defs: 0 flags: [has_side_effects, produces_code] @@ -910,6 +948,7 @@ instructions: symbol: CSRRW name: CSRRW assembly_mnemonic: csrrw + encoding: 1348723 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -924,6 +963,7 @@ instructions: symbol: CSRRS name: CSRRS assembly_mnemonic: csrrs + encoding: 1352819 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -938,6 +978,7 @@ instructions: symbol: CSRRC name: CSRRC assembly_mnemonic: csrrc + encoding: 1356915 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -952,6 +993,7 @@ instructions: symbol: CSRRWI name: CSRRWI assembly_mnemonic: csrrwi + encoding: 1102963 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -966,6 +1008,7 @@ instructions: symbol: MUL name: MUL assembly_mnemonic: mul + encoding: 44336179 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -980,6 +1023,7 @@ instructions: symbol: MULH name: MULH assembly_mnemonic: mulh + encoding: 44340275 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -994,6 +1038,7 @@ instructions: symbol: MULHSU name: MULHSU assembly_mnemonic: mulhsu + encoding: 44344371 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1008,6 +1053,7 @@ instructions: symbol: MULHU name: MULHU assembly_mnemonic: mulhu + encoding: 44348467 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1022,6 +1068,7 @@ instructions: symbol: DIV name: DIV assembly_mnemonic: div + encoding: 44352563 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1036,6 +1083,7 @@ instructions: symbol: DIVU name: DIVU assembly_mnemonic: divu + encoding: 44356659 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1050,6 +1098,7 @@ instructions: symbol: REM name: REM assembly_mnemonic: rem + encoding: 44360755 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1064,6 +1113,7 @@ instructions: symbol: REMU name: REMU assembly_mnemonic: remu + encoding: 44364851 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1078,6 +1128,7 @@ instructions: symbol: MULW name: MULW assembly_mnemonic: mulw + encoding: 44336187 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1092,6 +1143,7 @@ instructions: symbol: DIVW name: DIVW assembly_mnemonic: divw + encoding: 44352571 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1106,6 +1158,7 @@ instructions: symbol: DIVUW name: DIVUW assembly_mnemonic: divuw + encoding: 44356667 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1120,6 +1173,7 @@ instructions: symbol: REMW name: REMW assembly_mnemonic: remw + encoding: 44360763 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1134,6 +1188,7 @@ instructions: symbol: REMUW name: REMUW assembly_mnemonic: remuw + encoding: 44364859 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1148,6 +1203,7 @@ instructions: symbol: CSRRSI name: CSRRSI assembly_mnemonic: csrrsi + encoding: 1107059 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -1162,6 +1218,7 @@ instructions: symbol: CSRRCI name: CSRRCI assembly_mnemonic: csrrci + encoding: 1111155 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM12, name: CSR } @@ -1176,6 +1233,7 @@ instructions: symbol: ADD name: ADD assembly_mnemonic: add + encoding: 10781747 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1190,6 +1248,7 @@ instructions: symbol: SUB name: SUB assembly_mnemonic: sub + encoding: 1084523571 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1204,6 +1263,7 @@ instructions: symbol: LD name: LD assembly_mnemonic: ld + encoding: 8696835 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1219,6 +1279,7 @@ instructions: symbol: SD name: SD assembly_mnemonic: sd + encoding: 10794019 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1234,6 +1295,7 @@ instructions: symbol: BEQ name: BEQ assembly_mnemonic: beq + encoding: 9699427 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -1248,6 +1310,7 @@ instructions: symbol: BNE name: BNE assembly_mnemonic: bne + encoding: 9703523 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } @@ -1262,6 +1325,7 @@ instructions: symbol: JAL name: JAL assembly_mnemonic: jal + encoding: 1135 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [basic_block], name: TARGET } @@ -1275,6 +1339,7 @@ instructions: symbol: ECALL name: ECALL assembly_mnemonic: ecall + encoding: 115 operands: [] num_explicit_defs: 0 flags: [has_side_effects, produces_code] @@ -1286,6 +1351,7 @@ instructions: symbol: EBREAK name: EBREAK assembly_mnemonic: ebreak + encoding: 1048691 operands: [] num_explicit_defs: 0 flags: [has_side_effects, produces_code] @@ -1297,6 +1363,7 @@ instructions: symbol: SLTI name: SLTI assembly_mnemonic: slti + encoding: 1352723 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1311,6 +1378,7 @@ instructions: symbol: SLTIU name: SLTIU assembly_mnemonic: sltiu + encoding: 1356819 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1325,6 +1393,7 @@ instructions: symbol: XORI name: XORI assembly_mnemonic: xori + encoding: 1360915 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1339,6 +1408,7 @@ instructions: symbol: ORI name: ORI assembly_mnemonic: ori + encoding: 1369107 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1353,6 +1423,7 @@ instructions: symbol: ANDI name: ANDI assembly_mnemonic: andi + encoding: 1373203 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1367,6 +1438,7 @@ instructions: symbol: SLLI name: SLLI assembly_mnemonic: slli + encoding: 1348627 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1381,6 +1453,7 @@ instructions: symbol: LR_W name: LR_W assembly_mnemonic: lr.w + encoding: 268739631 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1395,6 +1468,7 @@ instructions: symbol: SC_W name: SC_W assembly_mnemonic: sc.w + encoding: 413443119 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -1410,6 +1484,7 @@ instructions: symbol: AMOSWAP_W name: AMOSWAP_W assembly_mnemonic: amoswap.w + encoding: 145007663 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -1425,6 +1500,7 @@ instructions: symbol: FLW name: FLW assembly_mnemonic: flw + encoding: 8692743 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, memory_role: value, name: FRD } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1440,6 +1516,7 @@ instructions: symbol: FSW name: FSW assembly_mnemonic: fsw + encoding: 10789927 operands: - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, memory_role: value, name: FRS2 } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1455,6 +1532,7 @@ instructions: symbol: FMADD_S name: FMADD_S assembly_mnemonic: fmadd.s + encoding: 1487176771 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1471,6 +1549,7 @@ instructions: symbol: FMSUB_S name: FMSUB_S assembly_mnemonic: fmsub.s + encoding: 1487176775 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1487,6 +1566,7 @@ instructions: symbol: FNMSUB_S name: FNMSUB_S assembly_mnemonic: fnmsub.s + encoding: 1487176779 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1503,6 +1583,7 @@ instructions: symbol: FNMADD_S name: FNMADD_S assembly_mnemonic: fnmadd.s + encoding: 1487176783 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1519,6 +1600,7 @@ instructions: symbol: FADD_S name: FADD_S assembly_mnemonic: fadd.s + encoding: 10781779 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1534,6 +1616,7 @@ instructions: symbol: FSUB_S name: FSUB_S assembly_mnemonic: fsub.s + encoding: 144999507 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1549,6 +1632,7 @@ instructions: symbol: FMUL_S name: FMUL_S assembly_mnemonic: fmul.s + encoding: 279217235 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1564,6 +1648,7 @@ instructions: symbol: FDIV_S name: FDIV_S assembly_mnemonic: fdiv.s + encoding: 413434963 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1579,6 +1664,7 @@ instructions: symbol: FSQRT_S name: FSQRT_S assembly_mnemonic: fsqrt.s + encoding: 1476691027 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1593,6 +1679,7 @@ instructions: symbol: FSGNJ_S name: FSGNJ_S assembly_mnemonic: fsgnj.s + encoding: 547652691 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1607,6 +1694,7 @@ instructions: symbol: FSGNJN_S name: FSGNJN_S assembly_mnemonic: fsgnjn.s + encoding: 547656787 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1621,6 +1709,7 @@ instructions: symbol: FSGNJX_S name: FSGNJX_S assembly_mnemonic: fsgnjx.s + encoding: 547660883 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1635,6 +1724,7 @@ instructions: symbol: FMIN_S name: FMIN_S assembly_mnemonic: fmin.s + encoding: 681870419 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1649,6 +1739,7 @@ instructions: symbol: FMAX_S name: FMAX_S assembly_mnemonic: fmax.s + encoding: 681874515 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1663,6 +1754,7 @@ instructions: symbol: FCVT_W_S name: FCVT_W_S assembly_mnemonic: fcvt.w.s + encoding: 3221521491 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1677,6 +1769,7 @@ instructions: symbol: FCVT_WU_S name: FCVT_WU_S assembly_mnemonic: fcvt.wu.s + encoding: 3222570067 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1691,6 +1784,7 @@ instructions: symbol: FCVT_L_S name: FCVT_L_S assembly_mnemonic: fcvt.l.s + encoding: 3223618643 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1705,6 +1799,7 @@ instructions: symbol: FCVT_LU_S name: FCVT_LU_S assembly_mnemonic: fcvt.lu.s + encoding: 3224667219 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1719,6 +1814,7 @@ instructions: symbol: FMV_X_W name: FMV_X_W assembly_mnemonic: fmv.x.w + encoding: 3758392403 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1732,6 +1828,7 @@ instructions: symbol: FEQ_S name: FEQ_S assembly_mnemonic: feq.s + encoding: 2695144531 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1746,6 +1843,7 @@ instructions: symbol: FLT_S name: FLT_S assembly_mnemonic: flt.s + encoding: 2695140435 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1760,6 +1858,7 @@ instructions: symbol: FLE_S name: FLE_S assembly_mnemonic: fle.s + encoding: 2695136339 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1774,6 +1873,7 @@ instructions: symbol: FCLASS_S name: FCLASS_S assembly_mnemonic: fclass.s + encoding: 3758396499 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -1787,6 +1887,7 @@ instructions: symbol: FCVT_S_W name: FCVT_S_W assembly_mnemonic: fcvt.s.w + encoding: 3489956947 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1801,6 +1902,7 @@ instructions: symbol: FCVT_S_WU name: FCVT_S_WU assembly_mnemonic: fcvt.s.wu + encoding: 3491005523 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1815,6 +1917,7 @@ instructions: symbol: FCVT_S_L name: FCVT_S_L assembly_mnemonic: fcvt.s.l + encoding: 3492054099 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1829,6 +1932,7 @@ instructions: symbol: FCVT_S_LU name: FCVT_S_LU assembly_mnemonic: fcvt.s.lu + encoding: 3493102675 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1843,6 +1947,7 @@ instructions: symbol: FMV_W_X name: FMV_W_X assembly_mnemonic: fmv.w.x + encoding: 4026827859 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -1856,6 +1961,7 @@ instructions: symbol: FLD name: FLD assembly_mnemonic: fld + encoding: 8696839 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRD } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1871,6 +1977,7 @@ instructions: symbol: FSD name: FSD assembly_mnemonic: fsd + encoding: 10794023 operands: - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRS2 } - { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -1886,6 +1993,7 @@ instructions: symbol: FMADD_D name: FMADD_D assembly_mnemonic: fmadd.d + encoding: 1520731203 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1902,6 +2010,7 @@ instructions: symbol: FMSUB_D name: FMSUB_D assembly_mnemonic: fmsub.d + encoding: 1520731207 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1918,6 +2027,7 @@ instructions: symbol: FNMSUB_D name: FNMSUB_D assembly_mnemonic: fnmsub.d + encoding: 1520731211 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1934,6 +2044,7 @@ instructions: symbol: FNMADD_D name: FNMADD_D assembly_mnemonic: fnmadd.d + encoding: 1520731215 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1950,6 +2061,7 @@ instructions: symbol: FADD_D name: FADD_D assembly_mnemonic: fadd.d + encoding: 44336211 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1965,6 +2077,7 @@ instructions: symbol: FSUB_D name: FSUB_D assembly_mnemonic: fsub.d + encoding: 178553939 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1980,6 +2093,7 @@ instructions: symbol: FMUL_D name: FMUL_D assembly_mnemonic: fmul.d + encoding: 312771667 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -1995,6 +2109,7 @@ instructions: symbol: FDIV_D name: FDIV_D assembly_mnemonic: fdiv.d + encoding: 446989395 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2010,6 +2125,7 @@ instructions: symbol: FSQRT_D name: FSQRT_D assembly_mnemonic: fsqrt.d + encoding: 1510245459 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2024,6 +2140,7 @@ instructions: symbol: FSGNJ_D name: FSGNJ_D assembly_mnemonic: fsgnj.d + encoding: 581207123 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2038,6 +2155,7 @@ instructions: symbol: FSGNJN_D name: FSGNJN_D assembly_mnemonic: fsgnjn.d + encoding: 581211219 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2052,6 +2170,7 @@ instructions: symbol: FSGNJX_D name: FSGNJX_D assembly_mnemonic: fsgnjx.d + encoding: 581215315 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2066,6 +2185,7 @@ instructions: symbol: FMIN_D name: FMIN_D assembly_mnemonic: fmin.d + encoding: 715424851 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2080,6 +2200,7 @@ instructions: symbol: FMAX_D name: FMAX_D assembly_mnemonic: fmax.d + encoding: 715428947 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2094,6 +2215,7 @@ instructions: symbol: FCVT_W_D name: FCVT_W_D assembly_mnemonic: fcvt.w.d + encoding: 3255075923 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2108,6 +2230,7 @@ instructions: symbol: FCVT_WU_D name: FCVT_WU_D assembly_mnemonic: fcvt.wu.d + encoding: 3256124499 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2122,6 +2245,7 @@ instructions: symbol: FCVT_L_D name: FCVT_L_D assembly_mnemonic: fcvt.l.d + encoding: 3257173075 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2136,6 +2260,7 @@ instructions: symbol: FCVT_LU_D name: FCVT_LU_D assembly_mnemonic: fcvt.lu.d + encoding: 3258221651 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2150,6 +2275,7 @@ instructions: symbol: FMV_X_D name: FMV_X_D assembly_mnemonic: fmv.x.d + encoding: 3791946835 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2163,6 +2289,7 @@ instructions: symbol: FEQ_D name: FEQ_D assembly_mnemonic: feq.d + encoding: 2728698963 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2177,6 +2304,7 @@ instructions: symbol: FLT_D name: FLT_D assembly_mnemonic: flt.d + encoding: 2728694867 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2191,6 +2319,7 @@ instructions: symbol: FLE_D name: FLE_D assembly_mnemonic: fle.d + encoding: 2728690771 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2205,6 +2334,7 @@ instructions: symbol: FCLASS_D name: FCLASS_D assembly_mnemonic: fclass.d + encoding: 3791950931 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2218,6 +2348,7 @@ instructions: symbol: FCVT_D_W name: FCVT_D_W assembly_mnemonic: fcvt.d.w + encoding: 3523511379 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -2232,6 +2363,7 @@ instructions: symbol: FCVT_D_WU name: FCVT_D_WU assembly_mnemonic: fcvt.d.wu + encoding: 3524559955 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -2246,6 +2378,7 @@ instructions: symbol: FCVT_D_L name: FCVT_D_L assembly_mnemonic: fcvt.d.l + encoding: 3525608531 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -2260,6 +2393,7 @@ instructions: symbol: FCVT_D_LU name: FCVT_D_LU assembly_mnemonic: fcvt.d.lu + encoding: 3526657107 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -2274,6 +2408,7 @@ instructions: symbol: FMV_D_X name: FMV_D_X assembly_mnemonic: fmv.d.x + encoding: 4060382291 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -2287,6 +2422,7 @@ instructions: symbol: FCVT_S_D name: FCVT_S_D assembly_mnemonic: fcvt.s.d + encoding: 1075086419 operands: - { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 } @@ -2301,6 +2437,7 @@ instructions: symbol: C_ADDI4SPN name: C_ADDI4SPN assembly_mnemonic: c.addi4spn + encoding: 2048 operands: - { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_UIMM10_NZ_A4, name: IMM } @@ -2315,6 +2452,7 @@ instructions: symbol: C_FLD name: C_FLD assembly_mnemonic: c.fld + encoding: 9344 operands: - { kinds: [register], role: def, register_class: FPR64C, register_bank: FPR, memory_role: value, name: FRD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2330,6 +2468,7 @@ instructions: symbol: C_LW name: C_LW assembly_mnemonic: c.lw + encoding: 17536 operands: - { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2345,6 +2484,7 @@ instructions: symbol: C_LD name: C_LD assembly_mnemonic: c.ld + encoding: 25728 operands: - { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2360,6 +2500,7 @@ instructions: symbol: C_FSD name: C_FSD assembly_mnemonic: c.fsd + encoding: 42120 operands: - { kinds: [register], role: use, register_class: FPR64C, register_bank: FPR, memory_role: value, name: FRS2 } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2375,6 +2516,7 @@ instructions: symbol: C_SW name: C_SW assembly_mnemonic: c.sw + encoding: 50312 operands: - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2390,6 +2532,7 @@ instructions: symbol: C_SD name: C_SD assembly_mnemonic: c.sd + encoding: 58504 operands: - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 } @@ -2405,6 +2548,7 @@ instructions: symbol: C_ADDI name: C_ADDI assembly_mnemonic: c.addi + encoding: 1029 operands: - { kinds: [register], role: def_use, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM } @@ -2418,6 +2562,7 @@ instructions: symbol: C_ADDIW name: C_ADDIW assembly_mnemonic: c.addiw + encoding: 9221 operands: - { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM } @@ -2431,6 +2576,7 @@ instructions: symbol: C_LI name: C_LI assembly_mnemonic: c.li + encoding: 17413 operands: - { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM } @@ -2444,6 +2590,7 @@ instructions: symbol: C_ADDI16SP name: C_ADDI16SP assembly_mnemonic: c.addi16sp + encoding: 24897 operands: - { kinds: [immediate], immediate_predicate: C_SIMM10_A16_NZ, name: IMM } num_explicit_defs: 0 @@ -2458,6 +2605,7 @@ instructions: symbol: C_LUI name: C_LUI assembly_mnemonic: c.lui + encoding: 25605 operands: - { kinds: [register], role: def, register_class: GPR_NX0_NX2, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_SIMM6_NZ, name: IMM } @@ -2471,6 +2619,7 @@ instructions: symbol: C_SRLI name: C_SRLI assembly_mnemonic: c.srli + encoding: 32773 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM6, name: IMM } @@ -2484,6 +2633,7 @@ instructions: symbol: C_SRAI name: C_SRAI assembly_mnemonic: c.srai + encoding: 33797 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM6, name: IMM } @@ -2497,6 +2647,7 @@ instructions: symbol: C_ANDI name: C_ANDI assembly_mnemonic: c.andi + encoding: 34821 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM } @@ -2510,6 +2661,7 @@ instructions: symbol: C_SUB name: C_SUB assembly_mnemonic: c.sub + encoding: 35845 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2523,6 +2675,7 @@ instructions: symbol: C_XOR name: C_XOR assembly_mnemonic: c.xor + encoding: 35877 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2536,6 +2689,7 @@ instructions: symbol: C_OR name: C_OR assembly_mnemonic: c.or + encoding: 35909 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2549,6 +2703,7 @@ instructions: symbol: C_AND name: C_AND assembly_mnemonic: c.and + encoding: 35941 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2562,6 +2717,7 @@ instructions: symbol: C_SUBW name: C_SUBW assembly_mnemonic: c.subw + encoding: 39941 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2575,6 +2731,7 @@ instructions: symbol: C_ADDW name: C_ADDW assembly_mnemonic: c.addw + encoding: 39973 operands: - { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 } @@ -2588,6 +2745,7 @@ instructions: symbol: C_J name: C_J assembly_mnemonic: c.j + encoding: 40961 operands: - { kinds: [basic_block], name: TARGET } num_explicit_defs: 0 @@ -2600,6 +2758,7 @@ instructions: symbol: C_BEQZ name: C_BEQZ assembly_mnemonic: c.beqz + encoding: 49153 operands: - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS1 } - { kinds: [basic_block], name: TARGET } @@ -2613,6 +2772,7 @@ instructions: symbol: C_BNEZ name: C_BNEZ assembly_mnemonic: c.bnez + encoding: 57345 operands: - { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS1 } - { kinds: [basic_block], name: TARGET } @@ -2626,6 +2786,7 @@ instructions: symbol: C_SLLI name: C_SLLI assembly_mnemonic: c.slli + encoding: 1030 operands: - { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD } - { kinds: [immediate], immediate_predicate: UIMM6, name: IMM } @@ -2639,6 +2800,7 @@ instructions: symbol: C_FLDSP name: C_FLDSP assembly_mnemonic: c.fldsp + encoding: 9250 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRD } - { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM } @@ -2654,6 +2816,7 @@ instructions: symbol: C_LWSP name: C_LWSP assembly_mnemonic: c.lwsp + encoding: 17442 operands: - { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, memory_role: value, name: RD } - { kinds: [immediate], immediate_predicate: C_UIMM8_A4, name: IMM } @@ -2669,6 +2832,7 @@ instructions: symbol: C_LDSP name: C_LDSP assembly_mnemonic: c.ldsp + encoding: 25634 operands: - { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, memory_role: value, name: RD } - { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM } @@ -2684,6 +2848,7 @@ instructions: symbol: C_JR name: C_JR assembly_mnemonic: c.jr + encoding: 33794 operands: - { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS1 } num_explicit_defs: 0 @@ -2696,6 +2861,7 @@ instructions: symbol: C_MV name: C_MV assembly_mnemonic: c.mv + encoding: 33830 operands: - { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS2 } @@ -2709,6 +2875,7 @@ instructions: symbol: C_EBREAK name: C_EBREAK assembly_mnemonic: c.ebreak + encoding: 36866 operands: [] num_explicit_defs: 0 flags: [has_side_effects, produces_code] @@ -2720,6 +2887,7 @@ instructions: symbol: C_JALR name: C_JALR assembly_mnemonic: c.jalr + encoding: 37890 operands: - { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS1 } num_explicit_defs: 0 @@ -2733,6 +2901,7 @@ instructions: symbol: C_ADD name: C_ADD assembly_mnemonic: c.add + encoding: 37926 operands: - { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS2 } @@ -2746,6 +2915,7 @@ instructions: symbol: C_FSDSP name: C_FSDSP assembly_mnemonic: c.fsdsp + encoding: 42018 operands: - { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRS2 } - { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM } @@ -2761,6 +2931,7 @@ instructions: symbol: C_SWSP name: C_SWSP assembly_mnemonic: c.swsp + encoding: 50210 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [immediate], immediate_predicate: C_UIMM8_A4, name: IMM } @@ -2776,6 +2947,7 @@ instructions: symbol: C_SDSP name: C_SDSP assembly_mnemonic: c.sdsp + encoding: 58402 operands: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } - { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM } @@ -2791,6 +2963,7 @@ instructions: symbol: FCVT_D_S name: FCVT_D_S assembly_mnemonic: fcvt.d.s + encoding: 1107592275 operands: - { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD } - { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 } @@ -2805,6 +2978,7 @@ instructions: symbol: AMOADD_W name: AMOADD_W assembly_mnemonic: amoadd.w + encoding: 10789935 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2820,6 +2994,7 @@ instructions: symbol: AMOXOR_W name: AMOXOR_W assembly_mnemonic: amoxor.w + encoding: 547660847 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2835,6 +3010,7 @@ instructions: symbol: AMOAND_W name: AMOAND_W assembly_mnemonic: amoand.w + encoding: 1621402671 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2850,6 +3026,7 @@ instructions: symbol: AMOOR_W name: AMOOR_W assembly_mnemonic: amoor.w + encoding: 1084531759 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2865,6 +3042,7 @@ instructions: symbol: AMOMIN_W name: AMOMIN_W assembly_mnemonic: amomin.w + encoding: 2158273583 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2880,6 +3058,7 @@ instructions: symbol: AMOMAX_W name: AMOMAX_W assembly_mnemonic: amomax.w + encoding: 2695144495 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2895,6 +3074,7 @@ instructions: symbol: AMOMINU_W name: AMOMINU_W assembly_mnemonic: amominu.w + encoding: 3232015407 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2910,6 +3090,7 @@ instructions: symbol: AMOMAXU_W name: AMOMAXU_W assembly_mnemonic: amomaxu.w + encoding: 3768886319 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2925,6 +3106,7 @@ instructions: symbol: LR_D name: LR_D assembly_mnemonic: lr.d + encoding: 268743727 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 } @@ -2939,6 +3121,7 @@ instructions: symbol: SC_D name: SC_D assembly_mnemonic: sc.d + encoding: 413447215 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2954,6 +3137,7 @@ instructions: symbol: AMOSWAP_D name: AMOSWAP_D assembly_mnemonic: amoswap.d + encoding: 145011759 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2969,6 +3153,7 @@ instructions: symbol: AMOADD_D name: AMOADD_D assembly_mnemonic: amoadd.d + encoding: 10794031 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2984,6 +3169,7 @@ instructions: symbol: AMOXOR_D name: AMOXOR_D assembly_mnemonic: amoxor.d + encoding: 547664943 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -2999,6 +3185,7 @@ instructions: symbol: AMOAND_D name: AMOAND_D assembly_mnemonic: amoand.d + encoding: 1621406767 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3014,6 +3201,7 @@ instructions: symbol: AMOOR_D name: AMOOR_D assembly_mnemonic: amoor.d + encoding: 1084535855 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3029,6 +3217,7 @@ instructions: symbol: AMOMIN_D name: AMOMIN_D assembly_mnemonic: amomin.d + encoding: 2158277679 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3044,6 +3233,7 @@ instructions: symbol: AMOMAX_D name: AMOMAX_D assembly_mnemonic: amomax.d + encoding: 2695148591 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3059,6 +3249,7 @@ instructions: symbol: AMOMINU_D name: AMOMINU_D assembly_mnemonic: amominu.d + encoding: 3232019503 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3074,6 +3265,7 @@ instructions: symbol: AMOMAXU_D name: AMOMAXU_D assembly_mnemonic: amomaxu.d + encoding: 3768890415 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 } @@ -3204,6 +3396,7 @@ instructions: symbol: JALR_CALL name: JALR_CALL assembly_mnemonic: jalr + encoding: 1344615 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -3221,6 +3414,7 @@ instructions: symbol: JALR_TAIL name: JALR_TAIL assembly_mnemonic: jalr + encoding: 1344615 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } @@ -3238,6 +3432,7 @@ instructions: symbol: JALR_RET name: JALR_RET assembly_mnemonic: jalr + encoding: 1344615 operands: - { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } diff --git a/backend/lib/Target/RISCV/RISCVAsmBackend.cpp b/backend/lib/Target/RISCV/RISCVAsmBackend.cpp new file mode 100644 index 0000000..4e07933 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVAsmBackend.cpp @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Target/RISCV/RISCVAsmBackend.h" + +#include "rcc/Target/RISCV/RISCVFixupKinds.h" +#include "rcc/Target/RISCV/RISCVInstPrinter.h" +#include "rcc/Target/RISCV/RISCVInstructions.h" +#include "rcc/Target/RISCV/RISCVRegisters.h" + +#include <cstddef> +#include <cstdint> +#include <limits> +#include <string> + +namespace rcc::riscv { +namespace { + +enum class RISCVRelocation : std::uint32_t { + Relocation32 = 1, + Relocation64 = 2, + Branch = 16, + JAL = 17, + CallPLT = 19, + PCRelativeHigh20 = 23, + PCRelativeLow12I = 24, + PCRelativeLow12S = 25, + High20 = 26, + Low12I = 27, + Low12S = 28, + Add8 = 33, + Add16 = 34, + Add32 = 35, + Add64 = 36, + Subtract8 = 37, + Subtract16 = 38, + Subtract32 = 39, + Subtract64 = 40, + RVCBranch = 44, + RVCJump = 45, + PCRelative32 = 57, +}; + +[[nodiscard]] bool isTargetKind(mc::MCFixupKind Kind, RISCVFixupKind TargetKind) noexcept { + return Kind == fixupKind(TargetKind); +} + +[[nodiscard]] Expected<void> requireStorage(std::span<std::uint8_t> Data, std::uint64_t Offset, + std::uint8_t Size) { + if (Offset > Data.size() || Size > Data.size() - static_cast<std::size_t>(Offset)) { + return makeUnexpected(ErrorCode::FixupApplicationFailed, + "RISC-V fixup exceeds its encoded fragment"); + } + return {}; +} + +void writeLittleEndian(std::span<std::uint8_t> Data, std::uint64_t Offset, std::uint64_t Value, + std::uint8_t Size) noexcept { + for (std::uint8_t Index = 0; Index < Size; ++Index) + Data[static_cast<std::size_t>(Offset) + Index] = + static_cast<std::uint8_t>(Value >> (Index * 8U)); +} + +[[nodiscard]] std::uint32_t readWord(std::span<const std::uint8_t> Data, + std::uint64_t Offset) noexcept { + std::uint32_t Result = 0; + for (std::uint8_t Index = 0; Index < 4; ++Index) + Result |= static_cast<std::uint32_t>(Data[static_cast<std::size_t>(Offset) + Index]) + << (Index * 8U); + return Result; +} + +[[nodiscard]] std::uint16_t readHalf(std::span<const std::uint8_t> Data, + std::uint64_t Offset) noexcept { + return static_cast<std::uint16_t>(Data[static_cast<std::size_t>(Offset)]) | + static_cast<std::uint16_t>(Data[static_cast<std::size_t>(Offset) + 1U] << 8U); +} + +[[nodiscard]] bool fitsSigned(std::int64_t Value, unsigned Bits) noexcept { + const std::int64_t Minimum = -(std::int64_t{1} << (Bits - 1U)); + const std::int64_t Maximum = (std::int64_t{1} << (Bits - 1U)) - 1; + return Value >= Minimum && Value <= Maximum; +} + +[[nodiscard]] Expected<void> requireDisplacement(std::int64_t Value, unsigned Bits, + std::string_view Name) { + if ((Value & 1) != 0 || !fitsSigned(Value, Bits)) { + return makeUnexpected(ErrorCode::FixupApplicationFailed, + std::string(Name) + " displacement is out of range or unaligned"); + } + return {}; +} + +[[nodiscard]] std::uint32_t encodeBranchImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint32_t>(Value); + return ((Bits >> 12U) & 0x1U) << 31U | ((Bits >> 5U) & 0x3fU) << 25U | + ((Bits >> 1U) & 0xfU) << 8U | ((Bits >> 11U) & 0x1U) << 7U; +} + +[[nodiscard]] std::uint32_t encodeJALImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint32_t>(Value); + return ((Bits >> 20U) & 0x1U) << 31U | ((Bits >> 1U) & 0x3ffU) << 21U | + ((Bits >> 11U) & 0x1U) << 20U | ((Bits >> 12U) & 0xffU) << 12U; +} + +[[nodiscard]] std::uint16_t encodeRVCJumpImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint16_t>(Value); + return static_cast<std::uint16_t>(((Bits >> 11U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 11U | + ((Bits >> 8U) & 3U) << 9U | ((Bits >> 10U) & 1U) << 8U | + ((Bits >> 6U) & 1U) << 7U | ((Bits >> 7U) & 1U) << 6U | + ((Bits >> 1U) & 7U) << 3U | ((Bits >> 5U) & 1U) << 2U); +} + +[[nodiscard]] std::uint16_t encodeRVCBranchImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint16_t>(Value); + return static_cast<std::uint16_t>(((Bits >> 8U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 10U | + ((Bits >> 6U) & 3U) << 5U | ((Bits >> 1U) & 3U) << 3U | + ((Bits >> 5U) & 1U) << 2U); +} + +[[nodiscard]] Expected<void> requireRelocationTargetKind(const mc::MCValue &Value, + std::uint32_t Expected, + std::string_view Name) { + if (Value.TargetKind != Expected) { + return makeUnexpected(ErrorCode::RelocationFailed, + std::string(Name) + " has an incompatible target expression"); + } + return {}; +} + +} // namespace + +Expected<mc::MCFixupKindInfo> RISCVAsmBackend::fixupKindInfo(mc::MCFixupKind Kind) const { + switch (Kind) { + case mc::fixup_kind::Data1: + return mc::MCFixupKindInfo{.StorageSize = 1, .PCRelative = false}; + case mc::fixup_kind::Data2: + return mc::MCFixupKindInfo{.StorageSize = 2, .PCRelative = false}; + case mc::fixup_kind::Data4: + return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = false}; + case mc::fixup_kind::Data8: + return mc::MCFixupKindInfo{.StorageSize = 8, .PCRelative = false}; + case mc::fixup_kind::PCRelative4: + return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = true}; + default: + break; + } + if (isTargetKind(Kind, RISCVFixupKind::RVCJump) || + isTargetKind(Kind, RISCVFixupKind::RVCBranch)) { + return mc::MCFixupKindInfo{.StorageSize = 2, .PCRelative = true}; + } + if (Kind >= fixupKind(RISCVFixupKind::High20) && Kind <= fixupKind(RISCVFixupKind::CallPLT)) { + const bool PCRelative = Kind >= fixupKind(RISCVFixupKind::PCRelativeHigh20); + return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = PCRelative}; + } + return makeUnexpected(ErrorCode::InvalidArgument, "unknown RISC-V fixup kind"); +} + +Expected<void> RISCVAsmBackend::applyFixup(mc::MCFixupKind Kind, std::span<std::uint8_t> Data, + std::uint64_t Offset, std::int64_t Value) const { + auto Info = fixupKindInfo(Kind); + if (!Info) + return std::unexpected(Info.error()); + auto Storage = requireStorage(Data, Offset, Info->StorageSize); + if (!Storage) + return std::unexpected(Storage.error()); + + if (Kind == mc::fixup_kind::Data1 || Kind == mc::fixup_kind::Data2 || + Kind == mc::fixup_kind::Data4 || Kind == mc::fixup_kind::Data8 || + Kind == mc::fixup_kind::PCRelative4) { + writeLittleEndian(Data, Offset, static_cast<std::uint64_t>(Value), Info->StorageSize); + return {}; + } + + if (Info->StorageSize == 2) { + std::uint16_t Instruction = readHalf(Data, Offset); + if (isTargetKind(Kind, RISCVFixupKind::RVCJump)) { + auto Range = requireDisplacement(Value, 12, "RISC-V compressed jump"); + if (!Range) + return std::unexpected(Range.error()); + Instruction = static_cast<std::uint16_t>((Instruction & ~std::uint16_t{0x1ffc}) | + encodeRVCJumpImmediate(Value)); + } else { + auto Range = requireDisplacement(Value, 9, "RISC-V compressed branch"); + if (!Range) + return std::unexpected(Range.error()); + Instruction = static_cast<std::uint16_t>((Instruction & ~std::uint16_t{0x1c7c}) | + encodeRVCBranchImmediate(Value)); + } + writeLittleEndian(Data, Offset, Instruction, 2); + return {}; + } + + std::uint32_t Instruction = readWord(Data, Offset); + if (isTargetKind(Kind, RISCVFixupKind::High20) || + isTargetKind(Kind, RISCVFixupKind::PCRelativeHigh20) || + isTargetKind(Kind, RISCVFixupKind::CallPLT)) { + const std::uint64_t Adjusted = static_cast<std::uint64_t>(Value) + 0x800U; + const std::uint32_t High = static_cast<std::uint32_t>(Adjusted >> 12U); + Instruction = (Instruction & 0xfffU) | (High << 12U); + } else if (isTargetKind(Kind, RISCVFixupKind::Low12I) || + isTargetKind(Kind, RISCVFixupKind::PCRelativeLow12I)) { + Instruction = (Instruction & 0x000fffffU) | (static_cast<std::uint32_t>(Value) & 0xfffU) << 20U; + } else if (isTargetKind(Kind, RISCVFixupKind::Low12S) || + isTargetKind(Kind, RISCVFixupKind::PCRelativeLow12S)) { + const std::uint32_t Low = static_cast<std::uint32_t>(Value) & 0xfffU; + Instruction = (Instruction & ~std::uint32_t{0xfe000f80}) | ((Low >> 5U) & 0x7fU) << 25U | + (Low & 0x1fU) << 7U; + } else if (isTargetKind(Kind, RISCVFixupKind::JAL)) { + auto Range = requireDisplacement(Value, 21, "RISC-V JAL"); + if (!Range) + return std::unexpected(Range.error()); + Instruction = (Instruction & 0xfffU) | encodeJALImmediate(Value); + } else if (isTargetKind(Kind, RISCVFixupKind::Branch)) { + auto Range = requireDisplacement(Value, 13, "RISC-V branch"); + if (!Range) + return std::unexpected(Range.error()); + Instruction = (Instruction & ~std::uint32_t{0xfe000f80}) | encodeBranchImmediate(Value); + } else { + return makeUnexpected(ErrorCode::FixupApplicationFailed, + "RISC-V fixup cannot be applied to an instruction"); + } + writeLittleEndian(Data, Offset, Instruction, 4); + return {}; +} + +Expected<std::uint32_t> RISCVAsmBackend::relocationType(const mc::MCFixup &Fixup, + const mc::MCValue &Value) const { + const auto Relocation = [](RISCVRelocation Type) { return static_cast<std::uint32_t>(Type); }; + switch (Fixup.Kind) { + case mc::fixup_kind::Data4: + return Relocation(RISCVRelocation::Relocation32); + case mc::fixup_kind::Data8: + return Relocation(RISCVRelocation::Relocation64); + case mc::fixup_kind::PCRelative4: + return Relocation(RISCVRelocation::PCRelative32); + default: + break; + } + + if (isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeHigh20)) { + auto Kind = requireRelocationTargetKind( + Value, static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeHigh), "R_RISCV_PCREL_HI20"); + if (!Kind) + return std::unexpected(Kind.error()); + return Relocation(RISCVRelocation::PCRelativeHigh20); + } + if (isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12I) || + isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12S)) { + auto Kind = requireRelocationTargetKind( + Value, static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeLow), "R_RISCV_PCREL_LO12"); + if (!Kind) + return std::unexpected(Kind.error()); + return Relocation(isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12I) + ? RISCVRelocation::PCRelativeLow12I + : RISCVRelocation::PCRelativeLow12S); + } + if (isTargetKind(Fixup.Kind, RISCVFixupKind::CallPLT)) { + auto Kind = requireRelocationTargetKind( + Value, static_cast<std::uint32_t>(RISCVMCExprKind::CallPLT), "R_RISCV_CALL_PLT"); + if (!Kind) + return std::unexpected(Kind.error()); + return Relocation(RISCVRelocation::CallPLT); + } + if (Value.TargetKind != 0) { + return makeUnexpected(ErrorCode::RelocationFailed, + "RISC-V relocation has an unsupported target expression"); + } + if (isTargetKind(Fixup.Kind, RISCVFixupKind::High20)) + return Relocation(RISCVRelocation::High20); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::Low12I)) + return Relocation(RISCVRelocation::Low12I); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::Low12S)) + return Relocation(RISCVRelocation::Low12S); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::JAL)) + return Relocation(RISCVRelocation::JAL); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::Branch)) + return Relocation(RISCVRelocation::Branch); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCJump)) + return Relocation(RISCVRelocation::RVCJump); + if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCBranch)) + return Relocation(RISCVRelocation::RVCBranch); + return makeUnexpected(ErrorCode::RelocationFailed, "RISC-V fixup has no ELF relocation type"); +} + +Expected<std::vector<mc::MCFixupRelocation>> +RISCVAsmBackend::relocationsForFixup(const mc::MCFixup &Fixup, const mc::MCValue &Value) const { + if (!Value.SubtractSymbol) + return mc::MCAsmBackend::relocationsForFixup(Fixup, Value); + if (!Value.AddSymbol || Value.TargetKind != 0) { + return makeUnexpected(ErrorCode::RelocationFailed, + "RISC-V symbol difference has an invalid relocation expression"); + } + + RISCVRelocation AddType; + RISCVRelocation SubtractType; + switch (Fixup.Kind) { + case mc::fixup_kind::Data1: + AddType = RISCVRelocation::Add8; + SubtractType = RISCVRelocation::Subtract8; + break; + case mc::fixup_kind::Data2: + AddType = RISCVRelocation::Add16; + SubtractType = RISCVRelocation::Subtract16; + break; + case mc::fixup_kind::Data4: + AddType = RISCVRelocation::Add32; + SubtractType = RISCVRelocation::Subtract32; + break; + case mc::fixup_kind::Data8: + AddType = RISCVRelocation::Add64; + SubtractType = RISCVRelocation::Subtract64; + break; + default: + return makeUnexpected(ErrorCode::RelocationFailed, + "RISC-V fixup cannot encode a symbol difference"); + } + return std::vector<mc::MCFixupRelocation>{ + {.Type = static_cast<std::uint32_t>(AddType), + .Symbol = Value.AddSymbol, + .Addend = Value.Addend}, + {.Type = static_cast<std::uint32_t>(SubtractType), + .Symbol = Value.SubtractSymbol, + .Addend = 0}, + }; +} + +bool RISCVAsmBackend::mayNeedRelaxation(const mc::MCInst &Instruction) const noexcept { + const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value()); + return Opcode == InstructionOpcode::C_J || Opcode == InstructionOpcode::C_BEQZ || + Opcode == InstructionOpcode::C_BNEZ; +} + +Expected<bool> RISCVAsmBackend::fixupNeedsRelaxation(const mc::MCFixup &Fixup, + std::int64_t Value) const { + if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCJump)) + return !fitsSigned(Value, 12) || (Value & 1) != 0; + if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCBranch)) + return !fitsSigned(Value, 9) || (Value & 1) != 0; + return false; +} + +Expected<mc::MCInst> RISCVAsmBackend::relaxInstruction(const mc::MCInst &Instruction) const { + const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value()); + const bool IsJump = Opcode == InstructionOpcode::C_J; + const bool IsBranch = Opcode == InstructionOpcode::C_BEQZ || Opcode == InstructionOpcode::C_BNEZ; + const std::size_t ExpectedOperands = IsJump ? 1U : 2U; + if ((!IsJump && !IsBranch) || Instruction.operands().size() != ExpectedOperands) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V MC relaxation received an unsupported instruction"); + } + + const mc::MCOperand &Target = Instruction.operands().back(); + if (Target.expressionValue() == nullptr) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V MC relaxation requires a symbolic target"); + } + const InstructionOpcode RelaxedOpcode = + IsJump + ? InstructionOpcode::JAL + : (Opcode == InstructionOpcode::C_BEQZ ? InstructionOpcode::BEQ : InstructionOpcode::BNE); + mc::MCInst Result(mc::MCOpcode::fromValue(static_cast<std::uint32_t>(RelaxedOpcode))); + Result.setFlags(Instruction.flags()); + Result.setSourceIdentity(Instruction.sourceIdentity()); + if (IsJump) { + Result.addOperand(mc::MCOperand::registerOperand( + mc::MCRegister::fromValue(static_cast<std::uint32_t>(PhysicalRegisterID::X0)))); + } else { + Result.addOperand(Instruction.operands().front()); + Result.addOperand(mc::MCOperand::registerOperand( + mc::MCRegister::fromValue(static_cast<std::uint32_t>(PhysicalRegisterID::X0)))); + } + Result.addOperand(Target); + return Result; +} + +std::uint32_t RISCVAsmBackend::objectFlags() const noexcept { + constexpr std::uint32_t RVC = 1; + constexpr std::uint32_t FloatABIDouble = 4; + return RVC | FloatABIDouble; +} + +} // namespace rcc::riscv diff --git a/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp new file mode 100644 index 0000000..5f98887 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp @@ -0,0 +1,984 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Target/RISCV/RISCVMCCodeEmitter.h" + +#include "rcc/CodeGen/Register.h" +#include "rcc/MC/MCExpr.h" +#include "rcc/Target/RISCV/RISCVFixupKinds.h" +#include "rcc/Target/RISCV/RISCVInstPrinter.h" +#include "rcc/Target/RISCV/RISCVTarget.h" + +#include <cstddef> +#include <cstdint> +#include <string> +#include <string_view> + +namespace rcc::riscv { +namespace { + +[[nodiscard]] Expected<void> requireOperandCount(const mc::MCInst &Instruction, std::size_t Count) { + if (Instruction.operands().size() != Count) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V instruction has an unexpected encoding operand count"); + } + return {}; +} + +[[nodiscard]] Expected<std::uint32_t> registerEncoding(const mc::MCInst &Instruction, + std::size_t Index, + const TargetDescription &Target) { + if (Index >= Instruction.operands().size()) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V encoding references an absent register operand"); + } + const mc::MCRegister *Register = Instruction.operands()[Index].registerValue(); + if (Register == nullptr) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V encoding requires a register operand"); + } + auto Physical = PhysicalRegister::create(Register->value()); + if (!Physical) + return std::unexpected(Physical.error()); + const PhysicalRegisterDesc *Description = Target.registers().physicalRegister(*Physical); + if (Description == nullptr || Description->Encoding >= 32) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V encoding references an unknown physical register"); + } + return Description->Encoding; +} + +[[nodiscard]] Expected<void> validateRegisterOperands(const mc::MCInst &Instruction, + const InstructionDescriptor &Descriptor, + const TargetDescription &Target) { + for (std::size_t Index = 0; Index < Instruction.operands().size(); ++Index) { + const mc::MCRegister *Register = Instruction.operands()[Index].registerValue(); + if (Register == nullptr) + continue; + if (Index >= Descriptor.Operands.size()) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V register operand has no target descriptor"); + } + auto Physical = PhysicalRegister::create(Register->value()); + if (!Physical) + return std::unexpected(Physical.error()); + const OperandDescriptor &Operand = Descriptor.Operands[Index]; + if (Operand.RegClass && + !Target.registers().registerClassContains(*Operand.RegClass, *Physical)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V register is outside its required register class"); + } + if (Operand.RegBank && !Target.registers().bankContainsRegister(*Operand.RegBank, *Physical)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V register is outside its required register bank"); + } + } + return {}; +} + +[[nodiscard]] Expected<std::uint32_t> compactRegisterEncoding(const mc::MCInst &Instruction, + std::size_t Index, + const TargetDescription &Target) { + auto Encoding = registerEncoding(Instruction, Index, Target); + if (!Encoding) + return std::unexpected(Encoding.error()); + if (*Encoding < 8 || *Encoding > 15) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "compressed RISC-V instruction requires an x8-x15 register"); + } + return *Encoding - 8U; +} + +[[nodiscard]] bool fitsSigned(std::int64_t Value, unsigned Bits) noexcept { + const std::int64_t Minimum = -(std::int64_t{1} << (Bits - 1U)); + const std::int64_t Maximum = (std::int64_t{1} << (Bits - 1U)) - 1; + return Value >= Minimum && Value <= Maximum; +} + +[[nodiscard]] bool fitsUnsigned(std::int64_t Value, unsigned Bits) noexcept { + return Value >= 0 && static_cast<std::uint64_t>(Value) < (std::uint64_t{1} << Bits); +} + +[[nodiscard]] Expected<void> requireSigned(std::int64_t Value, unsigned Bits, + std::string_view Name) { + if (!fitsSigned(Value, Bits)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + std::string(Name) + " immediate is out of range"); + } + return {}; +} + +[[nodiscard]] Expected<void> requireUnsigned(std::int64_t Value, unsigned Bits, + std::string_view Name) { + if (!fitsUnsigned(Value, Bits)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + std::string(Name) + " immediate is out of range"); + } + return {}; +} + +[[nodiscard]] Expected<void> requireRoundingMode(std::int64_t Value) { + if ((Value >= 0 && Value <= 4) || Value == 7) + return {}; + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V rounding mode is not an ISA-defined value"); +} + +[[nodiscard]] Expected<void> requireAligned(std::int64_t Value, std::uint64_t Alignment, + std::string_view Name) { + if (Value % static_cast<std::int64_t>(Alignment) != 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + std::string(Name) + " immediate is not aligned"); + } + return {}; +} + +[[nodiscard]] Expected<std::uint32_t> expressionTargetKind(const mc::MCOperand &Operand) { + const mc::MCExprRef *Expression = Operand.expressionValue(); + if (Expression == nullptr) + return 0U; + if (!*Expression) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V instruction has a null expression operand"); + } + auto Value = mc::evaluateAsRelocatable(**Expression); + if (!Value) + return std::unexpected(Value.error()); + return Value->TargetKind; +} + +[[nodiscard]] Expected<std::int64_t> immediateOrFixup(const mc::MCInst &Instruction, + std::size_t Index, mc::MCFixupKind Kind, + bool PCRelative, + mc::MCEncodedInstruction &Result) { + if (Index >= Instruction.operands().size()) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V encoding references an absent immediate operand"); + } + const mc::MCOperand &Operand = Instruction.operands()[Index]; + if (const std::int64_t *Immediate = Operand.immediateValue(); Immediate != nullptr) + return *Immediate; + const mc::MCExprRef *Expression = Operand.expressionValue(); + if (Expression == nullptr || !*Expression) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V encoding requires an immediate or expression operand"); + } + if (const auto Absolute = (*Expression)->evaluateAbsolute()) + return *Absolute; + if (Kind == mc::fixup_kind::None) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V instruction does not permit a symbolic immediate here"); + } + Result.Fixups.push_back(mc::MCFixup{.Offset = 0, + .Value = *Expression, + .Kind = Kind, + .PCRelative = PCRelative, + .LinkerRelaxable = false}); + return 0; +} + +[[nodiscard]] Expected<mc::MCFixupKind> uFixupKind(const mc::MCOperand &Operand) { + auto Kind = expressionTargetKind(Operand); + if (!Kind) + return std::unexpected(Kind.error()); + if (*Kind == 0) + return fixupKind(RISCVFixupKind::High20); + if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeHigh)) + return fixupKind(RISCVFixupKind::PCRelativeHigh20); + if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::CallPLT)) + return fixupKind(RISCVFixupKind::CallPLT); + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V U-type operand has an incompatible target expression"); +} + +[[nodiscard]] Expected<mc::MCFixupKind> lowFixupKind(const mc::MCOperand &Operand, bool Store) { + auto Kind = expressionTargetKind(Operand); + if (!Kind) + return std::unexpected(Kind.error()); + if (*Kind == 0) + return fixupKind(Store ? RISCVFixupKind::Low12S : RISCVFixupKind::Low12I); + if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeLow)) { + return fixupKind(Store ? RISCVFixupKind::PCRelativeLow12S : RISCVFixupKind::PCRelativeLow12I); + } + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V low immediate has an incompatible target expression"); +} + +[[nodiscard]] Expected<void> requirePlainExpression(const mc::MCOperand &Operand, + std::string_view Name) { + auto Kind = expressionTargetKind(Operand); + if (!Kind) + return std::unexpected(Kind.error()); + if (*Kind != 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + std::string(Name) + " does not accept a target expression modifier"); + } + return {}; +} + +[[nodiscard]] std::uint32_t encodeBranchImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint32_t>(Value); + return ((Bits >> 12U) & 1U) << 31U | ((Bits >> 5U) & 0x3fU) << 25U | ((Bits >> 1U) & 0xfU) << 8U | + ((Bits >> 11U) & 1U) << 7U; +} + +[[nodiscard]] std::uint32_t encodeJALImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint32_t>(Value); + return ((Bits >> 20U) & 1U) << 31U | ((Bits >> 1U) & 0x3ffU) << 21U | + ((Bits >> 11U) & 1U) << 20U | ((Bits >> 12U) & 0xffU) << 12U; +} + +[[nodiscard]] std::uint16_t encodeRVCJumpImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint16_t>(Value); + return static_cast<std::uint16_t>(((Bits >> 11U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 11U | + ((Bits >> 8U) & 3U) << 9U | ((Bits >> 10U) & 1U) << 8U | + ((Bits >> 6U) & 1U) << 7U | ((Bits >> 7U) & 1U) << 6U | + ((Bits >> 1U) & 7U) << 3U | ((Bits >> 5U) & 1U) << 2U); +} + +[[nodiscard]] std::uint16_t encodeRVCBranchImmediate(std::int64_t Value) noexcept { + const auto Bits = static_cast<std::uint16_t>(Value); + return static_cast<std::uint16_t>(((Bits >> 8U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 10U | + ((Bits >> 6U) & 3U) << 5U | ((Bits >> 1U) & 3U) << 3U | + ((Bits >> 5U) & 1U) << 2U); +} + +[[nodiscard]] Expected<std::uint32_t> encodeRType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly) { + const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value()); + std::size_t RegisterCount = 0; + bool HasRoundingMode = false; + switch (Format) { + case AssemblyFormat::RD_RS1_RS2: + case AssemblyFormat::FRD_FRS1_FRS2: + case AssemblyFormat::RD_FRS1_FRS2: + RegisterCount = 3; + break; + case AssemblyFormat::FRD_FRS1_FRS2_RM: + RegisterCount = 3; + HasRoundingMode = true; + break; + case AssemblyFormat::FRD_FRS1_RM: + case AssemblyFormat::RD_FRS1_RM: + case AssemblyFormat::FRD_RS1_RM: + RegisterCount = 2; + HasRoundingMode = true; + break; + case AssemblyFormat::RD_FRS1: + case AssemblyFormat::FRD_RS1: + RegisterCount = 2; + break; + default: + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "unsupported RISC-V R-type assembly format"); + } + auto Count = requireOperandCount(Instruction, RegisterCount + (HasRoundingMode ? 1U : 0U)); + if (!Count) + return std::unexpected(Count.error()); + + std::uint32_t Encoding = Assembly.Encoding & ~std::uint32_t{0x000f8f80}; + auto Destination = registerEncoding(Instruction, 0, Target); + auto Source1 = registerEncoding(Instruction, 1, Target); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Source1) + return std::unexpected(Source1.error()); + Encoding |= *Destination << 7U | *Source1 << 15U; + if (RegisterCount == 3) { + auto Source2 = registerEncoding(Instruction, 2, Target); + if (!Source2) + return std::unexpected(Source2.error()); + Encoding = (Encoding & ~std::uint32_t{0x01f00000}) | *Source2 << 20U; + } + return Encoding; +} + +[[nodiscard]] Expected<std::uint32_t> encodeRTypeWithResult(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Encoding = encodeRType(Instruction, Target, Assembly); + if (!Encoding) + return std::unexpected(Encoding.error()); + const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value()); + std::size_t ModeIndex = 0; + switch (Format) { + case AssemblyFormat::FRD_FRS1_FRS2_RM: + ModeIndex = 3; + break; + case AssemblyFormat::FRD_FRS1_RM: + case AssemblyFormat::RD_FRS1_RM: + case AssemblyFormat::FRD_RS1_RM: + ModeIndex = 2; + break; + default: + return *Encoding; + } + auto Mode = immediateOrFixup(Instruction, ModeIndex, mc::fixup_kind::None, false, Result); + if (!Mode) + return std::unexpected(Mode.error()); + auto Range = requireRoundingMode(*Mode); + if (!Range) + return std::unexpected(Range.error()); + return (*Encoding & ~std::uint32_t{0x7000}) | static_cast<std::uint32_t>(*Mode) << 12U; +} + +[[nodiscard]] Expected<std::uint32_t> encodeIType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value()); + if (Format == AssemblyFormat::NONE) { + auto Count = requireOperandCount(Instruction, 0); + if (!Count) + return std::unexpected(Count.error()); + return Assembly.Encoding; + } + if (Format == AssemblyFormat::IMM_IMM) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Predecessor = immediateOrFixup(Instruction, 0, mc::fixup_kind::None, false, Result); + auto Successor = immediateOrFixup(Instruction, 1, mc::fixup_kind::None, false, Result); + if (!Predecessor) + return std::unexpected(Predecessor.error()); + if (!Successor) + return std::unexpected(Successor.error()); + auto PredRange = requireUnsigned(*Predecessor, 4, "RISC-V fence predecessor"); + auto SuccRange = requireUnsigned(*Successor, 4, "RISC-V fence successor"); + if (!PredRange) + return std::unexpected(PredRange.error()); + if (!SuccRange) + return std::unexpected(SuccRange.error()); + return (Assembly.Encoding & ~std::uint32_t{0x0ff00000}) | + static_cast<std::uint32_t>(*Predecessor) << 24U | + static_cast<std::uint32_t>(*Successor) << 20U; + } + if (Format != AssemblyFormat::RD_RS1_IMM && Format != AssemblyFormat::RD_OFFSET_RS1 && + Format != AssemblyFormat::FRD_OFFSET_RS1) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "unsupported RISC-V I-type assembly format"); + } + auto Count = requireOperandCount(Instruction, 3); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + auto Source = registerEncoding(Instruction, 1, Target); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Source) + return std::unexpected(Source.error()); + std::uint32_t Encoding = + (Assembly.Encoding & ~std::uint32_t{0x000f8f80}) | *Destination << 7U | *Source << 15U; + + const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value()); + const bool Shift64 = Opcode == InstructionOpcode::SLLI || Opcode == InstructionOpcode::SRLI || + Opcode == InstructionOpcode::SRAI; + const bool Shift32 = Opcode == InstructionOpcode::SLLIW || Opcode == InstructionOpcode::SRLIW || + Opcode == InstructionOpcode::SRAIW; + if (Shift64 || Shift32) { + auto Immediate = immediateOrFixup(Instruction, 2, mc::fixup_kind::None, false, Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + auto Range = requireUnsigned(*Immediate, Shift64 ? 6U : 5U, "RISC-V shift"); + if (!Range) + return std::unexpected(Range.error()); + const std::uint32_t Mask = Shift64 ? 0x03f00000U : 0x01f00000U; + return (Encoding & ~Mask) | static_cast<std::uint32_t>(*Immediate) << 20U; + } + + auto Kind = lowFixupKind(Instruction.operands()[2], false); + if (!Kind) + return std::unexpected(Kind.error()); + auto Immediate = immediateOrFixup(Instruction, 2, *Kind, + *Kind == fixupKind(RISCVFixupKind::PCRelativeLow12I), Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + if (Instruction.operands()[2].expressionValue() == nullptr) { + auto Range = requireSigned(*Immediate, 12, "RISC-V I-type"); + if (!Range) + return std::unexpected(Range.error()); + } + return (Encoding & ~std::uint32_t{0xfff00000}) | (static_cast<std::uint32_t>(*Immediate) & 0xfffU) + << 20U; +} + +[[nodiscard]] Expected<std::uint32_t> encodeSType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 3); + if (!Count) + return std::unexpected(Count.error()); + auto Source2 = registerEncoding(Instruction, 0, Target); + auto Source1 = registerEncoding(Instruction, 1, Target); + if (!Source2) + return std::unexpected(Source2.error()); + if (!Source1) + return std::unexpected(Source1.error()); + auto Kind = lowFixupKind(Instruction.operands()[2], true); + if (!Kind) + return std::unexpected(Kind.error()); + auto Immediate = immediateOrFixup(Instruction, 2, *Kind, + *Kind == fixupKind(RISCVFixupKind::PCRelativeLow12S), Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + if (Instruction.operands()[2].expressionValue() == nullptr) { + auto Range = requireSigned(*Immediate, 12, "RISC-V S-type"); + if (!Range) + return std::unexpected(Range.error()); + } + const std::uint32_t Bits = static_cast<std::uint32_t>(*Immediate) & 0xfffU; + return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Source1 << 15U | *Source2 << 20U | + ((Bits >> 5U) & 0x7fU) << 25U | (Bits & 0x1fU) << 7U; +} + +[[nodiscard]] Expected<std::uint32_t> encodeBType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 3); + if (!Count) + return std::unexpected(Count.error()); + auto Source1 = registerEncoding(Instruction, 0, Target); + auto Source2 = registerEncoding(Instruction, 1, Target); + if (!Source1) + return std::unexpected(Source1.error()); + if (!Source2) + return std::unexpected(Source2.error()); + auto Plain = requirePlainExpression(Instruction.operands()[2], "RISC-V branch"); + if (!Plain) + return std::unexpected(Plain.error()); + auto Immediate = + immediateOrFixup(Instruction, 2, fixupKind(RISCVFixupKind::Branch), true, Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + if (Instruction.operands()[2].expressionValue() == nullptr && + (!fitsSigned(*Immediate, 13) || (*Immediate & 1) != 0)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V branch displacement is out of range or unaligned"); + } + return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Source1 << 15U | *Source2 << 20U | + encodeBranchImmediate(*Immediate); +} + +[[nodiscard]] Expected<std::uint32_t> encodeUType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + if (!Destination) + return std::unexpected(Destination.error()); + auto Kind = uFixupKind(Instruction.operands()[1]); + if (!Kind) + return std::unexpected(Kind.error()); + const bool PCRelative = *Kind == fixupKind(RISCVFixupKind::PCRelativeHigh20) || + *Kind == fixupKind(RISCVFixupKind::CallPLT); + auto Immediate = immediateOrFixup(Instruction, 1, *Kind, PCRelative, Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + if (Instruction.operands()[1].expressionValue() == nullptr) { + auto Range = requireSigned(*Immediate, 20, "RISC-V U-type"); + if (!Range) + return std::unexpected(Range.error()); + } + return (Assembly.Encoding & 0x7fU) | *Destination << 7U | + (static_cast<std::uint32_t>(*Immediate) & 0xfffffU) << 12U; +} + +[[nodiscard]] Expected<std::uint32_t> encodeJType(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + if (!Destination) + return std::unexpected(Destination.error()); + auto Plain = requirePlainExpression(Instruction.operands()[1], "RISC-V JAL"); + if (!Plain) + return std::unexpected(Plain.error()); + auto Immediate = immediateOrFixup(Instruction, 1, fixupKind(RISCVFixupKind::JAL), true, Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + if (Instruction.operands()[1].expressionValue() == nullptr && + (!fitsSigned(*Immediate, 21) || (*Immediate & 1) != 0)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V JAL displacement is out of range or unaligned"); + } + return (Assembly.Encoding & 0x7fU) | *Destination << 7U | encodeJALImmediate(*Immediate); +} + +[[nodiscard]] Expected<std::uint32_t> encodeSystem(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value()); + if (Format == AssemblyFormat::NONE) { + auto Count = requireOperandCount(Instruction, 0); + if (!Count) + return std::unexpected(Count.error()); + return Assembly.Encoding; + } + if (Format != AssemblyFormat::RD_CSR_RS1 && Format != AssemblyFormat::RD_CSR_IMM) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "unsupported RISC-V system assembly format"); + } + auto Count = requireOperandCount(Instruction, 3); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + if (!Destination) + return std::unexpected(Destination.error()); + auto CSR = immediateOrFixup(Instruction, 1, mc::fixup_kind::None, false, Result); + if (!CSR) + return std::unexpected(CSR.error()); + auto CSRRange = requireUnsigned(*CSR, 12, "RISC-V CSR"); + if (!CSRRange) + return std::unexpected(CSRRange.error()); + std::uint32_t Source = 0; + if (Format == AssemblyFormat::RD_CSR_RS1) { + auto Register = registerEncoding(Instruction, 2, Target); + if (!Register) + return std::unexpected(Register.error()); + Source = *Register; + } else { + auto Immediate = immediateOrFixup(Instruction, 2, mc::fixup_kind::None, false, Result); + if (!Immediate) + return std::unexpected(Immediate.error()); + auto Range = requireUnsigned(*Immediate, 5, "RISC-V CSR immediate"); + if (!Range) + return std::unexpected(Range.error()); + Source = static_cast<std::uint32_t>(*Immediate); + } + return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Destination << 7U | Source << 15U | + static_cast<std::uint32_t>(*CSR) << 20U; +} + +[[nodiscard]] Expected<std::uint32_t> encodeAMO(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly) { + const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value()); + const bool IsLoadReserved = Format == AssemblyFormat::RD_PAREN_RS1; + if (!IsLoadReserved && Format != AssemblyFormat::RD_RS2_PAREN_RS1) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "unsupported RISC-V atomic assembly format"); + } + auto Count = requireOperandCount(Instruction, IsLoadReserved ? 2U : 3U); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + auto Source1 = registerEncoding(Instruction, IsLoadReserved ? 1U : 2U, Target); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Source1) + return std::unexpected(Source1.error()); + std::uint32_t Encoding = + (Assembly.Encoding & ~std::uint32_t{0x000f8f80}) | *Destination << 7U | *Source1 << 15U; + if (!IsLoadReserved) { + auto Source2 = registerEncoding(Instruction, 1, Target); + if (!Source2) + return std::unexpected(Source2.error()); + Encoding = (Encoding & ~std::uint32_t{0x01f00000}) | *Source2 << 20U; + } + return Encoding; +} + +[[nodiscard]] Expected<std::uint32_t> encodeR4(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 5); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + auto Source1 = registerEncoding(Instruction, 1, Target); + auto Source2 = registerEncoding(Instruction, 2, Target); + auto Source3 = registerEncoding(Instruction, 3, Target); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Source1) + return std::unexpected(Source1.error()); + if (!Source2) + return std::unexpected(Source2.error()); + if (!Source3) + return std::unexpected(Source3.error()); + auto Mode = immediateOrFixup(Instruction, 4, mc::fixup_kind::None, false, Result); + if (!Mode) + return std::unexpected(Mode.error()); + auto Range = requireRoundingMode(*Mode); + if (!Range) + return std::unexpected(Range.error()); + return (Assembly.Encoding & ~std::uint32_t{0xf9ffff80}) | *Destination << 7U | + static_cast<std::uint32_t>(*Mode) << 12U | *Source1 << 15U | *Source2 << 20U | + *Source3 << 27U; +} + +[[nodiscard]] Expected<std::uint16_t> encodeCompressed(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value()); + std::uint16_t Encoding = static_cast<std::uint16_t>(Assembly.Encoding); + const auto Immediate = [&](std::size_t Index, mc::MCFixupKind Kind = mc::fixup_kind::None, + bool PCRelative = false) { + return immediateOrFixup(Instruction, Index, Kind, PCRelative, Result); + }; + + if (Opcode == InstructionOpcode::C_ADDI4SPN) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = compactRegisterEncoding(Instruction, 0, Target); + auto Value = Immediate(1); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Value) + return std::unexpected(Value.error()); + if (!fitsUnsigned(*Value, 10) || *Value == 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "C.ADDI4SPN immediate is out of range or zero"); + } + auto Alignment = requireAligned(*Value, 4, "C.ADDI4SPN"); + if (!Alignment) + return std::unexpected(Alignment.error()); + const auto Bits = static_cast<std::uint16_t>(*Value); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | + ((Bits >> 4U) & 3U) << 11U | ((Bits >> 6U) & 0xfU) << 7U | + ((Bits >> 2U) & 1U) << 6U | ((Bits >> 3U) & 1U) << 5U | + *Destination << 2U); + } + + const bool CompactDoubleLoad = + Opcode == InstructionOpcode::C_FLD || Opcode == InstructionOpcode::C_LD; + const bool CompactWordLoad = Opcode == InstructionOpcode::C_LW; + const bool CompactDoubleStore = + Opcode == InstructionOpcode::C_FSD || Opcode == InstructionOpcode::C_SD; + const bool CompactWordStore = Opcode == InstructionOpcode::C_SW; + if (CompactDoubleLoad || CompactWordLoad || CompactDoubleStore || CompactWordStore) { + auto Count = requireOperandCount(Instruction, 3); + if (!Count) + return std::unexpected(Count.error()); + auto ValueRegister = compactRegisterEncoding(Instruction, 0, Target); + auto Base = compactRegisterEncoding(Instruction, 1, Target); + auto Offset = Immediate(2); + if (!ValueRegister) + return std::unexpected(ValueRegister.error()); + if (!Base) + return std::unexpected(Base.error()); + if (!Offset) + return std::unexpected(Offset.error()); + const bool IsDouble = CompactDoubleLoad || CompactDoubleStore; + auto Range = requireUnsigned(*Offset, IsDouble ? 8U : 7U, "compressed load/store"); + if (!Range) + return std::unexpected(Range.error()); + auto Alignment = requireAligned(*Offset, IsDouble ? 8U : 4U, "compressed load/store"); + if (!Alignment) + return std::unexpected(Alignment.error()); + const auto Bits = static_cast<std::uint16_t>(*Offset); + std::uint16_t ImmediateBits = static_cast<std::uint16_t>(((Bits >> 3U) & 7U) << 10U); + ImmediateBits |= + IsDouble + ? static_cast<std::uint16_t>(((Bits >> 6U) & 3U) << 5U) + : static_cast<std::uint16_t>(((Bits >> 2U) & 1U) << 6U | ((Bits >> 6U) & 1U) << 5U); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits | + *Base << 7U | *ValueRegister << 2U); + } + + const bool CI = Opcode == InstructionOpcode::C_ADDI || Opcode == InstructionOpcode::C_ADDIW || + Opcode == InstructionOpcode::C_LI || Opcode == InstructionOpcode::C_LUI || + Opcode == InstructionOpcode::C_SLLI; + if (CI) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Register = registerEncoding(Instruction, 0, Target); + auto Value = Immediate(1); + if (!Register) + return std::unexpected(Register.error()); + if (!Value) + return std::unexpected(Value.error()); + const bool IsShift = Opcode == InstructionOpcode::C_SLLI; + auto Range = + IsShift ? requireUnsigned(*Value, 6, "C.SLLI") : requireSigned(*Value, 6, "compressed CI"); + if (!Range) + return std::unexpected(Range.error()); + if (Opcode == InstructionOpcode::C_LUI && *Value == 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "C.LUI immediate must be nonzero"); + } + const auto Bits = static_cast<std::uint16_t>(*Value); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | + ((Bits >> 5U) & 1U) << 12U | *Register << 7U | + (Bits & 0x1fU) << 2U); + } + + if (Opcode == InstructionOpcode::C_ADDI16SP) { + auto Count = requireOperandCount(Instruction, 1); + if (!Count) + return std::unexpected(Count.error()); + auto Value = Immediate(0); + if (!Value) + return std::unexpected(Value.error()); + if (!fitsSigned(*Value, 10) || *Value == 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "C.ADDI16SP immediate is out of range or zero"); + } + auto Alignment = requireAligned(*Value, 16, "C.ADDI16SP"); + if (!Alignment) + return std::unexpected(Alignment.error()); + const auto Bits = static_cast<std::uint16_t>(*Value); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x107c}) | + ((Bits >> 9U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 6U | + ((Bits >> 6U) & 1U) << 5U | ((Bits >> 7U) & 3U) << 3U | + ((Bits >> 5U) & 1U) << 2U); + } + + const bool CompactShift = + Opcode == InstructionOpcode::C_SRLI || Opcode == InstructionOpcode::C_SRAI; + if (CompactShift || Opcode == InstructionOpcode::C_ANDI) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Register = compactRegisterEncoding(Instruction, 0, Target); + auto Value = Immediate(1); + if (!Register) + return std::unexpected(Register.error()); + if (!Value) + return std::unexpected(Value.error()); + auto Range = CompactShift ? requireUnsigned(*Value, 6, "compressed shift") + : requireSigned(*Value, 6, "C.ANDI"); + if (!Range) + return std::unexpected(Range.error()); + const auto Bits = static_cast<std::uint16_t>(*Value); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x13fc}) | + ((Bits >> 5U) & 1U) << 12U | *Register << 7U | + (Bits & 0x1fU) << 2U); + } + + const bool CompactALU = + Opcode == InstructionOpcode::C_SUB || Opcode == InstructionOpcode::C_XOR || + Opcode == InstructionOpcode::C_OR || Opcode == InstructionOpcode::C_AND || + Opcode == InstructionOpcode::C_SUBW || Opcode == InstructionOpcode::C_ADDW; + if (CompactALU) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = compactRegisterEncoding(Instruction, 0, Target); + auto Source = compactRegisterEncoding(Instruction, 1, Target); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Source) + return std::unexpected(Source.error()); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x039c}) | *Destination << 7U | + *Source << 2U); + } + + if (Opcode == InstructionOpcode::C_J) { + auto Count = requireOperandCount(Instruction, 1); + if (!Count) + return std::unexpected(Count.error()); + auto Plain = requirePlainExpression(Instruction.operands()[0], "C.J"); + if (!Plain) + return std::unexpected(Plain.error()); + auto Value = Immediate(0, fixupKind(RISCVFixupKind::RVCJump), true); + if (!Value) + return std::unexpected(Value.error()); + if (Instruction.operands()[0].expressionValue() == nullptr && + (!fitsSigned(*Value, 12) || (*Value & 1) != 0)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "C.J displacement is out of range or unaligned"); + } + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | + encodeRVCJumpImmediate(*Value)); + } + + if (Opcode == InstructionOpcode::C_BEQZ || Opcode == InstructionOpcode::C_BNEZ) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Source = compactRegisterEncoding(Instruction, 0, Target); + if (!Source) + return std::unexpected(Source.error()); + auto Plain = requirePlainExpression(Instruction.operands()[1], "compressed branch"); + if (!Plain) + return std::unexpected(Plain.error()); + auto Value = Immediate(1, fixupKind(RISCVFixupKind::RVCBranch), true); + if (!Value) + return std::unexpected(Value.error()); + if (Instruction.operands()[1].expressionValue() == nullptr && + (!fitsSigned(*Value, 9) || (*Value & 1) != 0)) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "compressed branch displacement is out of range or unaligned"); + } + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | *Source << 7U | + encodeRVCBranchImmediate(*Value)); + } + + const bool StackDoubleLoad = + Opcode == InstructionOpcode::C_FLDSP || Opcode == InstructionOpcode::C_LDSP; + const bool StackWordLoad = Opcode == InstructionOpcode::C_LWSP; + if (StackDoubleLoad || StackWordLoad) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Destination = registerEncoding(Instruction, 0, Target); + auto Offset = Immediate(1); + if (!Destination) + return std::unexpected(Destination.error()); + if (!Offset) + return std::unexpected(Offset.error()); + auto Range = requireUnsigned(*Offset, StackDoubleLoad ? 9U : 8U, "stack load"); + if (!Range) + return std::unexpected(Range.error()); + auto Alignment = requireAligned(*Offset, StackDoubleLoad ? 8U : 4U, "stack load"); + if (!Alignment) + return std::unexpected(Alignment.error()); + const auto Bits = static_cast<std::uint16_t>(*Offset); + const std::uint16_t ImmediateBits = + StackDoubleLoad + ? static_cast<std::uint16_t>(((Bits >> 5U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 5U | + ((Bits >> 6U) & 7U) << 2U) + : static_cast<std::uint16_t>(((Bits >> 5U) & 1U) << 12U | ((Bits >> 2U) & 7U) << 4U | + ((Bits >> 6U) & 3U) << 2U); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits | + *Destination << 7U); + } + + const bool CRSingle = Opcode == InstructionOpcode::C_JR || Opcode == InstructionOpcode::C_JALR; + const bool CRDouble = Opcode == InstructionOpcode::C_MV || Opcode == InstructionOpcode::C_ADD; + if (CRSingle || CRDouble) { + auto Count = requireOperandCount(Instruction, CRSingle ? 1U : 2U); + if (!Count) + return std::unexpected(Count.error()); + auto First = registerEncoding(Instruction, 0, Target); + if (!First) + return std::unexpected(First.error()); + Encoding = static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x0f80}) | *First << 7U); + if (CRDouble) { + auto Second = registerEncoding(Instruction, 1, Target); + if (!Second) + return std::unexpected(Second.error()); + Encoding = static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x007c}) | *Second << 2U); + } + return Encoding; + } + + if (Opcode == InstructionOpcode::C_EBREAK) { + auto Count = requireOperandCount(Instruction, 0); + if (!Count) + return std::unexpected(Count.error()); + return Encoding; + } + + const bool StackDoubleStore = + Opcode == InstructionOpcode::C_FSDSP || Opcode == InstructionOpcode::C_SDSP; + const bool StackWordStore = Opcode == InstructionOpcode::C_SWSP; + if (StackDoubleStore || StackWordStore) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto Source = registerEncoding(Instruction, 0, Target); + auto Offset = Immediate(1); + if (!Source) + return std::unexpected(Source.error()); + if (!Offset) + return std::unexpected(Offset.error()); + auto Range = requireUnsigned(*Offset, StackDoubleStore ? 9U : 8U, "stack store"); + if (!Range) + return std::unexpected(Range.error()); + auto Alignment = requireAligned(*Offset, StackDoubleStore ? 8U : 4U, "stack store"); + if (!Alignment) + return std::unexpected(Alignment.error()); + const auto Bits = static_cast<std::uint16_t>(*Offset); + const std::uint16_t ImmediateBits = + StackDoubleStore + ? static_cast<std::uint16_t>(((Bits >> 3U) & 7U) << 10U | ((Bits >> 6U) & 7U) << 7U) + : static_cast<std::uint16_t>(((Bits >> 2U) & 0xfU) << 9U | ((Bits >> 6U) & 3U) << 7U); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits | + *Source << 2U); + } + + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "unsupported compressed RISC-V instruction"); +} + +void appendLittleEndian(mc::MCEncodedInstruction &Result, std::uint32_t Encoding, + std::uint8_t Size) { + Result.Bytes.reserve(Size); + for (std::uint8_t Index = 0; Index < Size; ++Index) + Result.Bytes.push_back(static_cast<std::uint8_t>(Encoding >> (Index * 8U))); +} + +} // namespace + +Expected<mc::MCEncodedInstruction> +RISCVMCCodeEmitter::encodeInstruction(const mc::MCInst &Instruction) const { + if (!Instruction.opcode().isValid()) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "cannot encode an invalid RISC-V MC opcode"); + } + const Opcode OpcodeValue = Opcode::fromValue(Instruction.opcode().value()); + const InstructionDescriptor *Descriptor = Target->instructionDescriptor(OpcodeValue); + const AssemblyInstructionInfo *Assembly = assemblyInstruction(OpcodeValue); + if (Descriptor == nullptr || Assembly == nullptr || Assembly->Encoding == 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V instruction has no binary encoding description"); + } + auto Registers = validateRegisterOperands(Instruction, *Descriptor, *Target); + if (!Registers) + return std::unexpected(Registers.error()); + + mc::MCEncodedInstruction Result; + const auto Category = static_cast<EncodingCategory>(Descriptor->EncodingCategory.value()); + Expected<std::uint32_t> Encoding = makeUnexpected(ErrorCode::InstructionEncodingFailed, + "RISC-V instruction has no encoding category"); + switch (Category) { + case EncodingCategory::R: + Encoding = encodeRTypeWithResult(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::I: + Encoding = encodeIType(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::S: + Encoding = encodeSType(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::B: + Encoding = encodeBType(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::U: + Encoding = encodeUType(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::J: + Encoding = encodeJType(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::SYSTEM: + Encoding = encodeSystem(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::AMO: + Encoding = encodeAMO(Instruction, *Target, *Assembly); + break; + case EncodingCategory::R4: + Encoding = encodeR4(Instruction, *Target, *Assembly, Result); + break; + case EncodingCategory::C: { + auto Compressed = encodeCompressed(Instruction, *Target, *Assembly, Result); + if (!Compressed) + return std::unexpected(Compressed.error()); + appendLittleEndian(Result, *Compressed, 2); + return Result; + } + case EncodingCategory::None: + break; + } + if (!Encoding) + return std::unexpected(Encoding.error()); + appendLittleEndian(Result, *Encoding, 4); + return Result; +} + +} // namespace rcc::riscv diff --git a/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp b/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp index 4e8d5ec..19b1b11 100644 --- a/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp +++ b/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp @@ -22,6 +22,7 @@ #include "rcc/MC/MCStreamer.h" #include "rcc/MC/MCSymbol.h" #include "rcc/Target/RISCV/RISCVTarget.h" +#include "rcc/Target/RISCV/RISCVTargetRelocationKinds.h" #include <algorithm> #include <bit> @@ -53,6 +54,15 @@ struct TypeLayout final { std::uint64_t Alignment = 1; }; +[[nodiscard]] Expected<std::uint8_t> targetRelocationSize(TargetRelocationKindID Kind) { + if (Kind == targetRelocationKind(RISCVTargetRelocationKind::Absolute32)) + return 4; + if (Kind == targetRelocationKind(RISCVTargetRelocationKind::Absolute64)) + return 8; + return makeUnexpected(ErrorCode::Unsupported, + "RV64GC target constant has an unknown relocation kind"); +} + [[nodiscard]] Expected<std::uint64_t> checkedAdd(std::uint64_t Left, std::uint64_t Right) { std::uint64_t Result = 0; if (__builtin_add_overflow(Left, Right, &Result)) @@ -612,6 +622,80 @@ struct TypeLayout final { return {}; } +[[nodiscard]] Expected<void> emitTargetBytes(std::span<const std::byte> Bytes, + mc::MCStreamer &Streamer) { + if (Bytes.empty()) + return {}; + std::vector<std::uint8_t> Storage; + Storage.reserve(Bytes.size()); + for (const std::byte Byte : Bytes) + Storage.push_back(std::to_integer<std::uint8_t>(Byte)); + return Streamer.emitBytes(Storage); +} + +[[nodiscard]] Expected<void> emitTargetConstantImpl(const TargetConstant &Constant, + MachineMCContext &Context, + mc::MCStreamer &Streamer) { + auto Emission = Constant.emit(); + if (!Emission) + return std::unexpected(Emission.error()); + auto DeclaredKind = Constant.relocationKind(); + if (!DeclaredKind) + return std::unexpected(DeclaredKind.error()); + if (Emission->Fixups.empty() != !DeclaredKind->has_value()) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "RV64GC target constant relocation declaration is inconsistent"); + } + if (Emission->Fixups.empty()) + return emitTargetBytes(Emission->Bytes, Streamer); + + std::vector<const TargetConstantFixup *> Fixups; + Fixups.reserve(Emission->Fixups.size()); + for (const TargetConstantFixup &Fixup : Emission->Fixups) { + if (Fixup.Kind != **DeclaredKind) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "RV64GC target constant contains mixed relocation kinds"); + } + Fixups.push_back(&Fixup); + } + std::ranges::sort(Fixups, {}, [](const TargetConstantFixup *Fixup) { return Fixup->Offset; }); + + std::uint64_t Cursor = 0; + for (const TargetConstantFixup *Fixup : Fixups) { + auto Size = targetRelocationSize(Fixup->Kind); + if (!Size) + return std::unexpected(Size.error()); + if (Fixup->Offset < Cursor || Fixup->Offset > Emission->Bytes.size() || + *Size > Emission->Bytes.size() - static_cast<std::size_t>(Fixup->Offset)) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "RV64GC target constant relocation storage is invalid"); + } + auto RawBytes = emitTargetBytes(std::span<const std::byte>(Emission->Bytes) + .subspan(static_cast<std::size_t>(Cursor), + static_cast<std::size_t>(Fixup->Offset - Cursor)), + Streamer); + if (!RawBytes) + return std::unexpected(RawBytes.error()); + + auto Symbol = Context.symbol(Fixup->Symbol); + if (!Symbol) + return std::unexpected(Symbol.error()); + auto Expression = mc::MCExpr::symbol(std::move(*Symbol)); + if (!Expression) + return std::unexpected(Expression.error()); + auto WithAddend = addOffset(std::move(*Expression), Fixup->Addend); + if (!WithAddend) + return std::unexpected(WithAddend.error()); + auto Value = Streamer.emitValue(std::move(*WithAddend), *Size); + if (!Value) + return std::unexpected(Value.error()); + Cursor = Fixup->Offset + *Size; + } + return emitTargetBytes( + std::span<const std::byte>(Emission->Bytes).subspan(static_cast<std::size_t>(Cursor)), + Streamer); +} + [[nodiscard]] Expected<void> emitGlobalInitializerImpl(const GlobalInitializer &Initializer, MachineMCContext &Context, mc::MCStreamer &Streamer, @@ -722,18 +806,7 @@ struct TypeLayout final { const auto *Value = Initializer.getIf<TargetConstant>(); if (Value == nullptr) return makeUnexpected(ErrorCode::InternalError, "target initializer has no value"); - auto Emission = Value->emit(); - if (!Emission) - return std::unexpected(Emission.error()); - if (!Emission->Fixups.empty()) { - return makeUnexpected(ErrorCode::Unsupported, - "RV64GC target initializer fixups require native object emission"); - } - std::vector<std::uint8_t> Bytes; - Bytes.reserve(Emission->Bytes.size()); - for (const std::byte Byte : Emission->Bytes) - Bytes.push_back(std::to_integer<std::uint8_t>(Byte)); - return Streamer.emitBytes(Bytes); + return emitTargetConstantImpl(*Value, Context, Streamer); } case GlobalInitializer::Kind::AlignmentPadding: { const auto *Value = Initializer.getIf<GlobalAlignmentPadding>(); @@ -1090,20 +1163,9 @@ Expected<void> RISCVMCTargetLowering::emitGlobalInitializer(const GlobalInitiali } Expected<void> RISCVMCTargetLowering::emitTargetConstant(const TargetConstant &Constant, - MachineMCContext &, + MachineMCContext &Context, mc::MCStreamer &Streamer) const { - auto Emission = Constant.emit(); - if (!Emission) - return std::unexpected(Emission.error()); - if (!Emission->Fixups.empty()) { - return makeUnexpected(ErrorCode::Unsupported, - "RV64GC target-constant fixups require the native object stage"); - } - std::vector<std::uint8_t> Bytes; - Bytes.reserve(Emission->Bytes.size()); - for (const std::byte Byte : Emission->Bytes) - Bytes.push_back(std::to_integer<std::uint8_t>(Byte)); - return Streamer.emitBytes(Bytes); + return emitTargetConstantImpl(Constant, Context, Streamer); } Expected<void> RISCVMCTargetLowering::emitTargetJumpTable(const MachineFunction &Function, diff --git a/backend/lib/Target/RISCV/RISCVObjectFile.cpp b/backend/lib/Target/RISCV/RISCVObjectFile.cpp new file mode 100644 index 0000000..15d4980 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVObjectFile.cpp @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Target/RISCV/RISCVObjectFile.h" + +#include "rcc/CodeGen/AsmPrinter.h" +#include "rcc/CodeGen/CompilationUnit.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineMCContext.h" +#include "rcc/MC/ELFObjectWriter.h" +#include "rcc/MC/MCContext.h" +#include "rcc/MC/MCObjectStreamer.h" +#include "rcc/Target/RISCV/RISCVAsmBackend.h" +#include "rcc/Target/RISCV/RISCVMCCodeEmitter.h" +#include "rcc/Target/RISCV/RISCVMCTargetLowering.h" + +#include <cstdint> +#include <utility> +#include <vector> + +namespace rcc::riscv { +namespace { + +constexpr std::uint16_t EMRISCV = 243; +constexpr std::uint32_t SHTRISCVAttributes = 0x70000003; + +[[nodiscard]] AsmPrinterOptions printerOptions(ObjectEmissionOptions Options) noexcept { + return AsmPrinterOptions{ + .EmitFunctionDirectives = Options.EmitFunctionDirectives, + .EmitCFI = Options.EmitCFI, + .EmitBlockLabels = Options.EmitBlockLabels, + .EmitInstructionSymbols = true, + .VerifyInput = Options.VerifyInput, + }; +} + +[[nodiscard]] std::vector<std::uint8_t> attributesSection() { + constexpr char Architecture[] = "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_" + "zmmul1p0_zaamo1p0_zalrsc1p0"; + const std::uint32_t FilePayloadSize = 1U + sizeof(Architecture) + 2U; + const std::uint32_t VendorSize = 4U + 6U + 1U + 4U + FilePayloadSize; + std::vector<std::uint8_t> Bytes; + Bytes.reserve(1U + VendorSize); + const auto AppendU32 = [&Bytes](std::uint32_t Value) { + for (std::uint8_t Shift = 0; Shift < 32; Shift += 8) + Bytes.push_back(static_cast<std::uint8_t>(Value >> Shift)); + }; + Bytes.push_back('A'); + AppendU32(VendorSize); + Bytes.insert(Bytes.end(), {'r', 'i', 's', 'c', 'v', 0}); + Bytes.push_back(1); + AppendU32(5U + FilePayloadSize); + Bytes.push_back(5); + Bytes.insert(Bytes.end(), Architecture, Architecture + sizeof(Architecture)); + Bytes.push_back(4); + Bytes.push_back(16); + return Bytes; +} + +[[nodiscard]] mc::ELFObjectTargetInfo objectTargetInfo() { + mc::ELFObjectTargetInfo Info; + Info.Machine = EMRISCV; + Info.ExtraSections.push_back(mc::ELFExtraSection{ + .Name = ".riscv.attributes", + .Type = SHTRISCVAttributes, + .Flags = 0, + .Alignment = 1, + .EntrySize = 0, + .Contents = attributesSection(), + }); + return Info; +} + +struct ObjectEmissionContext final { + explicit ObjectEmissionContext(const TargetDescription &Target) + : MachineContext(Context), Lowering(Target), Emitter(Target), Writer(objectTargetInfo()), + Streamer(Emitter, Backend, Writer) { + mc::MCSectionDesc EHFrameDescription{ + .Name = ".eh_frame", + .Kind = mc::MCSectionKind::EHFrame, + .Flags = {mc::MCSectionFlag::Alloc}, + .Alignment = 8, + .EntrySize = 0, + .Group = {}, + .UniqueID = std::nullopt, + }; + auto EHFrame = Context.getOrCreateSection(std::move(EHFrameDescription)); + if (!EHFrame) { + Initialization = std::unexpected(EHFrame.error()); + return; + } + Initialization = Streamer.configureDwarfFrame(std::move(*EHFrame), + mc::MCDwarfFrameInfo{.CodeAlignment = 1, + .DataAlignment = -8, + .ReturnAddressRegister = 1, + .InitialCFARegister = 2, + .InitialCFAOffset = 0}); + } + + mc::MCContext Context; + MachineMCContext MachineContext; + RISCVMCTargetLowering Lowering; + RISCVMCCodeEmitter Emitter; + RISCVAsmBackend Backend; + mc::ELF64LEObjectWriter Writer; + mc::ELFObjectStreamer Streamer; + Expected<void> Initialization; +}; + +} // namespace + +Expected<std::vector<std::uint8_t>> emitObject(const CompilationUnit &Unit, + const TargetDescription &Target, + ObjectEmissionOptions Options) { + ObjectEmissionContext Context(Target); + if (!Context.Initialization) + return std::unexpected(Context.Initialization.error()); + AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer, + printerOptions(Options)); + auto Emitted = Printer.emitCompilationUnit(Unit); + if (!Emitted) + return std::unexpected(Emitted.error()); + return Context.Streamer.takeOutput(); +} + +Expected<std::vector<std::uint8_t>> emitObject(const MachineFunction &Function, + const TargetDescription &Target, + ObjectEmissionOptions Options) { + ObjectEmissionContext Context(Target); + if (!Context.Initialization) + return std::unexpected(Context.Initialization.error()); + AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer, + printerOptions(Options)); + auto Header = Context.Lowering.emitFileHeader(Context.MachineContext, Context.Streamer); + if (!Header) + return std::unexpected(Header.error()); + auto Emitted = Printer.emitFunction(Function); + if (!Emitted) + return std::unexpected(Emitted.error()); + auto Trailer = Context.Lowering.emitFileTrailer(Context.MachineContext, Context.Streamer); + if (!Trailer) + return std::unexpected(Trailer.error()); + auto Finished = Context.Streamer.finish(); + if (!Finished) + return std::unexpected(Finished.error()); + return Context.Streamer.takeOutput(); +} + +} // namespace rcc::riscv diff --git a/backend/lib/Target/RISCV/RISCVTargetConstant.cpp b/backend/lib/Target/RISCV/RISCVTargetConstant.cpp new file mode 100644 index 0000000..6fda900 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVTargetConstant.cpp @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/Target/RISCV/RISCVTargetConstant.h" + +#include "rcc/Target/RISCV/RISCVTargetRelocationKinds.h" + +#include <bit> +#include <charconv> +#include <cstddef> +#include <cstdint> +#include <string> +#include <string_view> +#include <system_error> +#include <utility> +#include <vector> + +namespace rcc::riscv { +namespace { + +[[nodiscard]] std::string_view kindSpelling(RISCVSymbolConstantKind Kind) noexcept { + switch (Kind) { + case RISCVSymbolConstantKind::GlobalValue: + return "global"; + case RISCVSymbolConstantKind::ExternalSymbol: + return "external"; + } + return {}; +} + +[[nodiscard]] Expected<RISCVSymbolConstantKind> parseKind(std::string_view Text) { + if (Text == "global") + return RISCVSymbolConstantKind::GlobalValue; + if (Text == "external") + return RISCVSymbolConstantKind::ExternalSymbol; + return makeUnexpected(ErrorCode::ParseError, "unknown RV64GC symbol constant kind"); +} + +void appendU64(std::vector<std::byte> &Bytes, std::uint64_t Value) { + for (std::uint8_t Shift = 0; Shift < 64; Shift += 8) + Bytes.push_back(static_cast<std::byte>(Value >> Shift)); +} + +[[nodiscard]] std::uint64_t readU64(std::span<const std::byte> Bytes) noexcept { + std::uint64_t Result = 0; + for (std::uint8_t Shift = 0; Shift < 64; Shift += 8) + Result |= std::to_integer<std::uint64_t>(Bytes[Shift / 8U]) << Shift; + return Result; +} + +} // namespace + +Expected<void> RISCVSymbolConstant::verify() const { + if (kindSpelling(ConstantKind).empty()) + return makeUnexpected(ErrorCode::VerificationError, "RV64GC symbol constant kind is invalid"); + if (SymbolName.empty() || SymbolName.find('\0') != std::string::npos) { + return makeUnexpected(ErrorCode::VerificationError, + "RV64GC symbol constant requires a valid symbol name"); + } + return {}; +} + +Expected<RISCVSymbolConstant> RISCVSymbolConstant::clone() const { + return RISCVSymbolConstant(ConstantKind, SymbolName, SymbolAddend); +} + +std::uint64_t RISCVSymbolConstant::stableHash() const noexcept { + constexpr std::uint64_t OffsetBasis = 14695981039346656037ULL; + constexpr std::uint64_t Prime = 1099511628211ULL; + std::uint64_t Hash = OffsetBasis; + const auto Mix = [&Hash](std::uint8_t Byte) { + Hash ^= Byte; + Hash *= Prime; + }; + Mix(static_cast<std::uint8_t>(ConstantKind)); + const std::uint64_t AddendBits = std::bit_cast<std::uint64_t>(SymbolAddend); + for (std::uint8_t Shift = 0; Shift < 64; Shift += 8) + Mix(static_cast<std::uint8_t>(AddendBits >> Shift)); + for (const char Character : SymbolName) + Mix(static_cast<unsigned char>(Character)); + return Hash; +} + +std::string RISCVSymbolConstant::print() const { + return std::string(kindSpelling(ConstantKind)) + "," + std::to_string(SymbolAddend) + "," + + SymbolName; +} + +Expected<std::vector<std::byte>> RISCVSymbolConstant::encode() const { + auto Verification = verify(); + if (!Verification) + return std::unexpected(Verification.error()); + std::vector<std::byte> Payload; + Payload.reserve(9U + SymbolName.size()); + Payload.push_back(static_cast<std::byte>(static_cast<std::uint8_t>(ConstantKind))); + appendU64(Payload, std::bit_cast<std::uint64_t>(SymbolAddend)); + for (const char Character : SymbolName) + Payload.push_back(static_cast<std::byte>(static_cast<unsigned char>(Character))); + return Payload; +} + +Expected<TargetConstantEmission> RISCVSymbolConstant::emit() const { + auto Verification = verify(); + if (!Verification) + return std::unexpected(Verification.error()); + TargetConstantEmission Emission; + Emission.Bytes.resize(8); + Emission.Fixups.push_back(TargetConstantFixup{ + .Offset = 0, + .Kind = targetRelocationKind(RISCVTargetRelocationKind::Absolute64), + .Symbol = SymbolName, + .Addend = SymbolAddend, + }); + return Emission; +} + +Alignment RISCVSymbolConstant::requiredAlignment() const noexcept { + return *Alignment::create(8); +} + +std::optional<TargetRelocationKindID> RISCVSymbolConstant::relocationKind() const noexcept { + return targetRelocationKind(RISCVTargetRelocationKind::Absolute64); +} + +Expected<RISCVSymbolConstant> RISCVSymbolConstant::parse(std::string_view Text) { + const std::size_t KindEnd = Text.find(','); + const std::size_t AddendEnd = + KindEnd == std::string_view::npos ? std::string_view::npos : Text.find(',', KindEnd + 1U); + if (KindEnd == std::string_view::npos || AddendEnd == std::string_view::npos) { + return makeUnexpected(ErrorCode::ParseError, + "RV64GC symbol constant must be 'kind,addend,symbol'"); + } + auto Kind = parseKind(Text.substr(0, KindEnd)); + if (!Kind) + return std::unexpected(Kind.error()); + std::int64_t Addend = 0; + const std::string_view AddendText = Text.substr(KindEnd + 1U, AddendEnd - KindEnd - 1U); + const auto [End, Error] = + std::from_chars(AddendText.data(), AddendText.data() + AddendText.size(), Addend); + if (Error != std::errc{} || End != AddendText.data() + AddendText.size()) + return makeUnexpected(ErrorCode::ParseError, "RV64GC symbol constant addend is invalid"); + RISCVSymbolConstant Result(*Kind, std::string(Text.substr(AddendEnd + 1U)), Addend); + auto Verification = Result.verify(); + if (!Verification) + return std::unexpected(Verification.error()); + return Result; +} + +Expected<RISCVSymbolConstant> RISCVSymbolConstant::decode(std::uint32_t Version, + std::span<const std::byte> Payload) { + if (Version != schemaVersion() || Payload.size() < 10) { + return makeUnexpected(ErrorCode::ParseError, + "encoded RV64GC symbol constant has an invalid version or size"); + } + const auto KindValue = std::to_integer<std::uint8_t>(Payload.front()); + if (KindValue > static_cast<std::uint8_t>(RISCVSymbolConstantKind::ExternalSymbol)) + return makeUnexpected(ErrorCode::ParseError, "encoded RV64GC symbol constant kind is invalid"); + std::string Symbol; + Symbol.reserve(Payload.size() - 9U); + for (const std::byte Character : Payload.subspan(9)) + Symbol.push_back(static_cast<char>(std::to_integer<unsigned char>(Character))); + RISCVSymbolConstant Result(static_cast<RISCVSymbolConstantKind>(KindValue), std::move(Symbol), + std::bit_cast<std::int64_t>(readU64(Payload.subspan(1, 8)))); + auto Verification = Result.verify(); + if (!Verification) + return std::unexpected(Verification.error()); + return Result; +} + +} // namespace rcc::riscv |
