1 // LoongArchAsmParser.cpp - Parse LoongArch assembly to MCInst instructions -=// 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 #include "MCTargetDesc/LoongArchInstPrinter.h" 10 #include "MCTargetDesc/LoongArchMCExpr.h" 11 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 12 #include "MCTargetDesc/LoongArchMatInt.h" 13 #include "TargetInfo/LoongArchTargetInfo.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCInstBuilder.h" 16 #include "llvm/MC/MCInstrInfo.h" 17 #include "llvm/MC/MCParser/MCAsmLexer.h" 18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 19 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/MC/MCStreamer.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/MCValue.h" 24 #include "llvm/MC/TargetRegistry.h" 25 #include "llvm/Support/Casting.h" 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "loongarch-asm-parser" 30 31 namespace { 32 class LoongArchAsmParser : public MCTargetAsmParser { 33 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 34 bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); } 35 36 struct Inst { 37 unsigned Opc; 38 LoongArchMCExpr::VariantKind VK; 39 Inst(unsigned Opc, 40 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None) 41 : Opc(Opc), VK(VK) {} 42 }; 43 using InstSeq = SmallVector<Inst>; 44 45 /// Parse a register as used in CFI directives. 46 bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 47 SMLoc &EndLoc) override; 48 OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 49 SMLoc &EndLoc) override; 50 51 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 52 SMLoc NameLoc, OperandVector &Operands) override; 53 54 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 55 OperandVector &Operands, MCStreamer &Out, 56 uint64_t &ErrorInfo, 57 bool MatchingInlineAsm) override; 58 59 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 60 61 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 62 unsigned Kind) override; 63 64 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 65 int64_t Lower, int64_t Upper, 66 const Twine &Msg); 67 68 /// Helper for processing MC instructions that have been successfully matched 69 /// by MatchAndEmitInstruction. 70 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 71 MCStreamer &Out); 72 73 // Auto-generated instruction matching functions. 74 #define GET_ASSEMBLER_HEADER 75 #include "LoongArchGenAsmMatcher.inc" 76 77 ParseStatus parseRegister(OperandVector &Operands); 78 ParseStatus parseImmediate(OperandVector &Operands); 79 ParseStatus parseOperandWithModifier(OperandVector &Operands); 80 ParseStatus parseSImm26Operand(OperandVector &Operands); 81 ParseStatus parseAtomicMemOp(OperandVector &Operands); 82 83 bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 84 85 // Helper to emit the sequence of instructions generated by the 86 // "emitLoadAddress*" functions. 87 void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 88 const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts, 89 SMLoc IDLoc, MCStreamer &Out); 90 91 // Helper to emit pseudo instruction "la.abs $rd, sym". 92 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 93 94 // Helper to emit pseudo instruction "la.pcrel $rd, sym". 95 void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 96 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym". 97 void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 98 99 // Helper to emit pseudo instruction "la.got $rd, sym". 100 void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 101 // Helper to emit pseudo instruction "la.got $rd, $rj, sym". 102 void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 103 104 // Helper to emit pseudo instruction "la.tls.le $rd, sym". 105 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 106 107 // Helper to emit pseudo instruction "la.tls.ie $rd, sym". 108 void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 109 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym". 110 void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 111 112 // Helper to emit pseudo instruction "la.tls.ld $rd, sym". 113 void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 114 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym". 115 void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 116 117 // Helper to emit pseudo instruction "la.tls.gd $rd, sym". 118 void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 119 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym". 120 void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 121 122 // Helper to emit pseudo instruction "li.w/d $rd, $imm". 123 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 124 125 public: 126 enum LoongArchMatchResultTy { 127 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 128 Match_RequiresMsbNotLessThanLsb, 129 Match_RequiresOpnd2NotR0R1, 130 Match_RequiresAMORdDifferRkRj, 131 Match_RequiresLAORdDifferRj, 132 #define GET_OPERAND_DIAGNOSTIC_TYPES 133 #include "LoongArchGenAsmMatcher.inc" 134 #undef GET_OPERAND_DIAGNOSTIC_TYPES 135 }; 136 137 static bool classifySymbolRef(const MCExpr *Expr, 138 LoongArchMCExpr::VariantKind &Kind); 139 140 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 141 const MCInstrInfo &MII, const MCTargetOptions &Options) 142 : MCTargetAsmParser(Options, STI, MII) { 143 Parser.addAliasForDirective(".half", ".2byte"); 144 Parser.addAliasForDirective(".hword", ".2byte"); 145 Parser.addAliasForDirective(".word", ".4byte"); 146 Parser.addAliasForDirective(".dword", ".8byte"); 147 148 // Initialize the set of available features. 149 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 150 } 151 }; 152 153 // Instances of this class represent a parsed LoongArch machine instruction. 154 class LoongArchOperand : public MCParsedAsmOperand { 155 enum class KindTy { 156 Token, 157 Register, 158 Immediate, 159 } Kind; 160 161 struct RegOp { 162 MCRegister RegNum; 163 }; 164 165 struct ImmOp { 166 const MCExpr *Val; 167 }; 168 169 SMLoc StartLoc, EndLoc; 170 union { 171 StringRef Tok; 172 struct RegOp Reg; 173 struct ImmOp Imm; 174 }; 175 176 public: 177 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 178 179 bool isToken() const override { return Kind == KindTy::Token; } 180 bool isReg() const override { return Kind == KindTy::Register; } 181 bool isImm() const override { return Kind == KindTy::Immediate; } 182 bool isMem() const override { return false; } 183 void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; } 184 bool isGPR() const { 185 return Kind == KindTy::Register && 186 LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains( 187 Reg.RegNum); 188 } 189 190 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 191 LoongArchMCExpr::VariantKind &VK) { 192 if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) { 193 VK = LE->getKind(); 194 return false; 195 } 196 197 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 198 Imm = CE->getValue(); 199 return true; 200 } 201 202 return false; 203 } 204 205 template <unsigned N, int P = 0> bool isUImm() const { 206 if (!isImm()) 207 return false; 208 209 int64_t Imm; 210 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 211 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 212 return IsConstantImm && isUInt<N>(Imm - P) && 213 VK == LoongArchMCExpr::VK_LoongArch_None; 214 } 215 216 template <unsigned N, unsigned S = 0> bool isSImm() const { 217 if (!isImm()) 218 return false; 219 220 int64_t Imm; 221 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 222 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 223 return IsConstantImm && isShiftedInt<N, S>(Imm) && 224 VK == LoongArchMCExpr::VK_LoongArch_None; 225 } 226 227 bool isBareSymbol() const { 228 int64_t Imm; 229 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 230 // Must be of 'immediate' type but not a constant. 231 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 232 return false; 233 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 234 VK == LoongArchMCExpr::VK_LoongArch_None; 235 } 236 237 bool isUImm1() const { return isUImm<1>(); } 238 bool isUImm2() const { return isUImm<2>(); } 239 bool isUImm2plus1() const { return isUImm<2, 1>(); } 240 bool isUImm3() const { return isUImm<3>(); } 241 bool isUImm4() const { return isUImm<4>(); } 242 bool isSImm5() const { return isSImm<5>(); } 243 bool isUImm5() const { return isUImm<5>(); } 244 bool isUImm6() const { return isUImm<6>(); } 245 bool isUImm7() const { return isUImm<7>(); } 246 bool isSImm8() const { return isSImm<8>(); } 247 bool isSImm8lsl1() const { return isSImm<8, 1>(); } 248 bool isSImm8lsl2() const { return isSImm<8, 2>(); } 249 bool isSImm8lsl3() const { return isSImm<8, 3>(); } 250 bool isUImm8() const { return isUImm<8>(); } 251 bool isSImm9lsl3() const { return isSImm<9, 3>(); } 252 bool isSImm10() const { return isSImm<10>(); } 253 bool isSImm10lsl2() const { return isSImm<10, 2>(); } 254 bool isSImm11lsl1() const { return isSImm<11, 1>(); } 255 bool isSImm12() const { return isSImm<12>(); } 256 257 bool isSImm12addlike() const { 258 if (!isImm()) 259 return false; 260 261 int64_t Imm; 262 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 263 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 264 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 265 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 266 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 267 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 268 return IsConstantImm 269 ? isInt<12>(Imm) && IsValidKind 270 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 271 IsValidKind; 272 } 273 274 bool isSImm12lu52id() const { 275 if (!isImm()) 276 return false; 277 278 int64_t Imm; 279 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 280 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 281 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 282 VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 || 283 VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 || 284 VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 || 285 VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 || 286 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 || 287 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 || 288 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12; 289 return IsConstantImm 290 ? isInt<12>(Imm) && IsValidKind 291 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 292 IsValidKind; 293 } 294 295 bool isUImm12() const { return isUImm<12>(); } 296 297 bool isUImm12ori() const { 298 if (!isImm()) 299 return false; 300 301 int64_t Imm; 302 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 303 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 304 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 305 VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 || 306 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 || 307 VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 || 308 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 || 309 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 || 310 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 || 311 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 312 return IsConstantImm 313 ? isUInt<12>(Imm) && IsValidKind 314 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 315 IsValidKind; 316 } 317 318 bool isSImm13() const { return isSImm<13>(); } 319 bool isUImm14() const { return isUImm<14>(); } 320 bool isUImm15() const { return isUImm<15>(); } 321 322 bool isSImm14lsl2() const { return isSImm<14, 2>(); } 323 bool isSImm16() const { return isSImm<16>(); } 324 325 bool isSImm16lsl2() const { 326 if (!isImm()) 327 return false; 328 329 int64_t Imm; 330 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 331 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 332 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 333 VK == LoongArchMCExpr::VK_LoongArch_B16 || 334 VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12; 335 return IsConstantImm 336 ? isShiftedInt<16, 2>(Imm) && IsValidKind 337 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 338 IsValidKind; 339 } 340 341 bool isSImm20() const { return isSImm<20>(); } 342 343 bool isSImm20pcalau12i() const { 344 if (!isImm()) 345 return false; 346 347 int64_t Imm; 348 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 349 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 350 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 351 VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 || 352 VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 || 353 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 || 354 VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 || 355 VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 356 return IsConstantImm 357 ? isInt<20>(Imm) && IsValidKind 358 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 359 IsValidKind; 360 } 361 362 bool isSImm20lu12iw() const { 363 if (!isImm()) 364 return false; 365 366 int64_t Imm; 367 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 368 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 369 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 370 VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 || 371 VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 || 372 VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 || 373 VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 || 374 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 || 375 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 376 return IsConstantImm 377 ? isInt<20>(Imm) && IsValidKind 378 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 379 IsValidKind; 380 } 381 382 bool isSImm20lu32id() const { 383 if (!isImm()) 384 return false; 385 386 int64_t Imm; 387 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 388 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 389 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 390 VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 || 391 VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 || 392 VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 || 393 VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 || 394 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 || 395 VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 || 396 VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20; 397 398 return IsConstantImm 399 ? isInt<20>(Imm) && IsValidKind 400 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 401 IsValidKind; 402 } 403 404 bool isSImm21lsl2() const { 405 if (!isImm()) 406 return false; 407 408 int64_t Imm; 409 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 410 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 411 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 412 VK == LoongArchMCExpr::VK_LoongArch_B21; 413 return IsConstantImm 414 ? isShiftedInt<21, 2>(Imm) && IsValidKind 415 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 416 IsValidKind; 417 } 418 419 bool isSImm26Operand() const { 420 if (!isImm()) 421 return false; 422 423 int64_t Imm; 424 LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; 425 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 426 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None || 427 VK == LoongArchMCExpr::VK_LoongArch_CALL || 428 VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT || 429 VK == LoongArchMCExpr::VK_LoongArch_B26; 430 return IsConstantImm 431 ? isShiftedInt<26, 2>(Imm) && IsValidKind 432 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && 433 IsValidKind; 434 } 435 436 bool isImm32() const { return isSImm<32>() || isUImm<32>(); } 437 438 /// Gets location of the first token of this operand. 439 SMLoc getStartLoc() const override { return StartLoc; } 440 /// Gets location of the last token of this operand. 441 SMLoc getEndLoc() const override { return EndLoc; } 442 443 unsigned getReg() const override { 444 assert(Kind == KindTy::Register && "Invalid type access!"); 445 return Reg.RegNum.id(); 446 } 447 448 const MCExpr *getImm() const { 449 assert(Kind == KindTy::Immediate && "Invalid type access!"); 450 return Imm.Val; 451 } 452 453 StringRef getToken() const { 454 assert(Kind == KindTy::Token && "Invalid type access!"); 455 return Tok; 456 } 457 458 void print(raw_ostream &OS) const override { 459 auto RegName = [](MCRegister Reg) { 460 if (Reg) 461 return LoongArchInstPrinter::getRegisterName(Reg); 462 else 463 return "noreg"; 464 }; 465 466 switch (Kind) { 467 case KindTy::Immediate: 468 OS << *getImm(); 469 break; 470 case KindTy::Register: 471 OS << "<register " << RegName(getReg()) << ">"; 472 break; 473 case KindTy::Token: 474 OS << "'" << getToken() << "'"; 475 break; 476 } 477 } 478 479 static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) { 480 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token); 481 Op->Tok = Str; 482 Op->StartLoc = S; 483 Op->EndLoc = S; 484 return Op; 485 } 486 487 static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S, 488 SMLoc E) { 489 auto Op = std::make_unique<LoongArchOperand>(KindTy::Register); 490 Op->Reg.RegNum = RegNo; 491 Op->StartLoc = S; 492 Op->EndLoc = E; 493 return Op; 494 } 495 496 static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S, 497 SMLoc E) { 498 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate); 499 Op->Imm.Val = Val; 500 Op->StartLoc = S; 501 Op->EndLoc = E; 502 return Op; 503 } 504 505 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 506 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) 507 Inst.addOperand(MCOperand::createImm(CE->getValue())); 508 else 509 Inst.addOperand(MCOperand::createExpr(Expr)); 510 } 511 512 // Used by the TableGen Code. 513 void addRegOperands(MCInst &Inst, unsigned N) const { 514 assert(N == 1 && "Invalid number of operands!"); 515 Inst.addOperand(MCOperand::createReg(getReg())); 516 } 517 void addImmOperands(MCInst &Inst, unsigned N) const { 518 assert(N == 1 && "Invalid number of operands!"); 519 addExpr(Inst, getImm()); 520 } 521 }; 522 } // end namespace 523 524 #define GET_REGISTER_MATCHER 525 #define GET_SUBTARGET_FEATURE_NAME 526 #define GET_MATCHER_IMPLEMENTATION 527 #define GET_MNEMONIC_SPELL_CHECKER 528 #include "LoongArchGenAsmMatcher.inc" 529 530 static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 531 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register"); 532 return Reg - LoongArch::F0 + LoongArch::F0_64; 533 } 534 535 // Attempts to match Name as a register (either using the default name or 536 // alternative ABI names), setting RegNo to the matching register. Upon 537 // failure, returns true and sets RegNo to 0. 538 static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) { 539 RegNo = MatchRegisterName(Name); 540 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial 541 // match always matches the 32-bit variant, and not the 64-bit one. 542 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64)); 543 // The default FPR register class is based on the tablegen enum ordering. 544 static_assert(LoongArch::F0 < LoongArch::F0_64, 545 "FPR matching must be updated"); 546 if (RegNo == LoongArch::NoRegister) 547 RegNo = MatchRegisterAltName(Name); 548 549 return RegNo == LoongArch::NoRegister; 550 } 551 552 bool LoongArchAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, 553 SMLoc &EndLoc) { 554 return Error(getLoc(), "invalid register number"); 555 } 556 557 OperandMatchResultTy LoongArchAsmParser::tryParseRegister(MCRegister &RegNo, 558 SMLoc &StartLoc, 559 SMLoc &EndLoc) { 560 llvm_unreachable("Unimplemented function."); 561 } 562 563 bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr, 564 LoongArchMCExpr::VariantKind &Kind) { 565 Kind = LoongArchMCExpr::VK_LoongArch_None; 566 567 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) { 568 Kind = RE->getKind(); 569 Expr = RE->getSubExpr(); 570 } 571 572 MCValue Res; 573 if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr)) 574 return Res.getRefKind() == LoongArchMCExpr::VK_LoongArch_None; 575 return false; 576 } 577 578 ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) { 579 if (!parseOptionalToken(AsmToken::Dollar)) 580 return ParseStatus::NoMatch; 581 if (getLexer().getKind() != AsmToken::Identifier) 582 return ParseStatus::NoMatch; 583 584 StringRef Name = getLexer().getTok().getIdentifier(); 585 MCRegister RegNo; 586 matchRegisterNameHelper(RegNo, Name); 587 if (RegNo == LoongArch::NoRegister) 588 return ParseStatus::NoMatch; 589 590 SMLoc S = getLoc(); 591 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 592 getLexer().Lex(); 593 Operands.push_back(LoongArchOperand::createReg(RegNo, S, E)); 594 595 return ParseStatus::Success; 596 } 597 598 ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) { 599 SMLoc S = getLoc(); 600 SMLoc E; 601 const MCExpr *Res; 602 603 switch (getLexer().getKind()) { 604 default: 605 return ParseStatus::NoMatch; 606 case AsmToken::LParen: 607 case AsmToken::Dot: 608 case AsmToken::Minus: 609 case AsmToken::Plus: 610 case AsmToken::Exclaim: 611 case AsmToken::Tilde: 612 case AsmToken::Integer: 613 case AsmToken::String: 614 case AsmToken::Identifier: 615 if (getParser().parseExpression(Res, E)) 616 return ParseStatus::Failure; 617 break; 618 case AsmToken::Percent: 619 return parseOperandWithModifier(Operands); 620 } 621 622 Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 623 return ParseStatus::Success; 624 } 625 626 ParseStatus 627 LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) { 628 SMLoc S = getLoc(); 629 SMLoc E; 630 631 if (getLexer().getKind() != AsmToken::Percent) 632 return Error(getLoc(), "expected '%' for operand modifier"); 633 634 getParser().Lex(); // Eat '%' 635 636 if (getLexer().getKind() != AsmToken::Identifier) 637 return Error(getLoc(), "expected valid identifier for operand modifier"); 638 StringRef Identifier = getParser().getTok().getIdentifier(); 639 LoongArchMCExpr::VariantKind VK = 640 LoongArchMCExpr::getVariantKindForName(Identifier); 641 if (VK == LoongArchMCExpr::VK_LoongArch_Invalid) 642 return Error(getLoc(), "unrecognized operand modifier"); 643 644 getParser().Lex(); // Eat the identifier 645 if (getLexer().getKind() != AsmToken::LParen) 646 return Error(getLoc(), "expected '('"); 647 getParser().Lex(); // Eat '(' 648 649 const MCExpr *SubExpr; 650 if (getParser().parseParenExpression(SubExpr, E)) 651 return ParseStatus::Failure; 652 653 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext()); 654 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E)); 655 return ParseStatus::Success; 656 } 657 658 ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) { 659 SMLoc S = getLoc(); 660 const MCExpr *Res; 661 662 if (getLexer().getKind() == AsmToken::Percent) 663 return parseOperandWithModifier(Operands); 664 665 if (getLexer().getKind() != AsmToken::Identifier) 666 return ParseStatus::NoMatch; 667 668 StringRef Identifier; 669 if (getParser().parseIdentifier(Identifier)) 670 return ParseStatus::Failure; 671 672 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 673 674 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 675 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 676 Res = LoongArchMCExpr::create(Res, LoongArchMCExpr::VK_LoongArch_CALL, 677 getContext()); 678 Operands.push_back(LoongArchOperand::createImm(Res, S, E)); 679 return ParseStatus::Success; 680 } 681 682 ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) { 683 // Parse "$r*". 684 if (!parseRegister(Operands).isSuccess()) 685 return ParseStatus::NoMatch; 686 687 // If there is a next operand and it is 0, ignore it. Otherwise print a 688 // diagnostic message. 689 if (parseOptionalToken(AsmToken::Comma)) { 690 int64_t ImmVal; 691 SMLoc ImmStart = getLoc(); 692 if (getParser().parseIntToken(ImmVal, "expected optional integer offset")) 693 return ParseStatus::Failure; 694 if (ImmVal) 695 return Error(ImmStart, "optional integer offset must be 0"); 696 } 697 698 return ParseStatus::Success; 699 } 700 /// Looks at a token type and creates the relevant operand from this 701 /// information, adding to Operands. Return true upon an error. 702 bool LoongArchAsmParser::parseOperand(OperandVector &Operands, 703 StringRef Mnemonic) { 704 // Check if the current operand has a custom associated parser, if so, try to 705 // custom parse the operand, or fallback to the general approach. 706 ParseStatus Result = 707 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 708 if (Result.isSuccess()) 709 return false; 710 if (Result.isFailure()) 711 return true; 712 713 if (parseRegister(Operands).isSuccess() || 714 parseImmediate(Operands).isSuccess()) 715 return false; 716 717 // Finally we have exhausted all options and must declare defeat. 718 return Error(getLoc(), "unknown operand"); 719 } 720 721 bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, 722 StringRef Name, SMLoc NameLoc, 723 OperandVector &Operands) { 724 // First operand in MCInst is instruction mnemonic. 725 Operands.push_back(LoongArchOperand::createToken(Name, NameLoc)); 726 727 // If there are no more operands, then finish. 728 if (parseOptionalToken(AsmToken::EndOfStatement)) 729 return false; 730 731 // Parse first operand. 732 if (parseOperand(Operands, Name)) 733 return true; 734 735 // Parse until end of statement, consuming commas between operands. 736 while (parseOptionalToken(AsmToken::Comma)) 737 if (parseOperand(Operands, Name)) 738 return true; 739 740 // Parse end of statement and return successfully. 741 if (parseOptionalToken(AsmToken::EndOfStatement)) 742 return false; 743 744 SMLoc Loc = getLexer().getLoc(); 745 getParser().eatToEndOfStatement(); 746 return Error(Loc, "unexpected token"); 747 } 748 749 void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, 750 const MCExpr *Symbol, 751 SmallVectorImpl<Inst> &Insts, 752 SMLoc IDLoc, MCStreamer &Out) { 753 MCContext &Ctx = getContext(); 754 for (LoongArchAsmParser::Inst &Inst : Insts) { 755 unsigned Opc = Inst.Opc; 756 LoongArchMCExpr::VariantKind VK = Inst.VK; 757 const LoongArchMCExpr *LE = LoongArchMCExpr::create(Symbol, VK, Ctx); 758 switch (Opc) { 759 default: 760 llvm_unreachable("unexpected opcode"); 761 case LoongArch::PCALAU12I: 762 case LoongArch::LU12I_W: 763 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE), 764 getSTI()); 765 break; 766 case LoongArch::ORI: 767 case LoongArch::ADDI_W: 768 case LoongArch::LD_W: 769 case LoongArch::LD_D: { 770 if (VK == LoongArchMCExpr::VK_LoongArch_None) { 771 Out.emitInstruction( 772 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0), 773 getSTI()); 774 continue; 775 } 776 Out.emitInstruction( 777 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE), 778 getSTI()); 779 break; 780 } 781 case LoongArch::LU32I_D: 782 Out.emitInstruction(MCInstBuilder(Opc) 783 .addReg(DestReg == TmpReg ? DestReg : TmpReg) 784 .addReg(DestReg == TmpReg ? DestReg : TmpReg) 785 .addExpr(LE), 786 getSTI()); 787 break; 788 case LoongArch::LU52I_D: 789 Out.emitInstruction( 790 MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE), 791 getSTI()); 792 break; 793 case LoongArch::ADDI_D: 794 Out.emitInstruction( 795 MCInstBuilder(Opc) 796 .addReg(TmpReg) 797 .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0) 798 .addExpr(LE), 799 getSTI()); 800 break; 801 case LoongArch::ADD_D: 802 case LoongArch::LDX_D: 803 Out.emitInstruction( 804 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg), 805 getSTI()); 806 break; 807 } 808 } 809 } 810 811 void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, 812 MCStreamer &Out) { 813 // la.abs $rd, sym 814 // expands to: 815 // lu12i.w $rd, %abs_hi20(sym) 816 // ori $rd, $rd, %abs_lo12(sym) 817 // 818 // for 64bit appends: 819 // lu32i.d $rd, %abs64_lo20(sym) 820 // lu52i.d $rd, $rd, %abs64_hi12(sym) 821 MCRegister DestReg = Inst.getOperand(0).getReg(); 822 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS 823 ? Inst.getOperand(1).getExpr() 824 : Inst.getOperand(2).getExpr(); 825 InstSeq Insts; 826 827 Insts.push_back(LoongArchAsmParser::Inst( 828 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20)); 829 Insts.push_back(LoongArchAsmParser::Inst( 830 LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_ABS_LO12)); 831 832 if (is64Bit()) { 833 Insts.push_back(LoongArchAsmParser::Inst( 834 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20)); 835 Insts.push_back(LoongArchAsmParser::Inst( 836 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12)); 837 } 838 839 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 840 } 841 842 void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, 843 MCStreamer &Out) { 844 // la.pcrel $rd, sym 845 // expands to: 846 // pcalau12i $rd, %pc_hi20(sym) 847 // addi.w/d $rd, rd, %pc_lo12(sym) 848 MCRegister DestReg = Inst.getOperand(0).getReg(); 849 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 850 InstSeq Insts; 851 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 852 853 Insts.push_back(LoongArchAsmParser::Inst( 854 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 855 Insts.push_back( 856 LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 857 858 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 859 } 860 861 void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, 862 MCStreamer &Out) { 863 // la.pcrel $rd, $rj, sym 864 // expands to: 865 // pcalau12i $rd, %pc_hi20(sym) 866 // addi.d $rj, $r0, %pc_lo12(sym) 867 // lu32i.d $rj, %pc64_lo20(sym) 868 // lu52i.d $rj, $rj, %pc64_hi12(sym) 869 // add.d $rd, $rd, $rj 870 MCRegister DestReg = Inst.getOperand(0).getReg(); 871 MCRegister TmpReg = Inst.getOperand(1).getReg(); 872 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 873 InstSeq Insts; 874 875 Insts.push_back(LoongArchAsmParser::Inst( 876 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20)); 877 Insts.push_back(LoongArchAsmParser::Inst( 878 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); 879 Insts.push_back(LoongArchAsmParser::Inst( 880 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20)); 881 Insts.push_back(LoongArchAsmParser::Inst( 882 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12)); 883 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 884 885 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 886 } 887 888 void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, 889 MCStreamer &Out) { 890 // la.got $rd, sym 891 // expands to: 892 // pcalau12i $rd, %got_pc_hi20(sym) 893 // ld.w/d $rd, $rd, %got_pc_lo12(sym) 894 MCRegister DestReg = Inst.getOperand(0).getReg(); 895 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 896 InstSeq Insts; 897 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 898 899 Insts.push_back(LoongArchAsmParser::Inst( 900 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 901 Insts.push_back( 902 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 903 904 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 905 } 906 907 void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, 908 MCStreamer &Out) { 909 // la.got $rd, $rj, sym 910 // expands to: 911 // pcalau12i $rd, %got_pc_hi20(sym) 912 // addi.d $rj, $r0, %got_pc_lo12(sym) 913 // lu32i.d $rj, %got64_pc_lo20(sym) 914 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 915 // ldx.d $rd, $rd, $rj 916 MCRegister DestReg = Inst.getOperand(0).getReg(); 917 MCRegister TmpReg = Inst.getOperand(1).getReg(); 918 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 919 InstSeq Insts; 920 921 Insts.push_back(LoongArchAsmParser::Inst( 922 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20)); 923 Insts.push_back(LoongArchAsmParser::Inst( 924 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 925 Insts.push_back(LoongArchAsmParser::Inst( 926 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 927 Insts.push_back(LoongArchAsmParser::Inst( 928 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 929 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 930 931 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 932 } 933 934 void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, 935 MCStreamer &Out) { 936 // la.tls.le $rd, sym 937 // expands to: 938 // lu12i.w $rd, %le_hi20(sym) 939 // ori $rd, $rd, %le_lo12(sym) 940 MCRegister DestReg = Inst.getOperand(0).getReg(); 941 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 942 InstSeq Insts; 943 944 Insts.push_back(LoongArchAsmParser::Inst( 945 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20)); 946 Insts.push_back(LoongArchAsmParser::Inst( 947 LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12)); 948 949 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 950 } 951 952 void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, 953 MCStreamer &Out) { 954 // la.tls.ie $rd, sym 955 // expands to: 956 // pcalau12i $rd, %ie_pc_hi20(sym) 957 // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 958 MCRegister DestReg = Inst.getOperand(0).getReg(); 959 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 960 InstSeq Insts; 961 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 962 963 Insts.push_back(LoongArchAsmParser::Inst( 964 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 965 Insts.push_back(LoongArchAsmParser::Inst( 966 LD, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 967 968 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 969 } 970 971 void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, 972 MCStreamer &Out) { 973 // la.tls.ie $rd, $rj, sym 974 // expands to: 975 // pcalau12i $rd, %ie_pc_hi20(sym) 976 // addi.d $rj, $r0, %ie_pc_lo12(sym) 977 // lu32i.d $rj, %ie64_pc_lo20(sym) 978 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym) 979 // ldx.d $rd, $rd, $rj 980 MCRegister DestReg = Inst.getOperand(0).getReg(); 981 MCRegister TmpReg = Inst.getOperand(1).getReg(); 982 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 983 InstSeq Insts; 984 985 Insts.push_back(LoongArchAsmParser::Inst( 986 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20)); 987 Insts.push_back(LoongArchAsmParser::Inst( 988 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12)); 989 Insts.push_back(LoongArchAsmParser::Inst( 990 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20)); 991 Insts.push_back(LoongArchAsmParser::Inst( 992 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12)); 993 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D)); 994 995 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 996 } 997 998 void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, 999 MCStreamer &Out) { 1000 // la.tls.ld $rd, sym 1001 // expands to: 1002 // pcalau12i $rd, %ld_pc_hi20(sym) 1003 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1004 MCRegister DestReg = Inst.getOperand(0).getReg(); 1005 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1006 InstSeq Insts; 1007 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1008 1009 Insts.push_back(LoongArchAsmParser::Inst( 1010 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1011 Insts.push_back(LoongArchAsmParser::Inst( 1012 ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1013 1014 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1015 } 1016 1017 void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, 1018 MCStreamer &Out) { 1019 // la.tls.ld $rd, $rj, sym 1020 // expands to: 1021 // pcalau12i $rd, %ld_pc_hi20(sym) 1022 // addi.d $rj, $r0, %got_pc_lo12(sym) 1023 // lu32i.d $rj, %got64_pc_lo20(sym) 1024 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1025 // add.d $rd, $rd, $rj 1026 MCRegister DestReg = Inst.getOperand(0).getReg(); 1027 MCRegister TmpReg = Inst.getOperand(1).getReg(); 1028 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1029 InstSeq Insts; 1030 1031 Insts.push_back(LoongArchAsmParser::Inst( 1032 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20)); 1033 Insts.push_back(LoongArchAsmParser::Inst( 1034 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1035 Insts.push_back(LoongArchAsmParser::Inst( 1036 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1037 Insts.push_back(LoongArchAsmParser::Inst( 1038 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1039 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1040 1041 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1042 } 1043 1044 void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, 1045 MCStreamer &Out) { 1046 // la.tls.gd $rd, sym 1047 // expands to: 1048 // pcalau12i $rd, %gd_pc_hi20(sym) 1049 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 1050 MCRegister DestReg = Inst.getOperand(0).getReg(); 1051 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1052 InstSeq Insts; 1053 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 1054 1055 Insts.push_back(LoongArchAsmParser::Inst( 1056 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1057 Insts.push_back(LoongArchAsmParser::Inst( 1058 ADDI, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1059 1060 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); 1061 } 1062 1063 void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, 1064 MCStreamer &Out) { 1065 // la.tls.gd $rd, $rj, sym 1066 // expands to: 1067 // pcalau12i $rd, %gd_pc_hi20(sym) 1068 // addi.d $rj, $r0, %got_pc_lo12(sym) 1069 // lu32i.d $rj, %got64_pc_lo20(sym) 1070 // lu52i.d $rj, $rj, %got64_pc_hi12(sym) 1071 // add.d $rd, $rd, $rj 1072 MCRegister DestReg = Inst.getOperand(0).getReg(); 1073 MCRegister TmpReg = Inst.getOperand(1).getReg(); 1074 const MCExpr *Symbol = Inst.getOperand(2).getExpr(); 1075 InstSeq Insts; 1076 1077 Insts.push_back(LoongArchAsmParser::Inst( 1078 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20)); 1079 Insts.push_back(LoongArchAsmParser::Inst( 1080 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); 1081 Insts.push_back(LoongArchAsmParser::Inst( 1082 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20)); 1083 Insts.push_back(LoongArchAsmParser::Inst( 1084 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12)); 1085 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D)); 1086 1087 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out); 1088 } 1089 1090 void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc, 1091 MCStreamer &Out) { 1092 MCRegister DestReg = Inst.getOperand(0).getReg(); 1093 int64_t Imm = Inst.getOperand(1).getImm(); 1094 MCRegister SrcReg = LoongArch::R0; 1095 1096 if (Inst.getOpcode() == LoongArch::PseudoLI_W) 1097 Imm = SignExtend64<32>(Imm); 1098 1099 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 1100 unsigned Opc = Inst.Opc; 1101 if (Opc == LoongArch::LU12I_W) 1102 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm), 1103 getSTI()); 1104 else 1105 Out.emitInstruction( 1106 MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm), 1107 getSTI()); 1108 SrcReg = DestReg; 1109 } 1110 } 1111 1112 bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 1113 OperandVector &Operands, 1114 MCStreamer &Out) { 1115 Inst.setLoc(IDLoc); 1116 switch (Inst.getOpcode()) { 1117 default: 1118 break; 1119 case LoongArch::PseudoLA_ABS: 1120 case LoongArch::PseudoLA_ABS_LARGE: 1121 emitLoadAddressAbs(Inst, IDLoc, Out); 1122 return false; 1123 case LoongArch::PseudoLA_PCREL: 1124 emitLoadAddressPcrel(Inst, IDLoc, Out); 1125 return false; 1126 case LoongArch::PseudoLA_PCREL_LARGE: 1127 emitLoadAddressPcrelLarge(Inst, IDLoc, Out); 1128 return false; 1129 case LoongArch::PseudoLA_GOT: 1130 emitLoadAddressGot(Inst, IDLoc, Out); 1131 return false; 1132 case LoongArch::PseudoLA_GOT_LARGE: 1133 emitLoadAddressGotLarge(Inst, IDLoc, Out); 1134 return false; 1135 case LoongArch::PseudoLA_TLS_LE: 1136 emitLoadAddressTLSLE(Inst, IDLoc, Out); 1137 return false; 1138 case LoongArch::PseudoLA_TLS_IE: 1139 emitLoadAddressTLSIE(Inst, IDLoc, Out); 1140 return false; 1141 case LoongArch::PseudoLA_TLS_IE_LARGE: 1142 emitLoadAddressTLSIELarge(Inst, IDLoc, Out); 1143 return false; 1144 case LoongArch::PseudoLA_TLS_LD: 1145 emitLoadAddressTLSLD(Inst, IDLoc, Out); 1146 return false; 1147 case LoongArch::PseudoLA_TLS_LD_LARGE: 1148 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out); 1149 return false; 1150 case LoongArch::PseudoLA_TLS_GD: 1151 emitLoadAddressTLSGD(Inst, IDLoc, Out); 1152 return false; 1153 case LoongArch::PseudoLA_TLS_GD_LARGE: 1154 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out); 1155 return false; 1156 case LoongArch::PseudoLI_W: 1157 case LoongArch::PseudoLI_D: 1158 emitLoadImm(Inst, IDLoc, Out); 1159 return false; 1160 } 1161 Out.emitInstruction(Inst, getSTI()); 1162 return false; 1163 } 1164 1165 unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1166 unsigned Opc = Inst.getOpcode(); 1167 switch (Opc) { 1168 default: 1169 if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { 1170 unsigned Rd = Inst.getOperand(0).getReg(); 1171 unsigned Rk = Inst.getOperand(1).getReg(); 1172 unsigned Rj = Inst.getOperand(2).getReg(); 1173 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0) 1174 return Match_RequiresAMORdDifferRkRj; 1175 } 1176 break; 1177 case LoongArch::PseudoLA_PCREL_LARGE: 1178 case LoongArch::PseudoLA_GOT_LARGE: 1179 case LoongArch::PseudoLA_TLS_IE_LARGE: 1180 case LoongArch::PseudoLA_TLS_LD_LARGE: 1181 case LoongArch::PseudoLA_TLS_GD_LARGE: { 1182 unsigned Rd = Inst.getOperand(0).getReg(); 1183 unsigned Rj = Inst.getOperand(1).getReg(); 1184 if (Rd == Rj) 1185 return Match_RequiresLAORdDifferRj; 1186 break; 1187 } 1188 case LoongArch::CSRXCHG: 1189 case LoongArch::GCSRXCHG: { 1190 unsigned Rj = Inst.getOperand(2).getReg(); 1191 if (Rj == LoongArch::R0 || Rj == LoongArch::R1) 1192 return Match_RequiresOpnd2NotR0R1; 1193 return Match_Success; 1194 } 1195 case LoongArch::BSTRINS_W: 1196 case LoongArch::BSTRINS_D: 1197 case LoongArch::BSTRPICK_W: 1198 case LoongArch::BSTRPICK_D: { 1199 unsigned Opc = Inst.getOpcode(); 1200 const signed Msb = 1201 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 1202 ? Inst.getOperand(3).getImm() 1203 : Inst.getOperand(2).getImm(); 1204 const signed Lsb = 1205 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D) 1206 ? Inst.getOperand(4).getImm() 1207 : Inst.getOperand(3).getImm(); 1208 if (Msb < Lsb) 1209 return Match_RequiresMsbNotLessThanLsb; 1210 return Match_Success; 1211 } 1212 } 1213 1214 return Match_Success; 1215 } 1216 1217 unsigned 1218 LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 1219 unsigned Kind) { 1220 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp); 1221 if (!Op.isReg()) 1222 return Match_InvalidOperand; 1223 1224 MCRegister Reg = Op.getReg(); 1225 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 1226 // register from FPR32 to FPR64 if necessary. 1227 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) && 1228 Kind == MCK_FPR64) { 1229 Op.setReg(convertFPR32ToFPR64(Reg)); 1230 return Match_Success; 1231 } 1232 1233 return Match_InvalidOperand; 1234 } 1235 1236 bool LoongArchAsmParser::generateImmOutOfRangeError( 1237 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 1238 const Twine &Msg = "immediate must be an integer in the range") { 1239 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1240 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 1241 } 1242 1243 bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1244 OperandVector &Operands, 1245 MCStreamer &Out, 1246 uint64_t &ErrorInfo, 1247 bool MatchingInlineAsm) { 1248 MCInst Inst; 1249 FeatureBitset MissingFeatures; 1250 1251 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 1252 MatchingInlineAsm); 1253 switch (Result) { 1254 default: 1255 break; 1256 case Match_Success: 1257 return processInstruction(Inst, IDLoc, Operands, Out); 1258 case Match_MissingFeature: { 1259 assert(MissingFeatures.any() && "Unknown missing features!"); 1260 bool FirstFeature = true; 1261 std::string Msg = "instruction requires the following:"; 1262 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 1263 if (MissingFeatures[i]) { 1264 Msg += FirstFeature ? " " : ", "; 1265 Msg += getSubtargetFeatureName(i); 1266 FirstFeature = false; 1267 } 1268 } 1269 return Error(IDLoc, Msg); 1270 } 1271 case Match_MnemonicFail: { 1272 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 1273 std::string Suggestion = LoongArchMnemonicSpellCheck( 1274 ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0); 1275 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 1276 } 1277 case Match_InvalidOperand: { 1278 SMLoc ErrorLoc = IDLoc; 1279 if (ErrorInfo != ~0ULL) { 1280 if (ErrorInfo >= Operands.size()) 1281 return Error(ErrorLoc, "too few operands for instruction"); 1282 1283 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1284 if (ErrorLoc == SMLoc()) 1285 ErrorLoc = IDLoc; 1286 } 1287 return Error(ErrorLoc, "invalid operand for instruction"); 1288 } 1289 } 1290 1291 // Handle the case when the error message is of specific type 1292 // other than the generic Match_InvalidOperand, and the 1293 // corresponding operand is missing. 1294 if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 1295 SMLoc ErrorLoc = IDLoc; 1296 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 1297 return Error(ErrorLoc, "too few operands for instruction"); 1298 } 1299 1300 switch (Result) { 1301 default: 1302 break; 1303 case Match_RequiresMsbNotLessThanLsb: { 1304 SMLoc ErrorStart = Operands[3]->getStartLoc(); 1305 return Error(ErrorStart, "msb is less than lsb", 1306 SMRange(ErrorStart, Operands[4]->getEndLoc())); 1307 } 1308 case Match_RequiresOpnd2NotR0R1: 1309 return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); 1310 case Match_RequiresAMORdDifferRkRj: 1311 return Error(Operands[1]->getStartLoc(), 1312 "$rd must be different from both $rk and $rj"); 1313 case Match_RequiresLAORdDifferRj: 1314 return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj"); 1315 case Match_InvalidUImm1: 1316 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1317 /*Upper=*/(1 << 1) - 1); 1318 case Match_InvalidUImm2: 1319 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1320 /*Upper=*/(1 << 2) - 1); 1321 case Match_InvalidUImm2plus1: 1322 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1, 1323 /*Upper=*/(1 << 2)); 1324 case Match_InvalidUImm3: 1325 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1326 /*Upper=*/(1 << 3) - 1); 1327 case Match_InvalidUImm4: 1328 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1329 /*Upper=*/(1 << 4) - 1); 1330 case Match_InvalidUImm5: 1331 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1332 /*Upper=*/(1 << 5) - 1); 1333 case Match_InvalidUImm6: 1334 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1335 /*Upper=*/(1 << 6) - 1); 1336 case Match_InvalidUImm7: 1337 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1338 /*Upper=*/(1 << 7) - 1); 1339 case Match_InvalidUImm8: 1340 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1341 /*Upper=*/(1 << 8) - 1); 1342 case Match_InvalidUImm12: 1343 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1344 /*Upper=*/(1 << 12) - 1); 1345 case Match_InvalidUImm12ori: 1346 return generateImmOutOfRangeError( 1347 Operands, ErrorInfo, /*Lower=*/0, 1348 /*Upper=*/(1 << 12) - 1, 1349 "operand must be a symbol with modifier (e.g. %abs_lo12) or an " 1350 "integer in the range"); 1351 case Match_InvalidUImm14: 1352 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1353 /*Upper=*/(1 << 14) - 1); 1354 case Match_InvalidUImm15: 1355 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, 1356 /*Upper=*/(1 << 15) - 1); 1357 case Match_InvalidSImm5: 1358 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4), 1359 /*Upper=*/(1 << 4) - 1); 1360 case Match_InvalidSImm8: 1361 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7), 1362 /*Upper=*/(1 << 7) - 1); 1363 case Match_InvalidSImm8lsl1: 1364 return generateImmOutOfRangeError( 1365 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2, 1366 "immediate must be a multiple of 2 in the range"); 1367 case Match_InvalidSImm8lsl2: 1368 return generateImmOutOfRangeError( 1369 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4, 1370 "immediate must be a multiple of 4 in the range"); 1371 case Match_InvalidSImm10: 1372 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9), 1373 /*Upper=*/(1 << 9) - 1); 1374 case Match_InvalidSImm8lsl3: 1375 return generateImmOutOfRangeError( 1376 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8, 1377 "immediate must be a multiple of 8 in the range"); 1378 case Match_InvalidSImm9lsl3: 1379 return generateImmOutOfRangeError( 1380 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8, 1381 "immediate must be a multiple of 8 in the range"); 1382 case Match_InvalidSImm10lsl2: 1383 return generateImmOutOfRangeError( 1384 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4, 1385 "immediate must be a multiple of 4 in the range"); 1386 case Match_InvalidSImm11lsl1: 1387 return generateImmOutOfRangeError( 1388 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2, 1389 "immediate must be a multiple of 2 in the range"); 1390 case Match_InvalidSImm12: 1391 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1392 /*Upper=*/(1 << 11) - 1); 1393 case Match_InvalidSImm12addlike: 1394 return generateImmOutOfRangeError( 1395 Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1396 /*Upper=*/(1 << 11) - 1, 1397 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer " 1398 "in the range"); 1399 case Match_InvalidSImm12lu52id: 1400 return generateImmOutOfRangeError( 1401 Operands, ErrorInfo, /*Lower=*/-(1 << 11), 1402 /*Upper=*/(1 << 11) - 1, 1403 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an " 1404 "integer in the range"); 1405 case Match_InvalidSImm13: 1406 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12), 1407 /*Upper=*/(1 << 12) - 1); 1408 case Match_InvalidSImm14lsl2: 1409 return generateImmOutOfRangeError( 1410 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4, 1411 "immediate must be a multiple of 4 in the range"); 1412 case Match_InvalidSImm16: 1413 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15), 1414 /*Upper=*/(1 << 15) - 1); 1415 case Match_InvalidSImm16lsl2: 1416 return generateImmOutOfRangeError( 1417 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4, 1418 "operand must be a symbol with modifier (e.g. %b16) or an integer " 1419 "in the range"); 1420 case Match_InvalidSImm20: 1421 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1422 /*Upper=*/(1 << 19) - 1); 1423 case Match_InvalidSImm20lu12iw: 1424 return generateImmOutOfRangeError( 1425 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1426 /*Upper=*/(1 << 19) - 1, 1427 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer " 1428 "in the range"); 1429 case Match_InvalidSImm20lu32id: 1430 return generateImmOutOfRangeError( 1431 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1432 /*Upper=*/(1 << 19) - 1, 1433 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an " 1434 "integer in the range"); 1435 case Match_InvalidSImm20pcalau12i: 1436 return generateImmOutOfRangeError( 1437 Operands, ErrorInfo, /*Lower=*/-(1 << 19), 1438 /*Upper=*/(1 << 19) - 1, 1439 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer " 1440 "in the range"); 1441 case Match_InvalidSImm21lsl2: 1442 return generateImmOutOfRangeError( 1443 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, 1444 "operand must be a symbol with modifier (e.g. %b21) or an integer " 1445 "in the range"); 1446 case Match_InvalidSImm26Operand: 1447 return generateImmOutOfRangeError( 1448 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4, 1449 "operand must be a bare symbol name or an immediate must be a multiple " 1450 "of 4 in the range"); 1451 case Match_InvalidImm32: { 1452 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1453 return Error(ErrorLoc, "operand must be a 32 bit immediate"); 1454 } 1455 case Match_InvalidBareSymbol: { 1456 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); 1457 return Error(ErrorLoc, "operand must be a bare symbol name"); 1458 } 1459 } 1460 llvm_unreachable("Unknown match type detected!"); 1461 } 1462 1463 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser() { 1464 RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target()); 1465 RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target()); 1466 } 1467