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