1 //===-- RISCVAsmBackend.cpp - RISCV Assembler Backend ---------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/RISCVFixupKinds.h" 11 #include "MCTargetDesc/RISCVMCTargetDesc.h" 12 #include "llvm/ADT/APInt.h" 13 #include "llvm/MC/MCAsmBackend.h" 14 #include "llvm/MC/MCAssembler.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCDirectives.h" 17 #include "llvm/MC/MCELFObjectWriter.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCFixupKindInfo.h" 20 #include "llvm/MC/MCObjectWriter.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/MC/MCSymbol.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/raw_ostream.h" 25 26 using namespace llvm; 27 28 namespace { 29 class RISCVAsmBackend : public MCAsmBackend { 30 const MCSubtargetInfo &STI; 31 uint8_t OSABI; 32 bool Is64Bit; 33 34 public: 35 RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit) 36 : MCAsmBackend(), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit) {} 37 ~RISCVAsmBackend() override {} 38 39 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 40 const MCValue &Target, MutableArrayRef<char> Data, 41 uint64_t Value, bool IsResolved) const override; 42 43 std::unique_ptr<MCObjectWriter> 44 createObjectWriter(raw_pwrite_stream &OS) const override; 45 46 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, 47 const MCRelaxableFragment *DF, 48 const MCAsmLayout &Layout) const override; 49 50 unsigned getNumFixupKinds() const override { 51 return RISCV::NumTargetFixupKinds; 52 } 53 54 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { 55 const static MCFixupKindInfo Infos[RISCV::NumTargetFixupKinds] = { 56 // This table *must* be in the order that the fixup_* kinds are defined in 57 // RISCVFixupKinds.h. 58 // 59 // name offset bits flags 60 { "fixup_riscv_hi20", 12, 20, 0 }, 61 { "fixup_riscv_lo12_i", 20, 12, 0 }, 62 { "fixup_riscv_lo12_s", 0, 32, 0 }, 63 { "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, 64 { "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel }, 65 { "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 66 { "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, 67 { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 68 { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel }, 69 { "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel } 70 }; 71 72 if (Kind < FirstTargetFixupKind) 73 return MCAsmBackend::getFixupKindInfo(Kind); 74 75 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 76 "Invalid kind!"); 77 return Infos[Kind - FirstTargetFixupKind]; 78 } 79 80 bool mayNeedRelaxation(const MCInst &Inst) const override; 81 unsigned getRelaxedOpcode(unsigned Op) const; 82 83 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, 84 MCInst &Res) const override; 85 86 87 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; 88 }; 89 90 91 bool RISCVAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 92 uint64_t Value, 93 const MCRelaxableFragment *DF, 94 const MCAsmLayout &Layout) const { 95 int64_t Offset = int64_t(Value); 96 switch ((unsigned)Fixup.getKind()) { 97 default: 98 return false; 99 case RISCV::fixup_riscv_rvc_branch: 100 // For compressed branch instructions the immediate must be 101 // in the range [-256, 254]. 102 return Offset > 254 || Offset < -256; 103 case RISCV::fixup_riscv_rvc_jump: 104 // For compressed jump instructions the immediate must be 105 // in the range [-2048, 2046]. 106 return Offset > 2046 || Offset < -2048; 107 } 108 } 109 110 void RISCVAsmBackend::relaxInstruction(const MCInst &Inst, 111 const MCSubtargetInfo &STI, 112 MCInst &Res) const { 113 // TODO: replace this with call to auto generated uncompressinstr() function. 114 switch (Inst.getOpcode()) { 115 default: 116 llvm_unreachable("Opcode not expected!"); 117 case RISCV::C_BEQZ: 118 // c.beqz $rs1, $imm -> beq $rs1, X0, $imm. 119 Res.setOpcode(RISCV::BEQ); 120 Res.addOperand(Inst.getOperand(0)); 121 Res.addOperand(MCOperand::createReg(RISCV::X0)); 122 Res.addOperand(Inst.getOperand(1)); 123 break; 124 case RISCV::C_BNEZ: 125 // c.bnez $rs1, $imm -> bne $rs1, X0, $imm. 126 Res.setOpcode(RISCV::BNE); 127 Res.addOperand(Inst.getOperand(0)); 128 Res.addOperand(MCOperand::createReg(RISCV::X0)); 129 Res.addOperand(Inst.getOperand(1)); 130 break; 131 case RISCV::C_J: 132 // c.j $imm -> jal X0, $imm. 133 Res.setOpcode(RISCV::JAL); 134 Res.addOperand(MCOperand::createReg(RISCV::X0)); 135 Res.addOperand(Inst.getOperand(0)); 136 break; 137 case RISCV::C_JAL: 138 // c.jal $imm -> jal X1, $imm. 139 Res.setOpcode(RISCV::JAL); 140 Res.addOperand(MCOperand::createReg(RISCV::X1)); 141 Res.addOperand(Inst.getOperand(0)); 142 break; 143 } 144 } 145 146 // Given a compressed control flow instruction this function returns 147 // the expanded instruction. 148 unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const { 149 switch (Op) { 150 default: 151 return Op; 152 case RISCV::C_BEQZ: 153 return RISCV::BEQ; 154 case RISCV::C_BNEZ: 155 return RISCV::BNE; 156 case RISCV::C_J: 157 case RISCV::C_JAL: // fall through. 158 return RISCV::JAL; 159 } 160 } 161 162 bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 163 return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode(); 164 } 165 166 bool RISCVAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 167 bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC]; 168 unsigned MinNopLen = HasStdExtC ? 2 : 4; 169 170 if ((Count % MinNopLen) != 0) 171 return false; 172 173 // The canonical nop on RISC-V is addi x0, x0, 0. 174 uint64_t Nop32Count = Count / 4; 175 for (uint64_t i = Nop32Count; i != 0; --i) 176 OW->write32(0x13); 177 178 // The canonical nop on RVC is c.nop. 179 if (HasStdExtC) { 180 uint64_t Nop16Count = (Count - Nop32Count * 4) / 2; 181 for (uint64_t i = Nop16Count; i != 0; --i) 182 OW->write16(0x01); 183 } 184 185 return true; 186 } 187 188 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 189 MCContext &Ctx) { 190 unsigned Kind = Fixup.getKind(); 191 switch (Kind) { 192 default: 193 llvm_unreachable("Unknown fixup kind!"); 194 case FK_Data_1: 195 case FK_Data_2: 196 case FK_Data_4: 197 case FK_Data_8: 198 return Value; 199 case RISCV::fixup_riscv_lo12_i: 200 case RISCV::fixup_riscv_pcrel_lo12_i: 201 return Value & 0xfff; 202 case RISCV::fixup_riscv_lo12_s: 203 case RISCV::fixup_riscv_pcrel_lo12_s: 204 return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7); 205 case RISCV::fixup_riscv_hi20: 206 case RISCV::fixup_riscv_pcrel_hi20: 207 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative. 208 return ((Value + 0x800) >> 12) & 0xfffff; 209 case RISCV::fixup_riscv_jal: { 210 if (!isInt<21>(Value)) 211 Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); 212 if (Value & 0x1) 213 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned"); 214 // Need to produce imm[19|10:1|11|19:12] from the 21-bit Value. 215 unsigned Sbit = (Value >> 20) & 0x1; 216 unsigned Hi8 = (Value >> 12) & 0xff; 217 unsigned Mid1 = (Value >> 11) & 0x1; 218 unsigned Lo10 = (Value >> 1) & 0x3ff; 219 // Inst{31} = Sbit; 220 // Inst{30-21} = Lo10; 221 // Inst{20} = Mid1; 222 // Inst{19-12} = Hi8; 223 Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8; 224 return Value; 225 } 226 case RISCV::fixup_riscv_branch: { 227 if (!isInt<13>(Value)) 228 Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); 229 if (Value & 0x1) 230 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned"); 231 // Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit 232 // Value. 233 unsigned Sbit = (Value >> 12) & 0x1; 234 unsigned Hi1 = (Value >> 11) & 0x1; 235 unsigned Mid6 = (Value >> 5) & 0x3f; 236 unsigned Lo4 = (Value >> 1) & 0xf; 237 // Inst{31} = Sbit; 238 // Inst{30-25} = Mid6; 239 // Inst{11-8} = Lo4; 240 // Inst{7} = Hi1; 241 Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7); 242 return Value; 243 } 244 case RISCV::fixup_riscv_rvc_jump: { 245 // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value. 246 unsigned Bit11 = (Value >> 11) & 0x1; 247 unsigned Bit4 = (Value >> 4) & 0x1; 248 unsigned Bit9_8 = (Value >> 8) & 0x3; 249 unsigned Bit10 = (Value >> 10) & 0x1; 250 unsigned Bit6 = (Value >> 6) & 0x1; 251 unsigned Bit7 = (Value >> 7) & 0x1; 252 unsigned Bit3_1 = (Value >> 1) & 0x7; 253 unsigned Bit5 = (Value >> 5) & 0x1; 254 Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) | 255 (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5; 256 return Value; 257 } 258 case RISCV::fixup_riscv_rvc_branch: { 259 // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5] 260 unsigned Bit8 = (Value >> 8) & 0x1; 261 unsigned Bit7_6 = (Value >> 6) & 0x3; 262 unsigned Bit5 = (Value >> 5) & 0x1; 263 unsigned Bit4_3 = (Value >> 3) & 0x3; 264 unsigned Bit2_1 = (Value >> 1) & 0x3; 265 Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) | 266 (Bit5 << 2); 267 return Value; 268 } 269 270 } 271 } 272 273 static unsigned getSize(unsigned Kind) { 274 switch (Kind) { 275 default: 276 return 4; 277 case RISCV::fixup_riscv_rvc_jump: 278 case RISCV::fixup_riscv_rvc_branch: 279 return 2; 280 } 281 } 282 283 void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 284 const MCValue &Target, 285 MutableArrayRef<char> Data, uint64_t Value, 286 bool IsResolved) const { 287 MCContext &Ctx = Asm.getContext(); 288 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 289 if (!Value) 290 return; // Doesn't change encoding. 291 // Apply any target-specific value adjustments. 292 Value = adjustFixupValue(Fixup, Value, Ctx); 293 294 // Shift the value into position. 295 Value <<= Info.TargetOffset; 296 297 unsigned Offset = Fixup.getOffset(); 298 unsigned FullSize = getSize(Fixup.getKind()); 299 300 #ifndef NDEBUG 301 unsigned NumBytes = (Info.TargetSize + 7) / 8; 302 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 303 #endif 304 305 // For each byte of the fragment that the fixup touches, mask in the 306 // bits from the fixup value. 307 for (unsigned i = 0; i != FullSize; ++i) { 308 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 309 } 310 } 311 312 std::unique_ptr<MCObjectWriter> 313 RISCVAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { 314 return createRISCVELFObjectWriter(OS, OSABI, Is64Bit); 315 } 316 317 } // end anonymous namespace 318 319 MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T, 320 const MCSubtargetInfo &STI, 321 const MCRegisterInfo &MRI, 322 const MCTargetOptions &Options) { 323 const Triple &TT = STI.getTargetTriple(); 324 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); 325 return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit()); 326 } 327