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