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