LLVM 19.0.0git
LoongArchAsmParser.cpp
Go to the documentation of this file.
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
14#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCValue.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "loongarch-asm-parser"
30
31namespace {
32class 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;
39 Inst(unsigned Opc,
41 : Opc(Opc), VK(VK) {}
42 };
43 using InstSeq = SmallVector<Inst>;
44
45 /// Parse a register as used in CFI directives.
46 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
48 SMLoc &EndLoc) override;
49
51 SMLoc NameLoc, OperandVector &Operands) override;
52
53 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
56 bool MatchingInlineAsm) override;
57
58 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
59
61 unsigned Kind) override;
62
63 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
64 int64_t Lower, int64_t Upper,
65 const Twine &Msg);
66
67 /// Helper for processing MC instructions that have been successfully matched
68 /// by MatchAndEmitInstruction.
69 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
70 MCStreamer &Out);
71
72// Auto-generated instruction matching functions.
73#define GET_ASSEMBLER_HEADER
74#include "LoongArchGenAsmMatcher.inc"
75
78 ParseStatus parseOperandWithModifier(OperandVector &Operands);
79 ParseStatus parseSImm26Operand(OperandVector &Operands);
80 ParseStatus parseAtomicMemOp(OperandVector &Operands);
81
82 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
83
84 // Helper to emit the sequence of instructions generated by the
85 // "emitLoadAddress*" functions.
86 void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
87 const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
88 SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
89
90 // Helper to emit pseudo instruction "la.abs $rd, sym".
91 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
92
93 // Helper to emit pseudo instruction "la.pcrel $rd, sym".
94 void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
95 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
96 void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
97
98 // Helper to emit pseudo instruction "la.got $rd, sym".
99 void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
100 // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
101 void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
102
103 // Helper to emit pseudo instruction "la.tls.le $rd, sym".
104 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
105
106 // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
107 void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
108 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
109 void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
110
111 // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
112 void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
113 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
114 void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
115
116 // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
117 void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
118 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
119 void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
120
121 // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
122 void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
123 void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
124 // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
125 void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc,
126 MCStreamer &Out);
127
128 // Helper to emit pseudo instruction "li.w/d $rd, $imm".
129 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
130
131 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
132 void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
133 bool IsTailCall);
134
135public:
136 enum LoongArchMatchResultTy {
137 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
138 Match_RequiresMsbNotLessThanLsb,
139 Match_RequiresOpnd2NotR0R1,
140 Match_RequiresAMORdDifferRkRj,
141 Match_RequiresLAORdDifferRj,
142 Match_RequiresLAORdR4,
143#define GET_OPERAND_DIAGNOSTIC_TYPES
144#include "LoongArchGenAsmMatcher.inc"
145#undef GET_OPERAND_DIAGNOSTIC_TYPES
146 };
147
148 static bool classifySymbolRef(const MCExpr *Expr,
150
151 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
152 const MCInstrInfo &MII, const MCTargetOptions &Options)
153 : MCTargetAsmParser(Options, STI, MII) {
154 Parser.addAliasForDirective(".half", ".2byte");
155 Parser.addAliasForDirective(".hword", ".2byte");
156 Parser.addAliasForDirective(".word", ".4byte");
157 Parser.addAliasForDirective(".dword", ".8byte");
158
159 // Initialize the set of available features.
160 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
161 }
162};
163
164// Instances of this class represent a parsed LoongArch machine instruction.
165class LoongArchOperand : public MCParsedAsmOperand {
166 enum class KindTy {
167 Token,
168 Register,
169 Immediate,
170 } Kind;
171
172 struct RegOp {
173 MCRegister RegNum;
174 };
175
176 struct ImmOp {
177 const MCExpr *Val;
178 };
179
180 SMLoc StartLoc, EndLoc;
181 union {
182 StringRef Tok;
183 struct RegOp Reg;
184 struct ImmOp Imm;
185 };
186
187public:
188 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
189
190 bool isToken() const override { return Kind == KindTy::Token; }
191 bool isReg() const override { return Kind == KindTy::Register; }
192 bool isImm() const override { return Kind == KindTy::Immediate; }
193 bool isMem() const override { return false; }
194 void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
195 bool isGPR() const {
196 return Kind == KindTy::Register &&
197 LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
198 Reg.RegNum);
199 }
200
201 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
203 if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
204 VK = LE->getKind();
205 return false;
206 }
207
208 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
209 Imm = CE->getValue();
210 return true;
211 }
212
213 return false;
214 }
215
216 template <unsigned N, int P = 0> bool isUImm() const {
217 if (!isImm())
218 return false;
219
220 int64_t Imm;
222 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
223 return IsConstantImm && isUInt<N>(Imm - P) &&
225 }
226
227 template <unsigned N, unsigned S = 0> bool isSImm() const {
228 if (!isImm())
229 return false;
230
231 int64_t Imm;
233 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
234 return IsConstantImm && isShiftedInt<N, S>(Imm) &&
236 }
237
238 bool isBareSymbol() const {
239 int64_t Imm;
241 // Must be of 'immediate' type but not a constant.
242 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
243 return false;
244 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
246 }
247
248 bool isTPRelAddSymbol() const {
249 int64_t Imm;
251 // Must be of 'immediate' type but not a constant.
252 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
253 return false;
254 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
256 }
257
258 bool isUImm1() const { return isUImm<1>(); }
259 bool isUImm2() const { return isUImm<2>(); }
260 bool isUImm2plus1() const { return isUImm<2, 1>(); }
261 bool isUImm3() const { return isUImm<3>(); }
262 bool isUImm4() const { return isUImm<4>(); }
263 bool isSImm5() const { return isSImm<5>(); }
264 bool isUImm5() const { return isUImm<5>(); }
265 bool isUImm6() const { return isUImm<6>(); }
266 bool isUImm7() const { return isUImm<7>(); }
267 bool isSImm8() const { return isSImm<8>(); }
268 bool isSImm8lsl1() const { return isSImm<8, 1>(); }
269 bool isSImm8lsl2() const { return isSImm<8, 2>(); }
270 bool isSImm8lsl3() const { return isSImm<8, 3>(); }
271 bool isUImm8() const { return isUImm<8>(); }
272 bool isSImm9lsl3() const { return isSImm<9, 3>(); }
273 bool isSImm10() const { return isSImm<10>(); }
274 bool isSImm10lsl2() const { return isSImm<10, 2>(); }
275 bool isSImm11lsl1() const { return isSImm<11, 1>(); }
276 bool isSImm12() const { return isSImm<12>(); }
277
278 bool isSImm12addlike() const {
279 if (!isImm())
280 return false;
281
282 int64_t Imm;
284 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
285 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
292 return IsConstantImm
293 ? isInt<12>(Imm) && IsValidKind
294 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
295 IsValidKind;
296 }
297
298 bool isSImm12lu52id() const {
299 if (!isImm())
300 return false;
301
302 int64_t Imm;
304 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
305 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
315 return IsConstantImm
316 ? isInt<12>(Imm) && IsValidKind
317 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
318 IsValidKind;
319 }
320
321 bool isUImm12() const { return isUImm<12>(); }
322
323 bool isUImm12ori() const {
324 if (!isImm())
325 return false;
326
327 int64_t Imm;
329 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
330 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
339 return IsConstantImm
340 ? isUInt<12>(Imm) && IsValidKind
341 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
342 IsValidKind;
343 }
344
345 bool isSImm13() const { return isSImm<13>(); }
346 bool isUImm14() const { return isUImm<14>(); }
347 bool isUImm15() const { return isUImm<15>(); }
348
349 bool isSImm14lsl2() const { return isSImm<14, 2>(); }
350 bool isSImm16() const { return isSImm<16>(); }
351
352 bool isSImm16lsl2() const {
353 if (!isImm())
354 return false;
355
356 int64_t Imm;
358 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
359 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
363 return IsConstantImm
364 ? isShiftedInt<16, 2>(Imm) && IsValidKind
365 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
366 IsValidKind;
367 }
368
369 bool isSImm20() const { return isSImm<20>(); }
370
371 bool isSImm20pcalau12i() const {
372 if (!isImm())
373 return false;
374
375 int64_t Imm;
377 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
378 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
385 return IsConstantImm
386 ? isInt<20>(Imm) && IsValidKind
387 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
388 IsValidKind;
389 }
390
391 bool isSImm20lu12iw() const {
392 if (!isImm())
393 return false;
394
395 int64_t Imm;
397 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
398 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
407 return IsConstantImm
408 ? isInt<20>(Imm) && IsValidKind
409 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
410 IsValidKind;
411 }
412
413 bool isSImm20lu32id() const {
414 if (!isImm())
415 return false;
416
417 int64_t Imm;
419 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
420 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
430
431 return IsConstantImm
432 ? isInt<20>(Imm) && IsValidKind
433 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
434 IsValidKind;
435 }
436
437 bool isSImm20pcaddu18i() const {
438 if (!isImm())
439 return false;
440
441 int64_t Imm;
443 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
444 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
446
447 return IsConstantImm
448 ? isInt<20>(Imm) && IsValidKind
449 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
450 IsValidKind;
451 }
452
453 bool isSImm21lsl2() const {
454 if (!isImm())
455 return false;
456
457 int64_t Imm;
459 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
460 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
462 return IsConstantImm
463 ? isShiftedInt<21, 2>(Imm) && IsValidKind
464 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
465 IsValidKind;
466 }
467
468 bool isSImm26Operand() const {
469 if (!isImm())
470 return false;
471
472 int64_t Imm;
474 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
475 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
479 return IsConstantImm
480 ? isShiftedInt<26, 2>(Imm) && IsValidKind
481 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
482 IsValidKind;
483 }
484
485 bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
486 bool isImm64() const {
487 if (!isImm())
488 return false;
489 int64_t Imm;
491 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
492 return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
493 }
494
495 /// Gets location of the first token of this operand.
496 SMLoc getStartLoc() const override { return StartLoc; }
497 /// Gets location of the last token of this operand.
498 SMLoc getEndLoc() const override { return EndLoc; }
499
500 MCRegister getReg() const override {
501 assert(Kind == KindTy::Register && "Invalid type access!");
502 return Reg.RegNum;
503 }
504
505 const MCExpr *getImm() const {
506 assert(Kind == KindTy::Immediate && "Invalid type access!");
507 return Imm.Val;
508 }
509
510 StringRef getToken() const {
511 assert(Kind == KindTy::Token && "Invalid type access!");
512 return Tok;
513 }
514
515 void print(raw_ostream &OS) const override {
516 auto RegName = [](MCRegister Reg) {
517 if (Reg)
519 else
520 return "noreg";
521 };
522
523 switch (Kind) {
524 case KindTy::Immediate:
525 OS << *getImm();
526 break;
527 case KindTy::Register:
528 OS << "<register " << RegName(getReg()) << ">";
529 break;
530 case KindTy::Token:
531 OS << "'" << getToken() << "'";
532 break;
533 }
534 }
535
536 static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
537 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
538 Op->Tok = Str;
539 Op->StartLoc = S;
540 Op->EndLoc = S;
541 return Op;
542 }
543
544 static std::unique_ptr<LoongArchOperand> createReg(unsigned RegNo, SMLoc S,
545 SMLoc E) {
546 auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
547 Op->Reg.RegNum = RegNo;
548 Op->StartLoc = S;
549 Op->EndLoc = E;
550 return Op;
551 }
552
553 static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
554 SMLoc E) {
555 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
556 Op->Imm.Val = Val;
557 Op->StartLoc = S;
558 Op->EndLoc = E;
559 return Op;
560 }
561
562 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
563 if (auto CE = dyn_cast<MCConstantExpr>(Expr))
564 Inst.addOperand(MCOperand::createImm(CE->getValue()));
565 else
567 }
568
569 // Used by the TableGen Code.
570 void addRegOperands(MCInst &Inst, unsigned N) const {
571 assert(N == 1 && "Invalid number of operands!");
573 }
574 void addImmOperands(MCInst &Inst, unsigned N) const {
575 assert(N == 1 && "Invalid number of operands!");
576 addExpr(Inst, getImm());
577 }
578};
579} // end namespace
580
581#define GET_REGISTER_MATCHER
582#define GET_SUBTARGET_FEATURE_NAME
583#define GET_MATCHER_IMPLEMENTATION
584#define GET_MNEMONIC_SPELL_CHECKER
585#include "LoongArchGenAsmMatcher.inc"
586
588 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
589 return Reg - LoongArch::F0 + LoongArch::F0_64;
590}
591
592// Attempts to match Name as a register (either using the default name or
593// alternative ABI names), setting RegNo to the matching register. Upon
594// failure, returns true and sets RegNo to 0.
596 RegNo = MatchRegisterName(Name);
597 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
598 // match always matches the 32-bit variant, and not the 64-bit one.
599 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
600 // The default FPR register class is based on the tablegen enum ordering.
601 static_assert(LoongArch::F0 < LoongArch::F0_64,
602 "FPR matching must be updated");
603 if (RegNo == LoongArch::NoRegister)
604 RegNo = MatchRegisterAltName(Name);
605
606 return RegNo == LoongArch::NoRegister;
607}
608
609bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
610 SMLoc &EndLoc) {
611 return Error(getLoc(), "invalid register number");
612}
613
614ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
615 SMLoc &StartLoc,
616 SMLoc &EndLoc) {
617 llvm_unreachable("Unimplemented function.");
618}
619
620bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
623
624 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
625 Kind = RE->getKind();
626 Expr = RE->getSubExpr();
627 }
628
629 MCValue Res;
630 if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
632 return false;
633}
634
635ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
636 if (!parseOptionalToken(AsmToken::Dollar))
638 if (getLexer().getKind() != AsmToken::Identifier)
640
641 StringRef Name = getLexer().getTok().getIdentifier();
642 MCRegister RegNo;
644 if (RegNo == LoongArch::NoRegister)
646
647 SMLoc S = getLoc();
649 getLexer().Lex();
650 Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
651
653}
654
655ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
656 SMLoc S = getLoc();
657 SMLoc E;
658 const MCExpr *Res;
659
660 switch (getLexer().getKind()) {
661 default:
663 case AsmToken::LParen:
664 case AsmToken::Dot:
665 case AsmToken::Minus:
666 case AsmToken::Plus:
668 case AsmToken::Tilde:
670 case AsmToken::String:
672 if (getParser().parseExpression(Res, E))
674 break;
676 return parseOperandWithModifier(Operands);
677 }
678
679 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
681}
682
684LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
685 SMLoc S = getLoc();
686 SMLoc E;
687
688 if (getLexer().getKind() != AsmToken::Percent)
689 return Error(getLoc(), "expected '%' for operand modifier");
690
691 getParser().Lex(); // Eat '%'
692
693 if (getLexer().getKind() != AsmToken::Identifier)
694 return Error(getLoc(), "expected valid identifier for operand modifier");
695 StringRef Identifier = getParser().getTok().getIdentifier();
699 return Error(getLoc(), "unrecognized operand modifier");
700
701 getParser().Lex(); // Eat the identifier
702 if (getLexer().getKind() != AsmToken::LParen)
703 return Error(getLoc(), "expected '('");
704 getParser().Lex(); // Eat '('
705
706 const MCExpr *SubExpr;
707 if (getParser().parseParenExpression(SubExpr, E))
709
710 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
711 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
713}
714
715ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
716 SMLoc S = getLoc();
717 const MCExpr *Res;
718
719 if (getLexer().getKind() == AsmToken::Percent)
720 return parseOperandWithModifier(Operands);
721
722 if (getLexer().getKind() != AsmToken::Identifier)
724
726 if (getParser().parseIdentifier(Identifier))
728
730
731 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
734 getContext());
735 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
737}
738
739ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
740 // Parse "$r*".
741 if (!parseRegister(Operands).isSuccess())
743
744 // If there is a next operand and it is 0, ignore it. Otherwise print a
745 // diagnostic message.
746 if (parseOptionalToken(AsmToken::Comma)) {
747 int64_t ImmVal;
748 SMLoc ImmStart = getLoc();
749 if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
751 if (ImmVal)
752 return Error(ImmStart, "optional integer offset must be 0");
753 }
754
756}
757/// Looks at a token type and creates the relevant operand from this
758/// information, adding to Operands. Return true upon an error.
759bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
760 StringRef Mnemonic) {
761 // Check if the current operand has a custom associated parser, if so, try to
762 // custom parse the operand, or fallback to the general approach.
764 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
765 if (Result.isSuccess())
766 return false;
767 if (Result.isFailure())
768 return true;
769
770 if (parseRegister(Operands).isSuccess() ||
771 parseImmediate(Operands).isSuccess())
772 return false;
773
774 // Finally we have exhausted all options and must declare defeat.
775 return Error(getLoc(), "unknown operand");
776}
777
778bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info,
779 StringRef Name, SMLoc NameLoc,
781 // First operand in MCInst is instruction mnemonic.
782 Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
783
784 // If there are no more operands, then finish.
785 if (parseOptionalToken(AsmToken::EndOfStatement))
786 return false;
787
788 // Parse first operand.
789 if (parseOperand(Operands, Name))
790 return true;
791
792 // Parse until end of statement, consuming commas between operands.
793 while (parseOptionalToken(AsmToken::Comma))
794 if (parseOperand(Operands, Name))
795 return true;
796
797 // Parse end of statement and return successfully.
798 if (parseOptionalToken(AsmToken::EndOfStatement))
799 return false;
800
801 SMLoc Loc = getLexer().getLoc();
802 getParser().eatToEndOfStatement();
803 return Error(Loc, "unexpected token");
804}
805
806void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
807 const MCExpr *Symbol,
809 SMLoc IDLoc, MCStreamer &Out,
810 bool RelaxHint) {
811 MCContext &Ctx = getContext();
812 for (LoongArchAsmParser::Inst &Inst : Insts) {
813 unsigned Opc = Inst.Opc;
814 LoongArchMCExpr::VariantKind VK = Inst.VK;
815 const LoongArchMCExpr *LE =
816 LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
817 switch (Opc) {
818 default:
819 llvm_unreachable("unexpected opcode");
820 case LoongArch::PCALAU12I:
821 case LoongArch::LU12I_W:
822 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
823 getSTI());
824 break;
825 case LoongArch::ORI:
826 case LoongArch::ADDI_W:
827 case LoongArch::LD_W:
828 case LoongArch::LD_D: {
830 Out.emitInstruction(
831 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
832 getSTI());
833 continue;
836 .addReg(LoongArch::R1)
837 .addReg(DestReg)
838 .addExpr(LE),
839 getSTI());
840 continue;
841 }
842 Out.emitInstruction(
843 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
844 getSTI());
845 break;
846 }
847 case LoongArch::LU32I_D:
849 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
850 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
851 .addExpr(LE),
852 getSTI());
853 break;
854 case LoongArch::LU52I_D:
855 Out.emitInstruction(
856 MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
857 getSTI());
858 break;
859 case LoongArch::ADDI_D:
860 Out.emitInstruction(
861 MCInstBuilder(Opc)
862 .addReg(TmpReg)
863 .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
864 .addExpr(LE),
865 getSTI());
866 break;
867 case LoongArch::ADD_D:
868 case LoongArch::LDX_D:
869 Out.emitInstruction(
870 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
871 getSTI());
872 break;
873 case LoongArch::JIRL:
875 .addReg(LoongArch::R1)
876 .addReg(LoongArch::R1)
877 .addExpr(LE),
878 getSTI());
879 break;
880 }
881 }
882}
883
884void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
885 MCStreamer &Out) {
886 // la.abs $rd, sym
887 // expands to:
888 // lu12i.w $rd, %abs_hi20(sym)
889 // ori $rd, $rd, %abs_lo12(sym)
890 //
891 // for 64bit appends:
892 // lu32i.d $rd, %abs64_lo20(sym)
893 // lu52i.d $rd, $rd, %abs64_hi12(sym)
894 MCRegister DestReg = Inst.getOperand(0).getReg();
895 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
896 ? Inst.getOperand(1).getExpr()
897 : Inst.getOperand(2).getExpr();
898 InstSeq Insts;
899
900 Insts.push_back(LoongArchAsmParser::Inst(
901 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
902 Insts.push_back(LoongArchAsmParser::Inst(
904
905 if (is64Bit()) {
906 Insts.push_back(LoongArchAsmParser::Inst(
907 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
908 Insts.push_back(LoongArchAsmParser::Inst(
909 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
910 }
911
912 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
913}
914
915void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
916 MCStreamer &Out) {
917 // la.pcrel $rd, sym
918 // expands to:
919 // pcalau12i $rd, %pc_hi20(sym)
920 // addi.w/d $rd, rd, %pc_lo12(sym)
921 MCRegister DestReg = Inst.getOperand(0).getReg();
922 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
923 InstSeq Insts;
924 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
925
926 Insts.push_back(LoongArchAsmParser::Inst(
927 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
928 Insts.push_back(
929 LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
930
931 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
932}
933
934void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
935 MCStreamer &Out) {
936 // la.pcrel $rd, $rj, sym
937 // expands to:
938 // pcalau12i $rd, %pc_hi20(sym)
939 // addi.d $rj, $r0, %pc_lo12(sym)
940 // lu32i.d $rj, %pc64_lo20(sym)
941 // lu52i.d $rj, $rj, %pc64_hi12(sym)
942 // add.d $rd, $rd, $rj
943 MCRegister DestReg = Inst.getOperand(0).getReg();
944 MCRegister TmpReg = Inst.getOperand(1).getReg();
945 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
946 InstSeq Insts;
947
948 Insts.push_back(LoongArchAsmParser::Inst(
949 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
950 Insts.push_back(LoongArchAsmParser::Inst(
951 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
952 Insts.push_back(LoongArchAsmParser::Inst(
953 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
954 Insts.push_back(LoongArchAsmParser::Inst(
955 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
956 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
957
958 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
959}
960
961void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
962 MCStreamer &Out) {
963 // la.got $rd, sym
964 // expands to:
965 // pcalau12i $rd, %got_pc_hi20(sym)
966 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
967 MCRegister DestReg = Inst.getOperand(0).getReg();
968 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
969 InstSeq Insts;
970 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
971
972 Insts.push_back(LoongArchAsmParser::Inst(
973 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
974 Insts.push_back(
975 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
976
977 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
978}
979
980void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
981 MCStreamer &Out) {
982 // la.got $rd, $rj, sym
983 // expands to:
984 // pcalau12i $rd, %got_pc_hi20(sym)
985 // addi.d $rj, $r0, %got_pc_lo12(sym)
986 // lu32i.d $rj, %got64_pc_lo20(sym)
987 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
988 // ldx.d $rd, $rd, $rj
989 MCRegister DestReg = Inst.getOperand(0).getReg();
990 MCRegister TmpReg = Inst.getOperand(1).getReg();
991 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
992 InstSeq Insts;
993
994 Insts.push_back(LoongArchAsmParser::Inst(
995 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
996 Insts.push_back(LoongArchAsmParser::Inst(
998 Insts.push_back(LoongArchAsmParser::Inst(
1000 Insts.push_back(LoongArchAsmParser::Inst(
1001 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1002 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1003
1004 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1005}
1006
1007void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1008 MCStreamer &Out) {
1009 // la.tls.le $rd, sym
1010 // expands to:
1011 // lu12i.w $rd, %le_hi20(sym)
1012 // ori $rd, $rd, %le_lo12(sym)
1013 MCRegister DestReg = Inst.getOperand(0).getReg();
1014 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1015 InstSeq Insts;
1016
1017 Insts.push_back(LoongArchAsmParser::Inst(
1018 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
1019 Insts.push_back(LoongArchAsmParser::Inst(
1021
1022 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1023}
1024
1025void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1026 MCStreamer &Out) {
1027 // la.tls.ie $rd, sym
1028 // expands to:
1029 // pcalau12i $rd, %ie_pc_hi20(sym)
1030 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1031 MCRegister DestReg = Inst.getOperand(0).getReg();
1032 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1033 InstSeq Insts;
1034 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1035
1036 Insts.push_back(LoongArchAsmParser::Inst(
1037 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1038 Insts.push_back(LoongArchAsmParser::Inst(
1040
1041 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1042}
1043
1044void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1045 MCStreamer &Out) {
1046 // la.tls.ie $rd, $rj, sym
1047 // expands to:
1048 // pcalau12i $rd, %ie_pc_hi20(sym)
1049 // addi.d $rj, $r0, %ie_pc_lo12(sym)
1050 // lu32i.d $rj, %ie64_pc_lo20(sym)
1051 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1052 // ldx.d $rd, $rd, $rj
1053 MCRegister DestReg = Inst.getOperand(0).getReg();
1054 MCRegister TmpReg = Inst.getOperand(1).getReg();
1055 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1056 InstSeq Insts;
1057
1058 Insts.push_back(LoongArchAsmParser::Inst(
1059 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1060 Insts.push_back(LoongArchAsmParser::Inst(
1062 Insts.push_back(LoongArchAsmParser::Inst(
1064 Insts.push_back(LoongArchAsmParser::Inst(
1066 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1067
1068 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1069}
1070
1071void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1072 MCStreamer &Out) {
1073 // la.tls.ld $rd, sym
1074 // expands to:
1075 // pcalau12i $rd, %ld_pc_hi20(sym)
1076 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1077 MCRegister DestReg = Inst.getOperand(0).getReg();
1078 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1079 InstSeq Insts;
1080 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1081
1082 Insts.push_back(LoongArchAsmParser::Inst(
1083 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1084 Insts.push_back(LoongArchAsmParser::Inst(
1086
1087 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1088}
1089
1090void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1091 MCStreamer &Out) {
1092 // la.tls.ld $rd, $rj, sym
1093 // expands to:
1094 // pcalau12i $rd, %ld_pc_hi20(sym)
1095 // addi.d $rj, $r0, %got_pc_lo12(sym)
1096 // lu32i.d $rj, %got64_pc_lo20(sym)
1097 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1098 // add.d $rd, $rd, $rj
1099 MCRegister DestReg = Inst.getOperand(0).getReg();
1100 MCRegister TmpReg = Inst.getOperand(1).getReg();
1101 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1102 InstSeq Insts;
1103
1104 Insts.push_back(LoongArchAsmParser::Inst(
1105 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1106 Insts.push_back(LoongArchAsmParser::Inst(
1107 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1108 Insts.push_back(LoongArchAsmParser::Inst(
1109 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1110 Insts.push_back(LoongArchAsmParser::Inst(
1111 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1112 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1113
1114 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1115}
1116
1117void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1118 MCStreamer &Out) {
1119 // la.tls.gd $rd, sym
1120 // expands to:
1121 // pcalau12i $rd, %gd_pc_hi20(sym)
1122 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1123 MCRegister DestReg = Inst.getOperand(0).getReg();
1124 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1125 InstSeq Insts;
1126 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1127
1128 Insts.push_back(LoongArchAsmParser::Inst(
1129 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1130 Insts.push_back(LoongArchAsmParser::Inst(
1132
1133 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1134}
1135
1136void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1137 MCStreamer &Out) {
1138 // la.tls.gd $rd, $rj, sym
1139 // expands to:
1140 // pcalau12i $rd, %gd_pc_hi20(sym)
1141 // addi.d $rj, $r0, %got_pc_lo12(sym)
1142 // lu32i.d $rj, %got64_pc_lo20(sym)
1143 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1144 // add.d $rd, $rd, $rj
1145 MCRegister DestReg = Inst.getOperand(0).getReg();
1146 MCRegister TmpReg = Inst.getOperand(1).getReg();
1147 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1148 InstSeq Insts;
1149
1150 Insts.push_back(LoongArchAsmParser::Inst(
1151 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1152 Insts.push_back(LoongArchAsmParser::Inst(
1153 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1154 Insts.push_back(LoongArchAsmParser::Inst(
1155 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1156 Insts.push_back(LoongArchAsmParser::Inst(
1157 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1158 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1159
1160 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1161}
1162
1163void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc,
1164 MCStreamer &Out) {
1165 // `la.tls.desc $rd, sym` with `la-global-with-abs` feature
1166 // for la32 expands to:
1167 // lu12i.w $rd, %desc_hi20(sym)
1168 // ori $rd, $rd, %desc_lo12(sym)
1169 // ld.w $ra, $rd, %desc_ld(sym)
1170 // jirl $ra, $ra, %desc_call(sym)
1171 //
1172 // for la64 expands to:
1173 // lu12i.w $rd, %desc_hi20(sym)
1174 // ori $rd, $rd, %desc_lo12(sym)
1175 // lu32i.d $rd, %desc64_lo20(sym)
1176 // lu52i.d $rd, $rd, %desc64_hi12(sym)
1177 // ld.d $ra, $rd, %desc_ld(sym)
1178 // jirl $ra, $ra, %desc_call(sym)
1179 MCRegister DestReg = Inst.getOperand(0).getReg();
1180 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS
1181 ? Inst.getOperand(1).getExpr()
1182 : Inst.getOperand(2).getExpr();
1183 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1184 InstSeq Insts;
1185
1186 Insts.push_back(LoongArchAsmParser::Inst(
1187 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
1188 Insts.push_back(LoongArchAsmParser::Inst(
1190
1191 if (is64Bit()) {
1192 Insts.push_back(LoongArchAsmParser::Inst(
1194 Insts.push_back(LoongArchAsmParser::Inst(
1196 }
1197
1198 Insts.push_back(
1199 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1200 Insts.push_back(LoongArchAsmParser::Inst(
1202
1203 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1204}
1205
1206void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,
1207 MCStreamer &Out) {
1208 // la.tls.desc $rd, sym
1209 // expands to:
1210 // pcalau12i $rd, %desc_pc_hi20(sym)
1211 // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1212 // ld.w/d $ra, $rd, %desc_ld(sym)
1213 // jirl $ra, $ra, %desc_call(sym)
1214 MCRegister DestReg = Inst.getOperand(0).getReg();
1215 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1216 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1217 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1218 InstSeq Insts;
1219
1220 Insts.push_back(LoongArchAsmParser::Inst(
1221 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1222 Insts.push_back(LoongArchAsmParser::Inst(
1224 Insts.push_back(
1225 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1226 Insts.push_back(LoongArchAsmParser::Inst(
1228
1229 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1230}
1231
1232void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst,
1233 SMLoc IDLoc,
1234 MCStreamer &Out) {
1235 // la.tls.desc $rd, $rj, sym
1236 // expands to:
1237 // pcalau12i $rd, %desc_pc_hi20(sym)
1238 // addi.d $rj, $r0, %desc_pc_lo12(sym)
1239 // lu32i.d $rj, %desc64_pc_lo20(sym)
1240 // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1241 // add.d $rd, $rd, $rj
1242 // ld.w/d $ra, $rd, %desc_ld(sym)
1243 // jirl $ra, $ra, %desc_call(sym)
1244 MCRegister DestReg = Inst.getOperand(0).getReg();
1245 MCRegister TmpReg = Inst.getOperand(1).getReg();
1246 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1247 InstSeq Insts;
1248
1249 Insts.push_back(LoongArchAsmParser::Inst(
1250 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1251 Insts.push_back(LoongArchAsmParser::Inst(
1253 Insts.push_back(LoongArchAsmParser::Inst(
1255 Insts.push_back(LoongArchAsmParser::Inst(
1257 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1258 Insts.push_back(LoongArchAsmParser::Inst(
1260 Insts.push_back(LoongArchAsmParser::Inst(
1262
1263 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1264}
1265
1266void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1267 MCStreamer &Out) {
1268 MCRegister DestReg = Inst.getOperand(0).getReg();
1269 int64_t Imm = Inst.getOperand(1).getImm();
1270 MCRegister SrcReg = LoongArch::R0;
1271
1272 if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1273 Imm = SignExtend64<32>(Imm);
1274
1276 unsigned Opc = Inst.Opc;
1277 if (Opc == LoongArch::LU12I_W)
1278 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addImm(Inst.Imm),
1279 getSTI());
1280 else
1281 Out.emitInstruction(
1282 MCInstBuilder(Opc).addReg(DestReg).addReg(SrcReg).addImm(Inst.Imm),
1283 getSTI());
1284 SrcReg = DestReg;
1285 }
1286}
1287
1288void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1289 MCStreamer &Out, bool IsTailCall) {
1290 // call36 sym
1291 // expands to:
1292 // pcaddu18i $ra, %call36(sym)
1293 // jirl $ra, $ra, 0
1294 //
1295 // tail36 $rj, sym
1296 // expands to:
1297 // pcaddu18i $rj, %call36(sym)
1298 // jirl $r0, $rj, 0
1299 unsigned ScratchReg =
1300 IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1;
1301 const MCExpr *Sym =
1302 IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1305
1306 Out.emitInstruction(
1307 MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
1308 getSTI());
1309 Out.emitInstruction(
1310 MCInstBuilder(LoongArch::JIRL)
1311 .addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg)
1312 .addReg(ScratchReg)
1313 .addImm(0),
1314 getSTI());
1315}
1316
1317bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1319 MCStreamer &Out) {
1320 Inst.setLoc(IDLoc);
1321 switch (Inst.getOpcode()) {
1322 default:
1323 break;
1324 case LoongArch::PseudoLA_ABS:
1325 case LoongArch::PseudoLA_ABS_LARGE:
1326 emitLoadAddressAbs(Inst, IDLoc, Out);
1327 return false;
1328 case LoongArch::PseudoLA_PCREL:
1329 emitLoadAddressPcrel(Inst, IDLoc, Out);
1330 return false;
1331 case LoongArch::PseudoLA_PCREL_LARGE:
1332 emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1333 return false;
1334 case LoongArch::PseudoLA_GOT:
1335 emitLoadAddressGot(Inst, IDLoc, Out);
1336 return false;
1337 case LoongArch::PseudoLA_GOT_LARGE:
1338 emitLoadAddressGotLarge(Inst, IDLoc, Out);
1339 return false;
1340 case LoongArch::PseudoLA_TLS_LE:
1341 emitLoadAddressTLSLE(Inst, IDLoc, Out);
1342 return false;
1343 case LoongArch::PseudoLA_TLS_IE:
1344 emitLoadAddressTLSIE(Inst, IDLoc, Out);
1345 return false;
1346 case LoongArch::PseudoLA_TLS_IE_LARGE:
1347 emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1348 return false;
1349 case LoongArch::PseudoLA_TLS_LD:
1350 emitLoadAddressTLSLD(Inst, IDLoc, Out);
1351 return false;
1352 case LoongArch::PseudoLA_TLS_LD_LARGE:
1353 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1354 return false;
1355 case LoongArch::PseudoLA_TLS_GD:
1356 emitLoadAddressTLSGD(Inst, IDLoc, Out);
1357 return false;
1358 case LoongArch::PseudoLA_TLS_GD_LARGE:
1359 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1360 return false;
1361 case LoongArch::PseudoLA_TLS_DESC_ABS:
1362 case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
1363 emitLoadAddressTLSDescAbs(Inst, IDLoc, Out);
1364 return false;
1365 case LoongArch::PseudoLA_TLS_DESC_PC:
1366 emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out);
1367 return false;
1368 case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
1369 emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out);
1370 return false;
1371 case LoongArch::PseudoLI_W:
1372 case LoongArch::PseudoLI_D:
1373 emitLoadImm(Inst, IDLoc, Out);
1374 return false;
1375 case LoongArch::PseudoCALL36:
1376 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1377 return false;
1378 case LoongArch::PseudoTAIL36:
1379 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1380 return false;
1381 }
1382 Out.emitInstruction(Inst, getSTI());
1383 return false;
1384}
1385
1386unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1387 unsigned Opc = Inst.getOpcode();
1388 switch (Opc) {
1389 default:
1390 if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {
1391 unsigned Rd = Inst.getOperand(0).getReg();
1392 unsigned Rk = Inst.getOperand(1).getReg();
1393 unsigned Rj = Inst.getOperand(2).getReg();
1394 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1395 return Match_RequiresAMORdDifferRkRj;
1396 }
1397 break;
1398 case LoongArch::PseudoLA_TLS_DESC_ABS:
1399 case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
1400 case LoongArch::PseudoLA_TLS_DESC_PC:
1401 case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: {
1402 unsigned Rd = Inst.getOperand(0).getReg();
1403 if (Rd != LoongArch::R4)
1404 return Match_RequiresLAORdR4;
1405 break;
1406 }
1407 case LoongArch::PseudoLA_PCREL_LARGE:
1408 case LoongArch::PseudoLA_GOT_LARGE:
1409 case LoongArch::PseudoLA_TLS_IE_LARGE:
1410 case LoongArch::PseudoLA_TLS_LD_LARGE:
1411 case LoongArch::PseudoLA_TLS_GD_LARGE: {
1412 unsigned Rd = Inst.getOperand(0).getReg();
1413 unsigned Rj = Inst.getOperand(1).getReg();
1414 if (Rd == Rj)
1415 return Match_RequiresLAORdDifferRj;
1416 break;
1417 }
1418 case LoongArch::CSRXCHG:
1419 case LoongArch::GCSRXCHG: {
1420 unsigned Rj = Inst.getOperand(2).getReg();
1421 if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1422 return Match_RequiresOpnd2NotR0R1;
1423 return Match_Success;
1424 }
1425 case LoongArch::BSTRINS_W:
1426 case LoongArch::BSTRINS_D:
1427 case LoongArch::BSTRPICK_W:
1428 case LoongArch::BSTRPICK_D: {
1429 unsigned Opc = Inst.getOpcode();
1430 const signed Msb =
1431 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1432 ? Inst.getOperand(3).getImm()
1433 : Inst.getOperand(2).getImm();
1434 const signed Lsb =
1435 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1436 ? Inst.getOperand(4).getImm()
1437 : Inst.getOperand(3).getImm();
1438 if (Msb < Lsb)
1439 return Match_RequiresMsbNotLessThanLsb;
1440 return Match_Success;
1441 }
1442 }
1443
1444 return Match_Success;
1445}
1446
1447unsigned
1448LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1449 unsigned Kind) {
1450 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1451 if (!Op.isReg())
1452 return Match_InvalidOperand;
1453
1454 MCRegister Reg = Op.getReg();
1455 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1456 // register from FPR32 to FPR64 if necessary.
1457 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1458 Kind == MCK_FPR64) {
1459 Op.setReg(convertFPR32ToFPR64(Reg));
1460 return Match_Success;
1461 }
1462
1463 return Match_InvalidOperand;
1464}
1465
1466bool LoongArchAsmParser::generateImmOutOfRangeError(
1467 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1468 const Twine &Msg = "immediate must be an integer in the range") {
1469 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1470 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1471}
1472
1473bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1475 MCStreamer &Out,
1477 bool MatchingInlineAsm) {
1478 MCInst Inst;
1479 FeatureBitset MissingFeatures;
1480
1481 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1482 MatchingInlineAsm);
1483 switch (Result) {
1484 default:
1485 break;
1486 case Match_Success:
1487 return processInstruction(Inst, IDLoc, Operands, Out);
1488 case Match_MissingFeature: {
1489 assert(MissingFeatures.any() && "Unknown missing features!");
1490 bool FirstFeature = true;
1491 std::string Msg = "instruction requires the following:";
1492 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1493 if (MissingFeatures[i]) {
1494 Msg += FirstFeature ? " " : ", ";
1495 Msg += getSubtargetFeatureName(i);
1496 FirstFeature = false;
1497 }
1498 }
1499 return Error(IDLoc, Msg);
1500 }
1501 case Match_MnemonicFail: {
1502 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1503 std::string Suggestion = LoongArchMnemonicSpellCheck(
1504 ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
1505 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1506 }
1507 case Match_InvalidOperand: {
1508 SMLoc ErrorLoc = IDLoc;
1509 if (ErrorInfo != ~0ULL) {
1510 if (ErrorInfo >= Operands.size())
1511 return Error(ErrorLoc, "too few operands for instruction");
1512
1513 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1514 if (ErrorLoc == SMLoc())
1515 ErrorLoc = IDLoc;
1516 }
1517 return Error(ErrorLoc, "invalid operand for instruction");
1518 }
1519 }
1520
1521 // Handle the case when the error message is of specific type
1522 // other than the generic Match_InvalidOperand, and the
1523 // corresponding operand is missing.
1524 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1525 SMLoc ErrorLoc = IDLoc;
1526 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1527 return Error(ErrorLoc, "too few operands for instruction");
1528 }
1529
1530 switch (Result) {
1531 default:
1532 break;
1533 case Match_RequiresMsbNotLessThanLsb: {
1534 SMLoc ErrorStart = Operands[3]->getStartLoc();
1535 return Error(ErrorStart, "msb is less than lsb",
1536 SMRange(ErrorStart, Operands[4]->getEndLoc()));
1537 }
1538 case Match_RequiresOpnd2NotR0R1:
1539 return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1540 case Match_RequiresAMORdDifferRkRj:
1541 return Error(Operands[1]->getStartLoc(),
1542 "$rd must be different from both $rk and $rj");
1543 case Match_RequiresLAORdDifferRj:
1544 return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
1545 case Match_RequiresLAORdR4:
1546 return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
1547 case Match_InvalidUImm1:
1548 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1549 /*Upper=*/(1 << 1) - 1);
1550 case Match_InvalidUImm2:
1551 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1552 /*Upper=*/(1 << 2) - 1);
1553 case Match_InvalidUImm2plus1:
1554 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1555 /*Upper=*/(1 << 2));
1556 case Match_InvalidUImm3:
1557 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1558 /*Upper=*/(1 << 3) - 1);
1559 case Match_InvalidUImm4:
1560 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1561 /*Upper=*/(1 << 4) - 1);
1562 case Match_InvalidUImm5:
1563 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1564 /*Upper=*/(1 << 5) - 1);
1565 case Match_InvalidUImm6:
1566 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1567 /*Upper=*/(1 << 6) - 1);
1568 case Match_InvalidUImm7:
1569 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1570 /*Upper=*/(1 << 7) - 1);
1571 case Match_InvalidUImm8:
1572 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1573 /*Upper=*/(1 << 8) - 1);
1574 case Match_InvalidUImm12:
1575 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1576 /*Upper=*/(1 << 12) - 1);
1577 case Match_InvalidUImm12ori:
1578 return generateImmOutOfRangeError(
1579 Operands, ErrorInfo, /*Lower=*/0,
1580 /*Upper=*/(1 << 12) - 1,
1581 "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1582 "integer in the range");
1583 case Match_InvalidUImm14:
1584 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1585 /*Upper=*/(1 << 14) - 1);
1586 case Match_InvalidUImm15:
1587 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1588 /*Upper=*/(1 << 15) - 1);
1589 case Match_InvalidSImm5:
1590 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1591 /*Upper=*/(1 << 4) - 1);
1592 case Match_InvalidSImm8:
1593 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1594 /*Upper=*/(1 << 7) - 1);
1595 case Match_InvalidSImm8lsl1:
1596 return generateImmOutOfRangeError(
1597 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1598 "immediate must be a multiple of 2 in the range");
1599 case Match_InvalidSImm8lsl2:
1600 return generateImmOutOfRangeError(
1601 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1602 "immediate must be a multiple of 4 in the range");
1603 case Match_InvalidSImm10:
1604 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1605 /*Upper=*/(1 << 9) - 1);
1606 case Match_InvalidSImm8lsl3:
1607 return generateImmOutOfRangeError(
1608 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1609 "immediate must be a multiple of 8 in the range");
1610 case Match_InvalidSImm9lsl3:
1611 return generateImmOutOfRangeError(
1612 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1613 "immediate must be a multiple of 8 in the range");
1614 case Match_InvalidSImm10lsl2:
1615 return generateImmOutOfRangeError(
1616 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1617 "immediate must be a multiple of 4 in the range");
1618 case Match_InvalidSImm11lsl1:
1619 return generateImmOutOfRangeError(
1620 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1621 "immediate must be a multiple of 2 in the range");
1622 case Match_InvalidSImm12:
1623 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1624 /*Upper=*/(1 << 11) - 1);
1625 case Match_InvalidSImm12addlike:
1626 return generateImmOutOfRangeError(
1627 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1628 /*Upper=*/(1 << 11) - 1,
1629 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1630 "in the range");
1631 case Match_InvalidSImm12lu52id:
1632 return generateImmOutOfRangeError(
1633 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1634 /*Upper=*/(1 << 11) - 1,
1635 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1636 "integer in the range");
1637 case Match_InvalidSImm13:
1638 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1639 /*Upper=*/(1 << 12) - 1);
1640 case Match_InvalidSImm14lsl2:
1641 return generateImmOutOfRangeError(
1642 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1643 "immediate must be a multiple of 4 in the range");
1644 case Match_InvalidSImm16:
1645 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1646 /*Upper=*/(1 << 15) - 1);
1647 case Match_InvalidSImm16lsl2:
1648 return generateImmOutOfRangeError(
1649 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1650 "operand must be a symbol with modifier (e.g. %b16) or an integer "
1651 "in the range");
1652 case Match_InvalidSImm20:
1653 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1654 /*Upper=*/(1 << 19) - 1);
1655 case Match_InvalidSImm20lu12iw:
1656 return generateImmOutOfRangeError(
1657 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1658 /*Upper=*/(1 << 19) - 1,
1659 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1660 "in the range");
1661 case Match_InvalidSImm20lu32id:
1662 return generateImmOutOfRangeError(
1663 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1664 /*Upper=*/(1 << 19) - 1,
1665 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1666 "integer in the range");
1667 case Match_InvalidSImm20pcalau12i:
1668 return generateImmOutOfRangeError(
1669 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1670 /*Upper=*/(1 << 19) - 1,
1671 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1672 "in the range");
1673 case Match_InvalidSImm20pcaddu18i:
1674 return generateImmOutOfRangeError(
1675 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1676 /*Upper=*/(1 << 19) - 1,
1677 "operand must be a symbol with modifier (e.g. %call36) or an integer "
1678 "in the range");
1679 case Match_InvalidSImm21lsl2:
1680 return generateImmOutOfRangeError(
1681 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1682 "operand must be a symbol with modifier (e.g. %b21) or an integer "
1683 "in the range");
1684 case Match_InvalidSImm26Operand:
1685 return generateImmOutOfRangeError(
1686 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1687 "operand must be a bare symbol name or an immediate must be a multiple "
1688 "of 4 in the range");
1689 case Match_InvalidImm32: {
1690 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1691 return Error(ErrorLoc, "operand must be a 32 bit immediate");
1692 }
1693 case Match_InvalidImm64: {
1694 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1695 return Error(ErrorLoc, "operand must be a 64 bit immediate");
1696 }
1697 case Match_InvalidBareSymbol: {
1698 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1699 return Error(ErrorLoc, "operand must be a bare symbol name");
1700 }
1701 case Match_InvalidTPRelAddSymbol: {
1702 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1703 return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
1704 }
1705 }
1706 llvm_unreachable("Unknown match type detected!");
1707}
1708
1712}
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define RegName(no)
static LVOptions Options
Definition: LVOptions.cpp:25
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser()
static MCRegister convertFPR32ToFPR64(MCRegister Reg)
mir Rename Register Operands
unsigned Reg
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
static bool is64Bit(const char *name)
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
This class represents an Operation in the Expression.
Base class for user error types.
Definition: Error.h:355
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Container class for subtarget features.
constexpr size_t size() const
static const char * getRegisterName(MCRegister Reg)
static VariantKind getVariantKindForName(StringRef name)
static const LoongArchMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx, bool Hint=false)
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:789
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void setLoc(SMLoc loc)
Definition: MCInst.h:203
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
const MCExpr * getExpr() const
Definition: MCInst.h:114
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool isMem() const =0
isMem - Is this a memory operand?
virtual MCRegister getReg() const =0
virtual void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
virtual SMLoc getEndLoc() const =0
getEndLoc - Get the location of the last token of this operand.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Streaming machine code generation interface.
Definition: MCStreamer.h:213
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:393
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual unsigned checkTargetMatchPredicate(MCInst &Inst)
checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not ...
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
This represents an "assembler immediate".
Definition: MCValue.h:36
uint32_t getRefKind() const
Definition: MCValue.h:46
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Represents a location in source code.
Definition: SMLoc.h:23
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
constexpr const char * getPointer() const
Definition: SMLoc.h:34
Represents a range in source code.
Definition: SMLoc.h:48
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
InstSeq generateInstSeq(int64_t Val)
SmallVector< Inst, 4 > InstSeq
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheLoongArch64Target()
Target & getTheLoongArch32Target()
DWARFExpression::Operation Op
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...