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