1 //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the LoongArchMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchFixupKinds.h" 14 #include "MCTargetDesc/LoongArchMCExpr.h" 15 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 16 #include "llvm/MC/MCCodeEmitter.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCInstBuilder.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/Support/Casting.h" 23 #include "llvm/Support/EndianStream.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "mccodeemitter" 28 29 namespace { 30 class LoongArchMCCodeEmitter : public MCCodeEmitter { 31 LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 32 void operator=(const LoongArchMCCodeEmitter &) = delete; 33 MCContext &Ctx; 34 MCInstrInfo const &MCII; 35 36 public: 37 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 38 : Ctx(ctx), MCII(MCII) {} 39 40 ~LoongArchMCCodeEmitter() override {} 41 42 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 43 SmallVectorImpl<MCFixup> &Fixups, 44 const MCSubtargetInfo &STI) const override; 45 46 template <unsigned Opc> 47 void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB, 48 SmallVectorImpl<MCFixup> &Fixups, 49 const MCSubtargetInfo &STI) const; 50 51 void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB, 52 SmallVectorImpl<MCFixup> &Fixups, 53 const MCSubtargetInfo &STI) const; 54 55 /// TableGen'erated function for getting the binary encoding for an 56 /// instruction. 57 uint64_t getBinaryCodeForInstr(const MCInst &MI, 58 SmallVectorImpl<MCFixup> &Fixups, 59 const MCSubtargetInfo &STI) const; 60 61 /// Return binary encoding of operand. If the machine operand requires 62 /// relocation, record the relocation and return zero. 63 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 64 SmallVectorImpl<MCFixup> &Fixups, 65 const MCSubtargetInfo &STI) const; 66 67 /// Return binary encoding of an immediate operand specified by OpNo. 68 /// The value returned is the value of the immediate minus 1. 69 /// Note that this function is dedicated to specific immediate types, 70 /// e.g. uimm2_plus1. 71 unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 72 SmallVectorImpl<MCFixup> &Fixups, 73 const MCSubtargetInfo &STI) const; 74 75 /// Return binary encoding of an immediate operand specified by OpNo. 76 /// The value returned is the value of the immediate shifted right 77 // arithmetically by N. 78 /// Note that this function is dedicated to specific immediate types, 79 /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 80 template <unsigned N> 81 unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo, 82 SmallVectorImpl<MCFixup> &Fixups, 83 const MCSubtargetInfo &STI) const { 84 const MCOperand &MO = MI.getOperand(OpNo); 85 if (MO.isImm()) { 86 unsigned Res = MI.getOperand(OpNo).getImm(); 87 assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero"); 88 return Res >> N; 89 } 90 return getExprOpValue(MI, MO, Fixups, STI); 91 } 92 93 unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO, 94 SmallVectorImpl<MCFixup> &Fixups, 95 const MCSubtargetInfo &STI) const; 96 }; 97 } // end namespace 98 99 unsigned 100 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 101 SmallVectorImpl<MCFixup> &Fixups, 102 const MCSubtargetInfo &STI) const { 103 104 if (MO.isReg()) 105 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 106 107 if (MO.isImm()) 108 return static_cast<unsigned>(MO.getImm()); 109 110 // MO must be an Expr. 111 assert(MO.isExpr()); 112 return getExprOpValue(MI, MO, Fixups, STI); 113 } 114 115 unsigned 116 LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 117 SmallVectorImpl<MCFixup> &Fixups, 118 const MCSubtargetInfo &STI) const { 119 return MI.getOperand(OpNo).getImm() - 1; 120 } 121 122 unsigned 123 LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, 124 SmallVectorImpl<MCFixup> &Fixups, 125 const MCSubtargetInfo &STI) const { 126 assert(MO.isExpr() && "getExprOpValue expects only expressions"); 127 bool RelaxCandidate = false; 128 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); 129 const MCExpr *Expr = MO.getExpr(); 130 MCExpr::ExprKind Kind = Expr->getKind(); 131 LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid; 132 if (Kind == MCExpr::Target) { 133 const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr); 134 135 RelaxCandidate = LAExpr->getRelaxHint(); 136 switch (LAExpr->getKind()) { 137 case LoongArchMCExpr::VK_LoongArch_None: 138 case LoongArchMCExpr::VK_LoongArch_Invalid: 139 llvm_unreachable("Unhandled fixup kind!"); 140 case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R: 141 llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an " 142 "instruction operand"); 143 case LoongArchMCExpr::VK_LoongArch_B16: 144 FixupKind = LoongArch::fixup_loongarch_b16; 145 break; 146 case LoongArchMCExpr::VK_LoongArch_B21: 147 FixupKind = LoongArch::fixup_loongarch_b21; 148 break; 149 case LoongArchMCExpr::VK_LoongArch_B26: 150 case LoongArchMCExpr::VK_LoongArch_CALL: 151 case LoongArchMCExpr::VK_LoongArch_CALL_PLT: 152 FixupKind = LoongArch::fixup_loongarch_b26; 153 break; 154 case LoongArchMCExpr::VK_LoongArch_ABS_HI20: 155 FixupKind = LoongArch::fixup_loongarch_abs_hi20; 156 break; 157 case LoongArchMCExpr::VK_LoongArch_ABS_LO12: 158 FixupKind = LoongArch::fixup_loongarch_abs_lo12; 159 break; 160 case LoongArchMCExpr::VK_LoongArch_ABS64_LO20: 161 FixupKind = LoongArch::fixup_loongarch_abs64_lo20; 162 break; 163 case LoongArchMCExpr::VK_LoongArch_ABS64_HI12: 164 FixupKind = LoongArch::fixup_loongarch_abs64_hi12; 165 break; 166 case LoongArchMCExpr::VK_LoongArch_PCALA_HI20: 167 FixupKind = LoongArch::fixup_loongarch_pcala_hi20; 168 break; 169 case LoongArchMCExpr::VK_LoongArch_PCALA_LO12: 170 FixupKind = LoongArch::fixup_loongarch_pcala_lo12; 171 break; 172 case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20: 173 FixupKind = LoongArch::fixup_loongarch_pcala64_lo20; 174 break; 175 case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12: 176 FixupKind = LoongArch::fixup_loongarch_pcala64_hi12; 177 break; 178 case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20: 179 FixupKind = LoongArch::fixup_loongarch_got_pc_hi20; 180 break; 181 case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12: 182 FixupKind = LoongArch::fixup_loongarch_got_pc_lo12; 183 break; 184 case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20: 185 FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20; 186 break; 187 case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12: 188 FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12; 189 break; 190 case LoongArchMCExpr::VK_LoongArch_GOT_HI20: 191 FixupKind = LoongArch::fixup_loongarch_got_hi20; 192 break; 193 case LoongArchMCExpr::VK_LoongArch_GOT_LO12: 194 FixupKind = LoongArch::fixup_loongarch_got_lo12; 195 break; 196 case LoongArchMCExpr::VK_LoongArch_GOT64_LO20: 197 FixupKind = LoongArch::fixup_loongarch_got64_lo20; 198 break; 199 case LoongArchMCExpr::VK_LoongArch_GOT64_HI12: 200 FixupKind = LoongArch::fixup_loongarch_got64_hi12; 201 break; 202 case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20: 203 FixupKind = LoongArch::fixup_loongarch_tls_le_hi20; 204 break; 205 case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12: 206 FixupKind = LoongArch::fixup_loongarch_tls_le_lo12; 207 break; 208 case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20: 209 FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20; 210 break; 211 case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12: 212 FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12; 213 break; 214 case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20: 215 FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20; 216 break; 217 case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12: 218 FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12; 219 break; 220 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20: 221 FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20; 222 break; 223 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12: 224 FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12; 225 break; 226 case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20: 227 FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20; 228 break; 229 case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12: 230 FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12; 231 break; 232 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20: 233 FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20; 234 break; 235 case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12: 236 FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12; 237 break; 238 case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20: 239 FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20; 240 break; 241 case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20: 242 FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20; 243 break; 244 case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20: 245 FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20; 246 break; 247 case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20: 248 FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20; 249 break; 250 case LoongArchMCExpr::VK_LoongArch_CALL36: 251 FixupKind = LoongArch::fixup_loongarch_call36; 252 RelaxCandidate = true; 253 break; 254 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20: 255 FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20; 256 break; 257 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12: 258 FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_lo12; 259 break; 260 case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20: 261 FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_lo20; 262 break; 263 case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12: 264 FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_hi12; 265 break; 266 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20: 267 FixupKind = LoongArch::fixup_loongarch_tls_desc_hi20; 268 break; 269 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12: 270 FixupKind = LoongArch::fixup_loongarch_tls_desc_lo12; 271 break; 272 case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20: 273 FixupKind = LoongArch::fixup_loongarch_tls_desc64_lo20; 274 break; 275 case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12: 276 FixupKind = LoongArch::fixup_loongarch_tls_desc64_hi12; 277 break; 278 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD: 279 FixupKind = LoongArch::fixup_loongarch_tls_desc_ld; 280 break; 281 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL: 282 FixupKind = LoongArch::fixup_loongarch_tls_desc_call; 283 break; 284 case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R: 285 FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r; 286 RelaxCandidate = true; 287 break; 288 case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R: 289 FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r; 290 RelaxCandidate = true; 291 break; 292 case LoongArchMCExpr::VK_LoongArch_PCREL20_S2: 293 FixupKind = LoongArch::fixup_loongarch_pcrel20_s2; 294 break; 295 case LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2: 296 FixupKind = LoongArch::fixup_loongarch_tls_ld_pcrel20_s2; 297 break; 298 case LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2: 299 FixupKind = LoongArch::fixup_loongarch_tls_gd_pcrel20_s2; 300 break; 301 case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2: 302 FixupKind = LoongArch::fixup_loongarch_tls_desc_pcrel20_s2; 303 break; 304 } 305 } else if (Kind == MCExpr::SymbolRef && 306 cast<MCSymbolRefExpr>(Expr)->getKind() == 307 MCSymbolRefExpr::VK_None) { 308 switch (MI.getOpcode()) { 309 default: 310 break; 311 case LoongArch::BEQ: 312 case LoongArch::BNE: 313 case LoongArch::BLT: 314 case LoongArch::BGE: 315 case LoongArch::BLTU: 316 case LoongArch::BGEU: 317 FixupKind = LoongArch::fixup_loongarch_b16; 318 break; 319 case LoongArch::BEQZ: 320 case LoongArch::BNEZ: 321 case LoongArch::BCEQZ: 322 case LoongArch::BCNEZ: 323 FixupKind = LoongArch::fixup_loongarch_b21; 324 break; 325 case LoongArch::B: 326 case LoongArch::BL: 327 FixupKind = LoongArch::fixup_loongarch_b26; 328 break; 329 } 330 } 331 332 assert(FixupKind != LoongArch::fixup_loongarch_invalid && 333 "Unhandled expression!"); 334 335 Fixups.push_back( 336 MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); 337 338 // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax 339 // hint. 340 if (EnableRelax && RelaxCandidate) { 341 const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); 342 Fixups.push_back(MCFixup::create( 343 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc())); 344 } 345 346 return 0; 347 } 348 349 template <unsigned Opc> 350 void LoongArchMCCodeEmitter::expandToVectorLDI( 351 const MCInst &MI, SmallVectorImpl<char> &CB, 352 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 353 int64_t Imm = MI.getOperand(1).getImm() & 0x3FF; 354 switch (MI.getOpcode()) { 355 case LoongArch::PseudoVREPLI_B: 356 case LoongArch::PseudoXVREPLI_B: 357 break; 358 case LoongArch::PseudoVREPLI_H: 359 case LoongArch::PseudoXVREPLI_H: 360 Imm |= 0x400; 361 break; 362 case LoongArch::PseudoVREPLI_W: 363 case LoongArch::PseudoXVREPLI_W: 364 Imm |= 0x800; 365 break; 366 case LoongArch::PseudoVREPLI_D: 367 case LoongArch::PseudoXVREPLI_D: 368 Imm |= 0xC00; 369 break; 370 } 371 MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm); 372 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 373 support::endian::write(CB, Binary, llvm::endianness::little); 374 } 375 376 void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI, 377 SmallVectorImpl<char> &CB, 378 SmallVectorImpl<MCFixup> &Fixups, 379 const MCSubtargetInfo &STI) const { 380 MCOperand Rd = MI.getOperand(0); 381 MCOperand Rj = MI.getOperand(1); 382 MCOperand Rk = MI.getOperand(2); 383 MCOperand Symbol = MI.getOperand(3); 384 assert(Symbol.isExpr() && 385 "Expected expression as third input to TP-relative add"); 386 387 const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr()); 388 assert(Expr && 389 Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R && 390 "Expected %le_add_r relocation on TP-relative symbol"); 391 392 // Emit the correct %le_add_r relocation for the symbol. 393 Fixups.push_back(MCFixup::create( 394 0, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r), 395 MI.getLoc())); 396 397 // Emit R_LARCH_RELAX for %le_add_r when the relax feature is enabled. 398 if (STI.hasFeature(LoongArch::FeatureRelax)) { 399 const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); 400 Fixups.push_back(MCFixup::create( 401 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc())); 402 } 403 404 // Emit a normal ADD instruction with the given operands. 405 unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D 406 ? LoongArch::ADD_D 407 : LoongArch::ADD_W; 408 MCInst TmpInst = 409 MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk); 410 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 411 support::endian::write(CB, Binary, llvm::endianness::little); 412 } 413 414 void LoongArchMCCodeEmitter::encodeInstruction( 415 const MCInst &MI, SmallVectorImpl<char> &CB, 416 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { 417 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 418 // Get byte count of instruction. 419 unsigned Size = Desc.getSize(); 420 421 switch (MI.getOpcode()) { 422 default: 423 break; 424 case LoongArch::PseudoVREPLI_B: 425 case LoongArch::PseudoVREPLI_H: 426 case LoongArch::PseudoVREPLI_W: 427 case LoongArch::PseudoVREPLI_D: 428 return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI); 429 case LoongArch::PseudoXVREPLI_B: 430 case LoongArch::PseudoXVREPLI_H: 431 case LoongArch::PseudoXVREPLI_W: 432 case LoongArch::PseudoXVREPLI_D: 433 return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI); 434 case LoongArch::PseudoAddTPRel_W: 435 case LoongArch::PseudoAddTPRel_D: 436 return expandAddTPRel(MI, CB, Fixups, STI); 437 } 438 439 switch (Size) { 440 default: 441 llvm_unreachable("Unhandled encodeInstruction length!"); 442 case 4: { 443 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 444 support::endian::write(CB, Bits, llvm::endianness::little); 445 break; 446 } 447 } 448 } 449 450 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 451 MCContext &Ctx) { 452 return new LoongArchMCCodeEmitter(Ctx, MCII); 453 } 454 455 #include "LoongArchGenMCCodeEmitter.inc" 456