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