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