LLVM 20.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
16#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCValue.h"
28
29using namespace llvm;
30
31#define DEBUG_TYPE "loongarch-asm-parser"
32
33namespace {
34class LoongArchAsmParser : public MCTargetAsmParser {
35 SmallVector<FeatureBitset, 4> FeatureBitStack;
36
37 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
38 bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
39 LoongArchTargetStreamer &getTargetStreamer() {
40 assert(getParser().getStreamer().getTargetStreamer() &&
41 "do not have a target streamer");
43 return static_cast<LoongArchTargetStreamer &>(TS);
44 }
45
46 struct Inst {
47 unsigned Opc;
49 Inst(unsigned Opc,
51 : Opc(Opc), VK(VK) {}
52 };
53 using InstSeq = SmallVector<Inst>;
54
55 /// Parse a register as used in CFI directives.
56 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
58 SMLoc &EndLoc) override;
59
61 SMLoc NameLoc, OperandVector &Operands) override;
62
63 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
66 bool MatchingInlineAsm) override;
67
68 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
69
71 unsigned Kind) override;
72
73 ParseStatus parseDirective(AsmToken DirectiveID) override;
74
75 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
76 int64_t Lower, int64_t Upper,
77 const Twine &Msg);
78
79 /// Helper for processing MC instructions that have been successfully matched
80 /// by matchAndEmitInstruction.
81 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
82 MCStreamer &Out);
83
84// Auto-generated instruction matching functions.
85#define GET_ASSEMBLER_HEADER
86#include "LoongArchGenAsmMatcher.inc"
87
90 ParseStatus parseOperandWithModifier(OperandVector &Operands);
91 ParseStatus parseSImm26Operand(OperandVector &Operands);
92 ParseStatus parseAtomicMemOp(OperandVector &Operands);
93
94 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
95
96 bool parseDirectiveOption();
97
98 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
99 if (!(getSTI().hasFeature(Feature))) {
100 MCSubtargetInfo &STI = copySTI();
102 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
103 }
104 }
105
106 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
107 if (getSTI().hasFeature(Feature)) {
108 MCSubtargetInfo &STI = copySTI();
110 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
111 }
112 }
113
114 void pushFeatureBits() {
115 FeatureBitStack.push_back(getSTI().getFeatureBits());
116 }
117
118 bool popFeatureBits() {
119 if (FeatureBitStack.empty())
120 return true;
121
122 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
123 copySTI().setFeatureBits(FeatureBits);
124 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
125
126 return false;
127 }
128
129 // Helper to emit the sequence of instructions generated by the
130 // "emitLoadAddress*" functions.
131 void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
132 const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
133 SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
134
135 // Helper to emit pseudo instruction "la.abs $rd, sym".
136 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
137
138 // Helper to emit pseudo instruction "la.pcrel $rd, sym".
139 void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
140 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
141 void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
142
143 // Helper to emit pseudo instruction "la.got $rd, sym".
144 void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
145 // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
146 void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147
148 // Helper to emit pseudo instruction "la.tls.le $rd, sym".
149 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
150
151 // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
152 void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
153 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
154 void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
155
156 // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
157 void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
158 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
159 void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
160
161 // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
162 void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
163 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
164 void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
165
166 // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
167 void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
168 // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
169 void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
170
171 // Helper to emit pseudo instruction "li.w/d $rd, $imm".
172 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
173
174 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
175 void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
176 bool IsTailCall);
177
178public:
179 enum LoongArchMatchResultTy {
180 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
181 Match_RequiresMsbNotLessThanLsb,
182 Match_RequiresOpnd2NotR0R1,
183 Match_RequiresAMORdDifferRkRj,
184 Match_RequiresLAORdDifferRj,
185 Match_RequiresLAORdR4,
186#define GET_OPERAND_DIAGNOSTIC_TYPES
187#include "LoongArchGenAsmMatcher.inc"
188#undef GET_OPERAND_DIAGNOSTIC_TYPES
189 };
190
191 static bool classifySymbolRef(const MCExpr *Expr,
193
194 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
195 const MCInstrInfo &MII, const MCTargetOptions &Options)
196 : MCTargetAsmParser(Options, STI, MII) {
197 Parser.addAliasForDirective(".half", ".2byte");
198 Parser.addAliasForDirective(".hword", ".2byte");
199 Parser.addAliasForDirective(".word", ".4byte");
200 Parser.addAliasForDirective(".dword", ".8byte");
201
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
204 }
205};
206
207// Instances of this class represent a parsed LoongArch machine instruction.
208class LoongArchOperand : public MCParsedAsmOperand {
209 enum class KindTy {
210 Token,
211 Register,
212 Immediate,
213 } Kind;
214
215 struct RegOp {
216 MCRegister RegNum;
217 };
218
219 struct ImmOp {
220 const MCExpr *Val;
221 };
222
223 SMLoc StartLoc, EndLoc;
224 union {
225 StringRef Tok;
226 struct RegOp Reg;
227 struct ImmOp Imm;
228 };
229
230public:
231 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
232
233 bool isToken() const override { return Kind == KindTy::Token; }
234 bool isReg() const override { return Kind == KindTy::Register; }
235 bool isImm() const override { return Kind == KindTy::Immediate; }
236 bool isMem() const override { return false; }
237 void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
238 bool isGPR() const {
239 return Kind == KindTy::Register &&
240 LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
241 Reg.RegNum);
242 }
243
244 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
246 if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
247 VK = LE->getKind();
248 return false;
249 }
250
251 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
252 Imm = CE->getValue();
253 return true;
254 }
255
256 return false;
257 }
258
259 template <unsigned N, int P = 0> bool isUImm() const {
260 if (!isImm())
261 return false;
262
263 int64_t Imm;
265 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
266 return IsConstantImm && isUInt<N>(Imm - P) &&
268 }
269
270 template <unsigned N, unsigned S = 0> bool isSImm() const {
271 if (!isImm())
272 return false;
273
274 int64_t Imm;
276 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
277 return IsConstantImm && isShiftedInt<N, S>(Imm) &&
279 }
280
281 bool isBareSymbol() const {
282 int64_t Imm;
284 // Must be of 'immediate' type but not a constant.
285 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
286 return false;
287 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
289 }
290
291 bool isTPRelAddSymbol() const {
292 int64_t Imm;
294 // Must be of 'immediate' type but not a constant.
295 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
296 return false;
297 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
299 }
300
301 bool isUImm1() const { return isUImm<1>(); }
302 bool isUImm2() const { return isUImm<2>(); }
303 bool isUImm2plus1() const { return isUImm<2, 1>(); }
304 bool isUImm3() const { return isUImm<3>(); }
305 bool isUImm4() const { return isUImm<4>(); }
306 bool isSImm5() const { return isSImm<5>(); }
307 bool isUImm5() const { return isUImm<5>(); }
308 bool isUImm6() const { return isUImm<6>(); }
309 bool isUImm7() const { return isUImm<7>(); }
310 bool isSImm8() const { return isSImm<8>(); }
311 bool isSImm8lsl1() const { return isSImm<8, 1>(); }
312 bool isSImm8lsl2() const { return isSImm<8, 2>(); }
313 bool isSImm8lsl3() const { return isSImm<8, 3>(); }
314 bool isUImm8() const { return isUImm<8>(); }
315 bool isSImm9lsl3() const { return isSImm<9, 3>(); }
316 bool isSImm10() const { return isSImm<10>(); }
317 bool isSImm10lsl2() const { return isSImm<10, 2>(); }
318 bool isSImm11lsl1() const { return isSImm<11, 1>(); }
319 bool isSImm12() const { return isSImm<12>(); }
320
321 bool isSImm12addlike() const {
322 if (!isImm())
323 return false;
324
325 int64_t Imm;
327 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
328 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
335 return IsConstantImm
336 ? isInt<12>(Imm) && IsValidKind
337 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
338 IsValidKind;
339 }
340
341 bool isSImm12lu52id() const {
342 if (!isImm())
343 return false;
344
345 int64_t Imm;
347 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
348 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
358 return IsConstantImm
359 ? isInt<12>(Imm) && IsValidKind
360 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
361 IsValidKind;
362 }
363
364 bool isUImm12() const { return isUImm<12>(); }
365
366 bool isUImm12ori() const {
367 if (!isImm())
368 return false;
369
370 int64_t Imm;
372 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
373 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
382 return IsConstantImm
383 ? isUInt<12>(Imm) && IsValidKind
384 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
385 IsValidKind;
386 }
387
388 bool isSImm13() const { return isSImm<13>(); }
389 bool isUImm14() const { return isUImm<14>(); }
390 bool isUImm15() const { return isUImm<15>(); }
391
392 bool isSImm14lsl2() const { return isSImm<14, 2>(); }
393 bool isSImm16() const { return isSImm<16>(); }
394
395 bool isSImm16lsl2() const {
396 if (!isImm())
397 return false;
398
399 int64_t Imm;
401 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
402 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
406 return IsConstantImm
407 ? isShiftedInt<16, 2>(Imm) && IsValidKind
408 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
409 IsValidKind;
410 }
411
412 bool isSImm20() const { return isSImm<20>(); }
413
414 bool isSImm20pcalau12i() const {
415 if (!isImm())
416 return false;
417
418 int64_t Imm;
420 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
421 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
428 return IsConstantImm
429 ? isInt<20>(Imm) && IsValidKind
430 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
431 IsValidKind;
432 }
433
434 bool isSImm20lu12iw() const {
435 if (!isImm())
436 return false;
437
438 int64_t Imm;
440 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
441 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
450 return IsConstantImm
451 ? isInt<20>(Imm) && IsValidKind
452 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
453 IsValidKind;
454 }
455
456 bool isSImm20lu32id() const {
457 if (!isImm())
458 return false;
459
460 int64_t Imm;
462 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
463 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
473
474 return IsConstantImm
475 ? isInt<20>(Imm) && IsValidKind
476 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
477 IsValidKind;
478 }
479
480 bool isSImm20pcaddu18i() const {
481 if (!isImm())
482 return false;
483
484 int64_t Imm;
486 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
487 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
489
490 return IsConstantImm
491 ? isInt<20>(Imm) && IsValidKind
492 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
493 IsValidKind;
494 }
495
496 bool isSImm20pcaddi() const {
497 if (!isImm())
498 return false;
499
500 int64_t Imm;
502 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
503 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
508 return IsConstantImm
509 ? isInt<20>(Imm) && IsValidKind
510 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
511 IsValidKind;
512 }
513
514 bool isSImm21lsl2() const {
515 if (!isImm())
516 return false;
517
518 int64_t Imm;
520 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
521 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
523 return IsConstantImm
524 ? isShiftedInt<21, 2>(Imm) && IsValidKind
525 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
526 IsValidKind;
527 }
528
529 bool isSImm26Operand() const {
530 if (!isImm())
531 return false;
532
533 int64_t Imm;
535 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
536 bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
540 return IsConstantImm
541 ? isShiftedInt<26, 2>(Imm) && IsValidKind
542 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
543 IsValidKind;
544 }
545
546 bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
547 bool isImm64() const {
548 if (!isImm())
549 return false;
550 int64_t Imm;
552 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
553 return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None;
554 }
555
556 /// Gets location of the first token of this operand.
557 SMLoc getStartLoc() const override { return StartLoc; }
558 /// Gets location of the last token of this operand.
559 SMLoc getEndLoc() const override { return EndLoc; }
560
561 MCRegister getReg() const override {
562 assert(Kind == KindTy::Register && "Invalid type access!");
563 return Reg.RegNum;
564 }
565
566 const MCExpr *getImm() const {
567 assert(Kind == KindTy::Immediate && "Invalid type access!");
568 return Imm.Val;
569 }
570
571 StringRef getToken() const {
572 assert(Kind == KindTy::Token && "Invalid type access!");
573 return Tok;
574 }
575
576 void print(raw_ostream &OS) const override {
577 auto RegName = [](MCRegister Reg) {
578 if (Reg)
580 else
581 return "noreg";
582 };
583
584 switch (Kind) {
585 case KindTy::Immediate:
586 OS << *getImm();
587 break;
588 case KindTy::Register:
589 OS << "<register " << RegName(getReg()) << ">";
590 break;
591 case KindTy::Token:
592 OS << "'" << getToken() << "'";
593 break;
594 }
595 }
596
597 static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
598 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
599 Op->Tok = Str;
600 Op->StartLoc = S;
601 Op->EndLoc = S;
602 return Op;
603 }
604
605 static std::unique_ptr<LoongArchOperand> createReg(MCRegister Reg, SMLoc S,
606 SMLoc E) {
607 auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
608 Op->Reg.RegNum = Reg;
609 Op->StartLoc = S;
610 Op->EndLoc = E;
611 return Op;
612 }
613
614 static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
615 SMLoc E) {
616 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
617 Op->Imm.Val = Val;
618 Op->StartLoc = S;
619 Op->EndLoc = E;
620 return Op;
621 }
622
623 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
624 if (auto CE = dyn_cast<MCConstantExpr>(Expr))
625 Inst.addOperand(MCOperand::createImm(CE->getValue()));
626 else
628 }
629
630 // Used by the TableGen Code.
631 void addRegOperands(MCInst &Inst, unsigned N) const {
632 assert(N == 1 && "Invalid number of operands!");
634 }
635 void addImmOperands(MCInst &Inst, unsigned N) const {
636 assert(N == 1 && "Invalid number of operands!");
637 addExpr(Inst, getImm());
638 }
639};
640} // end namespace
641
642#define GET_REGISTER_MATCHER
643#define GET_SUBTARGET_FEATURE_NAME
644#define GET_MATCHER_IMPLEMENTATION
645#define GET_MNEMONIC_SPELL_CHECKER
646#include "LoongArchGenAsmMatcher.inc"
647
649 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
650 return Reg - LoongArch::F0 + LoongArch::F0_64;
651}
652
653// Attempts to match Name as a register (either using the default name or
654// alternative ABI names), setting RegNo to the matching register. Upon
655// failure, returns true and sets RegNo to 0.
657 RegNo = MatchRegisterName(Name);
658 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
659 // match always matches the 32-bit variant, and not the 64-bit one.
660 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
661 // The default FPR register class is based on the tablegen enum ordering.
662 static_assert(LoongArch::F0 < LoongArch::F0_64,
663 "FPR matching must be updated");
664 if (RegNo == LoongArch::NoRegister)
665 RegNo = MatchRegisterAltName(Name);
666
667 return RegNo == LoongArch::NoRegister;
668}
669
670bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
671 SMLoc &EndLoc) {
672 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
673 return Error(getLoc(), "invalid register name");
674
675 if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
676 !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
677 return Error(getLoc(), "invalid register name");
678
679 return false;
680}
681
682ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
683 SMLoc &StartLoc,
684 SMLoc &EndLoc) {
685 const AsmToken &Tok = getParser().getTok();
686 StartLoc = Tok.getLoc();
687 EndLoc = Tok.getEndLoc();
688
689 parseOptionalToken(AsmToken::Dollar);
690 if (getLexer().getKind() != AsmToken::Identifier)
692
696
697 getParser().Lex(); // Eat identifier token.
699}
700
701bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
704
705 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
706 Kind = RE->getKind();
707 Expr = RE->getSubExpr();
708 }
709
710 MCValue Res;
711 if (Expr->evaluateAsRelocatable(Res, nullptr, nullptr))
713 return false;
714}
715
716ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
717 if (!parseOptionalToken(AsmToken::Dollar))
719 if (getLexer().getKind() != AsmToken::Identifier)
721
722 StringRef Name = getLexer().getTok().getIdentifier();
723 MCRegister RegNo;
725 if (RegNo == LoongArch::NoRegister)
727
728 SMLoc S = getLoc();
730 getLexer().Lex();
731 Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
732
734}
735
736ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
737 SMLoc S = getLoc();
738 SMLoc E;
739 const MCExpr *Res;
740
741 switch (getLexer().getKind()) {
742 default:
744 case AsmToken::LParen:
745 case AsmToken::Dot:
746 case AsmToken::Minus:
747 case AsmToken::Plus:
749 case AsmToken::Tilde:
751 case AsmToken::String:
753 if (getParser().parseExpression(Res, E))
755 break;
757 return parseOperandWithModifier(Operands);
758 }
759
760 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
762}
763
765LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
766 SMLoc S = getLoc();
767 SMLoc E;
768
769 if (getLexer().getKind() != AsmToken::Percent)
770 return Error(getLoc(), "expected '%' for operand modifier");
771
772 getParser().Lex(); // Eat '%'
773
774 if (getLexer().getKind() != AsmToken::Identifier)
775 return Error(getLoc(), "expected valid identifier for operand modifier");
776 StringRef Identifier = getParser().getTok().getIdentifier();
780 return Error(getLoc(), "unrecognized operand modifier");
781
782 getParser().Lex(); // Eat the identifier
783 if (getLexer().getKind() != AsmToken::LParen)
784 return Error(getLoc(), "expected '('");
785 getParser().Lex(); // Eat '('
786
787 const MCExpr *SubExpr;
788 if (getParser().parseParenExpression(SubExpr, E))
790
791 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
792 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
794}
795
796ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
797 SMLoc S = getLoc();
798 const MCExpr *Res;
799
800 if (getLexer().getKind() == AsmToken::Percent)
801 return parseOperandWithModifier(Operands);
802
803 if (getLexer().getKind() != AsmToken::Identifier)
805
807 if (getParser().parseIdentifier(Identifier))
809
811
812 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
815 getContext());
816 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
818}
819
820ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
821 // Parse "$r*".
822 if (!parseRegister(Operands).isSuccess())
824
825 // If there is a next operand and it is 0, ignore it. Otherwise print a
826 // diagnostic message.
827 if (parseOptionalToken(AsmToken::Comma)) {
828 int64_t ImmVal;
829 SMLoc ImmStart = getLoc();
830 if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
832 if (ImmVal)
833 return Error(ImmStart, "optional integer offset must be 0");
834 }
835
837}
838/// Looks at a token type and creates the relevant operand from this
839/// information, adding to Operands. Return true upon an error.
840bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
841 StringRef Mnemonic) {
842 // Check if the current operand has a custom associated parser, if so, try to
843 // custom parse the operand, or fallback to the general approach.
845 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
846 if (Result.isSuccess())
847 return false;
848 if (Result.isFailure())
849 return true;
850
851 if (parseRegister(Operands).isSuccess() ||
852 parseImmediate(Operands).isSuccess())
853 return false;
854
855 // Finally we have exhausted all options and must declare defeat.
856 return Error(getLoc(), "unknown operand");
857}
858
859bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo &Info,
860 StringRef Name, SMLoc NameLoc,
862 // First operand in MCInst is instruction mnemonic.
863 Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
864
865 // If there are no more operands, then finish.
866 if (parseOptionalToken(AsmToken::EndOfStatement))
867 return false;
868
869 // Parse first operand.
870 if (parseOperand(Operands, Name))
871 return true;
872
873 // Parse until end of statement, consuming commas between operands.
874 while (parseOptionalToken(AsmToken::Comma))
875 if (parseOperand(Operands, Name))
876 return true;
877
878 // Parse end of statement and return successfully.
879 if (parseOptionalToken(AsmToken::EndOfStatement))
880 return false;
881
882 SMLoc Loc = getLexer().getLoc();
883 getParser().eatToEndOfStatement();
884 return Error(Loc, "unexpected token");
885}
886
887void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
888 const MCExpr *Symbol,
890 SMLoc IDLoc, MCStreamer &Out,
891 bool RelaxHint) {
892 MCContext &Ctx = getContext();
893 for (LoongArchAsmParser::Inst &Inst : Insts) {
894 unsigned Opc = Inst.Opc;
895 LoongArchMCExpr::VariantKind VK = Inst.VK;
896 const LoongArchMCExpr *LE =
897 LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
898 switch (Opc) {
899 default:
900 llvm_unreachable("unexpected opcode");
901 case LoongArch::PCALAU12I:
902 case LoongArch::LU12I_W:
903 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
904 getSTI());
905 break;
906 case LoongArch::ORI:
907 case LoongArch::ADDI_W:
908 case LoongArch::LD_W:
909 case LoongArch::LD_D: {
911 Out.emitInstruction(
912 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
913 getSTI());
914 continue;
917 .addReg(LoongArch::R1)
918 .addReg(DestReg)
919 .addExpr(LE),
920 getSTI());
921 continue;
922 }
923 Out.emitInstruction(
924 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
925 getSTI());
926 break;
927 }
928 case LoongArch::LU32I_D:
930 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
931 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
932 .addExpr(LE),
933 getSTI());
934 break;
935 case LoongArch::LU52I_D:
936 Out.emitInstruction(
937 MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
938 getSTI());
939 break;
940 case LoongArch::ADDI_D:
941 Out.emitInstruction(
942 MCInstBuilder(Opc)
943 .addReg(TmpReg)
944 .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
945 .addExpr(LE),
946 getSTI());
947 break;
948 case LoongArch::ADD_D:
949 case LoongArch::LDX_D:
950 Out.emitInstruction(
951 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
952 getSTI());
953 break;
954 case LoongArch::JIRL:
956 .addReg(LoongArch::R1)
957 .addReg(LoongArch::R1)
958 .addExpr(LE),
959 getSTI());
960 break;
961 }
962 }
963}
964
965void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
966 MCStreamer &Out) {
967 // la.abs $rd, sym
968 // expands to:
969 // lu12i.w $rd, %abs_hi20(sym)
970 // ori $rd, $rd, %abs_lo12(sym)
971 //
972 // for 64bit appends:
973 // lu32i.d $rd, %abs64_lo20(sym)
974 // lu52i.d $rd, $rd, %abs64_hi12(sym)
975 MCRegister DestReg = Inst.getOperand(0).getReg();
976 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
977 ? Inst.getOperand(1).getExpr()
978 : Inst.getOperand(2).getExpr();
979 InstSeq Insts;
980
981 Insts.push_back(LoongArchAsmParser::Inst(
982 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_ABS_HI20));
983 Insts.push_back(LoongArchAsmParser::Inst(
985
986 if (is64Bit()) {
987 Insts.push_back(LoongArchAsmParser::Inst(
988 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_ABS64_LO20));
989 Insts.push_back(LoongArchAsmParser::Inst(
990 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_ABS64_HI12));
991 }
992
993 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
994}
995
996void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
997 MCStreamer &Out) {
998 // la.pcrel $rd, sym
999 // expands to:
1000 // pcalau12i $rd, %pc_hi20(sym)
1001 // addi.w/d $rd, rd, %pc_lo12(sym)
1002 MCRegister DestReg = Inst.getOperand(0).getReg();
1003 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1004 InstSeq Insts;
1005 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1006
1007 Insts.push_back(LoongArchAsmParser::Inst(
1008 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
1009 Insts.push_back(
1010 LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
1011
1012 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
1013}
1014
1015void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
1016 MCStreamer &Out) {
1017 // la.pcrel $rd, $rj, sym
1018 // expands to:
1019 // pcalau12i $rd, %pc_hi20(sym)
1020 // addi.d $rj, $r0, %pc_lo12(sym)
1021 // lu32i.d $rj, %pc64_lo20(sym)
1022 // lu52i.d $rj, $rj, %pc64_hi12(sym)
1023 // add.d $rd, $rd, $rj
1024 MCRegister DestReg = Inst.getOperand(0).getReg();
1025 MCRegister TmpReg = Inst.getOperand(1).getReg();
1026 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1027 InstSeq Insts;
1028
1029 Insts.push_back(LoongArchAsmParser::Inst(
1030 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_PCALA_HI20));
1031 Insts.push_back(LoongArchAsmParser::Inst(
1032 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_PCALA_LO12));
1033 Insts.push_back(LoongArchAsmParser::Inst(
1034 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_LO20));
1035 Insts.push_back(LoongArchAsmParser::Inst(
1036 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_PCALA64_HI12));
1037 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1038
1039 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1040}
1041
1042void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
1043 MCStreamer &Out) {
1044 // la.got $rd, sym
1045 MCRegister DestReg = Inst.getOperand(0).getReg();
1046 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1047 InstSeq Insts;
1048 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1049
1050 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1051 // with feature: +la-glabal-with-abs
1052 // for 32bit:
1053 // lu12i.w $rd, %got_hi20(sym)
1054 // ori $rd, $rd, %got_lo12(sym)
1055 // ld.w $rd, $rd, 0
1056 //
1057 // for 64bit:
1058 // lu12i.w $rd, %got_hi20(sym)
1059 // ori $rd, $rd, %got_lo12(sym)
1060 // lu32i.d $rd, %got64_lo20(sym)
1061 // lu52i.d $rd, $rd, %got64_hi12(sym)
1062 // ld.d $rd, $rd, 0
1063 Insts.push_back(LoongArchAsmParser::Inst(
1064 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_GOT_HI20));
1065 Insts.push_back(LoongArchAsmParser::Inst(
1067
1068 if (is64Bit()) {
1069 Insts.push_back(LoongArchAsmParser::Inst(
1070 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1071 Insts.push_back(LoongArchAsmParser::Inst(
1072 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1073 }
1074 Insts.push_back(LoongArchAsmParser::Inst(LD));
1075 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1076 return;
1077 }
1078 // expands to:
1079 // pcalau12i $rd, %got_pc_hi20(sym)
1080 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
1081 Insts.push_back(LoongArchAsmParser::Inst(
1082 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
1083 Insts.push_back(
1084 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1085
1086 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true);
1087}
1088
1089void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
1090 MCStreamer &Out) {
1091 // la.got $rd, $rj, sym
1092 // expands to:
1093 // pcalau12i $rd, %got_pc_hi20(sym)
1094 // addi.d $rj, $r0, %got_pc_lo12(sym)
1095 // lu32i.d $rj, %got64_pc_lo20(sym)
1096 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1097 // ldx.d $rd, $rd, $rj
1098 MCRegister DestReg = Inst.getOperand(0).getReg();
1099 MCRegister TmpReg = Inst.getOperand(1).getReg();
1100 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1101 InstSeq Insts;
1102
1103 Insts.push_back(LoongArchAsmParser::Inst(
1104 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20));
1105 Insts.push_back(LoongArchAsmParser::Inst(
1106 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1107 Insts.push_back(LoongArchAsmParser::Inst(
1108 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1109 Insts.push_back(LoongArchAsmParser::Inst(
1110 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1111 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1112
1113 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1114}
1115
1116void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1117 MCStreamer &Out) {
1118 // la.tls.le $rd, sym
1119 // expands to:
1120 // lu12i.w $rd, %le_hi20(sym)
1121 // ori $rd, $rd, %le_lo12(sym)
1122 MCRegister DestReg = Inst.getOperand(0).getReg();
1123 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1124 InstSeq Insts;
1125
1126 Insts.push_back(LoongArchAsmParser::Inst(
1127 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20));
1128 Insts.push_back(LoongArchAsmParser::Inst(
1130
1131 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1132}
1133
1134void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1135 MCStreamer &Out) {
1136 // la.tls.ie $rd, sym
1137 MCRegister DestReg = Inst.getOperand(0).getReg();
1138 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1139 InstSeq Insts;
1140 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1141
1142 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1143 // with feature: +la-glabal-with-abs
1144 // for 32bit:
1145 // lu12i.w $rd, %ie_hi20(sym)
1146 // ori $rd, $rd, %ie_lo12(sym)
1147 // ld.w $rd, $rd, 0
1148 //
1149 // for 64bit:
1150 // lu12i.w $rd, %ie_hi20(sym)
1151 // ori $rd, $rd, %ie_lo12(sym)
1152 // lu32i.d $rd, %ie64_lo20(sym)
1153 // lu52i.d $rd, $rd, %ie64_hi12(sym)
1154 // ld.d $rd, $rd, 0
1155 Insts.push_back(LoongArchAsmParser::Inst(
1156 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20));
1157 Insts.push_back(LoongArchAsmParser::Inst(
1159
1160 if (is64Bit()) {
1161 Insts.push_back(LoongArchAsmParser::Inst(
1162 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20));
1163 Insts.push_back(LoongArchAsmParser::Inst(
1164 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12));
1165 }
1166 Insts.push_back(LoongArchAsmParser::Inst(LD));
1167 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1168 return;
1169 }
1170
1171 // expands to:
1172 // pcalau12i $rd, %ie_pc_hi20(sym)
1173 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1174 Insts.push_back(LoongArchAsmParser::Inst(
1175 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1176 Insts.push_back(LoongArchAsmParser::Inst(
1178
1179 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1180}
1181
1182void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1183 MCStreamer &Out) {
1184 // la.tls.ie $rd, $rj, sym
1185 // expands to:
1186 // pcalau12i $rd, %ie_pc_hi20(sym)
1187 // addi.d $rj, $r0, %ie_pc_lo12(sym)
1188 // lu32i.d $rj, %ie64_pc_lo20(sym)
1189 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1190 // ldx.d $rd, $rd, $rj
1191 MCRegister DestReg = Inst.getOperand(0).getReg();
1192 MCRegister TmpReg = Inst.getOperand(1).getReg();
1193 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1194 InstSeq Insts;
1195
1196 Insts.push_back(LoongArchAsmParser::Inst(
1197 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20));
1198 Insts.push_back(LoongArchAsmParser::Inst(
1200 Insts.push_back(LoongArchAsmParser::Inst(
1202 Insts.push_back(LoongArchAsmParser::Inst(
1204 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1205
1206 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1207}
1208
1209void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1210 MCStreamer &Out) {
1211 // la.tls.ld $rd, sym
1212 MCRegister DestReg = Inst.getOperand(0).getReg();
1213 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1214 InstSeq Insts;
1215 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1216
1217 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1218 // with feature: +la-glabal-with-abs
1219 // for 32bit:
1220 // lu12i.w $rd, %ld_hi20(sym)
1221 // ori $rd, $rd, %got_lo12(sym)
1222 //
1223 // for 64bit:
1224 // lu12i.w $rd, %ld_hi20(sym)
1225 // ori $rd, $rd, %got_lo12(sym)
1226 // lu32i.d $rd, %got64_lo20(sym)
1227 // lu52i.d $rd, $rd, %got64_hi12(sym)
1228 Insts.push_back(LoongArchAsmParser::Inst(
1229 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20));
1230 Insts.push_back(LoongArchAsmParser::Inst(
1232
1233 if (is64Bit()) {
1234 Insts.push_back(LoongArchAsmParser::Inst(
1235 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1236 Insts.push_back(LoongArchAsmParser::Inst(
1237 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1238 }
1239 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1240 return;
1241 }
1242
1243 // expands to:
1244 // pcalau12i $rd, %ld_pc_hi20(sym)
1245 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1246 Insts.push_back(LoongArchAsmParser::Inst(
1247 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1248 Insts.push_back(LoongArchAsmParser::Inst(
1250
1251 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1252}
1253
1254void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1255 MCStreamer &Out) {
1256 // la.tls.ld $rd, $rj, sym
1257 // expands to:
1258 // pcalau12i $rd, %ld_pc_hi20(sym)
1259 // addi.d $rj, $r0, %got_pc_lo12(sym)
1260 // lu32i.d $rj, %got64_pc_lo20(sym)
1261 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1262 // add.d $rd, $rd, $rj
1263 MCRegister DestReg = Inst.getOperand(0).getReg();
1264 MCRegister TmpReg = Inst.getOperand(1).getReg();
1265 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1266 InstSeq Insts;
1267
1268 Insts.push_back(LoongArchAsmParser::Inst(
1269 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20));
1270 Insts.push_back(LoongArchAsmParser::Inst(
1271 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1272 Insts.push_back(LoongArchAsmParser::Inst(
1273 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1274 Insts.push_back(LoongArchAsmParser::Inst(
1275 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1276 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1277
1278 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1279}
1280
1281void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1282 MCStreamer &Out) {
1283 // la.tls.gd $rd, sym
1284 MCRegister DestReg = Inst.getOperand(0).getReg();
1285 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1286 InstSeq Insts;
1287 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1288
1289 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1290 // with feature: +la-glabal-with-abs
1291 // for 32bit:
1292 // lu12i.w $rd, %gd_hi20(sym)
1293 // ori $rd, $rd, %got_lo12(sym)
1294 //
1295 // for 64bit:
1296 // lu12i.w $rd, %gd_hi20(sym)
1297 // ori $rd, $rd, %got_lo12(sym)
1298 // lu32i.d $rd, %got64_lo20(sym)
1299 // lu52i.d $rd, $rd, %got64_hi12(sym)
1300 Insts.push_back(LoongArchAsmParser::Inst(
1301 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20));
1302 Insts.push_back(LoongArchAsmParser::Inst(
1304
1305 if (is64Bit()) {
1306 Insts.push_back(LoongArchAsmParser::Inst(
1307 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_LO20));
1308 Insts.push_back(LoongArchAsmParser::Inst(
1309 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_HI12));
1310 }
1311 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1312 return;
1313 }
1314
1315 // expands to:
1316 // pcalau12i $rd, %gd_pc_hi20(sym)
1317 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1318 Insts.push_back(LoongArchAsmParser::Inst(
1319 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1320 Insts.push_back(LoongArchAsmParser::Inst(
1322
1323 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1324}
1325
1326void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1327 MCStreamer &Out) {
1328 // la.tls.gd $rd, $rj, sym
1329 // expands to:
1330 // pcalau12i $rd, %gd_pc_hi20(sym)
1331 // addi.d $rj, $r0, %got_pc_lo12(sym)
1332 // lu32i.d $rj, %got64_pc_lo20(sym)
1333 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1334 // add.d $rd, $rd, $rj
1335 MCRegister DestReg = Inst.getOperand(0).getReg();
1336 MCRegister TmpReg = Inst.getOperand(1).getReg();
1337 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1338 InstSeq Insts;
1339
1340 Insts.push_back(LoongArchAsmParser::Inst(
1341 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20));
1342 Insts.push_back(LoongArchAsmParser::Inst(
1343 LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12));
1344 Insts.push_back(LoongArchAsmParser::Inst(
1345 LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20));
1346 Insts.push_back(LoongArchAsmParser::Inst(
1347 LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12));
1348 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1349
1350 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1351}
1352
1353void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
1354 MCStreamer &Out) {
1355 // la.tls.desc $rd, sym
1356 MCRegister DestReg = Inst.getOperand(0).getReg();
1357 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1358 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1359 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1360 InstSeq Insts;
1361
1362 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1363 // with feature: +la-glabal-with-abs
1364 // for la32 expands to:
1365 // lu12i.w $rd, %desc_hi20(sym)
1366 // ori $rd, $rd, %desc_lo12(sym)
1367 // ld.w $ra, $rd, %desc_ld(sym)
1368 // jirl $ra, $ra, %desc_call(sym)
1369 //
1370 // for la64 expands to:
1371 // lu12i.w $rd, %desc_hi20(sym)
1372 // ori $rd, $rd, %desc_lo12(sym)
1373 // lu32i.d $rd, %desc64_lo20(sym)
1374 // lu52i.d $rd, $rd, %desc64_hi12(sym)
1375 // ld.d $ra, $rd, %desc_ld(sym)
1376 // jirl $ra, $ra, %desc_call(sym)
1377 Insts.push_back(LoongArchAsmParser::Inst(
1378 LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
1379 Insts.push_back(LoongArchAsmParser::Inst(
1381
1382 if (is64Bit()) {
1383 Insts.push_back(LoongArchAsmParser::Inst(
1385 Insts.push_back(LoongArchAsmParser::Inst(
1387 }
1388
1389 Insts.push_back(LoongArchAsmParser::Inst(
1391 Insts.push_back(LoongArchAsmParser::Inst(
1393
1394 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1395 return;
1396 }
1397
1398 // expands to:
1399 // pcalau12i $rd, %desc_pc_hi20(sym)
1400 // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1401 // ld.w/d $ra, $rd, %desc_ld(sym)
1402 // jirl $ra, $ra, %desc_call(sym)
1403 Insts.push_back(LoongArchAsmParser::Inst(
1404 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1405 Insts.push_back(LoongArchAsmParser::Inst(
1407 Insts.push_back(
1408 LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
1409 Insts.push_back(LoongArchAsmParser::Inst(
1411
1412 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1413}
1414
1415void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
1416 MCStreamer &Out) {
1417 // la.tls.desc $rd, $rj, sym
1418 // expands to:
1419 // pcalau12i $rd, %desc_pc_hi20(sym)
1420 // addi.d $rj, $r0, %desc_pc_lo12(sym)
1421 // lu32i.d $rj, %desc64_pc_lo20(sym)
1422 // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1423 // add.d $rd, $rd, $rj
1424 // ld.w/d $ra, $rd, %desc_ld(sym)
1425 // jirl $ra, $ra, %desc_call(sym)
1426 MCRegister DestReg = Inst.getOperand(0).getReg();
1427 MCRegister TmpReg = Inst.getOperand(1).getReg();
1428 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1429 InstSeq Insts;
1430
1431 Insts.push_back(LoongArchAsmParser::Inst(
1432 LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
1433 Insts.push_back(LoongArchAsmParser::Inst(
1435 Insts.push_back(LoongArchAsmParser::Inst(
1437 Insts.push_back(LoongArchAsmParser::Inst(
1439 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1440 Insts.push_back(LoongArchAsmParser::Inst(
1442 Insts.push_back(LoongArchAsmParser::Inst(
1444
1445 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1446}
1447
1448void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1449 MCStreamer &Out) {
1450 MCRegister DestReg = Inst.getOperand(0).getReg();
1451 int64_t Imm = Inst.getOperand(1).getImm();
1452 MCRegister SrcReg = LoongArch::R0;
1453
1454 if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1455 Imm = SignExtend64<32>(Imm);
1456
1458 switch (Inst.Opc) {
1459 case LoongArch::LU12I_W:
1460 Out.emitInstruction(
1461 MCInstBuilder(Inst.Opc).addReg(DestReg).addImm(Inst.Imm), getSTI());
1462 break;
1463 case LoongArch::ADDI_W:
1464 case LoongArch::ORI:
1465 case LoongArch::LU32I_D:
1466 case LoongArch::LU52I_D:
1467 Out.emitInstruction(
1468 MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1469 Inst.Imm),
1470 getSTI());
1471 break;
1472 case LoongArch::BSTRINS_D:
1473 Out.emitInstruction(MCInstBuilder(Inst.Opc)
1474 .addReg(DestReg)
1475 .addReg(SrcReg)
1476 .addReg(SrcReg)
1477 .addImm(Inst.Imm >> 32)
1478 .addImm(Inst.Imm & 0xFF),
1479 getSTI());
1480 break;
1481 default:
1482 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
1483 }
1484 SrcReg = DestReg;
1485 }
1486}
1487
1488void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1489 MCStreamer &Out, bool IsTailCall) {
1490 // call36 sym
1491 // expands to:
1492 // pcaddu18i $ra, %call36(sym)
1493 // jirl $ra, $ra, 0
1494 //
1495 // tail36 $rj, sym
1496 // expands to:
1497 // pcaddu18i $rj, %call36(sym)
1498 // jirl $r0, $rj, 0
1499 MCRegister ScratchReg =
1500 IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
1501 const MCExpr *Sym =
1502 IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1505
1506 Out.emitInstruction(
1507 MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
1508 getSTI());
1509 Out.emitInstruction(
1510 MCInstBuilder(LoongArch::JIRL)
1511 .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
1512 .addReg(ScratchReg)
1513 .addImm(0),
1514 getSTI());
1515}
1516
1517bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1519 MCStreamer &Out) {
1520 Inst.setLoc(IDLoc);
1521 switch (Inst.getOpcode()) {
1522 default:
1523 break;
1524 case LoongArch::PseudoLA_ABS:
1525 case LoongArch::PseudoLA_ABS_LARGE:
1526 emitLoadAddressAbs(Inst, IDLoc, Out);
1527 return false;
1528 case LoongArch::PseudoLA_PCREL:
1529 emitLoadAddressPcrel(Inst, IDLoc, Out);
1530 return false;
1531 case LoongArch::PseudoLA_PCREL_LARGE:
1532 emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1533 return false;
1534 case LoongArch::PseudoLA_GOT:
1535 emitLoadAddressGot(Inst, IDLoc, Out);
1536 return false;
1537 case LoongArch::PseudoLA_GOT_LARGE:
1538 emitLoadAddressGotLarge(Inst, IDLoc, Out);
1539 return false;
1540 case LoongArch::PseudoLA_TLS_LE:
1541 emitLoadAddressTLSLE(Inst, IDLoc, Out);
1542 return false;
1543 case LoongArch::PseudoLA_TLS_IE:
1544 emitLoadAddressTLSIE(Inst, IDLoc, Out);
1545 return false;
1546 case LoongArch::PseudoLA_TLS_IE_LARGE:
1547 emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1548 return false;
1549 case LoongArch::PseudoLA_TLS_LD:
1550 emitLoadAddressTLSLD(Inst, IDLoc, Out);
1551 return false;
1552 case LoongArch::PseudoLA_TLS_LD_LARGE:
1553 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1554 return false;
1555 case LoongArch::PseudoLA_TLS_GD:
1556 emitLoadAddressTLSGD(Inst, IDLoc, Out);
1557 return false;
1558 case LoongArch::PseudoLA_TLS_GD_LARGE:
1559 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1560 return false;
1561 case LoongArch::PseudoLA_TLS_DESC:
1562 emitLoadAddressTLSDesc(Inst, IDLoc, Out);
1563 return false;
1564 case LoongArch::PseudoLA_TLS_DESC_LARGE:
1565 emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
1566 return false;
1567 case LoongArch::PseudoLI_W:
1568 case LoongArch::PseudoLI_D:
1569 emitLoadImm(Inst, IDLoc, Out);
1570 return false;
1571 case LoongArch::PseudoCALL36:
1572 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1573 return false;
1574 case LoongArch::PseudoTAIL36:
1575 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1576 return false;
1577 }
1578 Out.emitInstruction(Inst, getSTI());
1579 return false;
1580}
1581
1582unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1583 unsigned Opc = Inst.getOpcode();
1584 const MCInstrDesc &MCID = MII.get(Opc);
1585 switch (Opc) {
1586 default:
1588 const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);
1589 MCRegister Rd = Inst.getOperand(0).getReg();
1590 MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();
1591 MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();
1592 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1593 return Match_RequiresAMORdDifferRkRj;
1594 }
1595 break;
1596 case LoongArch::PseudoLA_TLS_DESC:
1597 case LoongArch::PseudoLA_TLS_DESC_LARGE: {
1598 MCRegister Rd = Inst.getOperand(0).getReg();
1599 if (Rd != LoongArch::R4)
1600 return Match_RequiresLAORdR4;
1601 break;
1602 }
1603 case LoongArch::PseudoLA_PCREL_LARGE:
1604 case LoongArch::PseudoLA_GOT_LARGE:
1605 case LoongArch::PseudoLA_TLS_IE_LARGE:
1606 case LoongArch::PseudoLA_TLS_LD_LARGE:
1607 case LoongArch::PseudoLA_TLS_GD_LARGE: {
1608 MCRegister Rd = Inst.getOperand(0).getReg();
1609 MCRegister Rj = Inst.getOperand(1).getReg();
1610 if (Rd == Rj)
1611 return Match_RequiresLAORdDifferRj;
1612 break;
1613 }
1614 case LoongArch::CSRXCHG:
1615 case LoongArch::GCSRXCHG: {
1616 MCRegister Rj = Inst.getOperand(2).getReg();
1617 if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1618 return Match_RequiresOpnd2NotR0R1;
1619 return Match_Success;
1620 }
1621 case LoongArch::BSTRINS_W:
1622 case LoongArch::BSTRINS_D:
1623 case LoongArch::BSTRPICK_W:
1624 case LoongArch::BSTRPICK_D: {
1625 unsigned Opc = Inst.getOpcode();
1626 const signed Msb =
1627 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1628 ? Inst.getOperand(3).getImm()
1629 : Inst.getOperand(2).getImm();
1630 const signed Lsb =
1631 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1632 ? Inst.getOperand(4).getImm()
1633 : Inst.getOperand(3).getImm();
1634 if (Msb < Lsb)
1635 return Match_RequiresMsbNotLessThanLsb;
1636 return Match_Success;
1637 }
1638 }
1639
1640 return Match_Success;
1641}
1642
1643unsigned
1644LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1645 unsigned Kind) {
1646 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1647 if (!Op.isReg())
1648 return Match_InvalidOperand;
1649
1650 MCRegister Reg = Op.getReg();
1651 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1652 // register from FPR32 to FPR64 if necessary.
1653 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1654 Kind == MCK_FPR64) {
1655 Op.setReg(convertFPR32ToFPR64(Reg));
1656 return Match_Success;
1657 }
1658
1659 return Match_InvalidOperand;
1660}
1661
1662bool LoongArchAsmParser::generateImmOutOfRangeError(
1663 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1664 const Twine &Msg = "immediate must be an integer in the range") {
1665 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1666 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1667}
1668
1669bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1671 MCStreamer &Out,
1673 bool MatchingInlineAsm) {
1674 MCInst Inst;
1675 FeatureBitset MissingFeatures;
1676
1677 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1678 MatchingInlineAsm);
1679 switch (Result) {
1680 default:
1681 break;
1682 case Match_Success:
1683 return processInstruction(Inst, IDLoc, Operands, Out);
1684 case Match_MissingFeature: {
1685 assert(MissingFeatures.any() && "Unknown missing features!");
1686 bool FirstFeature = true;
1687 std::string Msg = "instruction requires the following:";
1688 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1689 if (MissingFeatures[i]) {
1690 Msg += FirstFeature ? " " : ", ";
1691 Msg += getSubtargetFeatureName(i);
1692 FirstFeature = false;
1693 }
1694 }
1695 return Error(IDLoc, Msg);
1696 }
1697 case Match_MnemonicFail: {
1698 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1699 std::string Suggestion = LoongArchMnemonicSpellCheck(
1700 ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
1701 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1702 }
1703 case Match_InvalidOperand: {
1704 SMLoc ErrorLoc = IDLoc;
1705 if (ErrorInfo != ~0ULL) {
1706 if (ErrorInfo >= Operands.size())
1707 return Error(ErrorLoc, "too few operands for instruction");
1708
1709 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1710 if (ErrorLoc == SMLoc())
1711 ErrorLoc = IDLoc;
1712 }
1713 return Error(ErrorLoc, "invalid operand for instruction");
1714 }
1715 }
1716
1717 // Handle the case when the error message is of specific type
1718 // other than the generic Match_InvalidOperand, and the
1719 // corresponding operand is missing.
1720 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1721 SMLoc ErrorLoc = IDLoc;
1722 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1723 return Error(ErrorLoc, "too few operands for instruction");
1724 }
1725
1726 switch (Result) {
1727 default:
1728 break;
1729 case Match_RequiresMsbNotLessThanLsb: {
1730 SMLoc ErrorStart = Operands[3]->getStartLoc();
1731 return Error(ErrorStart, "msb is less than lsb",
1732 SMRange(ErrorStart, Operands[4]->getEndLoc()));
1733 }
1734 case Match_RequiresOpnd2NotR0R1:
1735 return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1736 case Match_RequiresAMORdDifferRkRj:
1737 return Error(Operands[1]->getStartLoc(),
1738 "$rd must be different from both $rk and $rj");
1739 case Match_RequiresLAORdDifferRj:
1740 return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
1741 case Match_RequiresLAORdR4:
1742 return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
1743 case Match_InvalidUImm1:
1744 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1745 /*Upper=*/(1 << 1) - 1);
1746 case Match_InvalidUImm2:
1747 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1748 /*Upper=*/(1 << 2) - 1);
1749 case Match_InvalidUImm2plus1:
1750 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1751 /*Upper=*/(1 << 2));
1752 case Match_InvalidUImm3:
1753 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1754 /*Upper=*/(1 << 3) - 1);
1755 case Match_InvalidUImm4:
1756 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1757 /*Upper=*/(1 << 4) - 1);
1758 case Match_InvalidUImm5:
1759 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1760 /*Upper=*/(1 << 5) - 1);
1761 case Match_InvalidUImm6:
1762 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1763 /*Upper=*/(1 << 6) - 1);
1764 case Match_InvalidUImm7:
1765 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1766 /*Upper=*/(1 << 7) - 1);
1767 case Match_InvalidUImm8:
1768 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1769 /*Upper=*/(1 << 8) - 1);
1770 case Match_InvalidUImm12:
1771 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1772 /*Upper=*/(1 << 12) - 1);
1773 case Match_InvalidUImm12ori:
1774 return generateImmOutOfRangeError(
1775 Operands, ErrorInfo, /*Lower=*/0,
1776 /*Upper=*/(1 << 12) - 1,
1777 "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1778 "integer in the range");
1779 case Match_InvalidUImm14:
1780 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1781 /*Upper=*/(1 << 14) - 1);
1782 case Match_InvalidUImm15:
1783 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1784 /*Upper=*/(1 << 15) - 1);
1785 case Match_InvalidSImm5:
1786 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1787 /*Upper=*/(1 << 4) - 1);
1788 case Match_InvalidSImm8:
1789 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1790 /*Upper=*/(1 << 7) - 1);
1791 case Match_InvalidSImm8lsl1:
1792 return generateImmOutOfRangeError(
1793 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1794 "immediate must be a multiple of 2 in the range");
1795 case Match_InvalidSImm8lsl2:
1796 return generateImmOutOfRangeError(
1797 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1798 "immediate must be a multiple of 4 in the range");
1799 case Match_InvalidSImm10:
1800 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1801 /*Upper=*/(1 << 9) - 1);
1802 case Match_InvalidSImm8lsl3:
1803 return generateImmOutOfRangeError(
1804 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1805 "immediate must be a multiple of 8 in the range");
1806 case Match_InvalidSImm9lsl3:
1807 return generateImmOutOfRangeError(
1808 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1809 "immediate must be a multiple of 8 in the range");
1810 case Match_InvalidSImm10lsl2:
1811 return generateImmOutOfRangeError(
1812 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1813 "immediate must be a multiple of 4 in the range");
1814 case Match_InvalidSImm11lsl1:
1815 return generateImmOutOfRangeError(
1816 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1817 "immediate must be a multiple of 2 in the range");
1818 case Match_InvalidSImm12:
1819 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1820 /*Upper=*/(1 << 11) - 1);
1821 case Match_InvalidSImm12addlike:
1822 return generateImmOutOfRangeError(
1823 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1824 /*Upper=*/(1 << 11) - 1,
1825 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1826 "in the range");
1827 case Match_InvalidSImm12lu52id:
1828 return generateImmOutOfRangeError(
1829 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1830 /*Upper=*/(1 << 11) - 1,
1831 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1832 "integer in the range");
1833 case Match_InvalidSImm13:
1834 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1835 /*Upper=*/(1 << 12) - 1);
1836 case Match_InvalidSImm14lsl2:
1837 return generateImmOutOfRangeError(
1838 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1839 "immediate must be a multiple of 4 in the range");
1840 case Match_InvalidSImm16:
1841 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1842 /*Upper=*/(1 << 15) - 1);
1843 case Match_InvalidSImm16lsl2:
1844 return generateImmOutOfRangeError(
1845 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1846 "operand must be a symbol with modifier (e.g. %b16) or an integer "
1847 "in the range");
1848 case Match_InvalidSImm20:
1849 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1850 /*Upper=*/(1 << 19) - 1);
1851 case Match_InvalidSImm20lu12iw:
1852 return generateImmOutOfRangeError(
1853 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1854 /*Upper=*/(1 << 19) - 1,
1855 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1856 "in the range");
1857 case Match_InvalidSImm20lu32id:
1858 return generateImmOutOfRangeError(
1859 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1860 /*Upper=*/(1 << 19) - 1,
1861 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1862 "integer in the range");
1863 case Match_InvalidSImm20pcalau12i:
1864 return generateImmOutOfRangeError(
1865 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1866 /*Upper=*/(1 << 19) - 1,
1867 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1868 "in the range");
1869 case Match_InvalidSImm20pcaddu18i:
1870 return generateImmOutOfRangeError(
1871 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1872 /*Upper=*/(1 << 19) - 1,
1873 "operand must be a symbol with modifier (e.g. %call36) or an integer "
1874 "in the range");
1875 case Match_InvalidSImm20pcaddi:
1876 return generateImmOutOfRangeError(
1877 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1878 /*Upper=*/(1 << 19) - 1,
1879 "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1880 "in the range");
1881 case Match_InvalidSImm21lsl2:
1882 return generateImmOutOfRangeError(
1883 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1884 "operand must be a symbol with modifier (e.g. %b21) or an integer "
1885 "in the range");
1886 case Match_InvalidSImm26Operand:
1887 return generateImmOutOfRangeError(
1888 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1889 "operand must be a bare symbol name or an immediate must be a multiple "
1890 "of 4 in the range");
1891 case Match_InvalidImm32: {
1892 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1893 return Error(ErrorLoc, "operand must be a 32 bit immediate");
1894 }
1895 case Match_InvalidImm64: {
1896 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1897 return Error(ErrorLoc, "operand must be a 64 bit immediate");
1898 }
1899 case Match_InvalidBareSymbol: {
1900 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1901 return Error(ErrorLoc, "operand must be a bare symbol name");
1902 }
1903 case Match_InvalidTPRelAddSymbol: {
1904 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1905 return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
1906 }
1907 }
1908 llvm_unreachable("Unknown match type detected!");
1909}
1910
1911bool LoongArchAsmParser::parseDirectiveOption() {
1912 MCAsmParser &Parser = getParser();
1913 // Get the option token.
1914 AsmToken Tok = Parser.getTok();
1915
1916 // At the moment only identifiers are supported.
1917 if (parseToken(AsmToken::Identifier, "expected identifier"))
1918 return true;
1919
1921
1922 if (Option == "push") {
1923 if (Parser.parseEOL())
1924 return true;
1925
1926 getTargetStreamer().emitDirectiveOptionPush();
1927 pushFeatureBits();
1928 return false;
1929 }
1930
1931 if (Option == "pop") {
1932 SMLoc StartLoc = Parser.getTok().getLoc();
1933 if (Parser.parseEOL())
1934 return true;
1935
1936 getTargetStreamer().emitDirectiveOptionPop();
1937 if (popFeatureBits())
1938 return Error(StartLoc, ".option pop with no .option push");
1939
1940 return false;
1941 }
1942
1943 if (Option == "relax") {
1944 if (Parser.parseEOL())
1945 return true;
1946
1947 getTargetStreamer().emitDirectiveOptionRelax();
1948 setFeatureBits(LoongArch::FeatureRelax, "relax");
1949 return false;
1950 }
1951
1952 if (Option == "norelax") {
1953 if (Parser.parseEOL())
1954 return true;
1955
1956 getTargetStreamer().emitDirectiveOptionNoRelax();
1957 clearFeatureBits(LoongArch::FeatureRelax, "relax");
1958 return false;
1959 }
1960
1961 // Unknown option.
1962 Warning(Parser.getTok().getLoc(),
1963 "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
1964 Parser.eatToEndOfStatement();
1965 return false;
1966}
1967
1968ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
1969 if (DirectiveID.getString() == ".option")
1970 return parseDirectiveOption();
1971
1972 return ParseStatus::NoMatch;
1973}
1974
1978}
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:128
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)
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:99
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
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
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:819
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
void setLoc(SMLoc loc)
Definition: MCInst.h:204
unsigned getOpcode() const
Definition: MCInst.h:199
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:207
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:163
int64_t getImm() const
Definition: MCInst.h:81
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:135
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:142
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCExpr * getExpr() const
Definition: MCInst.h:115
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.
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:309
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
void setFeatureBits(const FeatureBitset &FeatureBits_)
const FeatureBitset & getFeatureBits() const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
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 ParseStatus parseDirective(AsmToken DirectiveID)
Parses a target-specific assembler directive.
virtual bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
Parse one assembly instruction.
MCSubtargetInfo & copySTI()
Create a copy of STI and return a non-const reference to it.
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
virtual bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
Recognize a series of operands of a parsed instruction as an actual MCInst and emit it to the specifi...
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 unsigned checkTargetMatchPredicate(MCInst &Inst)
checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not ...
Target specific streamer interface.
Definition: MCStreamer.h:94
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
bool empty() const
Definition: SmallVector.h:81
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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.
static bool isAMCAS(uint64_t TSFlags)
static bool isSubjectToAMORdConstraint(uint64_t TSFlags)
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,...