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