LLVM 19.0.0git
AArch64AsmParser.cpp
Go to the documentation of this file.
1//==- AArch64AsmParser.cpp - Parse AArch64 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
9#include "AArch64InstrInfo.h"
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/APInt.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/SmallSet.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
27#include "llvm/ADT/Twine.h"
28#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCExpr.h"
30#include "llvm/MC/MCInst.h"
39#include "llvm/MC/MCStreamer.h"
41#include "llvm/MC/MCSymbol.h"
43#include "llvm/MC/MCValue.h"
49#include "llvm/Support/SMLoc.h"
53#include <cassert>
54#include <cctype>
55#include <cstdint>
56#include <cstdio>
57#include <optional>
58#include <string>
59#include <tuple>
60#include <utility>
61#include <vector>
62
63using namespace llvm;
64
65namespace {
66
67enum class RegKind {
68 Scalar,
69 NeonVector,
70 SVEDataVector,
71 SVEPredicateAsCounter,
72 SVEPredicateVector,
73 Matrix,
74 LookupTable
75};
76
77enum class MatrixKind { Array, Tile, Row, Col };
78
79enum RegConstraintEqualityTy {
80 EqualsReg,
81 EqualsSuperReg,
82 EqualsSubReg
83};
84
85class AArch64AsmParser : public MCTargetAsmParser {
86private:
87 StringRef Mnemonic; ///< Instruction mnemonic.
88
89 // Map of register aliases registers via the .req directive.
91
92 class PrefixInfo {
93 public:
94 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
95 PrefixInfo Prefix;
96 switch (Inst.getOpcode()) {
97 case AArch64::MOVPRFX_ZZ:
98 Prefix.Active = true;
99 Prefix.Dst = Inst.getOperand(0).getReg();
100 break;
101 case AArch64::MOVPRFX_ZPmZ_B:
102 case AArch64::MOVPRFX_ZPmZ_H:
103 case AArch64::MOVPRFX_ZPmZ_S:
104 case AArch64::MOVPRFX_ZPmZ_D:
105 Prefix.Active = true;
106 Prefix.Predicated = true;
107 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
108 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
109 "No destructive element size set for movprfx");
110 Prefix.Dst = Inst.getOperand(0).getReg();
111 Prefix.Pg = Inst.getOperand(2).getReg();
112 break;
113 case AArch64::MOVPRFX_ZPzZ_B:
114 case AArch64::MOVPRFX_ZPzZ_H:
115 case AArch64::MOVPRFX_ZPzZ_S:
116 case AArch64::MOVPRFX_ZPzZ_D:
117 Prefix.Active = true;
118 Prefix.Predicated = true;
119 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
120 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
121 "No destructive element size set for movprfx");
122 Prefix.Dst = Inst.getOperand(0).getReg();
123 Prefix.Pg = Inst.getOperand(1).getReg();
124 break;
125 default:
126 break;
127 }
128
129 return Prefix;
130 }
131
132 PrefixInfo() = default;
133 bool isActive() const { return Active; }
134 bool isPredicated() const { return Predicated; }
135 unsigned getElementSize() const {
136 assert(Predicated);
137 return ElementSize;
138 }
139 unsigned getDstReg() const { return Dst; }
140 unsigned getPgReg() const {
141 assert(Predicated);
142 return Pg;
143 }
144
145 private:
146 bool Active = false;
147 bool Predicated = false;
148 unsigned ElementSize;
149 unsigned Dst;
150 unsigned Pg;
151 } NextPrefix;
152
153 AArch64TargetStreamer &getTargetStreamer() {
155 return static_cast<AArch64TargetStreamer &>(TS);
156 }
157
158 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
159
160 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
161 bool parseSyspAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
162 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
163 AArch64CC::CondCode parseCondCodeString(StringRef Cond,
164 std::string &Suggestion);
165 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
166 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
168 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
169 bool parseNeonVectorList(OperandVector &Operands);
170 bool parseOptionalMulOperand(OperandVector &Operands);
171 bool parseOptionalVGOperand(OperandVector &Operands, StringRef &VecGroup);
172 bool parseKeywordOperand(OperandVector &Operands);
173 bool parseOperand(OperandVector &Operands, bool isCondCode,
174 bool invertCondCode);
175 bool parseImmExpr(int64_t &Out);
176 bool parseComma();
177 bool parseRegisterInRange(unsigned &Out, unsigned Base, unsigned First,
178 unsigned Last);
179
180 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
182
183 bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);
184
185 bool parseDirectiveArch(SMLoc L);
186 bool parseDirectiveArchExtension(SMLoc L);
187 bool parseDirectiveCPU(SMLoc L);
188 bool parseDirectiveInst(SMLoc L);
189
190 bool parseDirectiveTLSDescCall(SMLoc L);
191
192 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
193 bool parseDirectiveLtorg(SMLoc L);
194
195 bool parseDirectiveReq(StringRef Name, SMLoc L);
196 bool parseDirectiveUnreq(SMLoc L);
197 bool parseDirectiveCFINegateRAState();
198 bool parseDirectiveCFIBKeyFrame();
199 bool parseDirectiveCFIMTETaggedFrame();
200
201 bool parseDirectiveVariantPCS(SMLoc L);
202
203 bool parseDirectiveSEHAllocStack(SMLoc L);
204 bool parseDirectiveSEHPrologEnd(SMLoc L);
205 bool parseDirectiveSEHSaveR19R20X(SMLoc L);
206 bool parseDirectiveSEHSaveFPLR(SMLoc L);
207 bool parseDirectiveSEHSaveFPLRX(SMLoc L);
208 bool parseDirectiveSEHSaveReg(SMLoc L);
209 bool parseDirectiveSEHSaveRegX(SMLoc L);
210 bool parseDirectiveSEHSaveRegP(SMLoc L);
211 bool parseDirectiveSEHSaveRegPX(SMLoc L);
212 bool parseDirectiveSEHSaveLRPair(SMLoc L);
213 bool parseDirectiveSEHSaveFReg(SMLoc L);
214 bool parseDirectiveSEHSaveFRegX(SMLoc L);
215 bool parseDirectiveSEHSaveFRegP(SMLoc L);
216 bool parseDirectiveSEHSaveFRegPX(SMLoc L);
217 bool parseDirectiveSEHSetFP(SMLoc L);
218 bool parseDirectiveSEHAddFP(SMLoc L);
219 bool parseDirectiveSEHNop(SMLoc L);
220 bool parseDirectiveSEHSaveNext(SMLoc L);
221 bool parseDirectiveSEHEpilogStart(SMLoc L);
222 bool parseDirectiveSEHEpilogEnd(SMLoc L);
223 bool parseDirectiveSEHTrapFrame(SMLoc L);
224 bool parseDirectiveSEHMachineFrame(SMLoc L);
225 bool parseDirectiveSEHContext(SMLoc L);
226 bool parseDirectiveSEHECContext(SMLoc L);
227 bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
228 bool parseDirectiveSEHPACSignLR(SMLoc L);
229 bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
230
231 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
233 unsigned getNumRegsForRegKind(RegKind K);
234 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
237 bool MatchingInlineAsm) override;
238/// @name Auto-generated Match Functions
239/// {
240
241#define GET_ASSEMBLER_HEADER
242#include "AArch64GenAsmMatcher.inc"
243
244 /// }
245
246 ParseStatus tryParseScalarRegister(MCRegister &Reg);
247 ParseStatus tryParseVectorRegister(MCRegister &Reg, StringRef &Kind,
248 RegKind MatchKind);
249 ParseStatus tryParseMatrixRegister(OperandVector &Operands);
250 ParseStatus tryParseSVCR(OperandVector &Operands);
251 ParseStatus tryParseOptionalShiftExtend(OperandVector &Operands);
252 ParseStatus tryParseBarrierOperand(OperandVector &Operands);
253 ParseStatus tryParseBarriernXSOperand(OperandVector &Operands);
254 ParseStatus tryParseSysReg(OperandVector &Operands);
255 ParseStatus tryParseSysCROperand(OperandVector &Operands);
256 template <bool IsSVEPrefetch = false>
257 ParseStatus tryParsePrefetch(OperandVector &Operands);
258 ParseStatus tryParseRPRFMOperand(OperandVector &Operands);
259 ParseStatus tryParsePSBHint(OperandVector &Operands);
260 ParseStatus tryParseBTIHint(OperandVector &Operands);
261 ParseStatus tryParseAdrpLabel(OperandVector &Operands);
262 ParseStatus tryParseAdrLabel(OperandVector &Operands);
263 template <bool AddFPZeroAsLiteral>
264 ParseStatus tryParseFPImm(OperandVector &Operands);
265 ParseStatus tryParseImmWithOptionalShift(OperandVector &Operands);
266 ParseStatus tryParseGPR64sp0Operand(OperandVector &Operands);
267 bool tryParseNeonVectorRegister(OperandVector &Operands);
268 ParseStatus tryParseVectorIndex(OperandVector &Operands);
269 ParseStatus tryParseGPRSeqPair(OperandVector &Operands);
270 ParseStatus tryParseSyspXzrPair(OperandVector &Operands);
271 template <bool ParseShiftExtend,
272 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
273 ParseStatus tryParseGPROperand(OperandVector &Operands);
274 ParseStatus tryParseZTOperand(OperandVector &Operands);
275 template <bool ParseShiftExtend, bool ParseSuffix>
276 ParseStatus tryParseSVEDataVector(OperandVector &Operands);
277 template <RegKind RK>
278 ParseStatus tryParseSVEPredicateVector(OperandVector &Operands);
280 tryParseSVEPredicateOrPredicateAsCounterVector(OperandVector &Operands);
281 template <RegKind VectorKind>
282 ParseStatus tryParseVectorList(OperandVector &Operands,
283 bool ExpectMatch = false);
284 ParseStatus tryParseMatrixTileList(OperandVector &Operands);
285 ParseStatus tryParseSVEPattern(OperandVector &Operands);
286 ParseStatus tryParseSVEVecLenSpecifier(OperandVector &Operands);
287 ParseStatus tryParseGPR64x8(OperandVector &Operands);
288 ParseStatus tryParseImmRange(OperandVector &Operands);
289
290public:
291 enum AArch64MatchResultTy {
292 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
293#define GET_OPERAND_DIAGNOSTIC_TYPES
294#include "AArch64GenAsmMatcher.inc"
295 };
296 bool IsILP32;
297 bool IsWindowsArm64EC;
298
299 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
300 const MCInstrInfo &MII, const MCTargetOptions &Options)
301 : MCTargetAsmParser(Options, STI, MII) {
303 IsWindowsArm64EC = STI.getTargetTriple().isWindowsArm64EC();
306 if (S.getTargetStreamer() == nullptr)
308
309 // Alias .hword/.word/.[dx]word to the target-independent
310 // .2byte/.4byte/.8byte directives as they have the same form and
311 // semantics:
312 /// ::= (.hword | .word | .dword | .xword ) [ expression (, expression)* ]
313 Parser.addAliasForDirective(".hword", ".2byte");
314 Parser.addAliasForDirective(".word", ".4byte");
315 Parser.addAliasForDirective(".dword", ".8byte");
316 Parser.addAliasForDirective(".xword", ".8byte");
317
318 // Initialize the set of available features.
319 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
320 }
321
322 bool areEqualRegs(const MCParsedAsmOperand &Op1,
323 const MCParsedAsmOperand &Op2) const override;
325 SMLoc NameLoc, OperandVector &Operands) override;
326 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
328 SMLoc &EndLoc) override;
329 bool ParseDirective(AsmToken DirectiveID) override;
331 unsigned Kind) override;
332
333 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
334
335 static bool classifySymbolRef(const MCExpr *Expr,
336 AArch64MCExpr::VariantKind &ELFRefKind,
337 MCSymbolRefExpr::VariantKind &DarwinRefKind,
338 int64_t &Addend);
339};
340
341/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
342/// instruction.
343class AArch64Operand : public MCParsedAsmOperand {
344private:
345 enum KindTy {
346 k_Immediate,
347 k_ShiftedImm,
348 k_ImmRange,
349 k_CondCode,
350 k_Register,
351 k_MatrixRegister,
352 k_MatrixTileList,
353 k_SVCR,
354 k_VectorList,
355 k_VectorIndex,
356 k_Token,
357 k_SysReg,
358 k_SysCR,
359 k_Prefetch,
360 k_ShiftExtend,
361 k_FPImm,
362 k_Barrier,
363 k_PSBHint,
364 k_BTIHint,
365 } Kind;
366
367 SMLoc StartLoc, EndLoc;
368
369 struct TokOp {
370 const char *Data;
371 unsigned Length;
372 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
373 };
374
375 // Separate shift/extend operand.
376 struct ShiftExtendOp {
378 unsigned Amount;
379 bool HasExplicitAmount;
380 };
381
382 struct RegOp {
383 unsigned RegNum;
384 RegKind Kind;
385 int ElementWidth;
386
387 // The register may be allowed as a different register class,
388 // e.g. for GPR64as32 or GPR32as64.
389 RegConstraintEqualityTy EqualityTy;
390
391 // In some cases the shift/extend needs to be explicitly parsed together
392 // with the register, rather than as a separate operand. This is needed
393 // for addressing modes where the instruction as a whole dictates the
394 // scaling/extend, rather than specific bits in the instruction.
395 // By parsing them as a single operand, we avoid the need to pass an
396 // extra operand in all CodeGen patterns (because all operands need to
397 // have an associated value), and we avoid the need to update TableGen to
398 // accept operands that have no associated bits in the instruction.
399 //
400 // An added benefit of parsing them together is that the assembler
401 // can give a sensible diagnostic if the scaling is not correct.
402 //
403 // The default is 'lsl #0' (HasExplicitAmount = false) if no
404 // ShiftExtend is specified.
405 ShiftExtendOp ShiftExtend;
406 };
407
408 struct MatrixRegOp {
409 unsigned RegNum;
410 unsigned ElementWidth;
411 MatrixKind Kind;
412 };
413
414 struct MatrixTileListOp {
415 unsigned RegMask = 0;
416 };
417
418 struct VectorListOp {
419 unsigned RegNum;
420 unsigned Count;
421 unsigned Stride;
422 unsigned NumElements;
423 unsigned ElementWidth;
424 RegKind RegisterKind;
425 };
426
427 struct VectorIndexOp {
428 int Val;
429 };
430
431 struct ImmOp {
432 const MCExpr *Val;
433 };
434
435 struct ShiftedImmOp {
436 const MCExpr *Val;
437 unsigned ShiftAmount;
438 };
439
440 struct ImmRangeOp {
441 unsigned First;
442 unsigned Last;
443 };
444
445 struct CondCodeOp {
447 };
448
449 struct FPImmOp {
450 uint64_t Val; // APFloat value bitcasted to uint64_t.
451 bool IsExact; // describes whether parsed value was exact.
452 };
453
454 struct BarrierOp {
455 const char *Data;
456 unsigned Length;
457 unsigned Val; // Not the enum since not all values have names.
458 bool HasnXSModifier;
459 };
460
461 struct SysRegOp {
462 const char *Data;
463 unsigned Length;
464 uint32_t MRSReg;
465 uint32_t MSRReg;
466 uint32_t PStateField;
467 };
468
469 struct SysCRImmOp {
470 unsigned Val;
471 };
472
473 struct PrefetchOp {
474 const char *Data;
475 unsigned Length;
476 unsigned Val;
477 };
478
479 struct PSBHintOp {
480 const char *Data;
481 unsigned Length;
482 unsigned Val;
483 };
484
485 struct BTIHintOp {
486 const char *Data;
487 unsigned Length;
488 unsigned Val;
489 };
490
491 struct SVCROp {
492 const char *Data;
493 unsigned Length;
494 unsigned PStateField;
495 };
496
497 union {
498 struct TokOp Tok;
499 struct RegOp Reg;
500 struct MatrixRegOp MatrixReg;
501 struct MatrixTileListOp MatrixTileList;
502 struct VectorListOp VectorList;
503 struct VectorIndexOp VectorIndex;
504 struct ImmOp Imm;
505 struct ShiftedImmOp ShiftedImm;
506 struct ImmRangeOp ImmRange;
507 struct CondCodeOp CondCode;
508 struct FPImmOp FPImm;
509 struct BarrierOp Barrier;
510 struct SysRegOp SysReg;
511 struct SysCRImmOp SysCRImm;
512 struct PrefetchOp Prefetch;
513 struct PSBHintOp PSBHint;
514 struct BTIHintOp BTIHint;
515 struct ShiftExtendOp ShiftExtend;
516 struct SVCROp SVCR;
517 };
518
519 // Keep the MCContext around as the MCExprs may need manipulated during
520 // the add<>Operands() calls.
521 MCContext &Ctx;
522
523public:
524 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
525
526 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
527 Kind = o.Kind;
528 StartLoc = o.StartLoc;
529 EndLoc = o.EndLoc;
530 switch (Kind) {
531 case k_Token:
532 Tok = o.Tok;
533 break;
534 case k_Immediate:
535 Imm = o.Imm;
536 break;
537 case k_ShiftedImm:
538 ShiftedImm = o.ShiftedImm;
539 break;
540 case k_ImmRange:
541 ImmRange = o.ImmRange;
542 break;
543 case k_CondCode:
544 CondCode = o.CondCode;
545 break;
546 case k_FPImm:
547 FPImm = o.FPImm;
548 break;
549 case k_Barrier:
550 Barrier = o.Barrier;
551 break;
552 case k_Register:
553 Reg = o.Reg;
554 break;
555 case k_MatrixRegister:
556 MatrixReg = o.MatrixReg;
557 break;
558 case k_MatrixTileList:
559 MatrixTileList = o.MatrixTileList;
560 break;
561 case k_VectorList:
562 VectorList = o.VectorList;
563 break;
564 case k_VectorIndex:
565 VectorIndex = o.VectorIndex;
566 break;
567 case k_SysReg:
568 SysReg = o.SysReg;
569 break;
570 case k_SysCR:
571 SysCRImm = o.SysCRImm;
572 break;
573 case k_Prefetch:
574 Prefetch = o.Prefetch;
575 break;
576 case k_PSBHint:
577 PSBHint = o.PSBHint;
578 break;
579 case k_BTIHint:
580 BTIHint = o.BTIHint;
581 break;
582 case k_ShiftExtend:
583 ShiftExtend = o.ShiftExtend;
584 break;
585 case k_SVCR:
586 SVCR = o.SVCR;
587 break;
588 }
589 }
590
591 /// getStartLoc - Get the location of the first token of this operand.
592 SMLoc getStartLoc() const override { return StartLoc; }
593 /// getEndLoc - Get the location of the last token of this operand.
594 SMLoc getEndLoc() const override { return EndLoc; }
595
596 StringRef getToken() const {
597 assert(Kind == k_Token && "Invalid access!");
598 return StringRef(Tok.Data, Tok.Length);
599 }
600
601 bool isTokenSuffix() const {
602 assert(Kind == k_Token && "Invalid access!");
603 return Tok.IsSuffix;
604 }
605
606 const MCExpr *getImm() const {
607 assert(Kind == k_Immediate && "Invalid access!");
608 return Imm.Val;
609 }
610
611 const MCExpr *getShiftedImmVal() const {
612 assert(Kind == k_ShiftedImm && "Invalid access!");
613 return ShiftedImm.Val;
614 }
615
616 unsigned getShiftedImmShift() const {
617 assert(Kind == k_ShiftedImm && "Invalid access!");
618 return ShiftedImm.ShiftAmount;
619 }
620
621 unsigned getFirstImmVal() const {
622 assert(Kind == k_ImmRange && "Invalid access!");
623 return ImmRange.First;
624 }
625
626 unsigned getLastImmVal() const {
627 assert(Kind == k_ImmRange && "Invalid access!");
628 return ImmRange.Last;
629 }
630
632 assert(Kind == k_CondCode && "Invalid access!");
633 return CondCode.Code;
634 }
635
636 APFloat getFPImm() const {
637 assert (Kind == k_FPImm && "Invalid access!");
638 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
639 }
640
641 bool getFPImmIsExact() const {
642 assert (Kind == k_FPImm && "Invalid access!");
643 return FPImm.IsExact;
644 }
645
646 unsigned getBarrier() const {
647 assert(Kind == k_Barrier && "Invalid access!");
648 return Barrier.Val;
649 }
650
651 StringRef getBarrierName() const {
652 assert(Kind == k_Barrier && "Invalid access!");
653 return StringRef(Barrier.Data, Barrier.Length);
654 }
655
656 bool getBarriernXSModifier() const {
657 assert(Kind == k_Barrier && "Invalid access!");
658 return Barrier.HasnXSModifier;
659 }
660
661 MCRegister getReg() const override {
662 assert(Kind == k_Register && "Invalid access!");
663 return Reg.RegNum;
664 }
665
666 unsigned getMatrixReg() const {
667 assert(Kind == k_MatrixRegister && "Invalid access!");
668 return MatrixReg.RegNum;
669 }
670
671 unsigned getMatrixElementWidth() const {
672 assert(Kind == k_MatrixRegister && "Invalid access!");
673 return MatrixReg.ElementWidth;
674 }
675
676 MatrixKind getMatrixKind() const {
677 assert(Kind == k_MatrixRegister && "Invalid access!");
678 return MatrixReg.Kind;
679 }
680
681 unsigned getMatrixTileListRegMask() const {
682 assert(isMatrixTileList() && "Invalid access!");
683 return MatrixTileList.RegMask;
684 }
685
686 RegConstraintEqualityTy getRegEqualityTy() const {
687 assert(Kind == k_Register && "Invalid access!");
688 return Reg.EqualityTy;
689 }
690
691 unsigned getVectorListStart() const {
692 assert(Kind == k_VectorList && "Invalid access!");
693 return VectorList.RegNum;
694 }
695
696 unsigned getVectorListCount() const {
697 assert(Kind == k_VectorList && "Invalid access!");
698 return VectorList.Count;
699 }
700
701 unsigned getVectorListStride() const {
702 assert(Kind == k_VectorList && "Invalid access!");
703 return VectorList.Stride;
704 }
705
706 int getVectorIndex() const {
707 assert(Kind == k_VectorIndex && "Invalid access!");
708 return VectorIndex.Val;
709 }
710
711 StringRef getSysReg() const {
712 assert(Kind == k_SysReg && "Invalid access!");
713 return StringRef(SysReg.Data, SysReg.Length);
714 }
715
716 unsigned getSysCR() const {
717 assert(Kind == k_SysCR && "Invalid access!");
718 return SysCRImm.Val;
719 }
720
721 unsigned getPrefetch() const {
722 assert(Kind == k_Prefetch && "Invalid access!");
723 return Prefetch.Val;
724 }
725
726 unsigned getPSBHint() const {
727 assert(Kind == k_PSBHint && "Invalid access!");
728 return PSBHint.Val;
729 }
730
731 StringRef getPSBHintName() const {
732 assert(Kind == k_PSBHint && "Invalid access!");
733 return StringRef(PSBHint.Data, PSBHint.Length);
734 }
735
736 unsigned getBTIHint() const {
737 assert(Kind == k_BTIHint && "Invalid access!");
738 return BTIHint.Val;
739 }
740
741 StringRef getBTIHintName() const {
742 assert(Kind == k_BTIHint && "Invalid access!");
743 return StringRef(BTIHint.Data, BTIHint.Length);
744 }
745
746 StringRef getSVCR() const {
747 assert(Kind == k_SVCR && "Invalid access!");
748 return StringRef(SVCR.Data, SVCR.Length);
749 }
750
751 StringRef getPrefetchName() const {
752 assert(Kind == k_Prefetch && "Invalid access!");
753 return StringRef(Prefetch.Data, Prefetch.Length);
754 }
755
756 AArch64_AM::ShiftExtendType getShiftExtendType() const {
757 if (Kind == k_ShiftExtend)
758 return ShiftExtend.Type;
759 if (Kind == k_Register)
760 return Reg.ShiftExtend.Type;
761 llvm_unreachable("Invalid access!");
762 }
763
764 unsigned getShiftExtendAmount() const {
765 if (Kind == k_ShiftExtend)
766 return ShiftExtend.Amount;
767 if (Kind == k_Register)
768 return Reg.ShiftExtend.Amount;
769 llvm_unreachable("Invalid access!");
770 }
771
772 bool hasShiftExtendAmount() const {
773 if (Kind == k_ShiftExtend)
774 return ShiftExtend.HasExplicitAmount;
775 if (Kind == k_Register)
776 return Reg.ShiftExtend.HasExplicitAmount;
777 llvm_unreachable("Invalid access!");
778 }
779
780 bool isImm() const override { return Kind == k_Immediate; }
781 bool isMem() const override { return false; }
782
783 bool isUImm6() const {
784 if (!isImm())
785 return false;
786 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
787 if (!MCE)
788 return false;
789 int64_t Val = MCE->getValue();
790 return (Val >= 0 && Val < 64);
791 }
792
793 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
794
795 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
796 return isImmScaled<Bits, Scale>(true);
797 }
798
799 template <int Bits, int Scale, int Offset = 0, bool IsRange = false>
800 DiagnosticPredicate isUImmScaled() const {
801 if (IsRange && isImmRange() &&
802 (getLastImmVal() != getFirstImmVal() + Offset))
803 return DiagnosticPredicateTy::NoMatch;
804
805 return isImmScaled<Bits, Scale, IsRange>(false);
806 }
807
808 template <int Bits, int Scale, bool IsRange = false>
809 DiagnosticPredicate isImmScaled(bool Signed) const {
810 if ((!isImm() && !isImmRange()) || (isImm() && IsRange) ||
811 (isImmRange() && !IsRange))
812 return DiagnosticPredicateTy::NoMatch;
813
814 int64_t Val;
815 if (isImmRange())
816 Val = getFirstImmVal();
817 else {
818 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
819 if (!MCE)
820 return DiagnosticPredicateTy::NoMatch;
821 Val = MCE->getValue();
822 }
823
824 int64_t MinVal, MaxVal;
825 if (Signed) {
826 int64_t Shift = Bits - 1;
827 MinVal = (int64_t(1) << Shift) * -Scale;
828 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
829 } else {
830 MinVal = 0;
831 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
832 }
833
834 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
835 return DiagnosticPredicateTy::Match;
836
837 return DiagnosticPredicateTy::NearMatch;
838 }
839
840 DiagnosticPredicate isSVEPattern() const {
841 if (!isImm())
842 return DiagnosticPredicateTy::NoMatch;
843 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
844 if (!MCE)
845 return DiagnosticPredicateTy::NoMatch;
846 int64_t Val = MCE->getValue();
847 if (Val >= 0 && Val < 32)
848 return DiagnosticPredicateTy::Match;
849 return DiagnosticPredicateTy::NearMatch;
850 }
851
852 DiagnosticPredicate isSVEVecLenSpecifier() const {
853 if (!isImm())
854 return DiagnosticPredicateTy::NoMatch;
855 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
856 if (!MCE)
857 return DiagnosticPredicateTy::NoMatch;
858 int64_t Val = MCE->getValue();
859 if (Val >= 0 && Val <= 1)
860 return DiagnosticPredicateTy::Match;
861 return DiagnosticPredicateTy::NearMatch;
862 }
863
864 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
866 MCSymbolRefExpr::VariantKind DarwinRefKind;
867 int64_t Addend;
868 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
869 Addend)) {
870 // If we don't understand the expression, assume the best and
871 // let the fixup and relocation code deal with it.
872 return true;
873 }
874
875 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
876 ELFRefKind == AArch64MCExpr::VK_LO12 ||
877 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
878 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
879 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
880 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
881 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
883 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
884 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
885 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 ||
886 ELFRefKind == AArch64MCExpr::VK_GOT_PAGE_LO15) {
887 // Note that we don't range-check the addend. It's adjusted modulo page
888 // size when converted, so there is no "out of range" condition when using
889 // @pageoff.
890 return true;
891 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
892 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
893 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
894 return Addend == 0;
895 }
896
897 return false;
898 }
899
900 template <int Scale> bool isUImm12Offset() const {
901 if (!isImm())
902 return false;
903
904 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
905 if (!MCE)
906 return isSymbolicUImm12Offset(getImm());
907
908 int64_t Val = MCE->getValue();
909 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
910 }
911
912 template <int N, int M>
913 bool isImmInRange() const {
914 if (!isImm())
915 return false;
916 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
917 if (!MCE)
918 return false;
919 int64_t Val = MCE->getValue();
920 return (Val >= N && Val <= M);
921 }
922
923 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
924 // a logical immediate can always be represented when inverted.
925 template <typename T>
926 bool isLogicalImm() const {
927 if (!isImm())
928 return false;
929 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
930 if (!MCE)
931 return false;
932
933 int64_t Val = MCE->getValue();
934 // Avoid left shift by 64 directly.
935 uint64_t Upper = UINT64_C(-1) << (sizeof(T) * 4) << (sizeof(T) * 4);
936 // Allow all-0 or all-1 in top bits to permit bitwise NOT.
937 if ((Val & Upper) && (Val & Upper) != Upper)
938 return false;
939
940 return AArch64_AM::isLogicalImmediate(Val & ~Upper, sizeof(T) * 8);
941 }
942
943 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
944
945 bool isImmRange() const { return Kind == k_ImmRange; }
946
947 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
948 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
949 /// immediate that can be shifted by 'Shift'.
950 template <unsigned Width>
951 std::optional<std::pair<int64_t, unsigned>> getShiftedVal() const {
952 if (isShiftedImm() && Width == getShiftedImmShift())
953 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
954 return std::make_pair(CE->getValue(), Width);
955
956 if (isImm())
957 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
958 int64_t Val = CE->getValue();
959 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
960 return std::make_pair(Val >> Width, Width);
961 else
962 return std::make_pair(Val, 0u);
963 }
964
965 return {};
966 }
967
968 bool isAddSubImm() const {
969 if (!isShiftedImm() && !isImm())
970 return false;
971
972 const MCExpr *Expr;
973
974 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
975 if (isShiftedImm()) {
976 unsigned Shift = ShiftedImm.ShiftAmount;
977 Expr = ShiftedImm.Val;
978 if (Shift != 0 && Shift != 12)
979 return false;
980 } else {
981 Expr = getImm();
982 }
983
985 MCSymbolRefExpr::VariantKind DarwinRefKind;
986 int64_t Addend;
987 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
988 DarwinRefKind, Addend)) {
989 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
990 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
991 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
992 || ELFRefKind == AArch64MCExpr::VK_LO12
993 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
994 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
995 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
996 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
997 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
998 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
999 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
1000 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
1001 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
1002 }
1003
1004 // If it's a constant, it should be a real immediate in range.
1005 if (auto ShiftedVal = getShiftedVal<12>())
1006 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
1007
1008 // If it's an expression, we hope for the best and let the fixup/relocation
1009 // code deal with it.
1010 return true;
1011 }
1012
1013 bool isAddSubImmNeg() const {
1014 if (!isShiftedImm() && !isImm())
1015 return false;
1016
1017 // Otherwise it should be a real negative immediate in range.
1018 if (auto ShiftedVal = getShiftedVal<12>())
1019 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
1020
1021 return false;
1022 }
1023
1024 // Signed value in the range -128 to +127. For element widths of
1025 // 16 bits or higher it may also be a signed multiple of 256 in the
1026 // range -32768 to +32512.
1027 // For element-width of 8 bits a range of -128 to 255 is accepted,
1028 // since a copy of a byte can be either signed/unsigned.
1029 template <typename T>
1030 DiagnosticPredicate isSVECpyImm() const {
1031 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
1032 return DiagnosticPredicateTy::NoMatch;
1033
1034 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
1035 std::is_same<int8_t, T>::value;
1036 if (auto ShiftedImm = getShiftedVal<8>())
1037 if (!(IsByte && ShiftedImm->second) &&
1038 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
1039 << ShiftedImm->second))
1040 return DiagnosticPredicateTy::Match;
1041
1042 return DiagnosticPredicateTy::NearMatch;
1043 }
1044
1045 // Unsigned value in the range 0 to 255. For element widths of
1046 // 16 bits or higher it may also be a signed multiple of 256 in the
1047 // range 0 to 65280.
1048 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
1049 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
1050 return DiagnosticPredicateTy::NoMatch;
1051
1052 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
1053 std::is_same<int8_t, T>::value;
1054 if (auto ShiftedImm = getShiftedVal<8>())
1055 if (!(IsByte && ShiftedImm->second) &&
1056 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
1057 << ShiftedImm->second))
1058 return DiagnosticPredicateTy::Match;
1059
1060 return DiagnosticPredicateTy::NearMatch;
1061 }
1062
1063 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
1064 if (isLogicalImm<T>() && !isSVECpyImm<T>())
1065 return DiagnosticPredicateTy::Match;
1066 return DiagnosticPredicateTy::NoMatch;
1067 }
1068
1069 bool isCondCode() const { return Kind == k_CondCode; }
1070
1071 bool isSIMDImmType10() const {
1072 if (!isImm())
1073 return false;
1074 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1075 if (!MCE)
1076 return false;
1078 }
1079
1080 template<int N>
1081 bool isBranchTarget() const {
1082 if (!isImm())
1083 return false;
1084 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1085 if (!MCE)
1086 return true;
1087 int64_t Val = MCE->getValue();
1088 if (Val & 0x3)
1089 return false;
1090 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
1091 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
1092 }
1093
1094 bool
1095 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
1096 if (!isImm())
1097 return false;
1098
1099 AArch64MCExpr::VariantKind ELFRefKind;
1100 MCSymbolRefExpr::VariantKind DarwinRefKind;
1101 int64_t Addend;
1102 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
1103 DarwinRefKind, Addend)) {
1104 return false;
1105 }
1106 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
1107 return false;
1108
1109 return llvm::is_contained(AllowedModifiers, ELFRefKind);
1110 }
1111
1112 bool isMovWSymbolG3() const {
1114 }
1115
1116 bool isMovWSymbolG2() const {
1117 return isMovWSymbol(
1122 }
1123
1124 bool isMovWSymbolG1() const {
1125 return isMovWSymbol(
1131 }
1132
1133 bool isMovWSymbolG0() const {
1134 return isMovWSymbol(
1140 }
1141
1142 template<int RegWidth, int Shift>
1143 bool isMOVZMovAlias() const {
1144 if (!isImm()) return false;
1145
1146 const MCExpr *E = getImm();
1147 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(E)) {
1148 uint64_t Value = CE->getValue();
1149
1150 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
1151 }
1152 // Only supports the case of Shift being 0 if an expression is used as an
1153 // operand
1154 return !Shift && E;
1155 }
1156
1157 template<int RegWidth, int Shift>
1158 bool isMOVNMovAlias() const {
1159 if (!isImm()) return false;
1160
1161 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1162 if (!CE) return false;
1163 uint64_t Value = CE->getValue();
1164
1165 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
1166 }
1167
1168 bool isFPImm() const {
1169 return Kind == k_FPImm &&
1170 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1171 }
1172
1173 bool isBarrier() const {
1174 return Kind == k_Barrier && !getBarriernXSModifier();
1175 }
1176 bool isBarriernXS() const {
1177 return Kind == k_Barrier && getBarriernXSModifier();
1178 }
1179 bool isSysReg() const { return Kind == k_SysReg; }
1180
1181 bool isMRSSystemRegister() const {
1182 if (!isSysReg()) return false;
1183
1184 return SysReg.MRSReg != -1U;
1185 }
1186
1187 bool isMSRSystemRegister() const {
1188 if (!isSysReg()) return false;
1189 return SysReg.MSRReg != -1U;
1190 }
1191
1192 bool isSystemPStateFieldWithImm0_1() const {
1193 if (!isSysReg()) return false;
1194 return AArch64PState::lookupPStateImm0_1ByEncoding(SysReg.PStateField);
1195 }
1196
1197 bool isSystemPStateFieldWithImm0_15() const {
1198 if (!isSysReg())
1199 return false;
1200 return AArch64PState::lookupPStateImm0_15ByEncoding(SysReg.PStateField);
1201 }
1202
1203 bool isSVCR() const {
1204 if (Kind != k_SVCR)
1205 return false;
1206 return SVCR.PStateField != -1U;
1207 }
1208
1209 bool isReg() const override {
1210 return Kind == k_Register;
1211 }
1212
1213 bool isVectorList() const { return Kind == k_VectorList; }
1214
1215 bool isScalarReg() const {
1216 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1217 }
1218
1219 bool isNeonVectorReg() const {
1220 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1221 }
1222
1223 bool isNeonVectorRegLo() const {
1224 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
1225 (AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1226 Reg.RegNum) ||
1227 AArch64MCRegisterClasses[AArch64::FPR64_loRegClassID].contains(
1228 Reg.RegNum));
1229 }
1230
1231 bool isNeonVectorReg0to7() const {
1232 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
1233 (AArch64MCRegisterClasses[AArch64::FPR128_0to7RegClassID].contains(
1234 Reg.RegNum));
1235 }
1236
1237 bool isMatrix() const { return Kind == k_MatrixRegister; }
1238 bool isMatrixTileList() const { return Kind == k_MatrixTileList; }
1239
1240 template <unsigned Class> bool isSVEPredicateAsCounterReg() const {
1241 RegKind RK;
1242 switch (Class) {
1243 case AArch64::PPRRegClassID:
1244 case AArch64::PPR_3bRegClassID:
1245 case AArch64::PPR_p8to15RegClassID:
1246 case AArch64::PNRRegClassID:
1247 case AArch64::PNR_p8to15RegClassID:
1248 case AArch64::PPRorPNRRegClassID:
1249 RK = RegKind::SVEPredicateAsCounter;
1250 break;
1251 default:
1252 llvm_unreachable("Unsupport register class");
1253 }
1254
1255 return (Kind == k_Register && Reg.Kind == RK) &&
1256 AArch64MCRegisterClasses[Class].contains(getReg());
1257 }
1258
1259 template <unsigned Class> bool isSVEVectorReg() const {
1260 RegKind RK;
1261 switch (Class) {
1262 case AArch64::ZPRRegClassID:
1263 case AArch64::ZPR_3bRegClassID:
1264 case AArch64::ZPR_4bRegClassID:
1265 RK = RegKind::SVEDataVector;
1266 break;
1267 case AArch64::PPRRegClassID:
1268 case AArch64::PPR_3bRegClassID:
1269 case AArch64::PPR_p8to15RegClassID:
1270 case AArch64::PNRRegClassID:
1271 case AArch64::PNR_p8to15RegClassID:
1272 case AArch64::PPRorPNRRegClassID:
1273 RK = RegKind::SVEPredicateVector;
1274 break;
1275 default:
1276 llvm_unreachable("Unsupport register class");
1277 }
1278
1279 return (Kind == k_Register && Reg.Kind == RK) &&
1280 AArch64MCRegisterClasses[Class].contains(getReg());
1281 }
1282
1283 template <unsigned Class> bool isFPRasZPR() const {
1284 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1285 AArch64MCRegisterClasses[Class].contains(getReg());
1286 }
1287
1288 template <int ElementWidth, unsigned Class>
1289 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1290 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1291 return DiagnosticPredicateTy::NoMatch;
1292
1293 if (isSVEVectorReg<Class>() && (Reg.ElementWidth == ElementWidth))
1294 return DiagnosticPredicateTy::Match;
1295
1296 return DiagnosticPredicateTy::NearMatch;
1297 }
1298
1299 template <int ElementWidth, unsigned Class>
1300 DiagnosticPredicate isSVEPredicateOrPredicateAsCounterRegOfWidth() const {
1301 if (Kind != k_Register || (Reg.Kind != RegKind::SVEPredicateAsCounter &&
1302 Reg.Kind != RegKind::SVEPredicateVector))
1303 return DiagnosticPredicateTy::NoMatch;
1304
1305 if ((isSVEPredicateAsCounterReg<Class>() ||
1306 isSVEPredicateVectorRegOfWidth<ElementWidth, Class>()) &&
1307 Reg.ElementWidth == ElementWidth)
1308 return DiagnosticPredicateTy::Match;
1309
1310 return DiagnosticPredicateTy::NearMatch;
1311 }
1312
1313 template <int ElementWidth, unsigned Class>
1314 DiagnosticPredicate isSVEPredicateAsCounterRegOfWidth() const {
1315 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateAsCounter)
1316 return DiagnosticPredicateTy::NoMatch;
1317
1318 if (isSVEPredicateAsCounterReg<Class>() && (Reg.ElementWidth == ElementWidth))
1319 return DiagnosticPredicateTy::Match;
1320
1321 return DiagnosticPredicateTy::NearMatch;
1322 }
1323
1324 template <int ElementWidth, unsigned Class>
1325 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1326 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1327 return DiagnosticPredicateTy::NoMatch;
1328
1329 if (isSVEVectorReg<Class>() && Reg.ElementWidth == ElementWidth)
1330 return DiagnosticPredicateTy::Match;
1331
1332 return DiagnosticPredicateTy::NearMatch;
1333 }
1334
1335 template <int ElementWidth, unsigned Class,
1336 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1337 bool ShiftWidthAlwaysSame>
1338 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1339 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1340 if (!VectorMatch.isMatch())
1341 return DiagnosticPredicateTy::NoMatch;
1342
1343 // Give a more specific diagnostic when the user has explicitly typed in
1344 // a shift-amount that does not match what is expected, but for which
1345 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1346 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1347 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1348 ShiftExtendTy == AArch64_AM::SXTW) &&
1349 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1350 return DiagnosticPredicateTy::NoMatch;
1351
1352 if (MatchShift && ShiftExtendTy == getShiftExtendType())
1353 return DiagnosticPredicateTy::Match;
1354
1355 return DiagnosticPredicateTy::NearMatch;
1356 }
1357
1358 bool isGPR32as64() const {
1359 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1360 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1361 }
1362
1363 bool isGPR64as32() const {
1364 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1365 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1366 }
1367
1368 bool isGPR64x8() const {
1369 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1370 AArch64MCRegisterClasses[AArch64::GPR64x8ClassRegClassID].contains(
1371 Reg.RegNum);
1372 }
1373
1374 bool isWSeqPair() const {
1375 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1376 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1377 Reg.RegNum);
1378 }
1379
1380 bool isXSeqPair() const {
1381 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1382 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1383 Reg.RegNum);
1384 }
1385
1386 bool isSyspXzrPair() const {
1387 return isGPR64<AArch64::GPR64RegClassID>() && Reg.RegNum == AArch64::XZR;
1388 }
1389
1390 template<int64_t Angle, int64_t Remainder>
1391 DiagnosticPredicate isComplexRotation() const {
1392 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
1393
1394 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1395 if (!CE) return DiagnosticPredicateTy::NoMatch;
1396 uint64_t Value = CE->getValue();
1397
1398 if (Value % Angle == Remainder && Value <= 270)
1399 return DiagnosticPredicateTy::Match;
1400 return DiagnosticPredicateTy::NearMatch;
1401 }
1402
1403 template <unsigned RegClassID> bool isGPR64() const {
1404 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1405 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1406 }
1407
1408 template <unsigned RegClassID, int ExtWidth>
1409 DiagnosticPredicate isGPR64WithShiftExtend() const {
1410 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1411 return DiagnosticPredicateTy::NoMatch;
1412
1413 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1414 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1415 return DiagnosticPredicateTy::Match;
1416 return DiagnosticPredicateTy::NearMatch;
1417 }
1418
1419 /// Is this a vector list with the type implicit (presumably attached to the
1420 /// instruction itself)?
1421 template <RegKind VectorKind, unsigned NumRegs>
1422 bool isImplicitlyTypedVectorList() const {
1423 return Kind == k_VectorList && VectorList.Count == NumRegs &&
1424 VectorList.NumElements == 0 &&
1425 VectorList.RegisterKind == VectorKind;
1426 }
1427
1428 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1429 unsigned ElementWidth, unsigned Stride = 1>
1430 bool isTypedVectorList() const {
1431 if (Kind != k_VectorList)
1432 return false;
1433 if (VectorList.Count != NumRegs)
1434 return false;
1435 if (VectorList.RegisterKind != VectorKind)
1436 return false;
1437 if (VectorList.ElementWidth != ElementWidth)
1438 return false;
1439 if (VectorList.Stride != Stride)
1440 return false;
1441 return VectorList.NumElements == NumElements;
1442 }
1443
1444 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1445 unsigned ElementWidth>
1446 DiagnosticPredicate isTypedVectorListMultiple() const {
1447 bool Res =
1448 isTypedVectorList<VectorKind, NumRegs, NumElements, ElementWidth>();
1449 if (!Res)
1450 return DiagnosticPredicateTy::NoMatch;
1451 if (((VectorList.RegNum - AArch64::Z0) % NumRegs) != 0)
1452 return DiagnosticPredicateTy::NearMatch;
1453 return DiagnosticPredicateTy::Match;
1454 }
1455
1456 template <RegKind VectorKind, unsigned NumRegs, unsigned Stride,
1457 unsigned ElementWidth>
1458 DiagnosticPredicate isTypedVectorListStrided() const {
1459 bool Res = isTypedVectorList<VectorKind, NumRegs, /*NumElements*/ 0,
1460 ElementWidth, Stride>();
1461 if (!Res)
1462 return DiagnosticPredicateTy::NoMatch;
1463 if ((VectorList.RegNum < (AArch64::Z0 + Stride)) ||
1464 ((VectorList.RegNum >= AArch64::Z16) &&
1465 (VectorList.RegNum < (AArch64::Z16 + Stride))))
1466 return DiagnosticPredicateTy::Match;
1467 return DiagnosticPredicateTy::NoMatch;
1468 }
1469
1470 template <int Min, int Max>
1471 DiagnosticPredicate isVectorIndex() const {
1472 if (Kind != k_VectorIndex)
1473 return DiagnosticPredicateTy::NoMatch;
1474 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1475 return DiagnosticPredicateTy::Match;
1476 return DiagnosticPredicateTy::NearMatch;
1477 }
1478
1479 bool isToken() const override { return Kind == k_Token; }
1480
1481 bool isTokenEqual(StringRef Str) const {
1482 return Kind == k_Token && getToken() == Str;
1483 }
1484 bool isSysCR() const { return Kind == k_SysCR; }
1485 bool isPrefetch() const { return Kind == k_Prefetch; }
1486 bool isPSBHint() const { return Kind == k_PSBHint; }
1487 bool isBTIHint() const { return Kind == k_BTIHint; }
1488 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1489 bool isShifter() const {
1490 if (!isShiftExtend())
1491 return false;
1492
1493 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1494 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1495 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1496 ST == AArch64_AM::MSL);
1497 }
1498
1499 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1500 if (Kind != k_FPImm)
1501 return DiagnosticPredicateTy::NoMatch;
1502
1503 if (getFPImmIsExact()) {
1504 // Lookup the immediate from table of supported immediates.
1505 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1506 assert(Desc && "Unknown enum value");
1507
1508 // Calculate its FP value.
1509 APFloat RealVal(APFloat::IEEEdouble());
1510 auto StatusOrErr =
1511 RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero);
1512 if (errorToBool(StatusOrErr.takeError()) || *StatusOrErr != APFloat::opOK)
1513 llvm_unreachable("FP immediate is not exact");
1514
1515 if (getFPImm().bitwiseIsEqual(RealVal))
1516 return DiagnosticPredicateTy::Match;
1517 }
1518
1519 return DiagnosticPredicateTy::NearMatch;
1520 }
1521
1522 template <unsigned ImmA, unsigned ImmB>
1523 DiagnosticPredicate isExactFPImm() const {
1524 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1525 if ((Res = isExactFPImm<ImmA>()))
1526 return DiagnosticPredicateTy::Match;
1527 if ((Res = isExactFPImm<ImmB>()))
1528 return DiagnosticPredicateTy::Match;
1529 return Res;
1530 }
1531
1532 bool isExtend() const {
1533 if (!isShiftExtend())
1534 return false;
1535
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1538 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1539 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1540 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1541 ET == AArch64_AM::LSL) &&
1542 getShiftExtendAmount() <= 4;
1543 }
1544
1545 bool isExtend64() const {
1546 if (!isExtend())
1547 return false;
1548 // Make sure the extend expects a 32-bit source register.
1549 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1550 return ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1551 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1552 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW;
1553 }
1554
1555 bool isExtendLSL64() const {
1556 if (!isExtend())
1557 return false;
1558 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1559 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1560 ET == AArch64_AM::LSL) &&
1561 getShiftExtendAmount() <= 4;
1562 }
1563
1564 bool isLSLImm3Shift() const {
1565 if (!isShiftExtend())
1566 return false;
1567 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1568 return ET == AArch64_AM::LSL && getShiftExtendAmount() <= 7;
1569 }
1570
1571 template<int Width> bool isMemXExtend() const {
1572 if (!isExtend())
1573 return false;
1574 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1575 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1576 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1577 getShiftExtendAmount() == 0);
1578 }
1579
1580 template<int Width> bool isMemWExtend() const {
1581 if (!isExtend())
1582 return false;
1583 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1584 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1585 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1586 getShiftExtendAmount() == 0);
1587 }
1588
1589 template <unsigned width>
1590 bool isArithmeticShifter() const {
1591 if (!isShifter())
1592 return false;
1593
1594 // An arithmetic shifter is LSL, LSR, or ASR.
1595 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1596 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1597 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1598 }
1599
1600 template <unsigned width>
1601 bool isLogicalShifter() const {
1602 if (!isShifter())
1603 return false;
1604
1605 // A logical shifter is LSL, LSR, ASR or ROR.
1606 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1607 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1608 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1609 getShiftExtendAmount() < width;
1610 }
1611
1612 bool isMovImm32Shifter() const {
1613 if (!isShifter())
1614 return false;
1615
1616 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1617 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1618 if (ST != AArch64_AM::LSL)
1619 return false;
1620 uint64_t Val = getShiftExtendAmount();
1621 return (Val == 0 || Val == 16);
1622 }
1623
1624 bool isMovImm64Shifter() const {
1625 if (!isShifter())
1626 return false;
1627
1628 // A MOVi shifter is LSL of 0 or 16.
1629 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1630 if (ST != AArch64_AM::LSL)
1631 return false;
1632 uint64_t Val = getShiftExtendAmount();
1633 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1634 }
1635
1636 bool isLogicalVecShifter() const {
1637 if (!isShifter())
1638 return false;
1639
1640 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1641 unsigned Shift = getShiftExtendAmount();
1642 return getShiftExtendType() == AArch64_AM::LSL &&
1643 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1644 }
1645
1646 bool isLogicalVecHalfWordShifter() const {
1647 if (!isLogicalVecShifter())
1648 return false;
1649
1650 // A logical vector shifter is a left shift by 0 or 8.
1651 unsigned Shift = getShiftExtendAmount();
1652 return getShiftExtendType() == AArch64_AM::LSL &&
1653 (Shift == 0 || Shift == 8);
1654 }
1655
1656 bool isMoveVecShifter() const {
1657 if (!isShiftExtend())
1658 return false;
1659
1660 // A logical vector shifter is a left shift by 8 or 16.
1661 unsigned Shift = getShiftExtendAmount();
1662 return getShiftExtendType() == AArch64_AM::MSL &&
1663 (Shift == 8 || Shift == 16);
1664 }
1665
1666 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1667 // to LDUR/STUR when the offset is not legal for the former but is for
1668 // the latter. As such, in addition to checking for being a legal unscaled
1669 // address, also check that it is not a legal scaled address. This avoids
1670 // ambiguity in the matcher.
1671 template<int Width>
1672 bool isSImm9OffsetFB() const {
1673 return isSImm<9>() && !isUImm12Offset<Width / 8>();
1674 }
1675
1676 bool isAdrpLabel() const {
1677 // Validation was handled during parsing, so we just verify that
1678 // something didn't go haywire.
1679 if (!isImm())
1680 return false;
1681
1682 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1683 int64_t Val = CE->getValue();
1684 int64_t Min = - (4096 * (1LL << (21 - 1)));
1685 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1686 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1687 }
1688
1689 return true;
1690 }
1691
1692 bool isAdrLabel() const {
1693 // Validation was handled during parsing, so we just verify that
1694 // something didn't go haywire.
1695 if (!isImm())
1696 return false;
1697
1698 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1699 int64_t Val = CE->getValue();
1700 int64_t Min = - (1LL << (21 - 1));
1701 int64_t Max = ((1LL << (21 - 1)) - 1);
1702 return Val >= Min && Val <= Max;
1703 }
1704
1705 return true;
1706 }
1707
1708 template <MatrixKind Kind, unsigned EltSize, unsigned RegClass>
1709 DiagnosticPredicate isMatrixRegOperand() const {
1710 if (!isMatrix())
1711 return DiagnosticPredicateTy::NoMatch;
1712 if (getMatrixKind() != Kind ||
1713 !AArch64MCRegisterClasses[RegClass].contains(getMatrixReg()) ||
1714 EltSize != getMatrixElementWidth())
1715 return DiagnosticPredicateTy::NearMatch;
1716 return DiagnosticPredicateTy::Match;
1717 }
1718
1719 bool isPAuthPCRelLabel16Operand() const {
1720 // PAuth PCRel16 operands are similar to regular branch targets, but only
1721 // negative values are allowed for concrete immediates as signing instr
1722 // should be in a lower address.
1723 if (!isImm())
1724 return false;
1725 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1726 if (!MCE)
1727 return true;
1728 int64_t Val = MCE->getValue();
1729 if (Val & 0b11)
1730 return false;
1731 return (Val <= 0) && (Val > -(1 << 18));
1732 }
1733
1734 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1735 // Add as immediates when possible. Null MCExpr = 0.
1736 if (!Expr)
1738 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1739 Inst.addOperand(MCOperand::createImm(CE->getValue()));
1740 else
1742 }
1743
1744 void addRegOperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 1 && "Invalid number of operands!");
1747 }
1748
1749 void addMatrixOperands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 Inst.addOperand(MCOperand::createReg(getMatrixReg()));
1752 }
1753
1754 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1755 assert(N == 1 && "Invalid number of operands!");
1756 assert(
1757 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1758
1759 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1760 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1761 RI->getEncodingValue(getReg()));
1762
1764 }
1765
1766 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1767 assert(N == 1 && "Invalid number of operands!");
1768 assert(
1769 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1770
1771 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1772 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1773 RI->getEncodingValue(getReg()));
1774
1776 }
1777
1778 template <int Width>
1779 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1780 unsigned Base;
1781 switch (Width) {
1782 case 8: Base = AArch64::B0; break;
1783 case 16: Base = AArch64::H0; break;
1784 case 32: Base = AArch64::S0; break;
1785 case 64: Base = AArch64::D0; break;
1786 case 128: Base = AArch64::Q0; break;
1787 default:
1788 llvm_unreachable("Unsupported width");
1789 }
1790 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1791 }
1792
1793 void addPPRorPNRRegOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 1 && "Invalid number of operands!");
1795 unsigned Reg = getReg();
1796 // Normalise to PPR
1797 if (Reg >= AArch64::PN0 && Reg <= AArch64::PN15)
1798 Reg = Reg - AArch64::PN0 + AArch64::P0;
1800 }
1801
1802 void addPNRasPPRRegOperands(MCInst &Inst, unsigned N) const {
1803 assert(N == 1 && "Invalid number of operands!");
1804 Inst.addOperand(
1805 MCOperand::createReg((getReg() - AArch64::PN0) + AArch64::P0));
1806 }
1807
1808 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1809 assert(N == 1 && "Invalid number of operands!");
1810 assert(
1811 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1812 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
1813 }
1814
1815 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1816 assert(N == 1 && "Invalid number of operands!");
1817 assert(
1818 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1820 }
1821
1822 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1823 assert(N == 1 && "Invalid number of operands!");
1825 }
1826
1827 void addVectorReg0to7Operands(MCInst &Inst, unsigned N) const {
1828 assert(N == 1 && "Invalid number of operands!");
1830 }
1831
1832 enum VecListIndexType {
1833 VecListIdx_DReg = 0,
1834 VecListIdx_QReg = 1,
1835 VecListIdx_ZReg = 2,
1836 VecListIdx_PReg = 3,
1837 };
1838
1839 template <VecListIndexType RegTy, unsigned NumRegs>
1840 void addVectorListOperands(MCInst &Inst, unsigned N) const {
1841 assert(N == 1 && "Invalid number of operands!");
1842 static const unsigned FirstRegs[][5] = {
1843 /* DReg */ { AArch64::Q0,
1844 AArch64::D0, AArch64::D0_D1,
1845 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1846 /* QReg */ { AArch64::Q0,
1847 AArch64::Q0, AArch64::Q0_Q1,
1848 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1849 /* ZReg */ { AArch64::Z0,
1850 AArch64::Z0, AArch64::Z0_Z1,
1851 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 },
1852 /* PReg */ { AArch64::P0,
1853 AArch64::P0, AArch64::P0_P1 }
1854 };
1855
1856 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1857 " NumRegs must be <= 4 for ZRegs");
1858
1859 assert((RegTy != VecListIdx_PReg || NumRegs <= 2) &&
1860 " NumRegs must be <= 2 for PRegs");
1861
1862 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1863 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1864 FirstRegs[(unsigned)RegTy][0]));
1865 }
1866
1867 template <unsigned NumRegs>
1868 void addStridedVectorListOperands(MCInst &Inst, unsigned N) const {
1869 assert(N == 1 && "Invalid number of operands!");
1870 assert((NumRegs == 2 || NumRegs == 4) && " NumRegs must be 2 or 4");
1871
1872 switch (NumRegs) {
1873 case 2:
1874 if (getVectorListStart() < AArch64::Z16) {
1875 assert((getVectorListStart() < AArch64::Z8) &&
1876 (getVectorListStart() >= AArch64::Z0) && "Invalid Register");
1878 AArch64::Z0_Z8 + getVectorListStart() - AArch64::Z0));
1879 } else {
1880 assert((getVectorListStart() < AArch64::Z24) &&
1881 (getVectorListStart() >= AArch64::Z16) && "Invalid Register");
1883 AArch64::Z16_Z24 + getVectorListStart() - AArch64::Z16));
1884 }
1885 break;
1886 case 4:
1887 if (getVectorListStart() < AArch64::Z16) {
1888 assert((getVectorListStart() < AArch64::Z4) &&
1889 (getVectorListStart() >= AArch64::Z0) && "Invalid Register");
1891 AArch64::Z0_Z4_Z8_Z12 + getVectorListStart() - AArch64::Z0));
1892 } else {
1893 assert((getVectorListStart() < AArch64::Z20) &&
1894 (getVectorListStart() >= AArch64::Z16) && "Invalid Register");
1896 AArch64::Z16_Z20_Z24_Z28 + getVectorListStart() - AArch64::Z16));
1897 }
1898 break;
1899 default:
1900 llvm_unreachable("Unsupported number of registers for strided vec list");
1901 }
1902 }
1903
1904 void addMatrixTileListOperands(MCInst &Inst, unsigned N) const {
1905 assert(N == 1 && "Invalid number of operands!");
1906 unsigned RegMask = getMatrixTileListRegMask();
1907 assert(RegMask <= 0xFF && "Invalid mask!");
1908 Inst.addOperand(MCOperand::createImm(RegMask));
1909 }
1910
1911 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1914 }
1915
1916 template <unsigned ImmIs0, unsigned ImmIs1>
1917 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1918 assert(N == 1 && "Invalid number of operands!");
1919 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1920 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1921 }
1922
1923 void addImmOperands(MCInst &Inst, unsigned N) const {
1924 assert(N == 1 && "Invalid number of operands!");
1925 // If this is a pageoff symrefexpr with an addend, adjust the addend
1926 // to be only the page-offset portion. Otherwise, just add the expr
1927 // as-is.
1928 addExpr(Inst, getImm());
1929 }
1930
1931 template <int Shift>
1932 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1933 assert(N == 2 && "Invalid number of operands!");
1934 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1935 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1936 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1937 } else if (isShiftedImm()) {
1938 addExpr(Inst, getShiftedImmVal());
1939 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
1940 } else {
1941 addExpr(Inst, getImm());
1943 }
1944 }
1945
1946 template <int Shift>
1947 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1948 assert(N == 2 && "Invalid number of operands!");
1949 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1950 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1951 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1952 } else
1953 llvm_unreachable("Not a shifted negative immediate");
1954 }
1955
1956 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1957 assert(N == 1 && "Invalid number of operands!");
1959 }
1960
1961 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1962 assert(N == 1 && "Invalid number of operands!");
1963 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1964 if (!MCE)
1965 addExpr(Inst, getImm());
1966 else
1967 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
1968 }
1969
1970 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1971 addImmOperands(Inst, N);
1972 }
1973
1974 template<int Scale>
1975 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1976 assert(N == 1 && "Invalid number of operands!");
1977 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1978
1979 if (!MCE) {
1980 Inst.addOperand(MCOperand::createExpr(getImm()));
1981 return;
1982 }
1983 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1984 }
1985
1986 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1987 assert(N == 1 && "Invalid number of operands!");
1988 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1990 }
1991
1992 template <int Scale>
1993 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1994 assert(N == 1 && "Invalid number of operands!");
1995 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1996 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1997 }
1998
1999 template <int Scale>
2000 void addImmScaledRangeOperands(MCInst &Inst, unsigned N) const {
2001 assert(N == 1 && "Invalid number of operands!");
2002 Inst.addOperand(MCOperand::createImm(getFirstImmVal() / Scale));
2003 }
2004
2005 template <typename T>
2006 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
2007 assert(N == 1 && "Invalid number of operands!");
2008 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
2009 std::make_unsigned_t<T> Val = MCE->getValue();
2010 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
2011 Inst.addOperand(MCOperand::createImm(encoding));
2012 }
2013
2014 template <typename T>
2015 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
2016 assert(N == 1 && "Invalid number of operands!");
2017 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
2018 std::make_unsigned_t<T> Val = ~MCE->getValue();
2019 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
2020 Inst.addOperand(MCOperand::createImm(encoding));
2021 }
2022
2023 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
2024 assert(N == 1 && "Invalid number of operands!");
2025 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
2027 Inst.addOperand(MCOperand::createImm(encoding));
2028 }
2029
2030 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
2031 // Branch operands don't encode the low bits, so shift them off
2032 // here. If it's a label, however, just put it on directly as there's
2033 // not enough information now to do anything.
2034 assert(N == 1 && "Invalid number of operands!");
2035 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2036 if (!MCE) {
2037 addExpr(Inst, getImm());
2038 return;
2039 }
2040 assert(MCE && "Invalid constant immediate operand!");
2041 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2042 }
2043
2044 void addPAuthPCRelLabel16Operands(MCInst &Inst, unsigned N) const {
2045 // PC-relative operands don't encode the low bits, so shift them off
2046 // here. If it's a label, however, just put it on directly as there's
2047 // not enough information now to do anything.
2048 assert(N == 1 && "Invalid number of operands!");
2049 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2050 if (!MCE) {
2051 addExpr(Inst, getImm());
2052 return;
2053 }
2054 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2055 }
2056
2057 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
2058 // Branch operands don't encode the low bits, so shift them off
2059 // here. If it's a label, however, just put it on directly as there's
2060 // not enough information now to do anything.
2061 assert(N == 1 && "Invalid number of operands!");
2062 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2063 if (!MCE) {
2064 addExpr(Inst, getImm());
2065 return;
2066 }
2067 assert(MCE && "Invalid constant immediate operand!");
2068 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2069 }
2070
2071 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
2072 // Branch operands don't encode the low bits, so shift them off
2073 // here. If it's a label, however, just put it on directly as there's
2074 // not enough information now to do anything.
2075 assert(N == 1 && "Invalid number of operands!");
2076 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
2077 if (!MCE) {
2078 addExpr(Inst, getImm());
2079 return;
2080 }
2081 assert(MCE && "Invalid constant immediate operand!");
2082 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
2083 }
2084
2085 void addFPImmOperands(MCInst &Inst, unsigned N) const {
2086 assert(N == 1 && "Invalid number of operands!");
2088 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
2089 }
2090
2091 void addBarrierOperands(MCInst &Inst, unsigned N) const {
2092 assert(N == 1 && "Invalid number of operands!");
2093 Inst.addOperand(MCOperand::createImm(getBarrier()));
2094 }
2095
2096 void addBarriernXSOperands(MCInst &Inst, unsigned N) const {
2097 assert(N == 1 && "Invalid number of operands!");
2098 Inst.addOperand(MCOperand::createImm(getBarrier()));
2099 }
2100
2101 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
2102 assert(N == 1 && "Invalid number of operands!");
2103
2104 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
2105 }
2106
2107 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
2108 assert(N == 1 && "Invalid number of operands!");
2109
2110 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
2111 }
2112
2113 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
2114 assert(N == 1 && "Invalid number of operands!");
2115
2116 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
2117 }
2118
2119 void addSVCROperands(MCInst &Inst, unsigned N) const {
2120 assert(N == 1 && "Invalid number of operands!");
2121
2122 Inst.addOperand(MCOperand::createImm(SVCR.PStateField));
2123 }
2124
2125 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
2126 assert(N == 1 && "Invalid number of operands!");
2127
2128 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
2129 }
2130
2131 void addSysCROperands(MCInst &Inst, unsigned N) const {
2132 assert(N == 1 && "Invalid number of operands!");
2133 Inst.addOperand(MCOperand::createImm(getSysCR()));
2134 }
2135
2136 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
2137 assert(N == 1 && "Invalid number of operands!");
2138 Inst.addOperand(MCOperand::createImm(getPrefetch()));
2139 }
2140
2141 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
2142 assert(N == 1 && "Invalid number of operands!");
2143 Inst.addOperand(MCOperand::createImm(getPSBHint()));
2144 }
2145
2146 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
2147 assert(N == 1 && "Invalid number of operands!");
2148 Inst.addOperand(MCOperand::createImm(getBTIHint()));
2149 }
2150
2151 void addShifterOperands(MCInst &Inst, unsigned N) const {
2152 assert(N == 1 && "Invalid number of operands!");
2153 unsigned Imm =
2154 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
2156 }
2157
2158 void addLSLImm3ShifterOperands(MCInst &Inst, unsigned N) const {
2159 assert(N == 1 && "Invalid number of operands!");
2160 unsigned Imm = getShiftExtendAmount();
2162 }
2163
2164 void addSyspXzrPairOperand(MCInst &Inst, unsigned N) const {
2165 assert(N == 1 && "Invalid number of operands!");
2166
2167 if (!isScalarReg())
2168 return;
2169
2170 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2171 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID)
2173 if (Reg != AArch64::XZR)
2174 llvm_unreachable("wrong register");
2175
2176 Inst.addOperand(MCOperand::createReg(AArch64::XZR));
2177 }
2178
2179 void addExtendOperands(MCInst &Inst, unsigned N) const {
2180 assert(N == 1 && "Invalid number of operands!");
2181 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2182 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
2183 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
2185 }
2186
2187 void addExtend64Operands(MCInst &Inst, unsigned N) const {
2188 assert(N == 1 && "Invalid number of operands!");
2189 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2190 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
2191 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
2193 }
2194
2195 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
2196 assert(N == 2 && "Invalid number of operands!");
2197 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2198 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
2199 Inst.addOperand(MCOperand::createImm(IsSigned));
2200 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
2201 }
2202
2203 // For 8-bit load/store instructions with a register offset, both the
2204 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
2205 // they're disambiguated by whether the shift was explicit or implicit rather
2206 // than its size.
2207 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
2208 assert(N == 2 && "Invalid number of operands!");
2209 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2210 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
2211 Inst.addOperand(MCOperand::createImm(IsSigned));
2212 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
2213 }
2214
2215 template<int Shift>
2216 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
2217 assert(N == 1 && "Invalid number of operands!");
2218
2219 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2220 if (CE) {
2221 uint64_t Value = CE->getValue();
2222 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
2223 } else {
2224 addExpr(Inst, getImm());
2225 }
2226 }
2227
2228 template<int Shift>
2229 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
2230 assert(N == 1 && "Invalid number of operands!");
2231
2232 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
2233 uint64_t Value = CE->getValue();
2234 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
2235 }
2236
2237 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
2238 assert(N == 1 && "Invalid number of operands!");
2239 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
2240 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
2241 }
2242
2243 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
2244 assert(N == 1 && "Invalid number of operands!");
2245 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
2246 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
2247 }
2248
2249 void print(raw_ostream &OS) const override;
2250
2251 static std::unique_ptr<AArch64Operand>
2252 CreateToken(StringRef Str, SMLoc S, MCContext &Ctx, bool IsSuffix = false) {
2253 auto Op = std::make_unique<AArch64Operand>(k_Token, Ctx);
2254 Op->Tok.Data = Str.data();
2255 Op->Tok.Length = Str.size();
2256 Op->Tok.IsSuffix = IsSuffix;
2257 Op->StartLoc = S;
2258 Op->EndLoc = S;
2259 return Op;
2260 }
2261
2262 static std::unique_ptr<AArch64Operand>
2263 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
2264 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
2266 unsigned ShiftAmount = 0,
2267 unsigned HasExplicitAmount = false) {
2268 auto Op = std::make_unique<AArch64Operand>(k_Register, Ctx);
2269 Op->Reg.RegNum = RegNum;
2270 Op->Reg.Kind = Kind;
2271 Op->Reg.ElementWidth = 0;
2272 Op->Reg.EqualityTy = EqTy;
2273 Op->Reg.ShiftExtend.Type = ExtTy;
2274 Op->Reg.ShiftExtend.Amount = ShiftAmount;
2275 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2276 Op->StartLoc = S;
2277 Op->EndLoc = E;
2278 return Op;
2279 }
2280
2281 static std::unique_ptr<AArch64Operand>
2282 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
2283 SMLoc S, SMLoc E, MCContext &Ctx,
2285 unsigned ShiftAmount = 0,
2286 unsigned HasExplicitAmount = false) {
2287 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
2288 Kind == RegKind::SVEPredicateVector ||
2289 Kind == RegKind::SVEPredicateAsCounter) &&
2290 "Invalid vector kind");
2291 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
2292 HasExplicitAmount);
2293 Op->Reg.ElementWidth = ElementWidth;
2294 return Op;
2295 }
2296
2297 static std::unique_ptr<AArch64Operand>
2298 CreateVectorList(unsigned RegNum, unsigned Count, unsigned Stride,
2299 unsigned NumElements, unsigned ElementWidth,
2300 RegKind RegisterKind, SMLoc S, SMLoc E, MCContext &Ctx) {
2301 auto Op = std::make_unique<AArch64Operand>(k_VectorList, Ctx);
2302 Op->VectorList.RegNum = RegNum;
2303 Op->VectorList.Count = Count;
2304 Op->VectorList.Stride = Stride;
2305 Op->VectorList.NumElements = NumElements;
2306 Op->VectorList.ElementWidth = ElementWidth;
2307 Op->VectorList.RegisterKind = RegisterKind;
2308 Op->StartLoc = S;
2309 Op->EndLoc = E;
2310 return Op;
2311 }
2312
2313 static std::unique_ptr<AArch64Operand>
2314 CreateVectorIndex(int Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
2315 auto Op = std::make_unique<AArch64Operand>(k_VectorIndex, Ctx);
2316 Op->VectorIndex.Val = Idx;
2317 Op->StartLoc = S;
2318 Op->EndLoc = E;
2319 return Op;
2320 }
2321
2322 static std::unique_ptr<AArch64Operand>
2323 CreateMatrixTileList(unsigned RegMask, SMLoc S, SMLoc E, MCContext &Ctx) {
2324 auto Op = std::make_unique<AArch64Operand>(k_MatrixTileList, Ctx);
2325 Op->MatrixTileList.RegMask = RegMask;
2326 Op->StartLoc = S;
2327 Op->EndLoc = E;
2328 return Op;
2329 }
2330
2331 static void ComputeRegsForAlias(unsigned Reg, SmallSet<unsigned, 8> &OutRegs,
2332 const unsigned ElementWidth) {
2333 static std::map<std::pair<unsigned, unsigned>, std::vector<unsigned>>
2334 RegMap = {
2335 {{0, AArch64::ZAB0},
2336 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2337 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2338 {{8, AArch64::ZAB0},
2339 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2340 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2341 {{16, AArch64::ZAH0},
2342 {AArch64::ZAD0, AArch64::ZAD2, AArch64::ZAD4, AArch64::ZAD6}},
2343 {{16, AArch64::ZAH1},
2344 {AArch64::ZAD1, AArch64::ZAD3, AArch64::ZAD5, AArch64::ZAD7}},
2345 {{32, AArch64::ZAS0}, {AArch64::ZAD0, AArch64::ZAD4}},
2346 {{32, AArch64::ZAS1}, {AArch64::ZAD1, AArch64::ZAD5}},
2347 {{32, AArch64::ZAS2}, {AArch64::ZAD2, AArch64::ZAD6}},
2348 {{32, AArch64::ZAS3}, {AArch64::ZAD3, AArch64::ZAD7}},
2349 };
2350
2351 if (ElementWidth == 64)
2352 OutRegs.insert(Reg);
2353 else {
2354 std::vector<unsigned> Regs = RegMap[std::make_pair(ElementWidth, Reg)];
2355 assert(!Regs.empty() && "Invalid tile or element width!");
2356 for (auto OutReg : Regs)
2357 OutRegs.insert(OutReg);
2358 }
2359 }
2360
2361 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
2362 SMLoc E, MCContext &Ctx) {
2363 auto Op = std::make_unique<AArch64Operand>(k_Immediate, Ctx);
2364 Op->Imm.Val = Val;
2365 Op->StartLoc = S;
2366 Op->EndLoc = E;
2367 return Op;
2368 }
2369
2370 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
2371 unsigned ShiftAmount,
2372 SMLoc S, SMLoc E,
2373 MCContext &Ctx) {
2374 auto Op = std::make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
2375 Op->ShiftedImm .Val = Val;
2376 Op->ShiftedImm.ShiftAmount = ShiftAmount;
2377 Op->StartLoc = S;
2378 Op->EndLoc = E;
2379 return Op;
2380 }
2381
2382 static std::unique_ptr<AArch64Operand> CreateImmRange(unsigned First,
2383 unsigned Last, SMLoc S,
2384 SMLoc E,
2385 MCContext &Ctx) {
2386 auto Op = std::make_unique<AArch64Operand>(k_ImmRange, Ctx);
2387 Op->ImmRange.First = First;
2388 Op->ImmRange.Last = Last;
2389 Op->EndLoc = E;
2390 return Op;
2391 }
2392
2393 static std::unique_ptr<AArch64Operand>
2394 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
2395 auto Op = std::make_unique<AArch64Operand>(k_CondCode, Ctx);
2396 Op->CondCode.Code = Code;
2397 Op->StartLoc = S;
2398 Op->EndLoc = E;
2399 return Op;
2400 }
2401
2402 static std::unique_ptr<AArch64Operand>
2403 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
2404 auto Op = std::make_unique<AArch64Operand>(k_FPImm, Ctx);
2405 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
2406 Op->FPImm.IsExact = IsExact;
2407 Op->StartLoc = S;
2408 Op->EndLoc = S;
2409 return Op;
2410 }
2411
2412 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
2413 StringRef Str,
2414 SMLoc S,
2415 MCContext &Ctx,
2416 bool HasnXSModifier) {
2417 auto Op = std::make_unique<AArch64Operand>(k_Barrier, Ctx);
2418 Op->Barrier.Val = Val;
2419 Op->Barrier.Data = Str.data();
2420 Op->Barrier.Length = Str.size();
2421 Op->Barrier.HasnXSModifier = HasnXSModifier;
2422 Op->StartLoc = S;
2423 Op->EndLoc = S;
2424 return Op;
2425 }
2426
2427 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
2428 uint32_t MRSReg,
2429 uint32_t MSRReg,
2430 uint32_t PStateField,
2431 MCContext &Ctx) {
2432 auto Op = std::make_unique<AArch64Operand>(k_SysReg, Ctx);
2433 Op->SysReg.Data = Str.data();
2434 Op->SysReg.Length = Str.size();
2435 Op->SysReg.MRSReg = MRSReg;
2436 Op->SysReg.MSRReg = MSRReg;
2437 Op->SysReg.PStateField = PStateField;
2438 Op->StartLoc = S;
2439 Op->EndLoc = S;
2440 return Op;
2441 }
2442
2443 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
2444 SMLoc E, MCContext &Ctx) {
2445 auto Op = std::make_unique<AArch64Operand>(k_SysCR, Ctx);
2446 Op->SysCRImm.Val = Val;
2447 Op->StartLoc = S;
2448 Op->EndLoc = E;
2449 return Op;
2450 }
2451
2452 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
2453 StringRef Str,
2454 SMLoc S,
2455 MCContext &Ctx) {
2456 auto Op = std::make_unique<AArch64Operand>(k_Prefetch, Ctx);
2457 Op->Prefetch.Val = Val;
2458 Op->Barrier.Data = Str.data();
2459 Op->Barrier.Length = Str.size();
2460 Op->StartLoc = S;
2461 Op->EndLoc = S;
2462 return Op;
2463 }
2464
2465 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
2466 StringRef Str,
2467 SMLoc S,
2468 MCContext &Ctx) {
2469 auto Op = std::make_unique<AArch64Operand>(k_PSBHint, Ctx);
2470 Op->PSBHint.Val = Val;
2471 Op->PSBHint.Data = Str.data();
2472 Op->PSBHint.Length = Str.size();
2473 Op->StartLoc = S;
2474 Op->EndLoc = S;
2475 return Op;
2476 }
2477
2478 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
2479 StringRef Str,
2480 SMLoc S,
2481 MCContext &Ctx) {
2482 auto Op = std::make_unique<AArch64Operand>(k_BTIHint, Ctx);
2483 Op->BTIHint.Val = Val | 32;
2484 Op->BTIHint.Data = Str.data();
2485 Op->BTIHint.Length = Str.size();
2486 Op->StartLoc = S;
2487 Op->EndLoc = S;
2488 return Op;
2489 }
2490
2491 static std::unique_ptr<AArch64Operand>
2492 CreateMatrixRegister(unsigned RegNum, unsigned ElementWidth, MatrixKind Kind,
2493 SMLoc S, SMLoc E, MCContext &Ctx) {
2494 auto Op = std::make_unique<AArch64Operand>(k_MatrixRegister, Ctx);
2495 Op->MatrixReg.RegNum = RegNum;
2496 Op->MatrixReg.ElementWidth = ElementWidth;
2497 Op->MatrixReg.Kind = Kind;
2498 Op->StartLoc = S;
2499 Op->EndLoc = E;
2500 return Op;
2501 }
2502
2503 static std::unique_ptr<AArch64Operand>
2504 CreateSVCR(uint32_t PStateField, StringRef Str, SMLoc S, MCContext &Ctx) {
2505 auto Op = std::make_unique<AArch64Operand>(k_SVCR, Ctx);
2506 Op->SVCR.PStateField = PStateField;
2507 Op->SVCR.Data = Str.data();
2508 Op->SVCR.Length = Str.size();
2509 Op->StartLoc = S;
2510 Op->EndLoc = S;
2511 return Op;
2512 }
2513
2514 static std::unique_ptr<AArch64Operand>
2515 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2516 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2517 auto Op = std::make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
2518 Op->ShiftExtend.Type = ShOp;
2519 Op->ShiftExtend.Amount = Val;
2520 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2521 Op->StartLoc = S;
2522 Op->EndLoc = E;
2523 return Op;
2524 }
2525};
2526
2527} // end anonymous namespace.
2528
2529void AArch64Operand::print(raw_ostream &OS) const {
2530 switch (Kind) {
2531 case k_FPImm:
2532 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2533 if (!getFPImmIsExact())
2534 OS << " (inexact)";
2535 OS << ">";
2536 break;
2537 case k_Barrier: {
2538 StringRef Name = getBarrierName();
2539 if (!Name.empty())
2540 OS << "<barrier " << Name << ">";
2541 else
2542 OS << "<barrier invalid #" << getBarrier() << ">";
2543 break;
2544 }
2545 case k_Immediate:
2546 OS << *getImm();
2547 break;
2548 case k_ShiftedImm: {
2549 unsigned Shift = getShiftedImmShift();
2550 OS << "<shiftedimm ";
2551 OS << *getShiftedImmVal();
2552 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2553 break;
2554 }
2555 case k_ImmRange: {
2556 OS << "<immrange ";
2557 OS << getFirstImmVal();
2558 OS << ":" << getLastImmVal() << ">";
2559 break;
2560 }
2561 case k_CondCode:
2562 OS << "<condcode " << getCondCode() << ">";
2563 break;
2564 case k_VectorList: {
2565 OS << "<vectorlist ";
2566 unsigned Reg = getVectorListStart();
2567 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2568 OS << Reg + i * getVectorListStride() << " ";
2569 OS << ">";
2570 break;
2571 }
2572 case k_VectorIndex:
2573 OS << "<vectorindex " << getVectorIndex() << ">";
2574 break;
2575 case k_SysReg:
2576 OS << "<sysreg: " << getSysReg() << '>';
2577 break;
2578 case k_Token:
2579 OS << "'" << getToken() << "'";
2580 break;
2581 case k_SysCR:
2582 OS << "c" << getSysCR();
2583 break;
2584 case k_Prefetch: {
2585 StringRef Name = getPrefetchName();
2586 if (!Name.empty())
2587 OS << "<prfop " << Name << ">";
2588 else
2589 OS << "<prfop invalid #" << getPrefetch() << ">";
2590 break;
2591 }
2592 case k_PSBHint:
2593 OS << getPSBHintName();
2594 break;
2595 case k_BTIHint:
2596 OS << getBTIHintName();
2597 break;
2598 case k_MatrixRegister:
2599 OS << "<matrix " << getMatrixReg() << ">";
2600 break;
2601 case k_MatrixTileList: {
2602 OS << "<matrixlist ";
2603 unsigned RegMask = getMatrixTileListRegMask();
2604 unsigned MaxBits = 8;
2605 for (unsigned I = MaxBits; I > 0; --I)
2606 OS << ((RegMask & (1 << (I - 1))) >> (I - 1));
2607 OS << '>';
2608 break;
2609 }
2610 case k_SVCR: {
2611 OS << getSVCR();
2612 break;
2613 }
2614 case k_Register:
2615 OS << "<register " << getReg() << ">";
2616 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2617 break;
2618 [[fallthrough]];
2619 case k_ShiftExtend:
2620 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2621 << getShiftExtendAmount();
2622 if (!hasShiftExtendAmount())
2623 OS << "<imp>";
2624 OS << '>';
2625 break;
2626 }
2627}
2628
2629/// @name Auto-generated Match Functions
2630/// {
2631
2633
2634/// }
2635
2637 return StringSwitch<unsigned>(Name.lower())
2638 .Case("v0", AArch64::Q0)
2639 .Case("v1", AArch64::Q1)
2640 .Case("v2", AArch64::Q2)
2641 .Case("v3", AArch64::Q3)
2642 .Case("v4", AArch64::Q4)
2643 .Case("v5", AArch64::Q5)
2644 .Case("v6", AArch64::Q6)
2645 .Case("v7", AArch64::Q7)
2646 .Case("v8", AArch64::Q8)
2647 .Case("v9", AArch64::Q9)
2648 .Case("v10", AArch64::Q10)
2649 .Case("v11", AArch64::Q11)
2650 .Case("v12", AArch64::Q12)
2651 .Case("v13", AArch64::Q13)
2652 .Case("v14", AArch64::Q14)
2653 .Case("v15", AArch64::Q15)
2654 .Case("v16", AArch64::Q16)
2655 .Case("v17", AArch64::Q17)
2656 .Case("v18", AArch64::Q18)
2657 .Case("v19", AArch64::Q19)
2658 .Case("v20", AArch64::Q20)
2659 .Case("v21", AArch64::Q21)
2660 .Case("v22", AArch64::Q22)
2661 .Case("v23", AArch64::Q23)
2662 .Case("v24", AArch64::Q24)
2663 .Case("v25", AArch64::Q25)
2664 .Case("v26", AArch64::Q26)
2665 .Case("v27", AArch64::Q27)
2666 .Case("v28", AArch64::Q28)
2667 .Case("v29", AArch64::Q29)
2668 .Case("v30", AArch64::Q30)
2669 .Case("v31", AArch64::Q31)
2670 .Default(0);
2671}
2672
2673/// Returns an optional pair of (#elements, element-width) if Suffix
2674/// is a valid vector kind. Where the number of elements in a vector
2675/// or the vector width is implicit or explicitly unknown (but still a
2676/// valid suffix kind), 0 is used.
2677static std::optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2678 RegKind VectorKind) {
2679 std::pair<int, int> Res = {-1, -1};
2680
2681 switch (VectorKind) {
2682 case RegKind::NeonVector:
2684 .Case("", {0, 0})
2685 .Case(".1d", {1, 64})
2686 .Case(".1q", {1, 128})
2687 // '.2h' needed for fp16 scalar pairwise reductions
2688 .Case(".2h", {2, 16})
2689 .Case(".2b", {2, 8})
2690 .Case(".2s", {2, 32})
2691 .Case(".2d", {2, 64})
2692 // '.4b' is another special case for the ARMv8.2a dot product
2693 // operand
2694 .Case(".4b", {4, 8})
2695 .Case(".4h", {4, 16})
2696 .Case(".4s", {4, 32})
2697 .Case(".8b", {8, 8})
2698 .Case(".8h", {8, 16})
2699 .Case(".16b", {16, 8})
2700 // Accept the width neutral ones, too, for verbose syntax. If
2701 // those aren't used in the right places, the token operand won't
2702 // match so all will work out.
2703 .Case(".b", {0, 8})
2704 .Case(".h", {0, 16})
2705 .Case(".s", {0, 32})
2706 .Case(".d", {0, 64})
2707 .Default({-1, -1});
2708 break;
2709 case RegKind::SVEPredicateAsCounter:
2710 case RegKind::SVEPredicateVector:
2711 case RegKind::SVEDataVector:
2712 case RegKind::Matrix:
2714 .Case("", {0, 0})
2715 .Case(".b", {0, 8})
2716 .Case(".h", {0, 16})
2717 .Case(".s", {0, 32})
2718 .Case(".d", {0, 64})
2719 .Case(".q", {0, 128})
2720 .Default({-1, -1});
2721 break;
2722 default:
2723 llvm_unreachable("Unsupported RegKind");
2724 }
2725
2726 if (Res == std::make_pair(-1, -1))
2727 return std::nullopt;
2728
2729 return std::optional<std::pair<int, int>>(Res);
2730}
2731
2732static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2733 return parseVectorKind(Suffix, VectorKind).has_value();
2734}
2735
2737 return StringSwitch<unsigned>(Name.lower())
2738 .Case("z0", AArch64::Z0)
2739 .Case("z1", AArch64::Z1)
2740 .Case("z2", AArch64::Z2)
2741 .Case("z3", AArch64::Z3)
2742 .Case("z4", AArch64::Z4)
2743 .Case("z5", AArch64::Z5)
2744 .Case("z6", AArch64::Z6)
2745 .Case("z7", AArch64::Z7)
2746 .Case("z8", AArch64::Z8)
2747 .Case("z9", AArch64::Z9)
2748 .Case("z10", AArch64::Z10)
2749 .Case("z11", AArch64::Z11)
2750 .Case("z12", AArch64::Z12)
2751 .Case("z13", AArch64::Z13)
2752 .Case("z14", AArch64::Z14)
2753 .Case("z15", AArch64::Z15)
2754 .Case("z16", AArch64::Z16)
2755 .Case("z17", AArch64::Z17)
2756 .Case("z18", AArch64::Z18)
2757 .Case("z19", AArch64::Z19)
2758 .Case("z20", AArch64::Z20)
2759 .Case("z21", AArch64::Z21)
2760 .Case("z22", AArch64::Z22)
2761 .Case("z23", AArch64::Z23)
2762 .Case("z24", AArch64::Z24)
2763 .Case("z25", AArch64::Z25)
2764 .Case("z26", AArch64::Z26)
2765 .Case("z27", AArch64::Z27)
2766 .Case("z28", AArch64::Z28)
2767 .Case("z29", AArch64::Z29)
2768 .Case("z30", AArch64::Z30)
2769 .Case("z31", AArch64::Z31)
2770 .Default(0);
2771}
2772
2774 return StringSwitch<unsigned>(Name.lower())
2775 .Case("p0", AArch64::P0)
2776 .Case("p1", AArch64::P1)
2777 .Case("p2", AArch64::P2)
2778 .Case("p3", AArch64::P3)
2779 .Case("p4", AArch64::P4)
2780 .Case("p5", AArch64::P5)
2781 .Case("p6", AArch64::P6)
2782 .Case("p7", AArch64::P7)
2783 .Case("p8", AArch64::P8)
2784 .Case("p9", AArch64::P9)
2785 .Case("p10", AArch64::P10)
2786 .Case("p11", AArch64::P11)
2787 .Case("p12", AArch64::P12)
2788 .Case("p13", AArch64::P13)
2789 .Case("p14", AArch64::P14)
2790 .Case("p15", AArch64::P15)
2791 .Default(0);
2792}
2793
2795 return StringSwitch<unsigned>(Name.lower())
2796 .Case("pn0", AArch64::PN0)
2797 .Case("pn1", AArch64::PN1)
2798 .Case("pn2", AArch64::PN2)
2799 .Case("pn3", AArch64::PN3)
2800 .Case("pn4", AArch64::PN4)
2801 .Case("pn5", AArch64::PN5)
2802 .Case("pn6", AArch64::PN6)
2803 .Case("pn7", AArch64::PN7)
2804 .Case("pn8", AArch64::PN8)
2805 .Case("pn9", AArch64::PN9)
2806 .Case("pn10", AArch64::PN10)
2807 .Case("pn11", AArch64::PN11)
2808 .Case("pn12", AArch64::PN12)
2809 .Case("pn13", AArch64::PN13)
2810 .Case("pn14", AArch64::PN14)
2811 .Case("pn15", AArch64::PN15)
2812 .Default(0);
2813}
2814
2816 return StringSwitch<unsigned>(Name.lower())
2817 .Case("za0.d", AArch64::ZAD0)
2818 .Case("za1.d", AArch64::ZAD1)
2819 .Case("za2.d", AArch64::ZAD2)
2820 .Case("za3.d", AArch64::ZAD3)
2821 .Case("za4.d", AArch64::ZAD4)
2822 .Case("za5.d", AArch64::ZAD5)
2823 .Case("za6.d", AArch64::ZAD6)
2824 .Case("za7.d", AArch64::ZAD7)
2825 .Case("za0.s", AArch64::ZAS0)
2826 .Case("za1.s", AArch64::ZAS1)
2827 .Case("za2.s", AArch64::ZAS2)
2828 .Case("za3.s", AArch64::ZAS3)
2829 .Case("za0.h", AArch64::ZAH0)
2830 .Case("za1.h", AArch64::ZAH1)
2831 .Case("za0.b", AArch64::ZAB0)
2832 .Default(0);
2833}
2834
2836 return StringSwitch<unsigned>(Name.lower())
2837 .Case("za", AArch64::ZA)
2838 .Case("za0.q", AArch64::ZAQ0)
2839 .Case("za1.q", AArch64::ZAQ1)
2840 .Case("za2.q", AArch64::ZAQ2)
2841 .Case("za3.q", AArch64::ZAQ3)
2842 .Case("za4.q", AArch64::ZAQ4)
2843 .Case("za5.q", AArch64::ZAQ5)
2844 .Case("za6.q", AArch64::ZAQ6)
2845 .Case("za7.q", AArch64::ZAQ7)
2846 .Case("za8.q", AArch64::ZAQ8)
2847 .Case("za9.q", AArch64::ZAQ9)
2848 .Case("za10.q", AArch64::ZAQ10)
2849 .Case("za11.q", AArch64::ZAQ11)
2850 .Case("za12.q", AArch64::ZAQ12)
2851 .Case("za13.q", AArch64::ZAQ13)
2852 .Case("za14.q", AArch64::ZAQ14)
2853 .Case("za15.q", AArch64::ZAQ15)
2854 .Case("za0.d", AArch64::ZAD0)
2855 .Case("za1.d", AArch64::ZAD1)
2856 .Case("za2.d", AArch64::ZAD2)
2857 .Case("za3.d", AArch64::ZAD3)
2858 .Case("za4.d", AArch64::ZAD4)
2859 .Case("za5.d", AArch64::ZAD5)
2860 .Case("za6.d", AArch64::ZAD6)
2861 .Case("za7.d", AArch64::ZAD7)
2862 .Case("za0.s", AArch64::ZAS0)
2863 .Case("za1.s", AArch64::ZAS1)
2864 .Case("za2.s", AArch64::ZAS2)
2865 .Case("za3.s", AArch64::ZAS3)
2866 .Case("za0.h", AArch64::ZAH0)
2867 .Case("za1.h", AArch64::ZAH1)
2868 .Case("za0.b", AArch64::ZAB0)
2869 .Case("za0h.q", AArch64::ZAQ0)
2870 .Case("za1h.q", AArch64::ZAQ1)
2871 .Case("za2h.q", AArch64::ZAQ2)
2872 .Case("za3h.q", AArch64::ZAQ3)
2873 .Case("za4h.q", AArch64::ZAQ4)
2874 .Case("za5h.q", AArch64::ZAQ5)
2875 .Case("za6h.q", AArch64::ZAQ6)
2876 .Case("za7h.q", AArch64::ZAQ7)
2877 .Case("za8h.q", AArch64::ZAQ8)
2878 .Case("za9h.q", AArch64::ZAQ9)
2879 .Case("za10h.q", AArch64::ZAQ10)
2880 .Case("za11h.q", AArch64::ZAQ11)
2881 .Case("za12h.q", AArch64::ZAQ12)
2882 .Case("za13h.q", AArch64::ZAQ13)
2883 .Case("za14h.q", AArch64::ZAQ14)
2884 .Case("za15h.q", AArch64::ZAQ15)
2885 .Case("za0h.d", AArch64::ZAD0)
2886 .Case("za1h.d", AArch64::ZAD1)
2887 .Case("za2h.d", AArch64::ZAD2)
2888 .Case("za3h.d", AArch64::ZAD3)
2889 .Case("za4h.d", AArch64::ZAD4)
2890 .Case("za5h.d", AArch64::ZAD5)
2891 .Case("za6h.d", AArch64::ZAD6)
2892 .Case("za7h.d", AArch64::ZAD7)
2893 .Case("za0h.s", AArch64::ZAS0)
2894 .Case("za1h.s", AArch64::ZAS1)
2895 .Case("za2h.s", AArch64::ZAS2)
2896 .Case("za3h.s", AArch64::ZAS3)
2897 .Case("za0h.h", AArch64::ZAH0)
2898 .Case("za1h.h", AArch64::ZAH1)
2899 .Case("za0h.b", AArch64::ZAB0)
2900 .Case("za0v.q", AArch64::ZAQ0)
2901 .Case("za1v.q", AArch64::ZAQ1)
2902 .Case("za2v.q", AArch64::ZAQ2)
2903 .Case("za3v.q", AArch64::ZAQ3)
2904 .Case("za4v.q", AArch64::ZAQ4)
2905 .Case("za5v.q", AArch64::ZAQ5)
2906 .Case("za6v.q", AArch64::ZAQ6)
2907 .Case("za7v.q", AArch64::ZAQ7)
2908 .Case("za8v.q", AArch64::ZAQ8)
2909 .Case("za9v.q", AArch64::ZAQ9)
2910 .Case("za10v.q", AArch64::ZAQ10)
2911 .Case("za11v.q", AArch64::ZAQ11)
2912 .Case("za12v.q", AArch64::ZAQ12)
2913 .Case("za13v.q", AArch64::ZAQ13)
2914 .Case("za14v.q", AArch64::ZAQ14)
2915 .Case("za15v.q", AArch64::ZAQ15)
2916 .Case("za0v.d", AArch64::ZAD0)
2917 .Case("za1v.d", AArch64::ZAD1)
2918 .Case("za2v.d", AArch64::ZAD2)
2919 .Case("za3v.d", AArch64::ZAD3)
2920 .Case("za4v.d", AArch64::ZAD4)
2921 .Case("za5v.d", AArch64::ZAD5)
2922 .Case("za6v.d", AArch64::ZAD6)
2923 .Case("za7v.d", AArch64::ZAD7)
2924 .Case("za0v.s", AArch64::ZAS0)
2925 .Case("za1v.s", AArch64::ZAS1)
2926 .Case("za2v.s", AArch64::ZAS2)
2927 .Case("za3v.s", AArch64::ZAS3)
2928 .Case("za0v.h", AArch64::ZAH0)
2929 .Case("za1v.h", AArch64::ZAH1)
2930 .Case("za0v.b", AArch64::ZAB0)
2931 .Default(0);
2932}
2933
2934bool AArch64AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
2935 SMLoc &EndLoc) {
2936 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
2937}
2938
2939ParseStatus AArch64AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
2940 SMLoc &EndLoc) {
2941 StartLoc = getLoc();
2942 ParseStatus Res = tryParseScalarRegister(Reg);
2943 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2944 return Res;
2945}
2946
2947// Matches a register name or register alias previously defined by '.req'
2948unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
2949 RegKind Kind) {
2950 unsigned RegNum = 0;
2951 if ((RegNum = matchSVEDataVectorRegName(Name)))
2952 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2953
2954 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2955 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2956
2958 return Kind == RegKind::SVEPredicateAsCounter ? RegNum : 0;
2959
2960 if ((RegNum = MatchNeonVectorRegName(Name)))
2961 return Kind == RegKind::NeonVector ? RegNum : 0;
2962
2963 if ((RegNum = matchMatrixRegName(Name)))
2964 return Kind == RegKind::Matrix ? RegNum : 0;
2965
2966 if (Name.equals_insensitive("zt0"))
2967 return Kind == RegKind::LookupTable ? AArch64::ZT0 : 0;
2968
2969 // The parsed register must be of RegKind Scalar
2970 if ((RegNum = MatchRegisterName(Name)))
2971 return (Kind == RegKind::Scalar) ? RegNum : 0;
2972
2973 if (!RegNum) {
2974 // Handle a few common aliases of registers.
2975 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2976 .Case("fp", AArch64::FP)
2977 .Case("lr", AArch64::LR)
2978 .Case("x31", AArch64::XZR)
2979 .Case("w31", AArch64::WZR)
2980 .Default(0))
2981 return Kind == RegKind::Scalar ? RegNum : 0;
2982
2983 // Check for aliases registered via .req. Canonicalize to lower case.
2984 // That's more consistent since register names are case insensitive, and
2985 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2986 auto Entry = RegisterReqs.find(Name.lower());
2987 if (Entry == RegisterReqs.end())
2988 return 0;
2989
2990 // set RegNum if the match is the right kind of register
2991 if (Kind == Entry->getValue().first)
2992 RegNum = Entry->getValue().second;
2993 }
2994 return RegNum;
2995}
2996
2997unsigned AArch64AsmParser::getNumRegsForRegKind(RegKind K) {
2998 switch (K) {
2999 case RegKind::Scalar:
3000 case RegKind::NeonVector:
3001 case RegKind::SVEDataVector:
3002 return 32;
3003 case RegKind::Matrix:
3004 case RegKind::SVEPredicateVector:
3005 case RegKind::SVEPredicateAsCounter:
3006 return 16;
3007 case RegKind::LookupTable:
3008 return 1;
3009 }
3010 llvm_unreachable("Unsupported RegKind");
3011}
3012
3013/// tryParseScalarRegister - Try to parse a register name. The token must be an
3014/// Identifier when called, and if it is a register name the token is eaten and
3015/// the register is added to the operand list.
3016ParseStatus AArch64AsmParser::tryParseScalarRegister(MCRegister &RegNum) {
3017 const AsmToken &Tok = getTok();
3018 if (Tok.isNot(AsmToken::Identifier))
3019 return ParseStatus::NoMatch;
3020
3021 std::string lowerCase = Tok.getString().lower();
3022 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
3023 if (Reg == 0)
3024 return ParseStatus::NoMatch;
3025
3026 RegNum = Reg;
3027 Lex(); // Eat identifier token.
3028 return ParseStatus::Success;
3029}
3030
3031/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
3032ParseStatus AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
3033 SMLoc S = getLoc();
3034
3035 if (getTok().isNot(AsmToken::Identifier))
3036 return Error(S, "Expected cN operand where 0 <= N <= 15");
3037
3038 StringRef Tok = getTok().getIdentifier();
3039 if (Tok[0] != 'c' && Tok[0] != 'C')
3040 return Error(S, "Expected cN operand where 0 <= N <= 15");
3041
3042 uint32_t CRNum;
3043 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
3044 if (BadNum || CRNum > 15)
3045 return Error(S, "Expected cN operand where 0 <= N <= 15");
3046
3047 Lex(); // Eat identifier token.
3048 Operands.push_back(
3049 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
3050 return ParseStatus::Success;
3051}
3052
3053// Either an identifier for named values or a 6-bit immediate.
3054ParseStatus AArch64AsmParser::tryParseRPRFMOperand(OperandVector &Operands) {
3055 SMLoc S = getLoc();
3056 const AsmToken &Tok = getTok();
3057
3058 unsigned MaxVal = 63;
3059
3060 // Immediate case, with optional leading hash:
3061 if (parseOptionalToken(AsmToken::Hash) ||
3062 Tok.is(AsmToken::Integer)) {
3063 const MCExpr *ImmVal;
3064 if (getParser().parseExpression(ImmVal))
3065 return ParseStatus::Failure;
3066
3067 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3068 if (!MCE)
3069 return TokError("immediate value expected for prefetch operand");
3070 unsigned prfop = MCE->getValue();
3071 if (prfop > MaxVal)
3072 return TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
3073 "] expected");
3074
3075 auto RPRFM = AArch64RPRFM::lookupRPRFMByEncoding(MCE->getValue());
3076 Operands.push_back(AArch64Operand::CreatePrefetch(
3077 prfop, RPRFM ? RPRFM->Name : "", S, getContext()));
3078 return ParseStatus::Success;
3079 }
3080
3081 if (Tok.isNot(AsmToken::Identifier))
3082 return TokError("prefetch hint expected");
3083
3084 auto RPRFM = AArch64RPRFM::lookupRPRFMByName(Tok.getString());
3085 if (!RPRFM)
3086 return TokError("prefetch hint expected");
3087
3088 Operands.push_back(AArch64Operand::CreatePrefetch(
3089 RPRFM->Encoding, Tok.getString(), S, getContext()));
3090 Lex(); // Eat identifier token.
3091 return ParseStatus::Success;
3092}
3093
3094/// tryParsePrefetch - Try to parse a prefetch operand.
3095template <bool IsSVEPrefetch>
3096ParseStatus AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
3097 SMLoc S = getLoc();
3098 const AsmToken &Tok = getTok();
3099
3100 auto LookupByName = [](StringRef N) {
3101 if (IsSVEPrefetch) {
3102 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
3103 return std::optional<unsigned>(Res->Encoding);
3104 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
3105 return std::optional<unsigned>(Res->Encoding);
3106 return std::optional<unsigned>();
3107 };
3108
3109 auto LookupByEncoding = [](unsigned E) {
3110 if (IsSVEPrefetch) {
3111 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
3112 return std::optional<StringRef>(Res->Name);
3113 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
3114 return std::optional<StringRef>(Res->Name);
3115 return std::optional<StringRef>();
3116 };
3117 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
3118
3119 // Either an identifier for named values or a 5-bit immediate.
3120 // Eat optional hash.
3121 if (parseOptionalToken(AsmToken::Hash) ||
3122 Tok.is(AsmToken::Integer)) {
3123 const MCExpr *ImmVal;
3124 if (getParser().parseExpression(ImmVal))
3125 return ParseStatus::Failure;
3126
3127 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3128 if (!MCE)
3129 return TokError("immediate value expected for prefetch operand");
3130 unsigned prfop = MCE->getValue();
3131 if (prfop > MaxVal)
3132 return TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
3133 "] expected");
3134
3135 auto PRFM = LookupByEncoding(MCE->getValue());
3136 Operands.push_back(AArch64Operand::CreatePrefetch(prfop, PRFM.value_or(""),
3137 S, getContext()));
3138 return ParseStatus::Success;
3139 }
3140
3141 if (Tok.isNot(AsmToken::Identifier))
3142 return TokError("prefetch hint expected");
3143
3144 auto PRFM = LookupByName(Tok.getString());
3145 if (!PRFM)
3146 return TokError("prefetch hint expected");
3147
3148 Operands.push_back(AArch64Operand::CreatePrefetch(
3149 *PRFM, Tok.getString(), S, getContext()));
3150 Lex(); // Eat identifier token.
3151 return ParseStatus::Success;
3152}
3153
3154/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
3155ParseStatus AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
3156 SMLoc S = getLoc();
3157 const AsmToken &Tok = getTok();
3158 if (Tok.isNot(AsmToken::Identifier))
3159 return TokError("invalid operand for instruction");
3160
3161 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
3162 if (!PSB)
3163 return TokError("invalid operand for instruction");
3164
3165 Operands.push_back(AArch64Operand::CreatePSBHint(
3166 PSB->Encoding, Tok.getString(), S, getContext()));
3167 Lex(); // Eat identifier token.
3168 return ParseStatus::Success;
3169}
3170
3171ParseStatus AArch64AsmParser::tryParseSyspXzrPair(OperandVector &Operands) {
3172 SMLoc StartLoc = getLoc();
3173
3174 MCRegister RegNum;
3175
3176 // The case where xzr, xzr is not present is handled by an InstAlias.
3177
3178 auto RegTok = getTok(); // in case we need to backtrack
3179 if (!tryParseScalarRegister(RegNum).isSuccess())
3180 return ParseStatus::NoMatch;
3181
3182 if (RegNum != AArch64::XZR) {
3183 getLexer().UnLex(RegTok);
3184 return ParseStatus::NoMatch;
3185 }
3186
3187 if (parseComma())
3188 return ParseStatus::Failure;
3189
3190 if (!tryParseScalarRegister(RegNum).isSuccess())
3191 return TokError("expected register operand");
3192
3193 if (RegNum != AArch64::XZR)
3194 return TokError("xzr must be followed by xzr");
3195
3196 // We need to push something, since we claim this is an operand in .td.
3197 // See also AArch64AsmParser::parseKeywordOperand.
3198 Operands.push_back(AArch64Operand::CreateReg(
3199 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3200
3201 return ParseStatus::Success;
3202}
3203
3204/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
3205ParseStatus AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
3206 SMLoc S = getLoc();
3207 const AsmToken &Tok = getTok();
3208 if (Tok.isNot(AsmToken::Identifier))
3209 return TokError("invalid operand for instruction");
3210
3211 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
3212 if (!BTI)
3213 return TokError("invalid operand for instruction");
3214
3215 Operands.push_back(AArch64Operand::CreateBTIHint(
3216 BTI->Encoding, Tok.getString(), S, getContext()));
3217 Lex(); // Eat identifier token.
3218 return ParseStatus::Success;
3219}
3220
3221/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
3222/// instruction.
3223ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
3224 SMLoc S = getLoc();
3225 const MCExpr *Expr = nullptr;
3226
3227 if (getTok().is(AsmToken::Hash)) {
3228 Lex(); // Eat hash token.
3229 }
3230
3231 if (parseSymbolicImmVal(Expr))
3232 return ParseStatus::Failure;
3233
3234 AArch64MCExpr::VariantKind ELFRefKind;
3235 MCSymbolRefExpr::VariantKind DarwinRefKind;
3236 int64_t Addend;
3237 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3238 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
3239 ELFRefKind == AArch64MCExpr::VK_INVALID) {
3240 // No modifier was specified at all; this is the syntax for an ELF basic
3241 // ADRP relocation (unfortunately).
3242 Expr =
3244 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
3245 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
3246 Addend != 0) {
3247 return Error(S, "gotpage label reference not allowed an addend");
3248 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
3249 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
3250 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
3251 ELFRefKind != AArch64MCExpr::VK_ABS_PAGE_NC &&
3252 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
3253 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 &&
3254 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
3255 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
3256 // The operand must be an @page or @gotpage qualified symbolref.
3257 return Error(S, "page or gotpage label reference expected");
3258 }
3259 }
3260
3261 // We have either a label reference possibly with addend or an immediate. The
3262 // addend is a raw value here. The linker will adjust it to only reference the
3263 // page.
3264 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3265 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3266
3267 return ParseStatus::Success;
3268}
3269
3270/// tryParseAdrLabel - Parse and validate a source label for the ADR
3271/// instruction.
3272ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
3273 SMLoc S = getLoc();
3274 const MCExpr *Expr = nullptr;
3275
3276 // Leave anything with a bracket to the default for SVE
3277 if (getTok().is(AsmToken::LBrac))
3278 return ParseStatus::NoMatch;
3279
3280 if (getTok().is(AsmToken::Hash))
3281 Lex(); // Eat hash token.
3282
3283 if (parseSymbolicImmVal(Expr))
3284 return ParseStatus::Failure;
3285
3286 AArch64MCExpr::VariantKind ELFRefKind;
3287 MCSymbolRefExpr::VariantKind DarwinRefKind;
3288 int64_t Addend;
3289 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3290 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
3291 ELFRefKind == AArch64MCExpr::VK_INVALID) {
3292 // No modifier was specified at all; this is the syntax for an ELF basic
3293 // ADR relocation (unfortunately).
3294 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
3295 } else {
3296 return Error(S, "unexpected adr label");
3297 }
3298 }
3299
3300 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3301 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3302 return ParseStatus::Success;
3303}
3304
3305/// tryParseFPImm - A floating point immediate expression operand.
3306template <bool AddFPZeroAsLiteral>
3307ParseStatus AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
3308 SMLoc S = getLoc();
3309
3310 bool Hash = parseOptionalToken(AsmToken::Hash);
3311
3312 // Handle negation, as that still comes through as a separate token.
3313 bool isNegative = parseOptionalToken(AsmToken::Minus);
3314
3315 const AsmToken &Tok = getTok();
3316 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
3317 if (!Hash)
3318 return ParseStatus::NoMatch;
3319 return TokError("invalid floating point immediate");
3320 }
3321
3322 // Parse hexadecimal representation.
3323 if (Tok.is(AsmToken::Integer) && Tok.getString().starts_with("0x")) {
3324 if (Tok.getIntVal() > 255 || isNegative)
3325 return TokError("encoded floating point value out of range");
3326
3328 Operands.push_back(
3329 AArch64Operand::CreateFPImm(F, true, S, getContext()));
3330 } else {
3331 // Parse FP representation.
3332 APFloat RealVal(APFloat::IEEEdouble());
3333 auto StatusOrErr =
3334 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
3335 if (errorToBool(StatusOrErr.takeError()))
3336 return TokError("invalid floating point representation");
3337
3338 if (isNegative)
3339 RealVal.changeSign();
3340
3341 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
3342 Operands.push_back(AArch64Operand::CreateToken("#0", S, getContext()));
3343 Operands.push_back(AArch64Operand::CreateToken(".0", S, getContext()));
3344 } else
3345 Operands.push_back(AArch64Operand::CreateFPImm(
3346 RealVal, *StatusOrErr == APFloat::opOK, S, getContext()));
3347 }
3348
3349 Lex(); // Eat the token.
3350
3351 return ParseStatus::Success;
3352}
3353
3354/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
3355/// a shift suffix, for example '#1, lsl #12'.
3357AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
3358 SMLoc S = getLoc();
3359
3360 if (getTok().is(AsmToken::Hash))
3361 Lex(); // Eat '#'
3362 else if (getTok().isNot(AsmToken::Integer))
3363 // Operand should start from # or should be integer, emit error otherwise.
3364 return ParseStatus::NoMatch;
3365
3366 if (getTok().is(AsmToken::Integer) &&
3367 getLexer().peekTok().is(AsmToken::Colon))
3368 return tryParseImmRange(Operands);
3369
3370 const MCExpr *Imm = nullptr;
3371 if (parseSymbolicImmVal(Imm))
3372 return ParseStatus::Failure;
3373 else if (getTok().isNot(AsmToken::Comma)) {
3374 Operands.push_back(
3375 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3376 return ParseStatus::Success;
3377 }
3378
3379 // Eat ','
3380 Lex();
3381 StringRef VecGroup;
3382 if (!parseOptionalVGOperand(Operands, VecGroup)) {
3383 Operands.push_back(
3384 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3385 Operands.push_back(
3386 AArch64Operand::CreateToken(VecGroup, getLoc(), getContext()));
3387 return ParseStatus::Success;
3388 }
3389
3390 // The optional operand must be "lsl #N" where N is non-negative.
3391 if (!getTok().is(AsmToken::Identifier) ||
3392 !getTok().getIdentifier().equals_insensitive("lsl"))
3393 return Error(getLoc(), "only 'lsl #+N' valid after immediate");
3394
3395 // Eat 'lsl'
3396 Lex();
3397
3398 parseOptionalToken(AsmToken::Hash);
3399
3400 if (getTok().isNot(AsmToken::Integer))
3401 return Error(getLoc(), "only 'lsl #+N' valid after immediate");
3402
3403 int64_t ShiftAmount = getTok().getIntVal();
3404
3405 if (ShiftAmount < 0)
3406 return Error(getLoc(), "positive shift amount required");
3407 Lex(); // Eat the number
3408
3409 // Just in case the optional lsl #0 is used for immediates other than zero.
3410 if (ShiftAmount == 0 && Imm != nullptr) {
3411 Operands.push_back(
3412 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3413 return ParseStatus::Success;
3414 }
3415
3416 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S,
3417 getLoc(), getContext()));
3418 return ParseStatus::Success;
3419}
3420
3421/// parseCondCodeString - Parse a Condition Code string, optionally returning a
3422/// suggestion to help common typos.
3424AArch64AsmParser::parseCondCodeString(StringRef Cond, std::string &Suggestion) {
3426 .Case("eq", AArch64CC::EQ)
3427 .Case("ne", AArch64CC::NE)
3428 .Case("cs", AArch64CC::HS)
3429 .Case("hs", AArch64CC::HS)
3430 .Case("cc", AArch64CC::LO)
3431 .Case("lo", AArch64CC::LO)
3432 .Case("mi", AArch64CC::MI)
3433 .Case("pl", AArch64CC::PL)
3434 .Case("vs", AArch64CC::VS)
3435 .Case("vc", AArch64CC::VC)
3436 .Case("hi", AArch64CC::HI)
3437 .Case("ls", AArch64CC::LS)
3438 .Case("ge", AArch64CC::GE)
3439 .Case("lt", AArch64CC::LT)
3440 .Case("gt", AArch64CC::GT)
3441 .Case("le", AArch64CC::LE)
3442 .Case("al", AArch64CC::AL)
3443 .Case("nv", AArch64CC::NV)
3445
3446 if (CC == AArch64CC::Invalid && getSTI().hasFeature(AArch64::FeatureSVE)) {
3448 .Case("none", AArch64CC::EQ)
3449 .Case("any", AArch64CC::NE)
3450 .Case("nlast", AArch64CC::HS)
3451 .Case("last", AArch64CC::LO)
3452 .Case("first", AArch64CC::MI)
3453 .Case("nfrst", AArch64CC::PL)
3454 .Case("pmore", AArch64CC::HI)
3455 .Case("plast", AArch64CC::LS)
3456 .Case("tcont", AArch64CC::GE)
3457 .Case("tstop", AArch64CC::LT)
3459
3460 if (CC == AArch64CC::Invalid && Cond.lower() == "nfirst")
3461 Suggestion = "nfrst";
3462 }
3463 return CC;
3464}
3465
3466/// parseCondCode - Parse a Condition Code operand.
3467bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
3468 bool invertCondCode) {
3469 SMLoc S = getLoc();
3470 const AsmToken &Tok = getTok();
3471 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3472
3473 StringRef Cond = Tok.getString();
3474 std::string Suggestion;
3475 AArch64CC::CondCode CC = parseCondCodeString(Cond, Suggestion);
3476 if (CC == AArch64CC::Invalid) {
3477 std::string Msg = "invalid condition code";
3478 if (!Suggestion.empty())
3479 Msg += ", did you mean " + Suggestion + "?";
3480 return TokError(Msg);
3481 }
3482 Lex(); // Eat identifier token.
3483
3484 if (invertCondCode) {
3485 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
3486 return TokError("condition codes AL and NV are invalid for this instruction");
3488 }
3489
3490 Operands.push_back(
3491 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
3492 return false;
3493}
3494
3495ParseStatus AArch64AsmParser::tryParseSVCR(OperandVector &Operands) {
3496 const AsmToken &Tok = getTok();
3497 SMLoc S = getLoc();
3498
3499 if (Tok.isNot(AsmToken::Identifier))
3500 return TokError("invalid operand for instruction");
3501
3502 unsigned PStateImm = -1;
3503 const auto *SVCR = AArch64SVCR::lookupSVCRByName(Tok.getString());
3504 if (!SVCR)
3505 return ParseStatus::NoMatch;
3506 if (SVCR->haveFeatures(getSTI().getFeatureBits()))
3507 PStateImm = SVCR->Encoding;
3508
3509 Operands.push_back(
3510 AArch64Operand::CreateSVCR(PStateImm, Tok.getString(), S, getContext()));
3511 Lex(); // Eat identifier token.
3512 return ParseStatus::Success;
3513}
3514
3515ParseStatus AArch64AsmParser::tryParseMatrixRegister(OperandVector &Operands) {
3516 const AsmToken &Tok = getTok();
3517 SMLoc S = getLoc();
3518
3519 StringRef Name = Tok.getString();
3520
3521 if (Name.equals_insensitive("za") || Name.starts_with_insensitive("za.")) {
3522 Lex(); // eat "za[.(b|h|s|d)]"
3523 unsigned ElementWidth = 0;
3524 auto DotPosition = Name.find('.');
3525 if (DotPosition != StringRef::npos) {
3526 const auto &KindRes =
3527 parseVectorKind(Name.drop_front(DotPosition), RegKind::Matrix);
3528 if (!KindRes)
3529 return TokError(
3530 "Expected the register to be followed by element width suffix");
3531 ElementWidth = KindRes->second;
3532 }
3533 Operands.push_back(AArch64Operand::CreateMatrixRegister(
3534 AArch64::ZA, ElementWidth, MatrixKind::Array, S, getLoc(),
3535 getContext()));
3536 if (getLexer().is(AsmToken::LBrac)) {
3537 // There's no comma after matrix operand, so we can parse the next operand
3538 // immediately.
3539 if (parseOperand(Operands, false, false))
3540 return ParseStatus::NoMatch;
3541 }
3542 return ParseStatus::Success;
3543 }
3544
3545 // Try to parse matrix register.
3546 unsigned Reg = matchRegisterNameAlias(Name, RegKind::Matrix);
3547 if (!Reg)
3548 return ParseStatus::NoMatch;
3549
3550 size_t DotPosition = Name.find('.');
3551 assert(DotPosition != StringRef::npos && "Unexpected register");
3552
3553 StringRef Head = Name.take_front(DotPosition);
3554 StringRef Tail = Name.drop_front(DotPosition);
3555 StringRef RowOrColumn = Head.take_back();
3556
3557 MatrixKind Kind = StringSwitch<MatrixKind>(RowOrColumn.lower())
3558 .Case("h", MatrixKind::Row)
3559 .Case("v", MatrixKind::Col)
3560 .Default(MatrixKind::Tile);
3561
3562 // Next up, parsing the suffix
3563 const auto &KindRes = parseVectorKind(Tail, RegKind::Matrix);
3564 if (!KindRes)
3565 return TokError(
3566 "Expected the register to be followed by element width suffix");
3567 unsigned ElementWidth = KindRes->second;
3568
3569 Lex();
3570
3571 Operands.push_back(AArch64Operand::CreateMatrixRegister(
3572 Reg, ElementWidth, Kind, S, getLoc(), getContext()));
3573
3574 if (getLexer().is(AsmToken::LBrac)) {
3575 // There's no comma after matrix operand, so we can parse the next operand
3576 // immediately.
3577 if (parseOperand(Operands, false, false))
3578 return ParseStatus::NoMatch;
3579 }
3580 return ParseStatus::Success;
3581}
3582
3583/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
3584/// them if present.
3586AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
3587 const AsmToken &Tok = getTok();
3588 std::string LowerID = Tok.getString().lower();
3591 .Case("lsl", AArch64_AM::LSL)
3592 .Case("lsr", AArch64_AM::LSR)
3593 .Case("asr", AArch64_AM::ASR)
3594 .Case("ror", AArch64_AM::ROR)
3595 .Case("msl", AArch64_AM::MSL)
3596 .Case("uxtb", AArch64_AM::UXTB)
3597 .Case("uxth", AArch64_AM::UXTH)
3598 .Case("uxtw", AArch64_AM::UXTW)
3599 .Case("uxtx", AArch64_AM::UXTX)
3600 .Case("sxtb", AArch64_AM::SXTB)
3601 .Case("sxth", AArch64_AM::SXTH)
3602 .Case("sxtw", AArch64_AM::SXTW)
3603 .Case("sxtx", AArch64_AM::SXTX)
3605
3607 return ParseStatus::NoMatch;
3608
3609 SMLoc S = Tok.getLoc();
3610 Lex();
3611
3612 bool Hash = parseOptionalToken(AsmToken::Hash);
3613
3614 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
3615 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
3616 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
3617 ShOp == AArch64_AM::MSL) {
3618 // We expect a number here.
3619 return TokError("expected #imm after shift specifier");
3620 }
3621
3622 // "extend" type operations don't need an immediate, #0 is implicit.
3623 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3624 Operands.push_back(
3625 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
3626 return ParseStatus::Success;
3627 }
3628
3629 // Make sure we do actually have a number, identifier or a parenthesized
3630 // expression.
3631 SMLoc E = getLoc();
3632 if (!getTok().is(AsmToken::Integer) && !getTok().is(AsmToken::LParen) &&
3633 !getTok().is(AsmToken::Identifier))
3634 return Error(E, "expected integer shift amount");
3635
3636 const MCExpr *ImmVal;
3637 if (getParser().parseExpression(ImmVal))
3638 return ParseStatus::Failure;
3639
3640 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3641 if (!MCE)
3642 return Error(E, "expected constant '#imm' after shift specifier");
3643
3644 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3645 Operands.push_back(AArch64Operand::CreateShiftExtend(
3646 ShOp, MCE->getValue(), true, S, E, getContext()));
3647 return ParseStatus::Success;
3648}
3649
3650static const struct Extension {
3651 const char *Name;
3653} ExtensionMap[] = {
3654 {"crc", {AArch64::FeatureCRC}},
3655 {"sm4", {AArch64::FeatureSM4}},
3656 {"sha3", {AArch64::FeatureSHA3}},
3657 {"sha2", {AArch64::FeatureSHA2}},
3658 {"aes", {AArch64::FeatureAES}},
3659 {"crypto", {AArch64::FeatureCrypto}},
3660 {"fp", {AArch64::FeatureFPARMv8}},
3661 {"simd", {AArch64::FeatureNEON}},
3662 {"ras", {AArch64::FeatureRAS}},
3663 {"rasv2", {AArch64::FeatureRASv2}},
3664 {"lse", {AArch64::FeatureLSE}},
3665 {"predres", {AArch64::FeaturePredRes}},
3666 {"predres2", {AArch64::FeatureSPECRES2}},
3667 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
3668 {"mte", {AArch64::FeatureMTE}},
3669 {"memtag", {AArch64::FeatureMTE}},
3670 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
3671 {"pan", {AArch64::FeaturePAN}},
3672 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
3673 {"ccpp", {AArch64::FeatureCCPP}},
3674 {"rcpc", {AArch64::FeatureRCPC}},
3675 {"rng", {AArch64::FeatureRandGen}},
3676 {"sve", {AArch64::FeatureSVE}},
3677 {"sve2", {AArch64::FeatureSVE2}},
3678 {"sve2-aes", {AArch64::FeatureSVE2AES}},
3679 {"sve2-sm4", {AArch64::FeatureSVE2SM4}},
3680 {"sve2-sha3", {AArch64::FeatureSVE2SHA3}},
3681 {"sve2-bitperm", {AArch64::FeatureSVE2BitPerm}},
3682 {"sve2p1", {AArch64::FeatureSVE2p1}},
3683 {"b16b16", {AArch64::FeatureB16B16}},
3684 {"ls64", {AArch64::FeatureLS64}},
3685 {"xs", {AArch64::FeatureXS}},
3686 {"pauth", {AArch64::FeaturePAuth}},
3687 {"flagm", {AArch64::FeatureFlagM}},
3688 {"rme", {AArch64::FeatureRME}},
3689 {"sme", {AArch64::FeatureSME}},
3690 {"sme-f64f64", {AArch64::FeatureSMEF64F64}},
3691 {"sme-f16f16", {AArch64::FeatureSMEF16F16}},
3692 {"sme-i16i64", {AArch64::FeatureSMEI16I64}},
3693 {"sme2", {AArch64::FeatureSME2}},
3694 {"sme2p1", {AArch64::FeatureSME2p1}},
3695 {"hbc", {AArch64::FeatureHBC}},
3696 {"mops", {AArch64::FeatureMOPS}},
3697 {"mec", {AArch64::FeatureMEC}},
3698 {"the", {AArch64::FeatureTHE}},
3699 {"d128", {AArch64::FeatureD128}},
3700 {"lse128", {AArch64::FeatureLSE128}},
3701 {"ite", {AArch64::FeatureITE}},
3702 {"cssc", {AArch64::FeatureCSSC}},
3703 {"rcpc3", {AArch64::FeatureRCPC3}},
3704 {"gcs", {AArch64::FeatureGCS}},
3705 {"bf16", {AArch64::FeatureBF16}},
3706 {"compnum", {AArch64::FeatureComplxNum}},
3707 {"dotprod", {AArch64::FeatureDotProd}},
3708 {"f32mm", {AArch64::FeatureMatMulFP32}},
3709 {"f64mm", {AArch64::FeatureMatMulFP64}},
3710 {"fp16", {AArch64::FeatureFullFP16}},
3711 {"fp16fml", {AArch64::FeatureFP16FML}},
3712 {"i8mm", {AArch64::FeatureMatMulInt8}},
3713 {"lor", {AArch64::FeatureLOR}},
3714 {"profile", {AArch64::FeatureSPE}},
3715 // "rdma" is the name documented by binutils for the feature, but
3716 // binutils also accepts incomplete prefixes of features, so "rdm"
3717 // works too. Support both spellings here.
3718 {"rdm", {AArch64::FeatureRDM}},
3719 {"rdma", {AArch64::FeatureRDM}},
3720 {"sb", {AArch64::FeatureSB}},
3721 {"ssbs", {AArch64::FeatureSSBS}},
3722 {"tme", {AArch64::FeatureTME}},
3723 {"fp8", {AArch64::FeatureFP8}},
3724 {"faminmax", {AArch64::FeatureFAMINMAX}},
3725 {"fp8fma", {AArch64::FeatureFP8FMA}},
3726 {"ssve-fp8fma", {AArch64::FeatureSSVE_FP8FMA}},
3727 {"fp8dot2", {AArch64::FeatureFP8DOT2}},
3728 {"ssve-fp8dot2", {AArch64::FeatureSSVE_FP8DOT2}},
3729 {"fp8dot4", {AArch64::FeatureFP8DOT4}},
3730 {"ssve-fp8dot4", {AArch64::FeatureSSVE_FP8DOT4}},
3731 {"lut", {AArch64::FeatureLUT}},
3732 {"sme-lutv2", {AArch64::FeatureSME_LUTv2}},
3733 {"sme-f8f16", {AArch64::FeatureSMEF8F16}},
3734 {"sme-f8f32", {AArch64::FeatureSMEF8F32}},
3735 {"sme-fa64", {AArch64::FeatureSMEFA64}},
3736 {"cpa", {AArch64::FeatureCPA}},
3737 {"tlbiw", {AArch64::FeatureTLBIW}},
3739
3740static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
3741 if (FBS[AArch64::HasV8_0aOps])
3742 Str += "ARMv8a";
3743 if (FBS[AArch64::HasV8_1aOps])
3744 Str += "ARMv8.1a";
3745 else if (FBS[AArch64::HasV8_2aOps])
3746 Str += "ARMv8.2a";
3747 else if (FBS[AArch64::HasV8_3aOps])
3748 Str += "ARMv8.3a";
3749 else if (FBS[AArch64::HasV8_4aOps])
3750 Str += "ARMv8.4a";
3751 else if (FBS[AArch64::HasV8_5aOps])
3752 Str += "ARMv8.5a";
3753 else if (FBS[AArch64::HasV8_6aOps])
3754 Str += "ARMv8.6a";
3755 else if (FBS[AArch64::HasV8_7aOps])
3756 Str += "ARMv8.7a";
3757 else if (FBS[AArch64::HasV8_8aOps])
3758 Str += "ARMv8.8a";
3759 else if (FBS[AArch64::HasV8_9aOps])
3760 Str += "ARMv8.9a";
3761 else if (FBS[AArch64::HasV9_0aOps])
3762 Str += "ARMv9-a";
3763 else if (FBS[AArch64::HasV9_1aOps])
3764 Str += "ARMv9.1a";
3765 else if (FBS[AArch64::HasV9_2aOps])
3766 Str += "ARMv9.2a";
3767 else if (FBS[AArch64::HasV9_3aOps])
3768 Str += "ARMv9.3a";
3769 else if (FBS[AArch64::HasV9_4aOps])
3770 Str += "ARMv9.4a";
3771 else if (FBS[AArch64::HasV9_5aOps])
3772 Str += "ARMv9.5a";
3773 else if (FBS[AArch64::HasV8_0rOps])
3774 Str += "ARMv8r";
3775 else {
3776 SmallVector<std::string, 2> ExtMatches;
3777 for (const auto& Ext : ExtensionMap) {
3778 // Use & in case multiple features are enabled
3779 if ((FBS & Ext.Features) != FeatureBitset())
3780 ExtMatches.push_back(Ext.Name);
3781 }
3782 Str += !ExtMatches.empty() ? llvm::join(ExtMatches, ", ") : "(unknown)";
3783 }
3784}
3785
3786void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
3787 SMLoc S) {
3788 const uint16_t Op2 = Encoding & 7;
3789 const uint16_t Cm = (Encoding & 0x78) >> 3;
3790 const uint16_t Cn = (Encoding & 0x780) >> 7;
3791 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
3792
3793 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
3794
3795 Operands.push_back(
3796 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
3797 Operands.push_back(
3798 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
3799 Operands.push_back(
3800 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
3801 Expr = MCConstantExpr::create(Op2, getContext());
3802 Operands.push_back(
3803 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
3804}
3805
3806/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
3807/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
3808bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
3810 if (Name.contains('.'))
3811 return TokError("invalid operand");
3812
3813 Mnemonic = Name;
3814 Operands.push_back(AArch64Operand::CreateToken("sys", NameLoc, getContext()));
3815
3816 const AsmToken &Tok = getTok();
3817 StringRef Op = Tok.getString();
3818 SMLoc S = Tok.getLoc();
3819
3820 if (Mnemonic == "ic") {
3821 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
3822 if (!IC)
3823 return TokError("invalid operand for IC instruction");
3824 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
3825 std::string Str("IC " + std::string(IC->Name) + " requires: ");
3827 return TokError(Str);
3828 }
3829 createSysAlias(IC->Encoding, Operands, S);
3830 } else if (Mnemonic == "dc") {
3831 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
3832 if (!DC)
3833 return TokError("invalid operand for DC instruction");
3834 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
3835 std::string Str("DC " + std::string(DC->Name) + " requires: ");
3837 return TokError(Str);
3838 }
3839 createSysAlias(DC->Encoding, Operands, S);
3840 } else if (Mnemonic == "at") {
3841 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
3842 if (!AT)
3843 return TokError("invalid operand for AT instruction");
3844 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
3845 std::string Str("AT " + std::string(AT->Name) + " requires: ");
3847 return TokError(Str);
3848 }
3849 createSysAlias(AT->Encoding, Operands, S);
3850 } else if (Mnemonic == "tlbi") {
3851 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
3852 if (!TLBI)
3853 return TokError("invalid operand for TLBI instruction");
3854 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
3855 std::string Str("TLBI " + std::string(TLBI->Name) + " requires: ");
3857 return TokError(Str);
3858 }
3859 createSysAlias(TLBI->Encoding, Operands, S);
3860 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp" || Mnemonic == "cosp") {
3861
3862 if (Op.lower() != "rctx")
3863 return TokError("invalid operand for prediction restriction instruction");
3864
3865 bool hasAll = getSTI().hasFeature(AArch64::FeatureAll);
3866 bool hasPredres = hasAll || getSTI().hasFeature(AArch64::FeaturePredRes);
3867 bool hasSpecres2 = hasAll || getSTI().hasFeature(AArch64::FeatureSPECRES2);
3868
3869 if (Mnemonic == "cosp" && !hasSpecres2)
3870 return TokError("COSP requires: predres2");
3871 if (!hasPredres)
3872 return TokError(Mnemonic.upper() + "RCTX requires: predres");
3873
3874 uint16_t PRCTX_Op2 = Mnemonic == "cfp" ? 0b100
3875 : Mnemonic == "dvp" ? 0b101
3876 : Mnemonic == "cosp" ? 0b110
3877 : Mnemonic == "cpp" ? 0b111
3878 : 0;
3879 assert(PRCTX_Op2 &&
3880 "Invalid mnemonic for prediction restriction instruction");
3881 const auto SYS_3_7_3 = 0b01101110011; // op=3, CRn=7, CRm=3
3882 const auto Encoding = SYS_3_7_3 << 3 | PRCTX_Op2;
3883
3884 createSysAlias(Encoding, Operands, S);
3885 }
3886
3887 Lex(); // Eat operand.
3888
3889 bool ExpectRegister = !Op.contains_insensitive("all");
3890 bool HasRegister = false;
3891
3892 // Check for the optional register operand.
3893 if (parseOptionalToken(AsmToken::Comma)) {
3894 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
3895 return TokError("expected register operand");
3896 HasRegister = true;
3897 }
3898
3899 if (ExpectRegister && !HasRegister)
3900 return TokError("specified " + Mnemonic + " op requires a register");
3901 else if (!ExpectRegister && HasRegister)
3902 return TokError("specified " + Mnemonic + " op does not use a register");
3903
3904 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3905 return true;
3906
3907 return false;
3908}
3909
3910/// parseSyspAlias - The TLBIP instructions are simple aliases for
3911/// the SYSP instruction. Parse them specially so that we create a SYSP MCInst.
3912bool AArch64AsmParser::parseSyspAlias(StringRef Name, SMLoc NameLoc,
3914 if (Name.contains('.'))
3915 return TokError("invalid operand");
3916
3917 Mnemonic = Name;
3918 Operands.push_back(
3919 AArch64Operand::CreateToken("sysp", NameLoc, getContext()));
3920
3921 const AsmToken &Tok = getTok();
3922 StringRef Op = Tok.getString();
3923 SMLoc S = Tok.getLoc();
3924
3925 if (Mnemonic == "tlbip") {
3926 bool HasnXSQualifier = Op.ends_with_insensitive("nXS");
3927 if (HasnXSQualifier) {
3928 Op = Op.drop_back(3);
3929 }
3930 const AArch64TLBI::TLBI *TLBIorig = AArch64TLBI::lookupTLBIByName(Op);
3931 if (!TLBIorig)
3932 return TokError("invalid operand for TLBIP instruction");
3933 const AArch64TLBI::TLBI TLBI(
3934 TLBIorig->Name, TLBIorig->Encoding | (HasnXSQualifier ? (1 << 7) : 0),
3935 TLBIorig->NeedsReg,
3936 HasnXSQualifier
3937 ? TLBIorig->FeaturesRequired | FeatureBitset({AArch64::FeatureXS})
3938 : TLBIorig->FeaturesRequired);
3939 if (!TLBI.haveFeatures(getSTI().getFeatureBits())) {
3940 std::string Name =
3941 std::string(TLBI.Name) + (HasnXSQualifier ? "nXS" : "");
3942 std::string Str("TLBIP " + Name + " requires: ");
3944 return TokError(Str);
3945 }
3946 createSysAlias(TLBI.Encoding, Operands, S);
3947 }
3948
3949 Lex(); // Eat operand.
3950
3951 if (parseComma())
3952 return true;
3953
3954 if (Tok.isNot(AsmToken::Identifier))
3955 return TokError("expected register identifier");
3956 auto Result = tryParseSyspXzrPair(Operands);
3957 if (Result.isNoMatch())
3958 Result = tryParseGPRSeqPair(Operands);
3959 if (!Result.isSuccess())
3960 return TokError("specified " + Mnemonic +
3961 " op requires a pair of registers");
3962
3963 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3964 return true;
3965
3966 return false;
3967}
3968
3969ParseStatus AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
3970 MCAsmParser &Parser = getParser();
3971 const AsmToken &Tok = getTok();
3972
3973 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier))
3974 return TokError("'csync' operand expected");
3975 if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
3976 // Immediate operand.
3977 const MCExpr *ImmVal;
3978 SMLoc ExprLoc = getLoc();
3979 AsmToken IntTok = Tok;
3980 if (getParser().parseExpression(ImmVal))
3981 return ParseStatus::Failure;
3982 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3983 if (!MCE)
3984 return Error(ExprLoc, "immediate value expected for barrier operand");
3985 int64_t Value = MCE->getValue();
3986 if (Mnemonic == "dsb" && Value > 15) {
3987 // This case is a no match here, but it might be matched by the nXS
3988 // variant. Deliberately not unlex the optional '#' as it is not necessary
3989 // to characterize an integer immediate.
3990 Parser.getLexer().UnLex(IntTok);
3991 return ParseStatus::NoMatch;
3992 }
3993 if (Value < 0 || Value > 15)
3994 return Error(ExprLoc, "barrier operand out of range");
3995 auto DB = AArch64DB::lookupDBByEncoding(Value);
3996 Operands.push_back(AArch64Operand::CreateBarrier(Value, DB ? DB->Name : "",
3997 ExprLoc, getContext(),
3998 false /*hasnXSModifier*/));
3999 return ParseStatus::Success;
4000 }
4001
4002 if (Tok.isNot(AsmToken::Identifier))
4003 return TokError("invalid operand for instruction");
4004
4005 StringRef Operand = Tok.getString();
4006 auto TSB = AArch64TSB::lookupTSBByName(Operand);
4007 auto DB = AArch64DB::lookupDBByName(Operand);
4008 // The only valid named option for ISB is 'sy'
4009 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy))
4010 return TokError("'sy' or #imm operand expected");
4011 // The only valid named option for TSB is 'csync'
4012 if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync))
4013 return TokError("'csync' operand expected");
4014 if (!DB && !TSB) {
4015 if (Mnemonic == "dsb") {
4016 // This case is a no match here, but it might be matched by the nXS
4017 // variant.
4018 return ParseStatus::NoMatch;
4019 }
4020 return TokError("invalid barrier option name");
4021 }
4022
4023 Operands.push_back(AArch64Operand::CreateBarrier(
4024 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(),
4025 getContext(), false /*hasnXSModifier*/));
4026 Lex(); // Consume the option
4027
4028 return ParseStatus::Success;
4029}
4030
4032AArch64AsmParser::tryParseBarriernXSOperand(OperandVector &Operands) {
4033 const AsmToken &Tok = getTok();
4034
4035 assert(Mnemonic == "dsb" && "Instruction does not accept nXS operands");
4036 if (Mnemonic != "dsb")
4037 return ParseStatus::Failure;
4038
4039 if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
4040 // Immediate operand.
4041 const MCExpr *ImmVal;
4042 SMLoc ExprLoc = getLoc();
4043 if (getParser().parseExpression(ImmVal))
4044 return ParseStatus::Failure;
4045 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4046 if (!MCE)
4047 return Error(ExprLoc, "immediate value expected for barrier operand");
4048 int64_t Value = MCE->getValue();
4049 // v8.7-A DSB in the nXS variant accepts only the following immediate
4050 // values: 16, 20, 24, 28.
4051 if (Value != 16 && Value != 20 && Value != 24 && Value != 28)
4052 return Error(ExprLoc, "barrier operand out of range");
4053 auto DB = AArch64DBnXS::lookupDBnXSByImmValue(Value);
4054 Operands.push_back(AArch64Operand::CreateBarrier(DB->Encoding, DB->Name,
4055 ExprLoc, getContext(),
4056 true /*hasnXSModifier*/));
4057 return ParseStatus::Success;
4058 }
4059
4060 if (Tok.isNot(AsmToken::Identifier))
4061 return TokError("invalid operand for instruction");
4062
4063 StringRef Operand = Tok.getString();
4064 auto DB = AArch64DBnXS::lookupDBnXSByName(Operand);
4065
4066 if (!DB)
4067 return TokError("invalid barrier option name");
4068
4069 Operands.push_back(
4070 AArch64Operand::CreateBarrier(DB->Encoding, Tok.getString(), getLoc(),
4071 getContext(), true /*hasnXSModifier*/));
4072 Lex(); // Consume the option
4073
4074 return ParseStatus::Success;
4075}
4076
4077ParseStatus AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
4078 const AsmToken &Tok = getTok();
4079
4080 if (Tok.isNot(AsmToken::Identifier))
4081 return ParseStatus::NoMatch;
4082
4083 if (AArch64SVCR::lookupSVCRByName(Tok.getString()))
4084 return ParseStatus::NoMatch;
4085
4086 int MRSReg, MSRReg;
4087 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
4088 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
4089 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
4090 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
4091 } else
4092 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
4093
4094 unsigned PStateImm = -1;
4095 auto PState15 = AArch64PState::lookupPStateImm0_15ByName(Tok.getString());
4096 if (PState15 && PState15->haveFeatures(getSTI().getFeatureBits()))
4097 PStateImm = PState15->Encoding;
4098 if (!PState15) {
4099 auto PState1 = AArch64PState::lookupPStateImm0_1ByName(Tok.getString());
4100 if (PState1 && PState1->haveFeatures(getSTI().getFeatureBits()))
4101 PStateImm = PState1->Encoding;
4102 }
4103
4104 Operands.push_back(
4105 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
4106 PStateImm, getContext()));
4107 Lex(); // Eat identifier
4108
4109 return ParseStatus::Success;
4110}
4111
4112/// tryParseNeonVectorRegister - Parse a vector register operand.
4113bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
4114 if (getTok().isNot(AsmToken::Identifier))
4115 return true;
4116
4117 SMLoc S = getLoc();
4118 // Check for a vector register specifier first.
4121 ParseStatus Res = tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
4122 if (!Res.isSuccess())
4123 return true;
4124
4125 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
4126 if (!KindRes)
4127 return true;
4128
4129 unsigned ElementWidth = KindRes->second;
4130 Operands.push_back(
4131 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
4132 S, getLoc(), getContext()));
4133
4134 // If there was an explicit qualifier, that goes on as a literal text
4135 // operand.
4136 if (!Kind.empty())
4137 Operands.push_back(AArch64Operand::CreateToken(Kind, S, getContext()));
4138
4139 return tryParseVectorIndex(Operands).isFailure();
4140}
4141
4142ParseStatus AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
4143 SMLoc SIdx = getLoc();
4144 if (parseOptionalToken(AsmToken::LBrac)) {
4145 const MCExpr *ImmVal;
4146 if (getParser().parseExpression(ImmVal))
4147 return ParseStatus::NoMatch;
4148 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4149 if (!MCE)
4150 return TokError("immediate value expected for vector index");
4151
4152 SMLoc E = getLoc();
4153
4154 if (parseToken(AsmToken::RBrac, "']' expected"))
4155 return ParseStatus::Failure;
4156
4157 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
4158 E, getContext()));
4159 return ParseStatus::Success;
4160 }
4161
4162 return ParseStatus::NoMatch;
4163}
4164
4165// tryParseVectorRegister - Try to parse a vector register name with
4166// optional kind specifier. If it is a register specifier, eat the token
4167// and return it.
4168ParseStatus AArch64AsmParser::tryParseVectorRegister(MCRegister &Reg,
4169 StringRef &Kind,
4170 RegKind MatchKind) {
4171 const AsmToken &Tok = getTok();
4172
4173 if (Tok.isNot(AsmToken::Identifier))
4174 return ParseStatus::NoMatch;
4175
4176 StringRef Name = Tok.getString();
4177 // If there is a kind specifier, it's separated from the register name by
4178 // a '.'.
4179 size_t Start = 0, Next = Name.find('.');
4180 StringRef Head = Name.slice(Start, Next);
4181 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
4182
4183 if (RegNum) {
4184 if (Next != StringRef::npos) {
4185 Kind = Name.slice(Next, StringRef::npos);
4186 if (!isValidVectorKind(Kind, MatchKind))
4187 return TokError("invalid vector kind qualifier");
4188 }
4189 Lex(); // Eat the register token.
4190
4191 Reg = RegNum;
4192 return ParseStatus::Success;
4193 }
4194
4195 return ParseStatus::NoMatch;
4196}
4197
4198ParseStatus AArch64AsmParser::tryParseSVEPredicateOrPredicateAsCounterVector(
4201 tryParseSVEPredicateVector<RegKind::SVEPredicateAsCounter>(Operands);
4202 if (!Status.isSuccess())
4203 Status = tryParseSVEPredicateVector<RegKind::SVEPredicateVector>(Operands);
4204 return Status;
4205}
4206
4207/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
4208template <RegKind RK>
4210AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
4211 // Check for a SVE predicate register specifier first.
4212 const SMLoc S = getLoc();
4214 MCRegister RegNum;
4215 auto Res = tryParseVectorRegister(RegNum, Kind, RK);
4216 if (!Res.isSuccess())
4217 return Res;
4218
4219 const auto &KindRes = parseVectorKind(Kind, RK);
4220 if (!KindRes)
4221 return ParseStatus::NoMatch;
4222
4223 unsigned ElementWidth = KindRes->second;
4224 Operands.push_back(AArch64Operand::CreateVectorReg(
4225 RegNum, RK, ElementWidth, S,
4226 getLoc(), getContext()));
4227
4228 if (getLexer().is(AsmToken::LBrac)) {
4229 if (RK == RegKind::SVEPredicateAsCounter) {
4230 ParseStatus ResIndex = tryParseVectorIndex(Operands);
4231 if (ResIndex.isSuccess())
4232 return ParseStatus::Success;
4233 } else {
4234 // Indexed predicate, there's no comma so try parse the next operand
4235 // immediately.
4236 if (parseOperand(Operands, false, false))
4237 return ParseStatus::NoMatch;
4238 }
4239 }
4240
4241 // Not all predicates are followed by a '/m' or '/z'.
4242 if (getTok().isNot(AsmToken::Slash))
4243 return ParseStatus::Success;
4244
4245 // But when they do they shouldn't have an element type suffix.
4246 if (!Kind.empty())
4247 return Error(S, "not expecting size suffix");
4248
4249 // Add a literal slash as operand
4250 Operands.push_back(AArch64Operand::CreateToken("/", getLoc(), getContext()));
4251
4252 Lex(); // Eat the slash.
4253
4254 // Zeroing or merging?
4255 auto Pred = getTok().getString().lower();
4256 if (RK == RegKind::SVEPredicateAsCounter && Pred != "z")
4257 return Error(getLoc(), "expecting 'z' predication");
4258
4259 if (RK == RegKind::SVEPredicateVector && Pred != "z" && Pred != "m")
4260 return Error(getLoc(), "expecting 'm' or 'z' predication");
4261
4262 // Add zero/merge token.
4263 const char *ZM = Pred == "z" ? "z" : "m";
4264 Operands.push_back(AArch64Operand::CreateToken(ZM, getLoc(), getContext()));
4265
4266 Lex(); // Eat zero/merge token.
4267 return ParseStatus::Success;
4268}
4269
4270/// parseRegister - Parse a register operand.
4271bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
4272 // Try for a Neon vector register.
4273 if (!tryParseNeonVectorRegister(Operands))
4274 return false;
4275
4276 if (tryParseZTOperand(Operands).isSuccess())
4277 return false;
4278
4279 // Otherwise try for a scalar register.
4280 if (tryParseGPROperand<false>(Operands).isSuccess())
4281 return false;
4282
4283 return true;
4284}
4285
4286bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
4287 bool HasELFModifier = false;
4289
4290 if (parseOptionalToken(AsmToken::Colon)) {
4291 HasELFModifier = true;
4292
4293 if (getTok().isNot(AsmToken::Identifier))
4294 return TokError("expect relocation specifier in operand after ':'");
4295
4296 std::string LowerCase = getTok().getIdentifier().lower();
4297 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
4299 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
4300 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
4301 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
4302 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
4303 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
4304 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
4305 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
4306 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
4307 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
4308 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
4309 .Case("prel_g3", AArch64MCExpr::VK_PREL_G3)
4310 .Case("prel_g2", AArch64MCExpr::VK_PREL_G2)
4311 .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC)
4312 .Case("prel_g1", AArch64MCExpr::VK_PREL_G1)
4313 .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC)
4314 .Case("prel_g0", AArch64MCExpr::VK_PREL_G0)
4315 .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC)
4316 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
4317 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
4318 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
4319 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
4320 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
4321 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
4322 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
4323 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
4324 .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC)
4325 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
4326 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
4327 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
4328 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
4329 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
4330 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
4331 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
4332 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
4333 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
4335 .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15)
4336 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
4338 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
4339 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
4340 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
4342 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
4343 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
4345
4346 if (RefKind == AArch64MCExpr::VK_INVALID)
4347 return TokError("expect relocation specifier in operand after ':'");
4348
4349 Lex(); // Eat identifier
4350
4351 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
4352 return true;
4353 }
4354
4355 if (getParser().parseExpression(ImmVal))
4356 return true;
4357
4358 if (HasELFModifier)
4359 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
4360
4361 return false;
4362}
4363
4364ParseStatus AArch64AsmParser::tryParseMatrixTileList(OperandVector &Operands) {
4365 if (getTok().isNot(AsmToken::LCurly))
4366 return ParseStatus::NoMatch;
4367
4368 auto ParseMatrixTile = [this](unsigned &Reg,
4369 unsigned &ElementWidth) -> ParseStatus {
4370 StringRef Name = getTok().getString();
4371 size_t DotPosition = Name.find('.');
4372 if (DotPosition == StringRef::npos)
4373 return ParseStatus::NoMatch;
4374
4375 unsigned RegNum = matchMatrixTileListRegName(Name);
4376 if (!RegNum)
4377 return ParseStatus::NoMatch;
4378
4379 StringRef Tail = Name.drop_front(DotPosition);
4380 const std::optional<std::pair<int, int>> &KindRes =
4381 parseVectorKind(Tail, RegKind::Matrix);
4382 if (!KindRes)
4383 return TokError(
4384 "Expected the register to be followed by element width suffix");
4385 ElementWidth = KindRes->second;
4386 Reg = RegNum;
4387 Lex(); // Eat the register.
4388 return ParseStatus::Success;
4389 };
4390
4391 SMLoc S = getLoc();
4392 auto LCurly = getTok();
4393 Lex(); // Eat left bracket token.
4394
4395 // Empty matrix list
4396 if (parseOptionalToken(AsmToken::RCurly)) {
4397 Operands.push_back(AArch64Operand::CreateMatrixTileList(
4398 /*RegMask=*/0, S, getLoc(), getContext()));
4399 return ParseStatus::Success;
4400 }
4401
4402 // Try parse {za} alias early
4403 if (getTok().getString().equals_insensitive("za")) {
4404 Lex(); // Eat 'za'
4405
4406 if (parseToken(AsmToken::RCurly, "'}' expected"))
4407 return ParseStatus::Failure;
4408
4409 Operands.push_back(AArch64Operand::CreateMatrixTileList(
4410 /*RegMask=*/0xFF, S, getLoc(), getContext()));
4411 return ParseStatus::Success;
4412 }
4413
4414 SMLoc TileLoc = getLoc();
4415
4416 unsigned FirstReg, ElementWidth;
4417 auto ParseRes = ParseMatrixTile(FirstReg, ElementWidth);
4418 if (!ParseRes.isSuccess()) {
4419 getLexer().UnLex(LCurly);
4420 return ParseRes;
4421 }
4422
4423 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4424
4425 unsigned PrevReg = FirstReg;
4426
4428 AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth);
4429
4430 SmallSet<unsigned, 8> SeenRegs;
4431 SeenRegs.insert(FirstReg);
4432
4433 while (parseOptionalToken(AsmToken::Comma)) {
4434 TileLoc = getLoc();
4435 unsigned Reg, NextElementWidth;
4436 ParseRes = ParseMatrixTile(Reg, NextElementWidth);
4437 if (!ParseRes.isSuccess())
4438 return ParseRes;
4439
4440 // Element size must match on all regs in the list.
4441 if (ElementWidth != NextElementWidth)
4442 return Error(TileLoc, "mismatched register size suffix");
4443
4444 if (RI->getEncodingValue(Reg) <= (RI->getEncodingValue(PrevReg)))
4445 Warning(TileLoc, "tile list not in ascending order");
4446
4447 if (SeenRegs.contains(Reg))
4448 Warning(TileLoc, "duplicate tile in list");
4449 else {
4450 SeenRegs.insert(Reg);
4451 AArch64Operand::ComputeRegsForAlias(Reg, DRegs, ElementWidth);
4452 }
4453
4454 PrevReg = Reg;
4455 }
4456
4457 if (parseToken(AsmToken::RCurly, "'}' expected"))
4458 return ParseStatus::Failure;
4459
4460 unsigned RegMask = 0;
4461 for (auto Reg : DRegs)
4462 RegMask |= 0x1 << (RI->getEncodingValue(Reg) -
4463 RI->getEncodingValue(AArch64::ZAD0));
4464 Operands.push_back(
4465 AArch64Operand::CreateMatrixTileList(RegMask, S, getLoc(), getContext()));
4466
4467 return ParseStatus::Success;
4468}
4469
4470template <RegKind VectorKind>
4471ParseStatus AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
4472 bool ExpectMatch) {
4473 MCAsmParser &Parser = getParser();
4474 if (!getTok().is(AsmToken::LCurly))
4475 return ParseStatus::NoMatch;
4476
4477 // Wrapper around parse function
4478 auto ParseVector = [this](MCRegister &Reg, StringRef &Kind, SMLoc Loc,
4479 bool NoMatchIsError) -> ParseStatus {
4480 auto RegTok = getTok();
4481 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
4482 if (ParseRes.isSuccess()) {
4483 if (parseVectorKind(Kind, VectorKind))
4484 return ParseRes;
4485 llvm_unreachable("Expected a valid vector kind");
4486 }
4487
4488 if (RegTok.is(AsmToken::Identifier) && ParseRes.isNoMatch() &&
4489 RegTok.getString().equals_insensitive("zt0"))
4490 return ParseStatus::NoMatch;
4491
4492 if (RegTok.isNot(AsmToken::Identifier) || ParseRes.isFailure() ||
4493 (ParseRes.isNoMatch() && NoMatchIsError &&
4494 !RegTok.getString().starts_with_insensitive("za")))
4495 return Error(Loc, "vector register expected");
4496
4497 return ParseStatus::NoMatch;
4498 };
4499
4500 int NumRegs = getNumRegsForRegKind(VectorKind);
4501 SMLoc S = getLoc();
4502 auto LCurly = getTok();
4503 Lex(); // Eat left bracket token.
4504
4506 MCRegister FirstReg;
4507 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
4508
4509 // Put back the original left bracket if there was no match, so that
4510 // different types of list-operands can be matched (e.g. SVE, Neon).
4511 if (ParseRes.isNoMatch())
4512 Parser.getLexer().UnLex(LCurly);
4513
4514 if (!ParseRes.isSuccess())
4515 return ParseRes;
4516
4517 int64_t PrevReg = FirstReg;
4518 unsigned Count = 1;
4519
4520 int Stride = 1;
4521 if (parseOptionalToken(AsmToken::Minus)) {
4522 SMLoc Loc = getLoc();
4523 StringRef NextKind;
4524
4526 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
4527 if (!ParseRes.isSuccess())
4528 return ParseRes;
4529
4530 // Any Kind suffices must match on all regs in the list.
4531 if (Kind != NextKind)
4532 return Error(Loc, "mismatched register size suffix");
4533
4534 unsigned Space =
4535 (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + NumRegs - PrevReg);
4536
4537 if (Space == 0 || Space > 3)
4538 return Error(Loc, "invalid number of vectors");
4539
4540 Count += Space;
4541 }
4542 else {
4543 bool HasCalculatedStride = false;
4544 while (parseOptionalToken(AsmToken::Comma)) {
4545 SMLoc Loc = getLoc();
4546 StringRef NextKind;
4548 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
4549 if (!ParseRes.isSuccess())
4550 return ParseRes;
4551
4552 // Any Kind suffices must match on all regs in the list.
4553 if (Kind != NextKind)
4554 return Error(Loc, "mismatched register size suffix");
4555
4556 unsigned RegVal = getContext().getRegisterInfo()->getEncodingValue(Reg);
4557 unsigned PrevRegVal =
4558 getContext().getRegisterInfo()->getEncodingValue(PrevReg);
4559 if (!HasCalculatedStride) {
4560 Stride = (PrevRegVal < RegVal) ? (RegVal - PrevRegVal)
4561 : (RegVal + NumRegs - PrevRegVal);
4562 HasCalculatedStride = true;
4563 }
4564
4565 // Register must be incremental (with a wraparound at last register).
4566 if (Stride == 0 || RegVal != ((PrevRegVal + Stride) % NumRegs))
4567 return Error(Loc, "registers must have the same sequential stride");
4568
4569 PrevReg = Reg;
4570 ++Count;
4571 }
4572 }
4573
4574 if (parseToken(AsmToken::RCurly, "'}' expected"))
4575 return ParseStatus::Failure;
4576
4577 if (Count > 4)
4578 return Error(S, "invalid number of vectors");
4579
4580 unsigned NumElements = 0;
4581 unsigned ElementWidth = 0;
4582 if (!Kind.empty()) {
4583 if (const auto &VK = parseVectorKind(Kind, VectorKind))
4584 std::tie(NumElements, ElementWidth) = *VK;
4585 }
4586
4587 Operands.push_back(AArch64Operand::CreateVectorList(
4588 FirstReg, Count, Stride, NumElements, ElementWidth, VectorKind, S,
4589 getLoc(), getContext()));
4590
4591 return ParseStatus::Success;
4592}
4593
4594/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
4595bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
4596 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
4597 if (!ParseRes.isSuccess())
4598 return true;
4599
4600 return tryParseVectorIndex(Operands).isFailure();
4601}
4602
4603ParseStatus AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
4604 SMLoc StartLoc = getLoc();
4605
4606 MCRegister RegNum;
4607 ParseStatus Res = tryParseScalarRegister(RegNum);
4608 if (!Res.isSuccess())
4609 return Res;
4610
4611 if (!parseOptionalToken(AsmToken::Comma)) {
4612 Operands.push_back(AArch64Operand::CreateReg(
4613 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
4614 return ParseStatus::Success;
4615 }
4616
4617 parseOptionalToken(AsmToken::Hash);
4618
4619 if (getTok().isNot(AsmToken::Integer))
4620 return Error(getLoc(), "index must be absent or #0");
4621
4622 const MCExpr *ImmVal;
4623 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
4624 cast<MCConstantExpr>(ImmVal)->getValue() != 0)
4625 return Error(getLoc(), "index must be absent or #0");
4626
4627 Operands.push_back(AArch64Operand::CreateReg(
4628 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
4629 return ParseStatus::Success;
4630}
4631
4632ParseStatus AArch64AsmParser::tryParseZTOperand(OperandVector &Operands) {
4633 SMLoc StartLoc = getLoc();
4634 const AsmToken &Tok = getTok();
4635 std::string Name = Tok.getString().lower();
4636
4637 unsigned RegNum = matchRegisterNameAlias(Name, RegKind::LookupTable);
4638
4639 if (RegNum == 0)
4640 return ParseStatus::NoMatch;
4641
4642 Operands.push_back(AArch64Operand::CreateReg(
4643 RegNum, RegKind::LookupTable, StartLoc, getLoc(), getContext()));
4644 Lex(); // Eat register.
4645
4646 // Check if register is followed by an index
4647 if (parseOptionalToken(AsmToken::LBrac)) {
4648 Operands.push_back(
4649 AArch64Operand::CreateToken("[", getLoc(), getContext()));
4650 const MCExpr *ImmVal;
4651 if (getParser().parseExpression(ImmVal))
4652 return ParseStatus::NoMatch;
4653 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4654 if (!MCE)
4655 return TokError("immediate value expected for vector index");
4656 Operands.push_back(AArch64Operand::CreateImm(
4657 MCConstantExpr::create(MCE->getValue(), getContext()), StartLoc,
4658 getLoc(), getContext()));
4659 if (parseOptionalToken(AsmToken::Comma))
4660 if (parseOptionalMulOperand(Operands))
4661 return ParseStatus::Failure;
4662 if (parseToken(AsmToken::RBrac, "']' expected"))
4663 return ParseStatus::Failure;
4664 Operands.push_back(
4665 AArch64Operand::CreateToken("]", getLoc(), getContext()));
4666 }
4667 return ParseStatus::Success;
4668}
4669
4670template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
4671ParseStatus AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
4672 SMLoc StartLoc = getLoc();
4673
4674 MCRegister RegNum;
4675 ParseStatus Res = tryParseScalarRegister(RegNum);
4676 if (!Res.isSuccess())
4677 return Res;
4678
4679 // No shift/extend is the default.
4680 if (!ParseShiftExtend || getTok().isNot(AsmToken::Comma)) {
4681 Operands.push_back(AArch64Operand::CreateReg(
4682 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
4683 return ParseStatus::Success;
4684 }
4685
4686 // Eat the comma
4687 Lex();
4688
4689 // Match the shift
4691 Res = tryParseOptionalShiftExtend(ExtOpnd);
4692 if (!Res.isSuccess())
4693 return Res;
4694
4695 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
4696 Operands.push_back(AArch64Operand::CreateReg(
4697 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
4698 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
4699 Ext->hasShiftExtendAmount()));
4700
4701 return ParseStatus::Success;
4702}
4703
4704bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
4705 MCAsmParser &Parser = getParser();
4706
4707 // Some SVE instructions have a decoration after the immediate, i.e.
4708 // "mul vl". We parse them here and add tokens, which must be present in the
4709 // asm string in the tablegen instruction.
4710 bool NextIsVL =
4711 Parser.getLexer().peekTok().getString().equals_insensitive("vl");
4712 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
4713 if (!getTok().getString().equals_insensitive("mul") ||
4714 !(NextIsVL || NextIsHash))
4715 return true;
4716
4717 Operands.push_back(
4718 AArch64Operand::CreateToken("mul", getLoc(), getContext()));
4719 Lex(); // Eat the "mul"
4720
4721 if (NextIsVL) {
4722 Operands.push_back(
4723 AArch64Operand::CreateToken("vl", getLoc(), getContext()));
4724 Lex(); // Eat the "vl"
4725 return false;
4726 }
4727
4728 if (NextIsHash) {
4729 Lex(); // Eat the #
4730 SMLoc S = getLoc();
4731
4732 // Parse immediate operand.
4733 const MCExpr *ImmVal;
4734 if (!Parser.parseExpression(ImmVal))
4735 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
4736 Operands.push_back(AArch64Operand::CreateImm(
4737 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
4738 getContext()));
4739 return false;
4740 }
4741 }
4742
4743 return Error(getLoc(), "expected 'vl' or '#<imm>'");
4744}
4745
4746bool AArch64AsmParser::parseOptionalVGOperand(OperandVector &Operands,
4747 StringRef &VecGroup) {
4748 MCAsmParser &Parser = getParser();
4749 auto Tok = Parser.getTok();
4750 if (Tok.isNot(AsmToken::Identifier))
4751 return true;
4752
4754 .Case("vgx2", "vgx2")
4755 .Case("vgx4", "vgx4")
4756 .Default("");
4757
4758 if (VG.empty())
4759 return true;
4760
4761 VecGroup = VG;
4762 Parser.Lex(); // Eat vgx[2|4]
4763 return false;
4764}
4765
4766bool AArch64AsmParser::parseKeywordOperand(OperandVector &Operands) {
4767 auto Tok = getTok();
4768 if (Tok.isNot(AsmToken::Identifier))
4769 return true;
4770
4771 auto Keyword = Tok.getString();
4773 .Case("sm", "sm")
4774 .Case("za", "za")
4775 .Default(Keyword);
4776 Operands.push_back(
4777 AArch64Operand::CreateToken(Keyword, Tok.getLoc(), getContext()));
4778
4779 Lex();
4780 return false;
4781}
4782
4783/// parseOperand - Parse a arm instruction operand. For now this parses the
4784/// operand regardless of the mnemonic.
4785bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
4786 bool invertCondCode) {
4787 MCAsmParser &Parser = getParser();
4788
4789 ParseStatus ResTy =
4790 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
4791
4792 // Check if the current operand has a custom associated parser, if so, try to
4793 // custom parse the operand, or fallback to the general approach.
4794 if (ResTy.isSuccess())
4795 return false;
4796 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4797 // there was a match, but an error occurred, in which case, just return that
4798 // the operand parsing failed.
4799 if (ResTy.isFailure())
4800 return true;
4801
4802 // Nothing custom, so do general case parsing.
4803 SMLoc S, E;
4804 auto parseOptionalShiftExtend = [&](AsmToken SavedTok) {
4805 if (parseOptionalToken(AsmToken::Comma)) {
4806 ParseStatus Res = tryParseOptionalShiftExtend(Operands);
4807 if (!Res.isNoMatch())
4808 return Res.isFailure();
4809 getLexer().UnLex(SavedTok);
4810 }
4811 return false;
4812 };
4813 switch (getLexer().getKind()) {
4814 default: {
4815 SMLoc S = getLoc();
4816 const MCExpr *Expr;
4817 if (parseSymbolicImmVal(Expr))
4818 return Error(S, "invalid operand");
4819
4820 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
4821 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
4822 return parseOptionalShiftExtend(getTok());
4823 }
4824 case AsmToken::LBrac: {
4825 Operands.push_back(
4826 AArch64Operand::CreateToken("[", getLoc(), getContext()));
4827 Lex(); // Eat '['
4828
4829 // There's no comma after a '[', so we can parse the next operand
4830 // immediately.
4831 return parseOperand(Operands, false, false);
4832 }
4833 case AsmToken::LCurly: {
4834 if (!parseNeonVectorList(Operands))
4835 return false;
4836
4837 Operands.push_back(
4838 AArch64Operand::CreateToken("{", getLoc(), getContext()));
4839 Lex(); // Eat '{'
4840
4841 // There's no comma after a '{', so we can parse the next operand
4842 // immediately.
4843 return parseOperand(Operands, false, false);
4844 }
4845 case AsmToken::Identifier: {
4846 // See if this is a "VG" decoration used by SME instructions.
4847 StringRef VecGroup;
4848 if (!parseOptionalVGOperand(Operands, VecGroup)) {
4849 Operands.push_back(
4850 AArch64Operand::CreateToken(VecGroup, getLoc(), getContext()));
4851 return false;
4852 }
4853 // If we're expecting a Condition Code operand, then just parse that.
4854 if (isCondCode)
4855 return parseCondCode(Operands, invertCondCode);
4856
4857 // If it's a register name, parse it.
4858 if (!parseRegister(Operands)) {
4859 // Parse an optional shift/extend modifier.
4860 AsmToken SavedTok = getTok();
4861 if (parseOptionalToken(AsmToken::Comma)) {
4862 // The operand after the register may be a label (e.g. ADR/ADRP). Check
4863 // such cases and don't report an error when <label> happens to match a
4864 // shift/extend modifier.
4865 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic,
4866 /*ParseForAllFeatures=*/true);
4867 if (!Res.isNoMatch())
4868 return Res.isFailure();
4869 Res = tryParseOptionalShiftExtend(Operands);
4870 if (!Res.isNoMatch())
4871 return Res.isFailure();
4872 getLexer().UnLex(SavedTok);
4873 }
4874 return false;
4875 }
4876
4877 // See if this is a "mul vl" decoration or "mul #<int>" operand used
4878 // by SVE instructions.
4879 if (!parseOptionalMulOperand(Operands))
4880 return false;
4881
4882 // If this is a two-word mnemonic, parse its special keyword
4883 // operand as an identifier.
4884 if (Mnemonic == "brb" || Mnemonic == "smstart" || Mnemonic == "smstop" ||
4885 Mnemonic == "gcsb")
4886 return parseKeywordOperand(Operands);
4887
4888 // This was not a register so parse other operands that start with an
4889 // identifier (like labels) as expressions and create them as immediates.
4890 const MCExpr *IdVal;
4891 S = getLoc();
4892 if (getParser().parseExpression(IdVal))
4893 return true;
4894 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
4895 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
4896 return false;
4897 }
4898 case AsmToken::Integer:
4899 case AsmToken::Real:
4900 case AsmToken::Hash: {
4901 // #42 -> immediate.
4902 S = getLoc();
4903
4904 parseOptionalToken(AsmToken::Hash);
4905
4906 // Parse a negative sign
4907 bool isNegative = false;
4908 if (getTok().is(AsmToken::Minus)) {
4909 isNegative = true;
4910 // We need to consume this token only when we have a Real, otherwise
4911 // we let parseSymbolicImmVal take care of it
4912 if (Parser.getLexer().peekTok().is(AsmToken::Real))
4913 Lex();
4914 }
4915
4916 // The only Real that should come through here is a literal #0.0 for
4917 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
4918 // so convert the value.
4919 const AsmToken &Tok = getTok();
4920 if (Tok.is(AsmToken::Real)) {
4921 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
4922 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4923 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
4924 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
4925 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
4926 return TokError("unexpected floating point literal");
4927 else if (IntVal != 0 || isNegative)
4928 return TokError("expected floating-point constant #0.0");
4929 Lex(); // Eat the token.
4930
4931 Operands.push_back(AArch64Operand::CreateToken("#0", S, getContext()));
4932 Operands.push_back(AArch64Operand::CreateToken(".0", S, getContext()));
4933 return false;
4934 }
4935
4936 const MCExpr *ImmVal;
4937 if (parseSymbolicImmVal(ImmVal))
4938 return true;
4939
4940 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
4941 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
4942
4943 // Parse an optional shift/extend modifier.
4944 return parseOptionalShiftExtend(Tok);
4945 }
4946 case AsmToken::Equal: {
4947 SMLoc Loc = getLoc();
4948 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
4949 return TokError("unexpected token in operand");
4950 Lex(); // Eat '='
4951 const MCExpr *SubExprVal;
4952 if (getParser().parseExpression(SubExprVal))
4953 return true;
4954
4955 if (Operands.size() < 2 ||
4956 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
4957 return Error(Loc, "Only valid when first operand is register");
4958
4959 bool IsXReg =
4960 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4961 Operands[1]->getReg());
4962
4963 MCContext& Ctx = getContext();
4964 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
4965 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
4966 if (isa<MCConstantExpr>(SubExprVal)) {
4967 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
4968 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
4969 while (Imm > 0xFFFF && llvm::countr_zero(Imm) >= 16) {
4970 ShiftAmt += 16;
4971 Imm >>= 16;
4972 }
4973 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
4974 Operands[0] = AArch64Operand::CreateToken("movz", Loc, Ctx);
4975 Operands.push_back(AArch64Operand::CreateImm(
4976 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
4977 if (ShiftAmt)
4978 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
4979 ShiftAmt, true, S, E, Ctx));
4980 return false;
4981 }
4982 APInt Simm = APInt(64, Imm << ShiftAmt);
4983 // check if the immediate is an unsigned or signed 32-bit int for W regs
4984 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
4985 return Error(Loc, "Immediate too large for register");
4986 }
4987 // If it is a label or an imm that cannot fit in a movz, put it into CP.
4988 const MCExpr *CPLoc =
4989 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
4990 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
4991 return false;
4992 }
4993 }
4994}
4995
4996bool AArch64AsmParser::parseImmExpr(int64_t &Out) {
4997 const MCExpr *Expr = nullptr;
4998 SMLoc L = getLoc();
4999 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5000 return true;
5001 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
5002 if (check(!Value, L, "expected constant expression"))
5003 return true;
5004 Out = Value->getValue();
5005 return false;
5006}
5007
5008bool AArch64AsmParser::parseComma() {
5009 if (check(getTok().isNot(AsmToken::Comma), getLoc(), "expected comma"))
5010 return true;
5011 // Eat the comma
5012 Lex();
5013 return false;
5014}
5015
5016bool AArch64AsmParser::parseRegisterInRange(unsigned &Out, unsigned Base,
5017 unsigned First, unsigned Last) {
5019 SMLoc Start, End;
5020 if (check(parseRegister(Reg, Start, End), getLoc(), "expected register"))
5021 return true;
5022
5023 // Special handling for FP and LR; they aren't linearly after x28 in
5024 // the registers enum.
5025 unsigned RangeEnd = Last;
5026 if (Base == AArch64::X0) {
5027 if (Last == AArch64::FP) {
5028 RangeEnd = AArch64::X28;
5029 if (Reg == AArch64::FP) {
5030 Out = 29;
5031 return false;
5032 }
5033 }
5034 if (Last == AArch64::LR) {
5035 RangeEnd = AArch64::X28;
5036 if (Reg == AArch64::FP) {
5037 Out = 29;
5038 return false;
5039 } else if (Reg == AArch64::LR) {
5040 Out = 30;
5041 return false;
5042 }
5043 }
5044 }
5045
5046 if (check(Reg < First || Reg > RangeEnd, Start,
5047 Twine("expected register in range ") +
5050 return true;
5051 Out = Reg - Base;
5052 return false;
5053}
5054
5055bool AArch64AsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
5056 const MCParsedAsmOperand &Op2) const {
5057 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
5058 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
5059
5060 if (AOp1.isVectorList() && AOp2.isVectorList())
5061 return AOp1.getVectorListCount() == AOp2.getVectorListCount() &&
5062 AOp1.getVectorListStart() == AOp2.getVectorListStart() &&
5063 AOp1.getVectorListStride() == AOp2.getVectorListStride();
5064
5065 if (!AOp1.isReg() || !AOp2.isReg())
5066 return false;
5067
5068 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
5069 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
5070 return MCTargetAsmParser::areEqualRegs(Op1, Op2);
5071
5072 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
5073 "Testing equality of non-scalar registers not supported");
5074
5075 // Check if a registers match their sub/super register classes.
5076 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
5077 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
5078 if (AOp1.getRegEqualityTy() == EqualsSubReg)
5079 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
5080 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
5081 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
5082 if (AOp2.getRegEqualityTy() == EqualsSubReg)
5083 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
5084
5085 return false;
5086}
5087
5088/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
5089/// operands.
5090bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
5091 StringRef Name, SMLoc NameLoc,
5094 .Case("beq", "b.eq")
5095 .Case("bne", "b.ne")
5096 .Case("bhs", "b.hs")
5097 .Case("bcs", "b.cs")
5098 .Case("blo", "b.lo")
5099 .Case("bcc", "b.cc")
5100 .Case("bmi", "b.mi")
5101 .Case("bpl", "b.pl")
5102 .Case("bvs", "b.vs")
5103 .Case("bvc", "b.vc")
5104 .Case("bhi", "b.hi")
5105 .Case("bls", "b.ls")
5106 .Case("bge", "b.ge")
5107 .Case("blt", "b.lt")
5108 .Case("bgt", "b.gt")
5109 .Case("ble", "b.le")
5110 .Case("bal", "b.al")
5111 .Case("bnv", "b.nv")
5112 .Default(Name);
5113
5114 // First check for the AArch64-specific .req directive.
5115 if (getTok().is(AsmToken::Identifier) &&
5116 getTok().getIdentifier().lower() == ".req") {
5117 parseDirectiveReq(Name, NameLoc);
5118 // We always return 'error' for this, as we're done with this
5119 // statement and don't need to match the 'instruction."
5120 return true;
5121 }
5122
5123 // Create the leading tokens for the mnemonic, split by '.' characters.
5124 size_t Start = 0, Next = Name.find('.');
5125 StringRef Head = Name.slice(Start, Next);
5126
5127 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
5128 // the SYS instruction.
5129 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
5130 Head == "cfp" || Head == "dvp" || Head == "cpp" || Head == "cosp")
5131 return parseSysAlias(Head, NameLoc, Operands);
5132
5133 // TLBIP instructions are aliases for the SYSP instruction.
5134 if (Head == "tlbip")
5135 return parseSyspAlias(Head, NameLoc, Operands);
5136
5137 Operands.push_back(AArch64Operand::CreateToken(Head, NameLoc, getContext()));
5138 Mnemonic = Head;
5139
5140 // Handle condition codes for a branch mnemonic
5141 if ((Head == "b" || Head == "bc") && Next != StringRef::npos) {
5142 Start = Next;
5143 Next = Name.find('.', Start + 1);
5144 Head = Name.slice(Start + 1, Next);
5145
5146 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
5147 (Head.data() - Name.data()));
5148 std::string Suggestion;
5149 AArch64CC::CondCode CC = parseCondCodeString(Head, Suggestion);
5150 if (CC == AArch64CC::Invalid) {
5151 std::string Msg = "invalid condition code";
5152 if (!Suggestion.empty())
5153 Msg += ", did you mean " + Suggestion + "?";
5154 return Error(SuffixLoc, Msg);
5155 }
5156 Operands.push_back(AArch64Operand::CreateToken(".", SuffixLoc, getContext(),
5157 /*IsSuffix=*/true));
5158 Operands.push_back(
5159 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
5160 }
5161
5162 // Add the remaining tokens in the mnemonic.
5163 while (Next != StringRef::npos) {
5164 Start = Next;
5165 Next = Name.find('.', Start + 1);
5166 Head = Name.slice(Start, Next);
5167 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
5168 (Head.data() - Name.data()) + 1);
5169 Operands.push_back(AArch64Operand::CreateToken(
5170 Head, SuffixLoc, getContext(), /*IsSuffix=*/true));
5171 }
5172
5173 // Conditional compare instructions have a Condition Code operand, which needs
5174 // to be parsed and an immediate operand created.
5175 bool condCodeFourthOperand =
5176 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
5177 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
5178 Head == "csinc" || Head == "csinv" || Head == "csneg");
5179
5180 // These instructions are aliases to some of the conditional select
5181 // instructions. However, the condition code is inverted in the aliased
5182 // instruction.
5183 //
5184 // FIXME: Is this the correct way to handle these? Or should the parser
5185 // generate the aliased instructions directly?
5186 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
5187 bool condCodeThirdOperand =
5188 (Head == "cinc" || Head == "cinv" || Head == "cneg");
5189
5190 // Read the remaining operands.
5191 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5192
5193 unsigned N = 1;
5194 do {
5195 // Parse and remember the operand.
5196 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
5197 (N == 3 && condCodeThirdOperand) ||
5198 (N == 2 && condCodeSecondOperand),
5199 condCodeSecondOperand || condCodeThirdOperand)) {
5200 return true;
5201 }
5202
5203 // After successfully parsing some operands there are three special cases
5204 // to consider (i.e. notional operands not separated by commas). Two are
5205 // due to memory specifiers:
5206 // + An RBrac will end an address for load/store/prefetch
5207 // + An '!' will indicate a pre-indexed operation.
5208 //
5209 // And a further case is '}', which ends a group of tokens specifying the
5210 // SME accumulator array 'ZA' or tile vector, i.e.
5211 //
5212 // '{ ZA }' or '{ <ZAt><HV>.<BHSDQ>[<Wv>, #<imm>] }'
5213 //
5214 // It's someone else's responsibility to make sure these tokens are sane
5215 // in the given context!
5216
5217 if (parseOptionalToken(AsmToken::RBrac))
5218 Operands.push_back(
5219 AArch64Operand::CreateToken("]", getLoc(), getContext()));
5220 if (parseOptionalToken(AsmToken::Exclaim))
5221 Operands.push_back(
5222 AArch64Operand::CreateToken("!", getLoc(), getContext()));
5223 if (parseOptionalToken(AsmToken::RCurly))
5224 Operands.push_back(
5225 AArch64Operand::CreateToken("}", getLoc(), getContext()));
5226
5227 ++N;
5228 } while (parseOptionalToken(AsmToken::Comma));
5229 }
5230
5231 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
5232 return true;
5233
5234 return false;
5235}
5236
5237static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
5238 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
5239 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
5240 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
5241 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
5242 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
5243 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
5244 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
5245}
5246
5247// FIXME: This entire function is a giant hack to provide us with decent
5248// operand range validation/diagnostics until TableGen/MC can be extended
5249// to support autogeneration of this kind of validation.
5250bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
5252 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5253 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
5254
5255 // A prefix only applies to the instruction following it. Here we extract
5256 // prefix information for the next instruction before validating the current
5257 // one so that in the case of failure we don't erronously continue using the
5258 // current prefix.
5259 PrefixInfo Prefix = NextPrefix;
5260 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
5261
5262 // Before validating the instruction in isolation we run through the rules
5263 // applicable when it follows a prefix instruction.
5264 // NOTE: brk & hlt can be prefixed but require no additional validation.
5265 if (Prefix.isActive() &&
5266 (Inst.getOpcode() != AArch64::BRK) &&
5267 (Inst.getOpcode() != AArch64::HLT)) {
5268
5269 // Prefixed intructions must have a destructive operand.
5272 return Error(IDLoc, "instruction is unpredictable when following a"
5273 " movprfx, suggest replacing movprfx with mov");
5274
5275 // Destination operands must match.
5276 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
5277 return Error(Loc[0], "instruction is unpredictable when following a"
5278 " movprfx writing to a different destination");
5279
5280 // Destination operand must not be used in any other location.
5281 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
5282 if (Inst.getOperand(i).isReg() &&
5283 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
5284 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
5285 return Error(Loc[0], "instruction is unpredictable when following a"
5286 " movprfx and destination also used as non-destructive"
5287 " source");
5288 }
5289
5290 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
5291 if (Prefix.isPredicated()) {
5292 int PgIdx = -1;
5293
5294 // Find the instructions general predicate.
5295 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
5296 if (Inst.getOperand(i).isReg() &&
5297 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
5298 PgIdx = i;
5299 break;
5300 }
5301
5302 // Instruction must be predicated if the movprfx is predicated.
5303 if (PgIdx == -1 ||
5305 return Error(IDLoc, "instruction is unpredictable when following a"
5306 " predicated movprfx, suggest using unpredicated movprfx");
5307
5308 // Instruction must use same general predicate as the movprfx.
5309 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
5310 return Error(IDLoc, "instruction is unpredictable when following a"
5311 " predicated movprfx using a different general predicate");
5312
5313 // Instruction element type must match the movprfx.
5314 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
5315 return Error(IDLoc, "instruction is unpredictable when following a"
5316 " predicated movprfx with a different element size");
5317 }
5318 }
5319
5320 // On ARM64EC, only valid registers may be used. Warn against using
5321 // explicitly disallowed registers.
5322 if (IsWindowsArm64EC) {
5323 for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
5324 if (Inst.getOperand(i).isReg()) {
5325 unsigned Reg = Inst.getOperand(i).getReg();
5326 // At this point, vector registers are matched to their
5327 // appropriately sized alias.
5328 if ((Reg == AArch64::W13 || Reg == AArch64::X13) ||
5329 (Reg == AArch64::W14 || Reg == AArch64::X14) ||
5330 (Reg == AArch64::W23 || Reg == AArch64::X23) ||
5331 (Reg == AArch64::W24 || Reg == AArch64::X24) ||
5332 (Reg == AArch64::W28 || Reg == AArch64::X28) ||
5333 (Reg >= AArch64::Q16 && Reg <= AArch64::Q31) ||
5334 (Reg >= AArch64::D16 && Reg <= AArch64::D31) ||
5335 (Reg >= AArch64::S16 && Reg <= AArch64::S31) ||
5336 (Reg >= AArch64::H16 && Reg <= AArch64::H31) ||
5337 (Reg >= AArch64::B16 && Reg <= AArch64::B31)) {
5338 Warning(IDLoc, "register " + Twine(RI->getName(Reg)) +
5339 " is disallowed on ARM64EC.");
5340 }
5341 }
5342 }
5343 }
5344
5345 // Check for indexed addressing modes w/ the base register being the
5346 // same as a destination/source register or pair load where
5347 // the Rt == Rt2. All of those are undefined behaviour.
5348 switch (Inst.getOpcode()) {
5349 case AArch64::LDPSWpre:
5350 case AArch64::LDPWpost:
5351 case AArch64::LDPWpre:
5352 case AArch64::LDPXpost:
5353 case AArch64::LDPXpre: {
5354 unsigned Rt = Inst.getOperand(1).getReg();
5355 unsigned Rt2 = Inst.getOperand(2).getReg();
5356 unsigned Rn = Inst.getOperand(3).getReg();
5357 if (RI->isSubRegisterEq(Rn, Rt))
5358 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
5359 "is also a destination");
5360 if (RI->isSubRegisterEq(Rn, Rt2))
5361 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
5362 "is also a destination");
5363 [[fallthrough]];
5364 }
5365 case AArch64::LDR_ZA:
5366 case AArch64::STR_ZA: {
5367 if (Inst.getOperand(2).isImm() && Inst.getOperand(4).isImm() &&
5368 Inst.getOperand(2).getImm() != Inst.getOperand(4).getImm())
5369 return Error(Loc[1],
5370 "unpredictable instruction, immediate and offset mismatch.");
5371 break;
5372 }
5373 case AArch64::LDPDi:
5374 case AArch64::LDPQi:
5375 case AArch64::LDPSi:
5376 case AArch64::LDPSWi:
5377 case AArch64::LDPWi:
5378 case AArch64::LDPXi: {
5379 unsigned Rt = Inst.getOperand(0).getReg();
5380 unsigned Rt2 = Inst.getOperand(1).getReg();
5381 if (Rt == Rt2)
5382 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
5383 break;
5384 }
5385 case AArch64::LDPDpost:
5386 case AArch64::LDPDpre:
5387 case AArch64::LDPQpost:
5388 case AArch64::LDPQpre:
5389 case AArch64::LDPSpost:
5390 case AArch64::LDPSpre:
5391 case AArch64::LDPSWpost: {
5392 unsigned Rt = Inst.getOperand(1).getReg();
5393 unsigned Rt2 = Inst.getOperand(2).getReg();
5394 if (Rt == Rt2)
5395 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
5396 break;
5397 }
5398 case AArch64::STPDpost:
5399 case AArch64::STPDpre:
5400 case AArch64::STPQpost:
5401 case AArch64::STPQpre:
5402 case AArch64::STPSpost:
5403 case AArch64::STPSpre:
5404 case AArch64::STPWpost:
5405 case AArch64::STPWpre:
5406 case AArch64::STPXpost:
5407 case AArch64::STPXpre: {
5408 unsigned Rt = Inst.getOperand(1).getReg();
5409 unsigned Rt2 = Inst.getOperand(2).getReg();
5410 unsigned Rn = Inst.getOperand(3).getReg();
5411 if (RI->isSubRegisterEq(Rn, Rt))
5412 return Error(Loc[0], "unpredictable STP instruction, writeback base "
5413 "is also a source");
5414 if (RI->isSubRegisterEq(Rn, Rt2))
5415 return Error(Loc[1], "unpredictable STP instruction, writeback base "
5416 "is also a source");
5417 break;
5418 }
5419 case AArch64::LDRBBpre:
5420 case AArch64::LDRBpre:
5421 case AArch64::LDRHHpre:
5422 case AArch64::LDRHpre:
5423 case AArch64::LDRSBWpre:
5424 case AArch64::LDRSBXpre:
5425 case AArch64::LDRSHWpre:
5426 case AArch64::LDRSHXpre:
5427 case AArch64::LDRSWpre:
5428 case AArch64::LDRWpre:
5429 case AArch64::LDRXpre:
5430 case AArch64::LDRBBpost:
5431 case AArch64::LDRBpost:
5432 case AArch64::LDRHHpost:
5433 case AArch64::LDRHpost:
5434 case AArch64::LDRSBWpost:
5435 case AArch64::LDRSBXpost:
5436 case AArch64::LDRSHWpost:
5437 case AArch64::LDRSHXpost:
5438 case AArch64::LDRSWpost:
5439 case AArch64::LDRWpost:
5440 case AArch64::LDRXpost: {
5441 unsigned Rt = Inst.getOperand(1).getReg();
5442 unsigned Rn = Inst.getOperand(2).getReg();
5443 if (RI->isSubRegisterEq(Rn, Rt))
5444 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
5445 "is also a source");
5446 break;
5447 }
5448 case AArch64::STRBBpost:
5449 case AArch64::STRBpost:
5450 case AArch64::STRHHpost:
5451 case AArch64::STRHpost:
5452 case AArch64::STRWpost:
5453 case AArch64::STRXpost:
5454 case AArch64::STRBBpre:
5455 case AArch64::STRBpre:
5456 case AArch64::STRHHpre:
5457 case AArch64::STRHpre:
5458 case AArch64::STRWpre:
5459 case AArch64::STRXpre: {
5460 unsigned Rt = Inst.getOperand(1).getReg();
5461 unsigned Rn = Inst.getOperand(2).getReg();
5462 if (RI->isSubRegisterEq(Rn, Rt))
5463 return Error(Loc[0], "unpredictable STR instruction, writeback base "
5464 "is also a source");
5465 break;
5466 }
5467 case AArch64::STXRB:
5468 case AArch64::STXRH:
5469 case AArch64::STXRW:
5470 case AArch64::STXRX:
5471 case AArch64::STLXRB:
5472 case AArch64::STLXRH:
5473 case AArch64::STLXRW:
5474 case AArch64::STLXRX: {
5475 unsigned Rs = Inst.getOperand(0).getReg();
5476 unsigned Rt = Inst.getOperand(1).getReg();
5477 unsigned Rn = Inst.getOperand(2).getReg();
5478 if (RI->isSubRegisterEq(Rt, Rs) ||
5479 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
5480 return Error(Loc[0],
5481 "unpredictable STXR instruction, status is also a source");
5482 break;
5483 }
5484 case AArch64::STXPW:
5485 case AArch64::STXPX:
5486 case AArch64::STLXPW:
5487 case AArch64::STLXPX: {
5488 unsigned Rs = Inst.getOperand(0).getReg();
5489 unsigned Rt1 = Inst.getOperand(1).getReg();
5490 unsigned Rt2 = Inst.getOperand(2).getReg();
5491 unsigned Rn = Inst.getOperand(3).getReg();
5492 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
5493 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
5494 return Error(Loc[0],
5495 "unpredictable STXP instruction, status is also a source");
5496 break;
5497 }
5498 case AArch64::LDRABwriteback:
5499 case AArch64::LDRAAwriteback: {
5500 unsigned Xt = Inst.getOperand(0).getReg();
5501 unsigned Xn = Inst.getOperand(1).getReg();
5502 if (Xt == Xn)
5503 return Error(Loc[0],
5504 "unpredictable LDRA instruction, writeback base"
5505 " is also a destination");
5506 break;
5507 }
5508 }
5509
5510 // Check v8.8-A memops instructions.
5511 switch (Inst.getOpcode()) {
5512 case AArch64::CPYFP:
5513 case AArch64::CPYFPWN:
5514 case AArch64::CPYFPRN:
5515 case AArch64::CPYFPN:
5516 case AArch64::CPYFPWT:
5517 case AArch64::CPYFPWTWN:
5518 case AArch64::CPYFPWTRN:
5519 case AArch64::CPYFPWTN:
5520 case AArch64::CPYFPRT:
5521 case AArch64::CPYFPRTWN:
5522 case AArch64::CPYFPRTRN:
5523 case AArch64::CPYFPRTN:
5524 case AArch64::CPYFPT:
5525 case AArch64::CPYFPTWN:
5526 case AArch64::CPYFPTRN:
5527 case AArch64::CPYFPTN:
5528 case AArch64::CPYFM:
5529 case AArch64::CPYFMWN:
5530 case AArch64::CPYFMRN:
5531 case AArch64::CPYFMN:
5532 case AArch64::CPYFMWT:
5533 case AArch64::CPYFMWTWN:
5534 case AArch64::CPYFMWTRN:
5535 case AArch64::CPYFMWTN:
5536 case AArch64::CPYFMRT:
5537 case AArch64::CPYFMRTWN:
5538 case AArch64::CPYFMRTRN:
5539 case AArch64::CPYFMRTN:
5540 case AArch64::CPYFMT:
5541 case AArch64::CPYFMTWN:
5542 case AArch64::CPYFMTRN:
5543 case AArch64::CPYFMTN:
5544 case AArch64::CPYFE:
5545 case AArch64::CPYFEWN:
5546 case AArch64::CPYFERN:
5547 case AArch64::CPYFEN:
5548 case AArch64::CPYFEWT:
5549 case AArch64::CPYFEWTWN:
5550 case AArch64::CPYFEWTRN:
5551 case AArch64::CPYFEWTN:
5552 case AArch64::CPYFERT:
5553 case AArch64::CPYFERTWN:
5554 case AArch64::CPYFERTRN:
5555 case AArch64::CPYFERTN:
5556 case AArch64::CPYFET:
5557 case AArch64::CPYFETWN:
5558 case AArch64::CPYFETRN:
5559 case AArch64::CPYFETN:
5560 case AArch64::CPYP:
5561 case AArch64::CPYPWN:
5562 case AArch64::CPYPRN:
5563 case AArch64::CPYPN:
5564 case AArch64::CPYPWT:
5565 case AArch64::CPYPWTWN:
5566 case AArch64::CPYPWTRN:
5567 case AArch64::CPYPWTN:
5568 case AArch64::CPYPRT:
5569 case AArch64::CPYPRTWN:
5570 case AArch64::CPYPRTRN:
5571 case AArch64::CPYPRTN:
5572 case AArch64::CPYPT:
5573 case AArch64::CPYPTWN:
5574 case AArch64::CPYPTRN:
5575 case AArch64::CPYPTN:
5576 case AArch64::CPYM:
5577 case AArch64::CPYMWN:
5578 case AArch64::CPYMRN:
5579 case AArch64::CPYMN:
5580 case AArch64::CPYMWT:
5581 case AArch64::CPYMWTWN:
5582 case AArch64::CPYMWTRN:
5583 case AArch64::CPYMWTN:
5584 case AArch64::CPYMRT:
5585 case AArch64::CPYMRTWN:
5586 case AArch64::CPYMRTRN:
5587 case AArch64::CPYMRTN:
5588 case AArch64::CPYMT:
5589 case AArch64::CPYMTWN:
5590 case AArch64::CPYMTRN:
5591 case AArch64::CPYMTN:
5592 case AArch64::CPYE:
5593 case AArch64::CPYEWN:
5594 case AArch64::CPYERN:
5595 case AArch64::CPYEN:
5596 case AArch64::CPYEWT:
5597 case AArch64::CPYEWTWN:
5598 case AArch64::CPYEWTRN:
5599 case AArch64::CPYEWTN:
5600 case AArch64::CPYERT:
5601 case AArch64::CPYERTWN:
5602 case AArch64::CPYERTRN:
5603 case AArch64::CPYERTN:
5604 case AArch64::CPYET:
5605 case AArch64::CPYETWN:
5606 case AArch64::CPYETRN:
5607 case AArch64::CPYETN: {
5608 unsigned Xd_wb = Inst.getOperand(0).getReg();
5609 unsigned Xs_wb = Inst.getOperand(1).getReg();
5610 unsigned Xn_wb = Inst.getOperand(2).getReg();
5611 unsigned Xd = Inst.getOperand(3).getReg();
5612 unsigned Xs = Inst.getOperand(4).getReg();
5613 unsigned Xn = Inst.getOperand(5).getReg();
5614 if (Xd_wb != Xd)
5615 return Error(Loc[0],
5616 "invalid CPY instruction, Xd_wb and Xd do not match");
5617 if (Xs_wb != Xs)
5618 return Error(Loc[0],
5619 "invalid CPY instruction, Xs_wb and Xs do not match");
5620 if (Xn_wb != Xn)
5621 return Error(Loc[0],
5622 "invalid CPY instruction, Xn_wb and Xn do not match");
5623 if (Xd == Xs)
5624 return Error(Loc[0], "invalid CPY instruction, destination and source"
5625 " registers are the same");
5626 if (Xd == Xn)
5627 return Error(Loc[0], "invalid CPY instruction, destination and size"
5628 " registers are the same");
5629 if (Xs == Xn)
5630 return Error(Loc[0], "invalid CPY instruction, source and size"
5631 " registers are the same");
5632 break;
5633 }
5634 case AArch64::SETP:
5635 case AArch64::SETPT:
5636 case AArch64::SETPN:
5637 case AArch64::SETPTN:
5638 case AArch64::SETM:
5639 case AArch64::SETMT:
5640 case AArch64::SETMN:
5641 case AArch64::SETMTN:
5642 case AArch64::SETE:
5643 case AArch64::SETET:
5644 case AArch64::SETEN:
5645 case AArch64::SETETN:
5646 case AArch64::SETGP:
5647 case AArch64::SETGPT:
5648 case AArch64::SETGPN:
5649 case AArch64::SETGPTN:
5650 case AArch64::SETGM:
5651 case AArch64::SETGMT:
5652 case AArch64::SETGMN:
5653 case AArch64::SETGMTN:
5654 case AArch64::MOPSSETGE:
5655 case AArch64::MOPSSETGET:
5656 case AArch64::MOPSSETGEN:
5657 case AArch64::MOPSSETGETN: {
5658 unsigned Xd_wb = Inst.getOperand(0).getReg();
5659 unsigned Xn_wb = Inst.getOperand(1).getReg();
5660 unsigned Xd = Inst.getOperand(2).getReg();
5661 unsigned Xn = Inst.getOperand(3).getReg();
5662 unsigned Xm = Inst.getOperand(4).getReg();
5663 if (Xd_wb != Xd)
5664 return Error(Loc[0],
5665 "invalid SET instruction, Xd_wb and Xd do not match");
5666 if (Xn_wb != Xn)
5667 return Error(Loc[0],
5668 "invalid SET instruction, Xn_wb and Xn do not match");
5669 if (Xd == Xn)
5670 return Error(Loc[0], "invalid SET instruction, destination and size"
5671 " registers are the same");
5672 if (Xd == Xm)
5673 return Error(Loc[0], "invalid SET instruction, destination and source"
5674 " registers are the same");
5675 if (Xn == Xm)
5676 return Error(Loc[0], "invalid SET instruction, source and size"
5677 " registers are the same");
5678 break;
5679 }
5680 }
5681
5682 // Now check immediate ranges. Separate from the above as there is overlap
5683 // in the instructions being checked and this keeps the nested conditionals
5684 // to a minimum.
5685 switch (Inst.getOpcode()) {
5686 case AArch64::ADDSWri:
5687 case AArch64::ADDSXri:
5688 case AArch64::ADDWri:
5689 case AArch64::ADDXri:
5690 case AArch64::SUBSWri:
5691 case AArch64::SUBSXri:
5692 case AArch64::SUBWri:
5693 case AArch64::SUBXri: {
5694 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
5695 // some slight duplication here.
5696 if (Inst.getOperand(2).isExpr()) {
5697 const MCExpr *Expr = Inst.getOperand(2).getExpr();
5698 AArch64MCExpr::VariantKind ELFRefKind;
5699 MCSymbolRefExpr::VariantKind DarwinRefKind;
5700 int64_t Addend;
5701 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
5702
5703 // Only allow these with ADDXri.
5704 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
5705 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
5706 Inst.getOpcode() == AArch64::ADDXri)
5707 return false;
5708
5709 // Only allow these with ADDXri/ADDWri
5710 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
5711 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
5712 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
5713 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
5714 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
5715 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
5716 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
5717 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
5718 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
5719 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
5720 (Inst.getOpcode() == AArch64::ADDXri ||
5721 Inst.getOpcode() == AArch64::ADDWri))
5722 return false;
5723
5724 // Don't allow symbol refs in the immediate field otherwise
5725 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
5726 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
5727 // 'cmp w0, 'borked')
5728 return Error(Loc.back(), "invalid immediate expression");
5729 }
5730 // We don't validate more complex expressions here
5731 }
5732 return false;
5733 }
5734 default:
5735 return false;
5736 }
5737}
5738
5740 const FeatureBitset &FBS,
5741 unsigned VariantID = 0);
5742
5743bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
5746 switch (ErrCode) {
5747 case Match_InvalidTiedOperand: {
5748 auto &Op = static_cast<const AArch64Operand &>(*Operands[ErrorInfo]);
5749 if (Op.isVectorList())
5750 return Error(Loc, "operand must match destination register list");
5751
5752 assert(Op.isReg() && "Unexpected operand type");
5753 switch (Op.getRegEqualityTy()) {
5754 case RegConstraintEqualityTy::EqualsSubReg:
5755 return Error(Loc, "operand must be 64-bit form of destination register");
5756 case RegConstraintEqualityTy::EqualsSuperReg:
5757 return Error(Loc, "operand must be 32-bit form of destination register");
5758 case RegConstraintEqualityTy::EqualsReg:
5759 return Error(Loc, "operand must match destination register");
5760 }
5761 llvm_unreachable("Unknown RegConstraintEqualityTy");
5762 }
5763 case Match_MissingFeature:
5764 return Error(Loc,
5765 "instruction requires a CPU feature not currently enabled");
5766 case Match_InvalidOperand:
5767 return Error(Loc, "invalid operand for instruction");
5768 case Match_InvalidSuffix:
5769 return Error(Loc, "invalid type suffix for instruction");
5770 case Match_InvalidCondCode:
5771 return Error(Loc, "expected AArch64 condition code");
5772 case Match_AddSubRegExtendSmall:
5773 return Error(Loc,
5774 "expected '[su]xt[bhw]' with optional integer in range [0, 4]");
5775 case Match_AddSubRegExtendLarge:
5776 return Error(Loc,
5777 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
5778 case Match_AddSubSecondSource:
5779 return Error(Loc,
5780 "expected compatible register, symbol or integer in range [0, 4095]");
5781 case Match_LogicalSecondSource:
5782 return Error(Loc, "expected compatible register or logical immediate");
5783 case Match_InvalidMovImm32Shift:
5784 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
5785 case Match_InvalidMovImm64Shift:
5786 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
5787 case Match_AddSubRegShift32:
5788 return Error(Loc,
5789 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
5790 case Match_AddSubRegShift64:
5791 return Error(Loc,
5792 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
5793 case Match_InvalidFPImm:
5794 return Error(Loc,
5795 "expected compatible register or floating-point constant");
5796 case Match_InvalidMemoryIndexedSImm6:
5797 return Error(Loc, "index must be an integer in range [-32, 31].");
5798 case Match_InvalidMemoryIndexedSImm5:
5799 return Error(Loc, "index must be an integer in range [-16, 15].");
5800 case Match_InvalidMemoryIndexed1SImm4:
5801 return Error(Loc, "index must be an integer in range [-8, 7].");
5802 case Match_InvalidMemoryIndexed2SImm4:
5803 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
5804 case Match_InvalidMemoryIndexed3SImm4:
5805 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
5806 case Match_InvalidMemoryIndexed4SImm4:
5807 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
5808 case Match_InvalidMemoryIndexed16SImm4:
5809 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
5810 case Match_InvalidMemoryIndexed32SImm4:
5811 return Error(Loc, "index must be a multiple of 32 in range [-256, 224].");
5812 case Match_InvalidMemoryIndexed1SImm6:
5813 return Error(Loc, "index must be an integer in range [-32, 31].");
5814 case Match_InvalidMemoryIndexedSImm8:
5815 return Error(Loc, "index must be an integer in range [-128, 127].");
5816 case Match_InvalidMemoryIndexedSImm9:
5817 return Error(Loc, "index must be an integer in range [-256, 255].");
5818 case Match_InvalidMemoryIndexed16SImm9:
5819 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
5820 case Match_InvalidMemoryIndexed8SImm10:
5821 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
5822 case Match_InvalidMemoryIndexed4SImm7:
5823 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
5824 case Match_InvalidMemoryIndexed8SImm7:
5825 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
5826 case Match_InvalidMemoryIndexed16SImm7:
5827 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
5828 case Match_InvalidMemoryIndexed8UImm5:
5829 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
5830 case Match_InvalidMemoryIndexed8UImm3:
5831 return Error(Loc, "index must be a multiple of 8 in range [0, 56].");
5832 case Match_InvalidMemoryIndexed4UImm5:
5833 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
5834 case Match_InvalidMemoryIndexed2UImm5:
5835 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
5836 case Match_InvalidMemoryIndexed8UImm6:
5837 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
5838 case Match_InvalidMemoryIndexed16UImm6:
5839 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
5840 case Match_InvalidMemoryIndexed4UImm6:
5841 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
5842 case Match_InvalidMemoryIndexed2UImm6:
5843 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
5844 case Match_InvalidMemoryIndexed1UImm6:
5845 return Error(Loc, "index must be in range [0, 63].");
5846 case Match_InvalidMemoryWExtend8:
5847 return Error(Loc,
5848 "expected 'uxtw' or 'sxtw' with optional shift of #0");
5849 case Match_InvalidMemoryWExtend16:
5850 return Error(Loc,
5851 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
5852 case Match_InvalidMemoryWExtend32:
5853 return Error(Loc,
5854 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
5855 case Match_InvalidMemoryWExtend64:
5856 return Error(Loc,
5857 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
5858 case Match_InvalidMemoryWExtend128:
5859 return Error(Loc,
5860 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
5861 case Match_InvalidMemoryXExtend8:
5862 return Error(Loc,
5863 "expected 'lsl' or 'sxtx' with optional shift of #0");
5864 case Match_InvalidMemoryXExtend16:
5865 return Error(Loc,
5866 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
5867 case Match_InvalidMemoryXExtend32:
5868 return Error(Loc,
5869 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
5870 case Match_InvalidMemoryXExtend64:
5871 return Error(Loc,
5872 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
5873 case Match_InvalidMemoryXExtend128:
5874 return Error(Loc,
5875 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
5876 case Match_InvalidMemoryIndexed1:
5877 return Error(Loc, "index must be an integer in range [0, 4095].");
5878 case Match_InvalidMemoryIndexed2:
5879 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
5880 case Match_InvalidMemoryIndexed4:
5881 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
5882 case Match_InvalidMemoryIndexed8:
5883 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
5884 case Match_InvalidMemoryIndexed16:
5885 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
5886 case Match_InvalidImm0_0:
5887 return Error(Loc, "immediate must be 0.");
5888 case Match_InvalidImm0_1:
5889 return Error(Loc, "immediate must be an integer in range [0, 1].");
5890 case Match_InvalidImm0_3:
5891 return Error(Loc, "immediate must be an integer in range [0, 3].");
5892 case Match_InvalidImm0_7:
5893 return Error(Loc, "immediate must be an integer in range [0, 7].");
5894 case Match_InvalidImm0_15:
5895 return Error(Loc, "immediate must be an integer in range [0, 15].");
5896 case Match_InvalidImm0_31:
5897 return Error(Loc, "immediate must be an integer in range [0, 31].");
5898 case Match_InvalidImm0_63:
5899 return Error(Loc, "immediate must be an integer in range [0, 63].");
5900 case Match_InvalidImm0_127:
5901 return Error(Loc, "immediate must be an integer in range [0, 127].");
5902 case Match_InvalidImm0_255:
5903 return Error(Loc, "immediate must be an integer in range [0, 255].");
5904 case Match_InvalidImm0_65535:
5905 return Error(Loc, "immediate must be an integer in range [0, 65535].");
5906 case Match_InvalidImm1_8:
5907 return Error(Loc, "immediate must be an integer in range [1, 8].");
5908 case Match_InvalidImm1_16:
5909 return Error(Loc, "immediate must be an integer in range [1, 16].");
5910 case Match_InvalidImm1_32:
5911 return Error(Loc, "immediate must be an integer in range [1, 32].");
5912 case Match_InvalidImm1_64:
5913 return Error(Loc, "immediate must be an integer in range [1, 64].");
5914 case Match_InvalidMemoryIndexedRange2UImm0:
5915 return Error(Loc, "vector select offset must be the immediate range 0:1.");
5916 case Match_InvalidMemoryIndexedRange2UImm1:
5917 return Error(Loc, "vector select offset must be an immediate range of the "
5918 "form <immf>:<imml>, where the first "
5919 "immediate is a multiple of 2 in the range [0, 2], and "
5920 "the second immediate is immf + 1.");
5921 case Match_InvalidMemoryIndexedRange2UImm2:
5922 case Match_InvalidMemoryIndexedRange2UImm3:
5923 return Error(
5924 Loc,
5925 "vector select offset must be an immediate range of the form "
5926 "<immf>:<imml>, "
5927 "where the first immediate is a multiple of 2 in the range [0, 6] or "
5928 "[0, 14] "
5929 "depending on the instruction, and the second immediate is immf + 1.");
5930 case Match_InvalidMemoryIndexedRange4UImm0:
5931 return Error(Loc, "vector select offset must be the immediate range 0:3.");
5932 case Match_InvalidMemoryIndexedRange4UImm1:
5933 case Match_InvalidMemoryIndexedRange4UImm2:
5934 return Error(
5935 Loc,
5936 "vector select offset must be an immediate range of the form "
5937 "<immf>:<imml>, "
5938 "where the first immediate is a multiple of 4 in the range [0, 4] or "
5939 "[0, 12] "
5940 "depending on the instruction, and the second immediate is immf + 3.");
5941 case Match_InvalidSVEAddSubImm8:
5942 return Error(Loc, "immediate must be an integer in range [0, 255]"
5943 " with a shift amount of 0");
5944 case Match_InvalidSVEAddSubImm16:
5945 case Match_InvalidSVEAddSubImm32:
5946 case Match_InvalidSVEAddSubImm64:
5947 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
5948 "multiple of 256 in range [256, 65280]");
5949 case Match_InvalidSVECpyImm8:
5950 return Error(Loc, "immediate must be an integer in range [-128, 255]"
5951 " with a shift amount of 0");
5952 case Match_InvalidSVECpyImm16:
5953 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
5954 "multiple of 256 in range [-32768, 65280]");
5955 case Match_InvalidSVECpyImm32:
5956 case Match_InvalidSVECpyImm64:
5957 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
5958 "multiple of 256 in range [-32768, 32512]");
5959 case Match_InvalidIndexRange0_0:
5960 return Error(Loc, "expected lane specifier '[0]'");
5961 case Match_InvalidIndexRange1_1:
5962 return Error(Loc, "expected lane specifier '[1]'");
5963 case Match_InvalidIndexRange0_15:
5964 return Error(Loc, "vector lane must be an integer in range [0, 15].");
5965 case Match_InvalidIndexRange0_7:
5966 return Error(Loc, "vector lane must be an integer in range [0, 7].");
5967 case Match_InvalidIndexRange0_3:
5968 return Error(Loc, "vector lane must be an integer in range [0, 3].");
5969 case Match_InvalidIndexRange0_1:
5970 return Error(Loc, "vector lane must be an integer in range [0, 1].");
5971 case Match_InvalidSVEIndexRange0_63:
5972 return Error(Loc, "vector lane must be an integer in range [0, 63].");
5973 case Match_InvalidSVEIndexRange0_31:
5974 return Error(Loc, "vector lane must be an integer in range [0, 31].");
5975 case Match_InvalidSVEIndexRange0_15:
5976 return Error(Loc, "vector lane must be an integer in range [0, 15].");
5977 case Match_InvalidSVEIndexRange0_7:
5978 return Error(Loc, "vector lane must be an integer in range [0, 7].");
5979 case Match_InvalidSVEIndexRange0_3:
5980 return Error(Loc, "vector lane must be an integer in range [0, 3].");
5981 case Match_InvalidLabel:
5982 return Error(Loc, "expected label or encodable integer pc offset");
5983 case Match_MRS:
5984 return Error(Loc, "expected readable system register");
5985 case Match_MSR:
5986 case Match_InvalidSVCR:
5987 return Error(Loc, "expected writable system register or pstate");
5988 case Match_InvalidComplexRotationEven:
5989 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
5990 case Match_InvalidComplexRotationOdd:
5991 return Error(Loc, "complex rotation must be 90 or 270.");
5992 case Match_MnemonicFail: {
5993 std::string Suggestion = AArch64MnemonicSpellCheck(
5994 ((AArch64Operand &)*Operands[0]).getToken(),
5995 ComputeAvailableFeatures(STI->getFeatureBits()));
5996 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
5997 }
5998 case Match_InvalidGPR64shifted8:
5999 return Error(Loc, "register must be x0..x30 or xzr, without shift");
6000 case Match_InvalidGPR64shifted16:
6001 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
6002 case Match_InvalidGPR64shifted32:
6003 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
6004 case Match_InvalidGPR64shifted64:
6005 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
6006 case Match_InvalidGPR64shifted128:
6007 return Error(
6008 Loc, "register must be x0..x30 or xzr, with required shift 'lsl #4'");
6009 case Match_InvalidGPR64NoXZRshifted8:
6010 return Error(Loc, "register must be x0..x30 without shift");
6011 case Match_InvalidGPR64NoXZRshifted16:
6012 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
6013 case Match_InvalidGPR64NoXZRshifted32:
6014 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
6015 case Match_InvalidGPR64NoXZRshifted64:
6016 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
6017 case Match_InvalidGPR64NoXZRshifted128:
6018 return Error(Loc, "register must be x0..x30 with required shift 'lsl #4'");
6019 case Match_InvalidZPR32UXTW8:
6020 case Match_InvalidZPR32SXTW8:
6021 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
6022 case Match_InvalidZPR32UXTW16:
6023 case Match_InvalidZPR32SXTW16:
6024 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
6025 case Match_InvalidZPR32UXTW32:
6026 case Match_InvalidZPR32SXTW32:
6027 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
6028 case Match_InvalidZPR32UXTW64:
6029 case Match_InvalidZPR32SXTW64:
6030 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
6031 case Match_InvalidZPR64UXTW8:
6032 case Match_InvalidZPR64SXTW8:
6033 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
6034 case Match_InvalidZPR64UXTW16:
6035 case Match_InvalidZPR64SXTW16:
6036 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
6037 case Match_InvalidZPR64UXTW32:
6038 case Match_InvalidZPR64SXTW32:
6039 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
6040 case Match_InvalidZPR64UXTW64:
6041 case Match_InvalidZPR64SXTW64:
6042 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
6043 case Match_InvalidZPR32LSL8:
6044 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
6045 case Match_InvalidZPR32LSL16:
6046 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
6047 case Match_InvalidZPR32LSL32:
6048 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
6049 case Match_InvalidZPR32LSL64:
6050 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
6051 case Match_InvalidZPR64LSL8:
6052 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
6053 case Match_InvalidZPR64LSL16:
6054 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
6055 case Match_InvalidZPR64LSL32:
6056 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
6057 case Match_InvalidZPR64LSL64:
6058 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
6059 case Match_InvalidZPR0:
6060 return Error(Loc, "expected register without element width suffix");
6061 case Match_InvalidZPR8:
6062 case Match_InvalidZPR16:
6063 case Match_InvalidZPR32:
6064 case Match_InvalidZPR64:
6065 case Match_InvalidZPR128:
6066 return Error(Loc, "invalid element width");
6067 case Match_InvalidZPR_3b8:
6068 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
6069 case Match_InvalidZPR_3b16:
6070 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
6071 case Match_InvalidZPR_3b32:
6072 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
6073 case Match_InvalidZPR_4b8:
6074 return Error(Loc,
6075 "Invalid restricted vector register, expected z0.b..z15.b");
6076 case Match_InvalidZPR_4b16:
6077 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
6078 case Match_InvalidZPR_4b32:
6079 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
6080 case Match_InvalidZPR_4b64:
6081 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
6082 case Match_InvalidSVEPattern:
6083 return Error(Loc, "invalid predicate pattern");
6084 case Match_InvalidSVEPPRorPNRAnyReg:
6085 case Match_InvalidSVEPPRorPNRBReg:
6086 case Match_InvalidSVEPredicateAnyReg:
6087 case Match_InvalidSVEPredicateBReg:
6088 case Match_InvalidSVEPredicateHReg:
6089 case Match_InvalidSVEPredicateSReg:
6090 case Match_InvalidSVEPredicateDReg:
6091 return Error(Loc, "invalid predicate register.");
6092 case Match_InvalidSVEPredicate3bAnyReg:
6093 return Error(Loc, "invalid restricted predicate register, expected p0..p7 (without element suffix)");
6094 case Match_InvalidSVEPNPredicateB_p8to15Reg:
6095 case Match_InvalidSVEPNPredicateH_p8to15Reg:
6096 case Match_InvalidSVEPNPredicateS_p8to15Reg:
6097 case Match_InvalidSVEPNPredicateD_p8to15Reg:
6098 return Error(Loc, "Invalid predicate register, expected PN in range "
6099 "pn8..pn15 with element suffix.");
6100 case Match_InvalidSVEPNPredicateAny_p8to15Reg:
6101 return Error(Loc, "invalid restricted predicate-as-counter register "
6102 "expected pn8..pn15");
6103 case Match_InvalidSVEPNPredicateBReg:
6104 case Match_InvalidSVEPNPredicateHReg:
6105 case Match_InvalidSVEPNPredicateSReg:
6106 case Match_InvalidSVEPNPredicateDReg:
6107 return Error(Loc, "Invalid predicate register, expected PN in range "
6108 "pn0..pn15 with element suffix.");
6109 case Match_InvalidSVEVecLenSpecifier:
6110 return Error(Loc, "Invalid vector length specifier, expected VLx2 or VLx4");
6111 case Match_InvalidSVEPredicateListMul2x8:
6112 case Match_InvalidSVEPredicateListMul2x16:
6113 case Match_InvalidSVEPredicateListMul2x32:
6114 case Match_InvalidSVEPredicateListMul2x64:
6115 return Error(Loc, "Invalid vector list, expected list with 2 consecutive "
6116 "predicate registers, where the first vector is a multiple of 2 "
6117 "and with correct element type");
6118 case Match_InvalidSVEExactFPImmOperandHalfOne:
6119 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
6120 case Match_InvalidSVEExactFPImmOperandHalfTwo:
6121 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
6122 case Match_InvalidSVEExactFPImmOperandZeroOne:
6123 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
6124 case Match_InvalidMatrixTileVectorH8:
6125 case Match_InvalidMatrixTileVectorV8:
6126 return Error(Loc, "invalid matrix operand, expected za0h.b or za0v.b");
6127 case Match_InvalidMatrixTileVectorH16:
6128 case Match_InvalidMatrixTileVectorV16:
6129 return Error(Loc,
6130 "invalid matrix operand, expected za[0-1]h.h or za[0-1]v.h");
6131 case Match_InvalidMatrixTileVectorH32:
6132 case Match_InvalidMatrixTileVectorV32:
6133 return Error(Loc,
6134 "invalid matrix operand, expected za[0-3]h.s or za[0-3]v.s");
6135 case Match_InvalidMatrixTileVectorH64:
6136 case Match_InvalidMatrixTileVectorV64:
6137 return Error(Loc,
6138 "invalid matrix operand, expected za[0-7]h.d or za[0-7]v.d");
6139 case Match_InvalidMatrixTileVectorH128:
6140 case Match_InvalidMatrixTileVectorV128:
6141 return Error(Loc,
6142 "invalid matrix operand, expected za[0-15]h.q or za[0-15]v.q");
6143 case Match_InvalidMatrixTile32:
6144 return Error(Loc, "invalid matrix operand, expected za[0-3].s");
6145 case Match_InvalidMatrixTile64:
6146 return Error(Loc, "invalid matrix operand, expected za[0-7].d");
6147 case Match_InvalidMatrix:
6148 return Error(Loc, "invalid matrix operand, expected za");
6149 case Match_InvalidMatrix8:
6150 return Error(Loc, "invalid matrix operand, expected suffix .b");
6151 case Match_InvalidMatrix16:
6152 return Error(Loc, "invalid matrix operand, expected suffix .h");
6153 case Match_InvalidMatrix32:
6154 return Error(Loc, "invalid matrix operand, expected suffix .s");
6155 case Match_InvalidMatrix64:
6156 return Error(Loc, "invalid matrix operand, expected suffix .d");
6157 case Match_InvalidMatrixIndexGPR32_12_15:
6158 return Error(Loc, "operand must be a register in range [w12, w15]");
6159 case Match_InvalidMatrixIndexGPR32_8_11:
6160 return Error(Loc, "operand must be a register in range [w8, w11]");
6161 case Match_InvalidSVEVectorListMul2x8:
6162 case Match_InvalidSVEVectorListMul2x16:
6163 case Match_InvalidSVEVectorListMul2x32:
6164 case Match_InvalidSVEVectorListMul2x64:
6165 case Match_InvalidSVEVectorListMul2x128:
6166 return Error(Loc, "Invalid vector list, expected list with 2 consecutive "
6167 "SVE vectors, where the first vector is a multiple of 2 "
6168 "and with matching element types");
6169 case Match_InvalidSVEVectorListMul4x8:
6170 case Match_InvalidSVEVectorListMul4x16:
6171 case Match_InvalidSVEVectorListMul4x32:
6172 case Match_InvalidSVEVectorListMul4x64:
6173 case Match_InvalidSVEVectorListMul4x128:
6174 return Error(Loc, "Invalid vector list, expected list with 4 consecutive "
6175 "SVE vectors, where the first vector is a multiple of 4 "
6176 "and with matching element types");
6177 case Match_InvalidLookupTable:
6178 return Error(Loc, "Invalid lookup table, expected zt0");
6179 case Match_InvalidSVEVectorListStrided2x8:
6180 case Match_InvalidSVEVectorListStrided2x16:
6181 case Match_InvalidSVEVectorListStrided2x32:
6182 case Match_InvalidSVEVectorListStrided2x64:
6183 return Error(
6184 Loc,
6185 "Invalid vector list, expected list with each SVE vector in the list "
6186 "8 registers apart, and the first register in the range [z0, z7] or "
6187 "[z16, z23] and with correct element type");
6188 case Match_InvalidSVEVectorListStrided4x8:
6189 case Match_InvalidSVEVectorListStrided4x16:
6190 case Match_InvalidSVEVectorListStrided4x32:
6191 case Match_InvalidSVEVectorListStrided4x64:
6192 return Error(
6193 Loc,
6194 "Invalid vector list, expected list with each SVE vector in the list "
6195 "4 registers apart, and the first register in the range [z0, z3] or "
6196 "[z16, z19] and with correct element type");
6197 case Match_AddSubLSLImm3ShiftLarge:
6198 return Error(Loc,
6199 "expected 'lsl' with optional integer in range [0, 7]");
6200 default:
6201 llvm_unreachable("unexpected error code!");
6202 }
6203}
6204
6205static const char *getSubtargetFeatureName(uint64_t Val);
6206
6207bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
6209 MCStreamer &Out,
6211 bool MatchingInlineAsm) {
6212 assert(!Operands.empty() && "Unexpect empty operand list!");
6213 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
6214 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
6215
6216 StringRef Tok = Op.getToken();
6217 unsigned NumOperands = Operands.size();
6218
6219 if (NumOperands == 4 && Tok == "lsl") {
6220 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6221 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6222 if (Op2.isScalarReg() && Op3.isImm()) {
6223 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6224 if (Op3CE) {
6225 uint64_t Op3Val = Op3CE->getValue();
6226 uint64_t NewOp3Val = 0;
6227 uint64_t NewOp4Val = 0;
6228 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
6229 Op2.getReg())) {
6230 NewOp3Val = (32 - Op3Val) & 0x1f;
6231 NewOp4Val = 31 - Op3Val;
6232 } else {
6233 NewOp3Val = (64 - Op3Val) & 0x3f;
6234 NewOp4Val = 63 - Op3Val;
6235 }
6236
6237 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
6238 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
6239
6240 Operands[0] =
6241 AArch64Operand::CreateToken("ubfm", Op.getStartLoc(), getContext());
6242 Operands.push_back(AArch64Operand::CreateImm(
6243 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
6244 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
6245 Op3.getEndLoc(), getContext());
6246 }
6247 }
6248 } else if (NumOperands == 4 && Tok == "bfc") {
6249 // FIXME: Horrible hack to handle BFC->BFM alias.
6250 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6251 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
6252 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
6253
6254 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
6255 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
6256 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
6257
6258 if (LSBCE && WidthCE) {
6259 uint64_t LSB = LSBCE->getValue();
6260 uint64_t Width = WidthCE->getValue();
6261
6262 uint64_t RegWidth = 0;
6263 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
6264 Op1.getReg()))
6265 RegWidth = 64;
6266 else
6267 RegWidth = 32;
6268
6269 if (LSB >= RegWidth)
6270 return Error(LSBOp.getStartLoc(),
6271 "expected integer in range [0, 31]");
6272 if (Width < 1 || Width > RegWidth)
6273 return Error(WidthOp.getStartLoc(),
6274 "expected integer in range [1, 32]");
6275
6276 uint64_t ImmR = 0;
6277 if (RegWidth == 32)
6278 ImmR = (32 - LSB) & 0x1f;
6279 else
6280 ImmR = (64 - LSB) & 0x3f;
6281
6282 uint64_t ImmS = Width - 1;
6283
6284 if (ImmR != 0 && ImmS >= ImmR)
6285 return Error(WidthOp.getStartLoc(),
6286 "requested insert overflows register");
6287
6288 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
6289 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
6290 Operands[0] =
6291 AArch64Operand::CreateToken("bfm", Op.getStartLoc(), getContext());
6292 Operands[2] = AArch64Operand::CreateReg(
6293 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
6294 SMLoc(), SMLoc(), getContext());
6295 Operands[3] = AArch64Operand::CreateImm(
6296 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
6297 Operands.emplace_back(
6298 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
6299 WidthOp.getEndLoc(), getContext()));
6300 }
6301 }
6302 } else if (NumOperands == 5) {
6303 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
6304 // UBFIZ -> UBFM aliases.
6305 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
6306 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6307 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6308 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6309
6310 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6311 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6312 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
6313
6314 if (Op3CE && Op4CE) {
6315 uint64_t Op3Val = Op3CE->getValue();
6316 uint64_t Op4Val = Op4CE->getValue();
6317
6318 uint64_t RegWidth = 0;
6319 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
6320 Op1.getReg()))
6321 RegWidth = 64;
6322 else
6323 RegWidth = 32;
6324
6325 if (Op3Val >= RegWidth)
6326 return Error(Op3.getStartLoc(),
6327 "expected integer in range [0, 31]");
6328 if (Op4Val < 1 || Op4Val > RegWidth)
6329 return Error(Op4.getStartLoc(),
6330 "expected integer in range [1, 32]");
6331
6332 uint64_t NewOp3Val = 0;
6333 if (RegWidth == 32)
6334 NewOp3Val = (32 - Op3Val) & 0x1f;
6335 else
6336 NewOp3Val = (64 - Op3Val) & 0x3f;
6337
6338 uint64_t NewOp4Val = Op4Val - 1;
6339
6340 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
6341 return Error(Op4.getStartLoc(),
6342 "requested insert overflows register");
6343
6344 const MCExpr *NewOp3 =
6345 MCConstantExpr::create(NewOp3Val, getContext());
6346 const MCExpr *NewOp4 =
6347 MCConstantExpr::create(NewOp4Val, getContext());
6348 Operands[3] = AArch64Operand::CreateImm(
6349 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
6350 Operands[4] = AArch64Operand::CreateImm(
6351 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
6352 if (Tok == "bfi")
6353 Operands[0] = AArch64Operand::CreateToken("bfm", Op.getStartLoc(),
6354 getContext());
6355 else if (Tok == "sbfiz")
6356 Operands[0] = AArch64Operand::CreateToken("sbfm", Op.getStartLoc(),
6357 getContext());
6358 else if (Tok == "ubfiz")
6359 Operands[0] = AArch64Operand::CreateToken("ubfm", Op.getStartLoc(),
6360 getContext());
6361 else
6362 llvm_unreachable("No valid mnemonic for alias?");
6363 }
6364 }
6365
6366 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
6367 // UBFX -> UBFM aliases.
6368 } else if (NumOperands == 5 &&
6369 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
6370 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6371 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6372 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6373
6374 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6375 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6376 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
6377
6378 if (Op3CE && Op4CE) {
6379 uint64_t Op3Val = Op3CE->getValue();
6380 uint64_t Op4Val = Op4CE->getValue();
6381
6382 uint64_t RegWidth = 0;
6383 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
6384 Op1.getReg()))
6385 RegWidth = 64;
6386 else
6387 RegWidth = 32;
6388
6389 if (Op3Val >= RegWidth)
6390 return Error(Op3.getStartLoc(),
6391 "expected integer in range [0, 31]");
6392 if (Op4Val < 1 || Op4Val > RegWidth)
6393 return Error(Op4.getStartLoc(),
6394 "expected integer in range [1, 32]");
6395
6396 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
6397
6398 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
6399 return Error(Op4.getStartLoc(),
6400 "requested extract overflows register");
6401
6402 const MCExpr *NewOp4 =
6403 MCConstantExpr::create(NewOp4Val, getContext());
6404 Operands[4] = AArch64Operand::CreateImm(
6405 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
6406 if (Tok == "bfxil")
6407 Operands[0] = AArch64Operand::CreateToken("bfm", Op.getStartLoc(),
6408 getContext());
6409 else if (Tok == "sbfx")
6410 Operands[0] = AArch64Operand::CreateToken("sbfm", Op.getStartLoc(),
6411 getContext());
6412 else if (Tok == "ubfx")
6413 Operands[0] = AArch64Operand::CreateToken("ubfm", Op.getStartLoc(),
6414 getContext());
6415 else
6416 llvm_unreachable("No valid mnemonic for alias?");
6417 }
6418 }
6419 }
6420 }
6421
6422 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
6423 // instruction for FP registers correctly in some rare circumstances. Convert
6424 // it to a safe instruction and warn (because silently changing someone's
6425 // assembly is rude).
6426 if (getSTI().hasFeature(AArch64::FeatureZCZeroingFPWorkaround) &&
6427 NumOperands == 4 && Tok == "movi") {
6428 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6429 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6430 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6431 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
6432 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
6433 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
6434 if (Suffix.lower() == ".2d" &&
6435 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
6436 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
6437 " correctly on this CPU, converting to equivalent movi.16b");
6438 // Switch the suffix to .16b.
6439 unsigned Idx = Op1.isToken() ? 1 : 2;
6440 Operands[Idx] =
6441 AArch64Operand::CreateToken(".16b", IDLoc, getContext());
6442 }
6443 }
6444 }
6445
6446 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
6447 // InstAlias can't quite handle this since the reg classes aren't
6448 // subclasses.
6449 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
6450 // The source register can be Wn here, but the matcher expects a
6451 // GPR64. Twiddle it here if necessary.
6452 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6453 if (Op.isScalarReg()) {
6454 unsigned Reg = getXRegFromWReg(Op.getReg());
6455 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6456 Op.getStartLoc(), Op.getEndLoc(),
6457 getContext());
6458 }
6459 }
6460 // FIXME: Likewise for sxt[bh] with a Xd dst operand
6461 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
6462 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6463 if (Op.isScalarReg() &&
6464 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
6465 Op.getReg())) {
6466 // The source register can be Wn here, but the matcher expects a
6467 // GPR64. Twiddle it here if necessary.
6468 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6469 if (Op.isScalarReg()) {
6470 unsigned Reg = getXRegFromWReg(Op.getReg());
6471 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6472 Op.getStartLoc(),
6473 Op.getEndLoc(), getContext());
6474 }
6475 }
6476 }
6477 // FIXME: Likewise for uxt[bh] with a Xd dst operand
6478 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
6479 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6480 if (Op.isScalarReg() &&
6481 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
6482 Op.getReg())) {
6483 // The source register can be Wn here, but the matcher expects a
6484 // GPR32. Twiddle it here if necessary.
6485 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6486 if (Op.isScalarReg()) {
6487 unsigned Reg = getWRegFromXReg(Op.getReg());
6488 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6489 Op.getStartLoc(),
6490 Op.getEndLoc(), getContext());
6491 }
6492 }
6493 }
6494
6495 MCInst Inst;
6496 FeatureBitset MissingFeatures;
6497 // First try to match against the secondary set of tables containing the
6498 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
6499 unsigned MatchResult =
6500 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6501 MatchingInlineAsm, 1);
6502
6503 // If that fails, try against the alternate table containing long-form NEON:
6504 // "fadd v0.2s, v1.2s, v2.2s"
6505 if (MatchResult != Match_Success) {
6506 // But first, save the short-form match result: we can use it in case the
6507 // long-form match also fails.
6508 auto ShortFormNEONErrorInfo = ErrorInfo;
6509 auto ShortFormNEONMatchResult = MatchResult;
6510 auto ShortFormNEONMissingFeatures = MissingFeatures;
6511
6512 MatchResult =
6513 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6514 MatchingInlineAsm, 0);
6515
6516 // Now, both matches failed, and the long-form match failed on the mnemonic
6517 // suffix token operand. The short-form match failure is probably more
6518 // relevant: use it instead.
6519 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
6520 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
6521 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
6522 MatchResult = ShortFormNEONMatchResult;
6523 ErrorInfo = ShortFormNEONErrorInfo;
6524 MissingFeatures = ShortFormNEONMissingFeatures;
6525 }
6526 }
6527
6528 switch (MatchResult) {
6529 case Match_Success: {
6530 // Perform range checking and other semantic validations
6531 SmallVector<SMLoc, 8> OperandLocs;
6532 NumOperands = Operands.size();
6533 for (unsigned i = 1; i < NumOperands; ++i)
6534 OperandLocs.push_back(Operands[i]->getStartLoc());
6535 if (validateInstruction(Inst, IDLoc, OperandLocs))
6536 return true;
6537
6538 Inst.setLoc(IDLoc);
6539 Out.emitInstruction(Inst, getSTI());
6540 return false;
6541 }
6542 case Match_MissingFeature: {
6543 assert(MissingFeatures.any() && "Unknown missing feature!");
6544 // Special case the error message for the very common case where only
6545 // a single subtarget feature is missing (neon, e.g.).
6546 std::string Msg = "instruction requires:";
6547 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
6548 if (MissingFeatures[i]) {
6549 Msg += " ";
6550 Msg += getSubtargetFeatureName(i);
6551 }
6552 }
6553 return Error(IDLoc, Msg);
6554 }
6555 case Match_MnemonicFail:
6556 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
6557 case Match_InvalidOperand: {
6558 SMLoc ErrorLoc = IDLoc;
6559
6560 if (ErrorInfo != ~0ULL) {
6561 if (ErrorInfo >= Operands.size())
6562 return Error(IDLoc, "too few operands for instruction",
6563 SMRange(IDLoc, getTok().getLoc()));
6564
6565 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
6566 if (ErrorLoc == SMLoc())
6567 ErrorLoc = IDLoc;
6568 }
6569 // If the match failed on a suffix token operand, tweak the diagnostic
6570 // accordingly.
6571 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
6572 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
6573 MatchResult = Match_InvalidSuffix;
6574
6575 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
6576 }
6577 case Match_InvalidTiedOperand:
6578 case Match_InvalidMemoryIndexed1:
6579 case Match_InvalidMemoryIndexed2:
6580 case Match_InvalidMemoryIndexed4:
6581 case Match_InvalidMemoryIndexed8:
6582 case Match_InvalidMemoryIndexed16:
6583 case Match_InvalidCondCode:
6584 case Match_AddSubLSLImm3ShiftLarge:
6585 case Match_AddSubRegExtendSmall:
6586 case Match_AddSubRegExtendLarge:
6587 case Match_AddSubSecondSource:
6588 case Match_LogicalSecondSource:
6589 case Match_AddSubRegShift32:
6590 case Match_AddSubRegShift64:
6591 case Match_InvalidMovImm32Shift:
6592 case Match_InvalidMovImm64Shift:
6593 case Match_InvalidFPImm:
6594 case Match_InvalidMemoryWExtend8:
6595 case Match_InvalidMemoryWExtend16:
6596 case Match_InvalidMemoryWExtend32:
6597 case Match_InvalidMemoryWExtend64:
6598 case Match_InvalidMemoryWExtend128:
6599 case Match_InvalidMemoryXExtend8:
6600 case Match_InvalidMemoryXExtend16:
6601 case Match_InvalidMemoryXExtend32:
6602 case Match_InvalidMemoryXExtend64:
6603 case Match_InvalidMemoryXExtend128:
6604 case Match_InvalidMemoryIndexed1SImm4:
6605 case Match_InvalidMemoryIndexed2SImm4:
6606 case Match_InvalidMemoryIndexed3SImm4:
6607 case Match_InvalidMemoryIndexed4SImm4:
6608 case Match_InvalidMemoryIndexed1SImm6:
6609 case Match_InvalidMemoryIndexed16SImm4:
6610 case Match_InvalidMemoryIndexed32SImm4:
6611 case Match_InvalidMemoryIndexed4SImm7:
6612 case Match_InvalidMemoryIndexed8SImm7:
6613 case Match_InvalidMemoryIndexed16SImm7:
6614 case Match_InvalidMemoryIndexed8UImm5:
6615 case Match_InvalidMemoryIndexed8UImm3:
6616 case Match_InvalidMemoryIndexed4UImm5:
6617 case Match_InvalidMemoryIndexed2UImm5:
6618 case Match_InvalidMemoryIndexed1UImm6:
6619 case Match_InvalidMemoryIndexed2UImm6:
6620 case Match_InvalidMemoryIndexed4UImm6:
6621 case Match_InvalidMemoryIndexed8UImm6:
6622 case Match_InvalidMemoryIndexed16UImm6:
6623 case Match_InvalidMemoryIndexedSImm6:
6624 case Match_InvalidMemoryIndexedSImm5:
6625 case Match_InvalidMemoryIndexedSImm8:
6626 case Match_InvalidMemoryIndexedSImm9:
6627 case Match_InvalidMemoryIndexed16SImm9:
6628 case Match_InvalidMemoryIndexed8SImm10:
6629 case Match_InvalidImm0_0:
6630 case Match_InvalidImm0_1:
6631 case Match_InvalidImm0_3:
6632 case Match_InvalidImm0_7:
6633 case Match_InvalidImm0_15:
6634 case Match_InvalidImm0_31:
6635 case Match_InvalidImm0_63:
6636 case Match_InvalidImm0_127:
6637 case Match_InvalidImm0_255:
6638 case Match_InvalidImm0_65535:
6639 case Match_InvalidImm1_8:
6640 case Match_InvalidImm1_16:
6641 case Match_InvalidImm1_32:
6642 case Match_InvalidImm1_64:
6643 case Match_InvalidMemoryIndexedRange2UImm0:
6644 case Match_InvalidMemoryIndexedRange2UImm1:
6645 case Match_InvalidMemoryIndexedRange2UImm2:
6646 case Match_InvalidMemoryIndexedRange2UImm3:
6647 case Match_InvalidMemoryIndexedRange4UImm0:
6648 case Match_InvalidMemoryIndexedRange4UImm1:
6649 case Match_InvalidMemoryIndexedRange4UImm2:
6650 case Match_InvalidSVEAddSubImm8:
6651 case Match_InvalidSVEAddSubImm16:
6652 case Match_InvalidSVEAddSubImm32:
6653 case Match_InvalidSVEAddSubImm64:
6654 case Match_InvalidSVECpyImm8:
6655 case Match_InvalidSVECpyImm16:
6656 case Match_InvalidSVECpyImm32:
6657 case Match_InvalidSVECpyImm64:
6658 case Match_InvalidIndexRange0_0:
6659 case Match_InvalidIndexRange1_1:
6660 case Match_InvalidIndexRange0_15:
6661 case Match_InvalidIndexRange0_7:
6662 case Match_InvalidIndexRange0_3:
6663 case Match_InvalidIndexRange0_1:
6664 case Match_InvalidSVEIndexRange0_63:
6665 case Match_InvalidSVEIndexRange0_31:
6666 case Match_InvalidSVEIndexRange0_15:
6667 case Match_InvalidSVEIndexRange0_7:
6668 case Match_InvalidSVEIndexRange0_3:
6669 case Match_InvalidLabel:
6670 case Match_InvalidComplexRotationEven:
6671 case Match_InvalidComplexRotationOdd:
6672 case Match_InvalidGPR64shifted8:
6673 case Match_InvalidGPR64shifted16:
6674 case Match_InvalidGPR64shifted32:
6675 case Match_InvalidGPR64shifted64:
6676 case Match_InvalidGPR64shifted128:
6677 case Match_InvalidGPR64NoXZRshifted8:
6678 case Match_InvalidGPR64NoXZRshifted16:
6679 case Match_InvalidGPR64NoXZRshifted32:
6680 case Match_InvalidGPR64NoXZRshifted64:
6681 case Match_InvalidGPR64NoXZRshifted128:
6682 case Match_InvalidZPR32UXTW8:
6683 case Match_InvalidZPR32UXTW16:
6684 case Match_InvalidZPR32UXTW32:
6685 case Match_InvalidZPR32UXTW64:
6686 case Match_InvalidZPR32SXTW8:
6687 case Match_InvalidZPR32SXTW16:
6688 case Match_InvalidZPR32SXTW32:
6689 case Match_InvalidZPR32SXTW64:
6690 case Match_InvalidZPR64UXTW8:
6691 case Match_InvalidZPR64SXTW8:
6692 case Match_InvalidZPR64UXTW16:
6693 case Match_InvalidZPR64SXTW16:
6694 case Match_InvalidZPR64UXTW32:
6695 case Match_InvalidZPR64SXTW32:
6696 case Match_InvalidZPR64UXTW64:
6697 case Match_InvalidZPR64SXTW64:
6698 case Match_InvalidZPR32LSL8:
6699 case Match_InvalidZPR32LSL16:
6700 case Match_InvalidZPR32LSL32:
6701 case Match_InvalidZPR32LSL64:
6702 case Match_InvalidZPR64LSL8:
6703 case Match_InvalidZPR64LSL16:
6704 case Match_InvalidZPR64LSL32:
6705 case Match_InvalidZPR64LSL64:
6706 case Match_InvalidZPR0:
6707 case Match_InvalidZPR8:
6708 case Match_InvalidZPR16:
6709 case Match_InvalidZPR32:
6710 case Match_InvalidZPR64:
6711 case Match_InvalidZPR128:
6712 case Match_InvalidZPR_3b8:
6713 case Match_InvalidZPR_3b16:
6714 case Match_InvalidZPR_3b32:
6715 case Match_InvalidZPR_4b8:
6716 case Match_InvalidZPR_4b16:
6717 case Match_InvalidZPR_4b32:
6718 case Match_InvalidZPR_4b64:
6719 case Match_InvalidSVEPPRorPNRAnyReg:
6720 case Match_InvalidSVEPPRorPNRBReg:
6721 case Match_InvalidSVEPredicateAnyReg:
6722 case Match_InvalidSVEPattern:
6723 case Match_InvalidSVEVecLenSpecifier:
6724 case Match_InvalidSVEPredicateBReg:
6725 case Match_InvalidSVEPredicateHReg:
6726 case Match_InvalidSVEPredicateSReg:
6727 case Match_InvalidSVEPredicateDReg:
6728 case Match_InvalidSVEPredicate3bAnyReg:
6729 case Match_InvalidSVEPNPredicateB_p8to15Reg:
6730 case Match_InvalidSVEPNPredicateH_p8to15Reg:
6731 case Match_InvalidSVEPNPredicateS_p8to15Reg:
6732 case Match_InvalidSVEPNPredicateD_p8to15Reg:
6733 case Match_InvalidSVEPNPredicateAny_p8to15Reg:
6734 case Match_InvalidSVEPNPredicateBReg:
6735 case Match_InvalidSVEPNPredicateHReg:
6736 case Match_InvalidSVEPNPredicateSReg:
6737 case Match_InvalidSVEPNPredicateDReg:
6738 case Match_InvalidSVEPredicateListMul2x8:
6739 case Match_InvalidSVEPredicateListMul2x16:
6740 case Match_InvalidSVEPredicateListMul2x32:
6741 case Match_InvalidSVEPredicateListMul2x64:
6742 case Match_InvalidSVEExactFPImmOperandHalfOne:
6743 case Match_InvalidSVEExactFPImmOperandHalfTwo:
6744 case Match_InvalidSVEExactFPImmOperandZeroOne:
6745 case Match_InvalidMatrixTile32:
6746 case Match_InvalidMatrixTile64:
6747 case Match_InvalidMatrix:
6748 case Match_InvalidMatrix8:
6749 case Match_InvalidMatrix16:
6750 case Match_InvalidMatrix32:
6751 case Match_InvalidMatrix64:
6752 case Match_InvalidMatrixTileVectorH8:
6753 case Match_InvalidMatrixTileVectorH16:
6754 case Match_InvalidMatrixTileVectorH32:
6755 case Match_InvalidMatrixTileVectorH64:
6756 case Match_InvalidMatrixTileVectorH128:
6757 case Match_InvalidMatrixTileVectorV8:
6758 case Match_InvalidMatrixTileVectorV16:
6759 case Match_InvalidMatrixTileVectorV32:
6760 case Match_InvalidMatrixTileVectorV64:
6761 case Match_InvalidMatrixTileVectorV128:
6762 case Match_InvalidSVCR:
6763 case Match_InvalidMatrixIndexGPR32_12_15:
6764 case Match_InvalidMatrixIndexGPR32_8_11:
6765 case Match_InvalidLookupTable:
6766 case Match_InvalidSVEVectorListMul2x8:
6767 case Match_InvalidSVEVectorListMul2x16:
6768 case Match_InvalidSVEVectorListMul2x32:
6769 case Match_InvalidSVEVectorListMul2x64:
6770 case Match_InvalidSVEVectorListMul2x128:
6771 case Match_InvalidSVEVectorListMul4x8:
6772 case Match_InvalidSVEVectorListMul4x16:
6773 case Match_InvalidSVEVectorListMul4x32:
6774 case Match_InvalidSVEVectorListMul4x64:
6775 case Match_InvalidSVEVectorListMul4x128:
6776 case Match_InvalidSVEVectorListStrided2x8:
6777 case Match_InvalidSVEVectorListStrided2x16:
6778 case Match_InvalidSVEVectorListStrided2x32:
6779 case Match_InvalidSVEVectorListStrided2x64:
6780 case Match_InvalidSVEVectorListStrided4x8:
6781 case Match_InvalidSVEVectorListStrided4x16:
6782 case Match_InvalidSVEVectorListStrided4x32:
6783 case Match_InvalidSVEVectorListStrided4x64:
6784 case Match_MSR:
6785 case Match_MRS: {
6786 if (ErrorInfo >= Operands.size())
6787 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
6788 // Any time we get here, there's nothing fancy to do. Just get the
6789 // operand SMLoc and display the diagnostic.
6790 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
6791 if (ErrorLoc == SMLoc())
6792 ErrorLoc = IDLoc;
6793 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
6794 }
6795 }
6796
6797 llvm_unreachable("Implement any new match types added!");
6798}
6799
6800/// ParseDirective parses the arm specific directives
6801bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
6802 const MCContext::Environment Format = getContext().getObjectFileType();
6803 bool IsMachO = Format == MCContext::IsMachO;
6804 bool IsCOFF = Format == MCContext::IsCOFF;
6805
6806 auto IDVal = DirectiveID.getIdentifier().lower();
6807 SMLoc Loc = DirectiveID.getLoc();
6808 if (IDVal == ".arch")
6809 parseDirectiveArch(Loc);
6810 else if (IDVal == ".cpu")
6811 parseDirectiveCPU(Loc);
6812 else if (IDVal == ".tlsdesccall")
6813 parseDirectiveTLSDescCall(Loc);
6814 else if (IDVal == ".ltorg" || IDVal == ".pool")
6815 parseDirectiveLtorg(Loc);
6816 else if (IDVal == ".unreq")
6817 parseDirectiveUnreq(Loc);
6818 else if (IDVal == ".inst")
6819 parseDirectiveInst(Loc);
6820 else if (IDVal == ".cfi_negate_ra_state")
6821 parseDirectiveCFINegateRAState();
6822 else if (IDVal == ".cfi_b_key_frame")
6823 parseDirectiveCFIBKeyFrame();
6824 else if (IDVal == ".cfi_mte_tagged_frame")
6825 parseDirectiveCFIMTETaggedFrame();
6826 else if (IDVal == ".arch_extension")
6827 parseDirectiveArchExtension(Loc);
6828 else if (IDVal == ".variant_pcs")
6829 parseDirectiveVariantPCS(Loc);
6830 else if (IsMachO) {
6831 if (IDVal == MCLOHDirectiveName())
6832 parseDirectiveLOH(IDVal, Loc);
6833 else
6834 return true;
6835 } else if (IsCOFF) {
6836 if (IDVal == ".seh_stackalloc")
6837 parseDirectiveSEHAllocStack(Loc);
6838 else if (IDVal == ".seh_endprologue")
6839 parseDirectiveSEHPrologEnd(Loc);
6840 else if (IDVal == ".seh_save_r19r20_x")
6841 parseDirectiveSEHSaveR19R20X(Loc);
6842 else if (IDVal == ".seh_save_fplr")
6843 parseDirectiveSEHSaveFPLR(Loc);
6844 else if (IDVal == ".seh_save_fplr_x")
6845 parseDirectiveSEHSaveFPLRX(Loc);
6846 else if (IDVal == ".seh_save_reg")
6847 parseDirectiveSEHSaveReg(Loc);
6848 else if (IDVal == ".seh_save_reg_x")
6849 parseDirectiveSEHSaveRegX(Loc);
6850 else if (IDVal == ".seh_save_regp")
6851 parseDirectiveSEHSaveRegP(Loc);
6852 else if (IDVal == ".seh_save_regp_x")
6853 parseDirectiveSEHSaveRegPX(Loc);
6854 else if (IDVal == ".seh_save_lrpair")
6855 parseDirectiveSEHSaveLRPair(Loc);
6856 else if (IDVal == ".seh_save_freg")
6857 parseDirectiveSEHSaveFReg(Loc);
6858 else if (IDVal == ".seh_save_freg_x")
6859 parseDirectiveSEHSaveFRegX(Loc);
6860 else if (IDVal == ".seh_save_fregp")
6861 parseDirectiveSEHSaveFRegP(Loc);
6862 else if (IDVal == ".seh_save_fregp_x")
6863 parseDirectiveSEHSaveFRegPX(Loc);
6864 else if (IDVal == ".seh_set_fp")
6865 parseDirectiveSEHSetFP(Loc);
6866 else if (IDVal == ".seh_add_fp")
6867 parseDirectiveSEHAddFP(Loc);
6868 else if (IDVal == ".seh_nop")
6869 parseDirectiveSEHNop(Loc);
6870 else if (IDVal == ".seh_save_next")
6871 parseDirectiveSEHSaveNext(Loc);
6872 else if (IDVal == ".seh_startepilogue")
6873 parseDirectiveSEHEpilogStart(Loc);
6874 else if (IDVal == ".seh_endepilogue")
6875 parseDirectiveSEHEpilogEnd(Loc);
6876 else if (IDVal == ".seh_trap_frame")
6877 parseDirectiveSEHTrapFrame(Loc);
6878 else if (IDVal == ".seh_pushframe")
6879 parseDirectiveSEHMachineFrame(Loc);
6880 else if (IDVal == ".seh_context")
6881 parseDirectiveSEHContext(Loc);
6882 else if (IDVal == ".seh_ec_context")
6883 parseDirectiveSEHECContext(Loc);
6884 else if (IDVal == ".seh_clear_unwound_to_call")
6885 parseDirectiveSEHClearUnwoundToCall(Loc);
6886 else if (IDVal == ".seh_pac_sign_lr")
6887 parseDirectiveSEHPACSignLR(Loc);
6888 else if (IDVal == ".seh_save_any_reg")
6889 parseDirectiveSEHSaveAnyReg(Loc, false, false);
6890 else if (IDVal == ".seh_save_any_reg_p")
6891 parseDirectiveSEHSaveAnyReg(Loc, true, false);
6892 else if (IDVal == ".seh_save_any_reg_x")
6893 parseDirectiveSEHSaveAnyReg(Loc, false, true);
6894 else if (IDVal == ".seh_save_any_reg_px")
6895 parseDirectiveSEHSaveAnyReg(Loc, true, true);
6896 else
6897 return true;
6898 } else
6899 return true;
6900 return false;
6901}
6902
6903static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
6904 SmallVector<StringRef, 4> &RequestedExtensions) {
6905 const bool NoCrypto = llvm::is_contained(RequestedExtensions, "nocrypto");
6906 const bool Crypto = llvm::is_contained(RequestedExtensions, "crypto");
6907
6908 if (!NoCrypto && Crypto) {
6909 // Map 'generic' (and others) to sha2 and aes, because
6910 // that was the traditional meaning of crypto.
6911 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
6912 ArchInfo == AArch64::ARMV8_3A) {
6913 RequestedExtensions.push_back("sha2");
6914 RequestedExtensions.push_back("aes");
6915 }
6916 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
6917 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
6918 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
6919 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
6920 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
6921 ArchInfo == AArch64::ARMV9_4A || ArchInfo == AArch64::ARMV8R) {
6922 RequestedExtensions.push_back("sm4");
6923 RequestedExtensions.push_back("sha3");
6924 RequestedExtensions.push_back("sha2");
6925 RequestedExtensions.push_back("aes");
6926 }
6927 } else if (NoCrypto) {
6928 // Map 'generic' (and others) to sha2 and aes, because
6929 // that was the traditional meaning of crypto.
6930 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
6931 ArchInfo == AArch64::ARMV8_3A) {
6932 RequestedExtensions.push_back("nosha2");
6933 RequestedExtensions.push_back("noaes");
6934 }
6935 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
6936 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
6937 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
6938 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
6939 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
6940 ArchInfo == AArch64::ARMV9_4A) {
6941 RequestedExtensions.push_back("nosm4");
6942 RequestedExtensions.push_back("nosha3");
6943 RequestedExtensions.push_back("nosha2");
6944 RequestedExtensions.push_back("noaes");
6945 }
6946 }
6947}
6948
6949/// parseDirectiveArch
6950/// ::= .arch token
6951bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
6952 SMLoc ArchLoc = getLoc();
6953
6954 StringRef Arch, ExtensionString;
6955 std::tie(Arch, ExtensionString) =
6956 getParser().parseStringToEndOfStatement().trim().split('+');
6957
6958 const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch);
6959 if (!ArchInfo)
6960 return Error(ArchLoc, "unknown arch name");
6961
6962 if (parseToken(AsmToken::EndOfStatement))
6963 return true;
6964
6965 // Get the architecture and extension features.
6966 std::vector<StringRef> AArch64Features;
6967 AArch64Features.push_back(ArchInfo->ArchFeature);
6968 AArch64::getExtensionFeatures(ArchInfo->DefaultExts, AArch64Features);
6969
6970 MCSubtargetInfo &STI = copySTI();
6971 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
6972 STI.setDefaultFeatures("generic", /*TuneCPU*/ "generic",
6973 join(ArchFeatures.begin(), ArchFeatures.end(), ","));
6974
6975 SmallVector<StringRef, 4> RequestedExtensions;
6976 if (!ExtensionString.empty())
6977 ExtensionString.split(RequestedExtensions, '+');
6978
6979 ExpandCryptoAEK(*ArchInfo, RequestedExtensions);
6980
6981 FeatureBitset Features = STI.getFeatureBits();
6982 setAvailableFeatures(ComputeAvailableFeatures(Features));
6983 for (auto Name : RequestedExtensions) {
6984 bool EnableFeature = !Name.consume_front_insensitive("no");
6985
6986 for (const auto &Extension : ExtensionMap) {
6987 if (Extension.Name != Name)
6988 continue;
6989
6990 if (Extension.Features.none())
6991 report_fatal_error("unsupported architectural extension: " + Name);
6992
6993 FeatureBitset ToggleFeatures =
6994 EnableFeature
6996 : STI.ToggleFeature(Features & Extension.Features);
6997 setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
6998 break;
6999 }
7000 }
7001 return false;
7002}
7003
7004/// parseDirectiveArchExtension
7005/// ::= .arch_extension [no]feature
7006bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
7007 SMLoc ExtLoc = getLoc();
7008
7009 StringRef Name = getParser().parseStringToEndOfStatement().trim();
7010
7011 if (parseEOL())
7012 return true;
7013
7014 bool EnableFeature = true;
7015 if (Name.starts_with_insensitive("no")) {
7016 EnableFeature = false;
7017 Name = Name.substr(2);
7018 }
7019
7020 MCSubtargetInfo &STI = copySTI();
7021 FeatureBitset Features = STI.getFeatureBits();
7022 for (const auto &Extension : ExtensionMap) {
7023 if (Extension.Name != Name)
7024 continue;
7025
7026 if (Extension.Features.none())
7027 return Error(ExtLoc, "unsupported architectural extension: " + Name);
7028
7029 FeatureBitset ToggleFeatures =
7030 EnableFeature
7032 : STI.ToggleFeature(Features & Extension.Features);
7033 setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7034 return false;
7035 }
7036
7037 return Error(ExtLoc, "unknown architectural extension: " + Name);
7038}
7039
7041 return SMLoc::getFromPointer(L.getPointer() + Offset);
7042}
7043
7044/// parseDirectiveCPU
7045/// ::= .cpu id
7046bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
7047 SMLoc CurLoc = getLoc();
7048
7049 StringRef CPU, ExtensionString;
7050 std::tie(CPU, ExtensionString) =
7051 getParser().parseStringToEndOfStatement().trim().split('+');
7052
7053 if (parseToken(AsmToken::EndOfStatement))
7054 return true;
7055
7056 SmallVector<StringRef, 4> RequestedExtensions;
7057 if (!ExtensionString.empty())
7058 ExtensionString.split(RequestedExtensions, '+');
7059
7061 if (!CpuArch) {
7062 Error(CurLoc, "unknown CPU name");
7063 return false;
7064 }
7065 ExpandCryptoAEK(*CpuArch, RequestedExtensions);
7066
7067 MCSubtargetInfo &STI = copySTI();
7068 STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
7069 CurLoc = incrementLoc(CurLoc, CPU.size());
7070
7071 for (auto Name : RequestedExtensions) {
7072 // Advance source location past '+'.
7073 CurLoc = incrementLoc(CurLoc, 1);
7074
7075 bool EnableFeature = !Name.consume_front_insensitive("no");
7076
7077 bool FoundExtension = false;
7078 for (const auto &Extension : ExtensionMap) {
7079 if (Extension.Name != Name)
7080 continue;
7081
7082 if (Extension.Features.none())
7083 report_fatal_error("unsupported architectural extension: " + Name);
7084
7085 FeatureBitset Features = STI.getFeatureBits();
7086 FeatureBitset ToggleFeatures =
7087 EnableFeature
7089 : STI.ToggleFeature(Features & Extension.Features);
7090 setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7091 FoundExtension = true;
7092
7093 break;
7094 }
7095
7096 if (!FoundExtension)
7097 Error(CurLoc, "unsupported architectural extension");
7098
7099 CurLoc = incrementLoc(CurLoc, Name.size());
7100 }
7101 return false;
7102}
7103
7104/// parseDirectiveInst
7105/// ::= .inst opcode [, ...]
7106bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
7107 if (getLexer().is(AsmToken::EndOfStatement))
7108 return Error(Loc, "expected expression following '.inst' directive");
7109
7110 auto parseOp = [&]() -> bool {
7111 SMLoc L = getLoc();
7112 const MCExpr *Expr = nullptr;
7113 if (check(getParser().parseExpression(Expr), L, "expected expression"))
7114 return true;
7115 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
7116 if (check(!Value, L, "expected constant expression"))
7117 return true;
7118 getTargetStreamer().emitInst(Value->getValue());
7119 return false;
7120 };
7121
7122 return parseMany(parseOp);
7123}
7124
7125// parseDirectiveTLSDescCall:
7126// ::= .tlsdesccall symbol
7127bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
7129 if (check(getParser().parseIdentifier(Name), L, "expected symbol") ||
7130 parseToken(AsmToken::EndOfStatement))
7131 return true;
7132
7133 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
7134 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
7135 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
7136
7137 MCInst Inst;
7138 Inst.setOpcode(AArch64::TLSDESCCALL);
7140
7141 getParser().getStreamer().emitInstruction(Inst, getSTI());
7142 return false;
7143}
7144
7145/// ::= .loh <lohName | lohId> label1, ..., labelN
7146/// The number of arguments depends on the loh identifier.
7147bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
7149 if (getTok().isNot(AsmToken::Identifier)) {
7150 if (getTok().isNot(AsmToken::Integer))
7151 return TokError("expected an identifier or a number in directive");
7152 // We successfully get a numeric value for the identifier.
7153 // Check if it is valid.
7154 int64_t Id = getTok().getIntVal();
7155 if (Id <= -1U && !isValidMCLOHType(Id))
7156 return TokError("invalid numeric identifier in directive");
7157 Kind = (MCLOHType)Id;
7158 } else {
7159 StringRef Name = getTok().getIdentifier();
7160 // We successfully parse an identifier.
7161 // Check if it is a recognized one.
7162 int Id = MCLOHNameToId(Name);
7163
7164 if (Id == -1)
7165 return TokError("invalid identifier in directive");
7166 Kind = (MCLOHType)Id;
7167 }
7168 // Consume the identifier.
7169 Lex();
7170 // Get the number of arguments of this LOH.
7171 int NbArgs = MCLOHIdToNbArgs(Kind);
7172
7173 assert(NbArgs != -1 && "Invalid number of arguments");
7174
7176 for (int Idx = 0; Idx < NbArgs; ++Idx) {
7178 if (getParser().parseIdentifier(Name))
7179 return TokError("expected identifier in directive");
7180 Args.push_back(getContext().getOrCreateSymbol(Name));
7181
7182 if (Idx + 1 == NbArgs)
7183 break;
7184 if (parseComma())
7185 return true;
7186 }
7187 if (parseEOL())
7188 return true;
7189
7190 getStreamer().emitLOHDirective((MCLOHType)Kind, Args);
7191 return false;
7192}
7193
7194/// parseDirectiveLtorg
7195/// ::= .ltorg | .pool
7196bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
7197 if (parseEOL())
7198 return true;
7199 getTargetStreamer().emitCurrentConstantPool();
7200 return false;
7201}
7202
7203/// parseDirectiveReq
7204/// ::= name .req registername
7205bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7206 Lex(); // Eat the '.req' token.
7207 SMLoc SRegLoc = getLoc();
7208 RegKind RegisterKind = RegKind::Scalar;
7209 MCRegister RegNum;
7210 ParseStatus ParseRes = tryParseScalarRegister(RegNum);
7211
7212 if (!ParseRes.isSuccess()) {
7214 RegisterKind = RegKind::NeonVector;
7215 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
7216
7217 if (ParseRes.isFailure())
7218 return true;
7219
7220 if (ParseRes.isSuccess() && !Kind.empty())
7221 return Error(SRegLoc, "vector register without type specifier expected");
7222 }
7223
7224 if (!ParseRes.isSuccess()) {
7226 RegisterKind = RegKind::SVEDataVector;
7227 ParseRes =
7228 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
7229
7230 if (ParseRes.isFailure())
7231 return true;
7232
7233 if (ParseRes.isSuccess() && !Kind.empty())
7234 return Error(SRegLoc,
7235 "sve vector register without type specifier expected");
7236 }
7237
7238 if (!ParseRes.isSuccess()) {
7240 RegisterKind = RegKind::SVEPredicateVector;
7241 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
7242
7243 if (ParseRes.isFailure())
7244 return true;
7245
7246 if (ParseRes.isSuccess() && !Kind.empty())
7247 return Error(SRegLoc,
7248 "sve predicate register without type specifier expected");
7249 }
7250
7251 if (!ParseRes.isSuccess())
7252 return Error(SRegLoc, "register name or alias expected");
7253
7254 // Shouldn't be anything else.
7255 if (parseEOL())
7256 return true;
7257
7258 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
7259 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
7260 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
7261
7262 return false;
7263}
7264
7265/// parseDirectiveUneq
7266/// ::= .unreq registername
7267bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
7268 if (getTok().isNot(AsmToken::Identifier))
7269 return TokError("unexpected input in .unreq directive.");
7270 RegisterReqs.erase(getTok().getIdentifier().lower());
7271 Lex(); // Eat the identifier.
7272 return parseToken(AsmToken::EndOfStatement);
7273}
7274
7275bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
7276 if (parseEOL())
7277 return true;
7278 getStreamer().emitCFINegateRAState();
7279 return false;
7280}
7281
7282/// parseDirectiveCFIBKeyFrame
7283/// ::= .cfi_b_key
7284bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
7285 if (parseEOL())
7286 return true;
7287 getStreamer().emitCFIBKeyFrame();
7288 return false;
7289}
7290
7291/// parseDirectiveCFIMTETaggedFrame
7292/// ::= .cfi_mte_tagged_frame
7293bool AArch64AsmParser::parseDirectiveCFIMTETaggedFrame() {
7294 if (parseEOL())
7295 return true;
7296 getStreamer().emitCFIMTETaggedFrame();
7297 return false;
7298}
7299
7300/// parseDirectiveVariantPCS
7301/// ::= .variant_pcs symbolname
7302bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L) {
7304 if (getParser().parseIdentifier(Name))
7305 return TokError("expected symbol name");
7306 if (parseEOL())
7307 return true;
7308 getTargetStreamer().emitDirectiveVariantPCS(
7309 getContext().getOrCreateSymbol(Name));
7310 return false;
7311}
7312
7313/// parseDirectiveSEHAllocStack
7314/// ::= .seh_stackalloc
7315bool AArch64AsmParser::parseDirectiveSEHAllocStack(SMLoc L) {
7316 int64_t Size;
7317 if (parseImmExpr(Size))
7318 return true;
7319 getTargetStreamer().emitARM64WinCFIAllocStack(Size);
7320 return false;
7321}
7322
7323/// parseDirectiveSEHPrologEnd
7324/// ::= .seh_endprologue
7325bool AArch64AsmParser::parseDirectiveSEHPrologEnd(SMLoc L) {
7326 getTargetStreamer().emitARM64WinCFIPrologEnd();
7327 return false;
7328}
7329
7330/// parseDirectiveSEHSaveR19R20X
7331/// ::= .seh_save_r19r20_x
7332bool AArch64AsmParser::parseDirectiveSEHSaveR19R20X(SMLoc L) {
7333 int64_t Offset;
7334 if (parseImmExpr(Offset))
7335 return true;
7336 getTargetStreamer().emitARM64WinCFISaveR19R20X(Offset);
7337 return false;
7338}
7339
7340/// parseDirectiveSEHSaveFPLR
7341/// ::= .seh_save_fplr
7342bool AArch64AsmParser::parseDirectiveSEHSaveFPLR(SMLoc L) {
7343 int64_t Offset;
7344 if (parseImmExpr(Offset))
7345 return true;
7346 getTargetStreamer().emitARM64WinCFISaveFPLR(Offset);
7347 return false;
7348}
7349
7350/// parseDirectiveSEHSaveFPLRX
7351/// ::= .seh_save_fplr_x
7352bool AArch64AsmParser::parseDirectiveSEHSaveFPLRX(SMLoc L) {
7353 int64_t Offset;
7354 if (parseImmExpr(Offset))
7355 return true;
7356 getTargetStreamer().emitARM64WinCFISaveFPLRX(Offset);
7357 return false;
7358}
7359
7360/// parseDirectiveSEHSaveReg
7361/// ::= .seh_save_reg
7362bool AArch64AsmParser::parseDirectiveSEHSaveReg(SMLoc L) {
7363 unsigned Reg;
7364 int64_t Offset;
7365 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7366 parseComma() || parseImmExpr(Offset))
7367 return true;
7368 getTargetStreamer().emitARM64WinCFISaveReg(Reg, Offset);
7369 return false;
7370}
7371
7372/// parseDirectiveSEHSaveRegX
7373/// ::= .seh_save_reg_x
7374bool AArch64AsmParser::parseDirectiveSEHSaveRegX(SMLoc L) {
7375 unsigned Reg;
7376 int64_t Offset;
7377 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7378 parseComma() || parseImmExpr(Offset))
7379 return true;
7380 getTargetStreamer().emitARM64WinCFISaveRegX(Reg, Offset);
7381 return false;
7382}
7383
7384/// parseDirectiveSEHSaveRegP
7385/// ::= .seh_save_regp
7386bool AArch64AsmParser::parseDirectiveSEHSaveRegP(SMLoc L) {
7387 unsigned Reg;
7388 int64_t Offset;
7389 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::FP) ||
7390 parseComma() || parseImmExpr(Offset))
7391 return true;
7392 getTargetStreamer().emitARM64WinCFISaveRegP(Reg, Offset);
7393 return false;
7394}
7395
7396/// parseDirectiveSEHSaveRegPX
7397/// ::= .seh_save_regp_x
7398bool AArch64AsmParser::parseDirectiveSEHSaveRegPX(SMLoc L) {
7399 unsigned Reg;
7400 int64_t Offset;
7401 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::FP) ||
7402 parseComma() || parseImmExpr(Offset))
7403 return true;
7404 getTargetStreamer().emitARM64WinCFISaveRegPX(Reg, Offset);
7405 return false;
7406}
7407
7408/// parseDirectiveSEHSaveLRPair
7409/// ::= .seh_save_lrpair
7410bool AArch64AsmParser::parseDirectiveSEHSaveLRPair(SMLoc L) {
7411 unsigned Reg;
7412 int64_t Offset;
7413 L = getLoc();
7414 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7415 parseComma() || parseImmExpr(Offset))
7416 return true;
7417 if (check(((Reg - 19) % 2 != 0), L,
7418 "expected register with even offset from x19"))
7419 return true;
7420 getTargetStreamer().emitARM64WinCFISaveLRPair(Reg, Offset);
7421 return false;
7422}
7423
7424/// parseDirectiveSEHSaveFReg
7425/// ::= .seh_save_freg
7426bool AArch64AsmParser::parseDirectiveSEHSaveFReg(SMLoc L) {
7427 unsigned Reg;
7428 int64_t Offset;
7429 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D15) ||
7430 parseComma() || parseImmExpr(Offset))
7431 return true;
7432 getTargetStreamer().emitARM64WinCFISaveFReg(Reg, Offset);
7433 return false;
7434}
7435
7436/// parseDirectiveSEHSaveFRegX
7437/// ::= .seh_save_freg_x
7438bool AArch64AsmParser::parseDirectiveSEHSaveFRegX(SMLoc L) {
7439 unsigned Reg;
7440 int64_t Offset;
7441 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D15) ||
7442 parseComma() || parseImmExpr(Offset))
7443 return true;
7444 getTargetStreamer().emitARM64WinCFISaveFRegX(Reg, Offset);
7445 return false;
7446}
7447
7448/// parseDirectiveSEHSaveFRegP
7449/// ::= .seh_save_fregp
7450bool AArch64AsmParser::parseDirectiveSEHSaveFRegP(SMLoc L) {
7451 unsigned Reg;
7452 int64_t Offset;
7453 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D14) ||
7454 parseComma() || parseImmExpr(Offset))
7455 return true;
7456 getTargetStreamer().emitARM64WinCFISaveFRegP(Reg, Offset);
7457 return false;
7458}
7459
7460/// parseDirectiveSEHSaveFRegPX
7461/// ::= .seh_save_fregp_x
7462bool AArch64AsmParser::parseDirectiveSEHSaveFRegPX(SMLoc L) {
7463 unsigned Reg;
7464 int64_t Offset;
7465 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D14) ||
7466 parseComma() || parseImmExpr(Offset))
7467 return true;
7468 getTargetStreamer().emitARM64WinCFISaveFRegPX(Reg, Offset);
7469 return false;
7470}
7471
7472/// parseDirectiveSEHSetFP
7473/// ::= .seh_set_fp
7474bool AArch64AsmParser::parseDirectiveSEHSetFP(SMLoc L) {
7475 getTargetStreamer().emitARM64WinCFISetFP();
7476 return false;
7477}
7478
7479/// parseDirectiveSEHAddFP
7480/// ::= .seh_add_fp
7481bool AArch64AsmParser::parseDirectiveSEHAddFP(SMLoc L) {
7482 int64_t Size;
7483 if (parseImmExpr(Size))
7484 return true;
7485 getTargetStreamer().emitARM64WinCFIAddFP(Size);
7486 return false;
7487}
7488
7489/// parseDirectiveSEHNop
7490/// ::= .seh_nop
7491bool AArch64AsmParser::parseDirectiveSEHNop(SMLoc L) {
7492 getTargetStreamer().emitARM64WinCFINop();
7493 return false;
7494}
7495
7496/// parseDirectiveSEHSaveNext
7497/// ::= .seh_save_next
7498bool AArch64AsmParser::parseDirectiveSEHSaveNext(SMLoc L) {
7499 getTargetStreamer().emitARM64WinCFISaveNext();
7500 return false;
7501}
7502
7503/// parseDirectiveSEHEpilogStart
7504/// ::= .seh_startepilogue
7505bool AArch64AsmParser::parseDirectiveSEHEpilogStart(SMLoc L) {
7506 getTargetStreamer().emitARM64WinCFIEpilogStart();
7507 return false;
7508}
7509
7510/// parseDirectiveSEHEpilogEnd
7511/// ::= .seh_endepilogue
7512bool AArch64AsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) {
7513 getTargetStreamer().emitARM64WinCFIEpilogEnd();
7514 return false;
7515}
7516
7517/// parseDirectiveSEHTrapFrame
7518/// ::= .seh_trap_frame
7519bool AArch64AsmParser::parseDirectiveSEHTrapFrame(SMLoc L) {
7520 getTargetStreamer().emitARM64WinCFITrapFrame();
7521 return false;
7522}
7523
7524/// parseDirectiveSEHMachineFrame
7525/// ::= .seh_pushframe
7526bool AArch64AsmParser::parseDirectiveSEHMachineFrame(SMLoc L) {
7527 getTargetStreamer().emitARM64WinCFIMachineFrame();
7528 return false;
7529}
7530
7531/// parseDirectiveSEHContext
7532/// ::= .seh_context
7533bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L) {
7534 getTargetStreamer().emitARM64WinCFIContext();
7535 return false;
7536}
7537
7538/// parseDirectiveSEHECContext
7539/// ::= .seh_ec_context
7540bool AArch64AsmParser::parseDirectiveSEHECContext(SMLoc L) {
7541 getTargetStreamer().emitARM64WinCFIECContext();
7542 return false;
7543}
7544
7545/// parseDirectiveSEHClearUnwoundToCall
7546/// ::= .seh_clear_unwound_to_call
7547bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
7548 getTargetStreamer().emitARM64WinCFIClearUnwoundToCall();
7549 return false;
7550}
7551
7552/// parseDirectiveSEHPACSignLR
7553/// ::= .seh_pac_sign_lr
7554bool AArch64AsmParser::parseDirectiveSEHPACSignLR(SMLoc L) {
7555 getTargetStreamer().emitARM64WinCFIPACSignLR();
7556 return false;
7557}
7558
7559/// parseDirectiveSEHSaveAnyReg
7560/// ::= .seh_save_any_reg
7561/// ::= .seh_save_any_reg_p
7562/// ::= .seh_save_any_reg_x
7563/// ::= .seh_save_any_reg_px
7564bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
7565 bool Writeback) {
7567 SMLoc Start, End;
7568 int64_t Offset;
7569 if (check(parseRegister(Reg, Start, End), getLoc(), "expected register") ||
7570 parseComma() || parseImmExpr(Offset))
7571 return true;
7572
7573 if (Reg == AArch64::FP || Reg == AArch64::LR ||
7574 (Reg >= AArch64::X0 && Reg <= AArch64::X28)) {
7575 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7576 return Error(L, "invalid save_any_reg offset");
7577 unsigned EncodedReg;
7578 if (Reg == AArch64::FP)
7579 EncodedReg = 29;
7580 else if (Reg == AArch64::LR)
7581 EncodedReg = 30;
7582 else
7583 EncodedReg = Reg - AArch64::X0;
7584 if (Paired) {
7585 if (Reg == AArch64::LR)
7586 return Error(Start, "lr cannot be paired with another register");
7587 if (Writeback)
7588 getTargetStreamer().emitARM64WinCFISaveAnyRegIPX(EncodedReg, Offset);
7589 else
7590 getTargetStreamer().emitARM64WinCFISaveAnyRegIP(EncodedReg, Offset);
7591 } else {
7592 if (Writeback)
7593 getTargetStreamer().emitARM64WinCFISaveAnyRegIX(EncodedReg, Offset);
7594 else
7595 getTargetStreamer().emitARM64WinCFISaveAnyRegI(EncodedReg, Offset);
7596 }
7597 } else if (Reg >= AArch64::D0 && Reg <= AArch64::D31) {
7598 unsigned EncodedReg = Reg - AArch64::D0;
7599 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7600 return Error(L, "invalid save_any_reg offset");
7601 if (Paired) {
7602 if (Reg == AArch64::D31)
7603 return Error(Start, "d31 cannot be paired with another register");
7604 if (Writeback)
7605 getTargetStreamer().emitARM64WinCFISaveAnyRegDPX(EncodedReg, Offset);
7606 else
7607 getTargetStreamer().emitARM64WinCFISaveAnyRegDP(EncodedReg, Offset);
7608 } else {
7609 if (Writeback)
7610 getTargetStreamer().emitARM64WinCFISaveAnyRegDX(EncodedReg, Offset);
7611 else
7612 getTargetStreamer().emitARM64WinCFISaveAnyRegD(EncodedReg, Offset);
7613 }
7614 } else if (Reg >= AArch64::Q0 && Reg <= AArch64::Q31) {
7615 unsigned EncodedReg = Reg - AArch64::Q0;
7616 if (Offset < 0 || Offset % 16)
7617 return Error(L, "invalid save_any_reg offset");
7618 if (Paired) {
7619 if (Reg == AArch64::Q31)
7620 return Error(Start, "q31 cannot be paired with another register");
7621 if (Writeback)
7622 getTargetStreamer().emitARM64WinCFISaveAnyRegQPX(EncodedReg, Offset);
7623 else
7624 getTargetStreamer().emitARM64WinCFISaveAnyRegQP(EncodedReg, Offset);
7625 } else {
7626 if (Writeback)
7627 getTargetStreamer().emitARM64WinCFISaveAnyRegQX(EncodedReg, Offset);
7628 else
7629 getTargetStreamer().emitARM64WinCFISaveAnyRegQ(EncodedReg, Offset);
7630 }
7631 } else {
7632 return Error(Start, "save_any_reg register must be x, q or d register");
7633 }
7634 return false;
7635}
7636
7637bool AArch64AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
7638 // Try @AUTH expressions: they're more complex than the usual symbol variants.
7639 if (!parseAuthExpr(Res, EndLoc))
7640 return false;
7641 return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
7642}
7643
7644/// parseAuthExpr
7645/// ::= _sym@AUTH(ib,123[,addr])
7646/// ::= (_sym + 5)@AUTH(ib,123[,addr])
7647/// ::= (_sym - 5)@AUTH(ib,123[,addr])
7648bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
7649 MCAsmParser &Parser = getParser();
7650 MCContext &Ctx = getContext();
7651
7652 AsmToken Tok = Parser.getTok();
7653
7654 // Look for '_sym@AUTH' ...
7655 if (Tok.is(AsmToken::Identifier) && Tok.getIdentifier().ends_with("@AUTH")) {
7656 StringRef SymName = Tok.getIdentifier().drop_back(strlen("@AUTH"));
7657 if (SymName.contains('@'))
7658 return TokError(
7659 "combination of @AUTH with other modifiers not supported");
7660 Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
7661
7662 Parser.Lex(); // Eat the identifier.
7663 } else {
7664 // ... or look for a more complex symbol reference, such as ...
7666
7667 // ... '"_long sym"@AUTH' ...
7668 if (Tok.is(AsmToken::String))
7669 Tokens.resize(2);
7670 // ... or '(_sym + 5)@AUTH'.
7671 else if (Tok.is(AsmToken::LParen))
7672 Tokens.resize(6);
7673 else
7674 return true;
7675
7676 if (Parser.getLexer().peekTokens(Tokens) != Tokens.size())
7677 return true;
7678
7679 // In either case, the expression ends with '@' 'AUTH'.
7680 if (Tokens[Tokens.size() - 2].isNot(AsmToken::At) ||
7681 Tokens[Tokens.size() - 1].isNot(AsmToken::Identifier) ||
7682 Tokens[Tokens.size() - 1].getIdentifier() != "AUTH")
7683 return true;
7684
7685 if (Tok.is(AsmToken::String)) {
7686 StringRef SymName;
7687 if (Parser.parseIdentifier(SymName))
7688 return true;
7689 Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
7690 } else {
7691 if (Parser.parsePrimaryExpr(Res, EndLoc, nullptr))
7692 return true;
7693 }
7694
7695 Parser.Lex(); // '@'
7696 Parser.Lex(); // 'AUTH'
7697 }
7698
7699 // At this point, we encountered "<id>@AUTH". There is no fallback anymore.
7700 if (parseToken(AsmToken::LParen, "expected '('"))
7701 return true;
7702
7703 if (Parser.getTok().isNot(AsmToken::Identifier))
7704 return TokError("expected key name");
7705
7706 StringRef KeyStr = Parser.getTok().getIdentifier();
7707 auto KeyIDOrNone = AArch64StringToPACKeyID(KeyStr);
7708 if (!KeyIDOrNone)
7709 return TokError("invalid key '" + KeyStr + "'");
7710 Parser.Lex();
7711
7712 if (parseToken(AsmToken::Comma, "expected ','"))
7713 return true;
7714
7715 if (Parser.getTok().isNot(AsmToken::Integer))
7716 return TokError("expected integer discriminator");
7717 int64_t Discriminator = Parser.getTok().getIntVal();
7718
7719 if (!isUInt<16>(Discriminator))
7720 return TokError("integer discriminator " + Twine(Discriminator) +
7721 " out of range [0, 0xFFFF]");
7722 Parser.Lex();
7723
7724 bool UseAddressDiversity = false;
7725 if (Parser.getTok().is(AsmToken::Comma)) {
7726 Parser.Lex();
7727 if (Parser.getTok().isNot(AsmToken::Identifier) ||
7728 Parser.getTok().getIdentifier() != "addr")
7729 return TokError("expected 'addr'");
7730 UseAddressDiversity = true;
7731 Parser.Lex();
7732 }
7733
7734 EndLoc = Parser.getTok().getEndLoc();
7735 if (parseToken(AsmToken::RParen, "expected ')'"))
7736 return true;
7737
7738 Res = AArch64AuthMCExpr::create(Res, Discriminator, *KeyIDOrNone,
7739 UseAddressDiversity, Ctx);
7740 return false;
7741}
7742
7743bool
7744AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
7745 AArch64MCExpr::VariantKind &ELFRefKind,
7746 MCSymbolRefExpr::VariantKind &DarwinRefKind,
7747 int64_t &Addend) {
7748 ELFRefKind = AArch64MCExpr::VK_INVALID;
7749 DarwinRefKind = MCSymbolRefExpr::VK_None;
7750 Addend = 0;
7751
7752 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
7753 ELFRefKind = AE->getKind();
7754 Expr = AE->getSubExpr();
7755 }
7756
7757 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
7758 if (SE) {
7759 // It's a simple symbol reference with no addend.
7760 DarwinRefKind = SE->getKind();
7761 return true;
7762 }
7763
7764 // Check that it looks like a symbol + an addend
7765 MCValue Res;
7766 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
7767 if (!Relocatable || Res.getSymB())
7768 return false;
7769
7770 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
7771 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
7772 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
7773 return false;
7774
7775 if (Res.getSymA())
7776 DarwinRefKind = Res.getSymA()->getKind();
7777 Addend = Res.getConstant();
7778
7779 // It's some symbol reference + a constant addend, but really
7780 // shouldn't use both Darwin and ELF syntax.
7781 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
7782 DarwinRefKind == MCSymbolRefExpr::VK_None;
7783}
7784
7785/// Force static initialization.
7792}
7793
7794#define GET_REGISTER_MATCHER
7795#define GET_SUBTARGET_FEATURE_NAME
7796#define GET_MATCHER_IMPLEMENTATION
7797#define GET_MNEMONIC_SPELL_CHECKER
7798#include "AArch64GenAsmMatcher.inc"
7799
7800// Define this matcher function after the auto-generated include so we
7801// have the match class enum definitions.
7802unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
7803 unsigned Kind) {
7804 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
7805
7806 auto MatchesOpImmediate = [&](int64_t ExpectedVal) -> MatchResultTy {
7807 if (!Op.isImm())
7808 return Match_InvalidOperand;
7809 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
7810 if (!CE)
7811 return Match_InvalidOperand;
7812 if (CE->getValue() == ExpectedVal)
7813 return Match_Success;
7814 return Match_InvalidOperand;
7815 };
7816
7817 switch (Kind) {
7818 default:
7819 return Match_InvalidOperand;
7820 case MCK_MPR:
7821 // If the Kind is a token for the MPR register class which has the "za"
7822 // register (SME accumulator array), check if the asm is a literal "za"
7823 // token. This is for the "smstart za" alias that defines the register
7824 // as a literal token.
7825 if (Op.isTokenEqual("za"))
7826 return Match_Success;
7827 return Match_InvalidOperand;
7828
7829 // If the kind is a token for a literal immediate, check if our asm operand
7830 // matches. This is for InstAliases which have a fixed-value immediate in
7831 // the asm string, such as hints which are parsed into a specific
7832 // instruction definition.
7833#define MATCH_HASH(N) \
7834 case MCK__HASH_##N: \
7835 return MatchesOpImmediate(N);
7836 MATCH_HASH(0)
7837 MATCH_HASH(1)
7838 MATCH_HASH(2)
7839 MATCH_HASH(3)
7840 MATCH_HASH(4)
7841 MATCH_HASH(6)
7842 MATCH_HASH(7)
7843 MATCH_HASH(8)
7844 MATCH_HASH(10)
7845 MATCH_HASH(12)
7846 MATCH_HASH(14)
7847 MATCH_HASH(16)
7848 MATCH_HASH(24)
7849 MATCH_HASH(25)
7850 MATCH_HASH(26)
7851 MATCH_HASH(27)
7852 MATCH_HASH(28)
7853 MATCH_HASH(29)
7854 MATCH_HASH(30)
7855 MATCH_HASH(31)
7856 MATCH_HASH(32)
7857 MATCH_HASH(40)
7858 MATCH_HASH(48)
7859 MATCH_HASH(64)
7860#undef MATCH_HASH
7861#define MATCH_HASH_MINUS(N) \
7862 case MCK__HASH__MINUS_##N: \
7863 return MatchesOpImmediate(-N);
7867#undef MATCH_HASH_MINUS
7868 }
7869}
7870
7871ParseStatus AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
7872
7873 SMLoc S = getLoc();
7874
7875 if (getTok().isNot(AsmToken::Identifier))
7876 return Error(S, "expected register");
7877
7878 MCRegister FirstReg;
7879 ParseStatus Res = tryParseScalarRegister(FirstReg);
7880 if (!Res.isSuccess())
7881 return Error(S, "expected first even register of a consecutive same-size "
7882 "even/odd register pair");
7883
7884 const MCRegisterClass &WRegClass =
7885 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
7886 const MCRegisterClass &XRegClass =
7887 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
7888
7889 bool isXReg = XRegClass.contains(FirstReg),
7890 isWReg = WRegClass.contains(FirstReg);
7891 if (!isXReg && !isWReg)
7892 return Error(S, "expected first even register of a consecutive same-size "
7893 "even/odd register pair");
7894
7895 const MCRegisterInfo *RI = getContext().getRegisterInfo();
7896 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
7897
7898 if (FirstEncoding & 0x1)
7899 return Error(S, "expected first even register of a consecutive same-size "
7900 "even/odd register pair");
7901
7902 if (getTok().isNot(AsmToken::Comma))
7903 return Error(getLoc(), "expected comma");
7904 // Eat the comma
7905 Lex();
7906
7907 SMLoc E = getLoc();
7908 MCRegister SecondReg;
7909 Res = tryParseScalarRegister(SecondReg);
7910 if (!Res.isSuccess())
7911 return Error(E, "expected second odd register of a consecutive same-size "
7912 "even/odd register pair");
7913
7914 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
7915 (isXReg && !XRegClass.contains(SecondReg)) ||
7916 (isWReg && !WRegClass.contains(SecondReg)))
7917 return Error(E, "expected second odd register of a consecutive same-size "
7918 "even/odd register pair");
7919
7920 unsigned Pair = 0;
7921 if (isXReg) {
7922 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
7923 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
7924 } else {
7925 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
7926 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
7927 }
7928
7929 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
7930 getLoc(), getContext()));
7931
7932 return ParseStatus::Success;
7933}
7934
7935template <bool ParseShiftExtend, bool ParseSuffix>
7936ParseStatus AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
7937 const SMLoc S = getLoc();
7938 // Check for a SVE vector register specifier first.
7939 MCRegister RegNum;
7941
7942 ParseStatus Res =
7943 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
7944
7945 if (!Res.isSuccess())
7946 return Res;
7947
7948 if (ParseSuffix && Kind.empty())
7949 return ParseStatus::NoMatch;
7950
7951 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
7952 if (!KindRes)
7953 return ParseStatus::NoMatch;
7954
7955 unsigned ElementWidth = KindRes->second;
7956
7957 // No shift/extend is the default.
7958 if (!ParseShiftExtend || getTok().isNot(AsmToken::Comma)) {
7959 Operands.push_back(AArch64Operand::CreateVectorReg(
7960 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
7961
7962 ParseStatus Res = tryParseVectorIndex(Operands);
7963 if (Res.isFailure())
7964 return ParseStatus::Failure;
7965 return ParseStatus::Success;
7966 }
7967
7968 // Eat the comma
7969 Lex();
7970
7971 // Match the shift
7973 Res = tryParseOptionalShiftExtend(ExtOpnd);
7974 if (!Res.isSuccess())
7975 return Res;
7976
7977 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
7978 Operands.push_back(AArch64Operand::CreateVectorReg(
7979 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
7980 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
7981 Ext->hasShiftExtendAmount()));
7982
7983 return ParseStatus::Success;
7984}
7985
7986ParseStatus AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
7987 MCAsmParser &Parser = getParser();
7988
7989 SMLoc SS = getLoc();
7990 const AsmToken &TokE = getTok();
7991 bool IsHash = TokE.is(AsmToken::Hash);
7992
7993 if (!IsHash && TokE.isNot(AsmToken::Identifier))
7994 return ParseStatus::NoMatch;
7995
7996 int64_t Pattern;
7997 if (IsHash) {
7998 Lex(); // Eat hash
7999
8000 // Parse the immediate operand.
8001 const MCExpr *ImmVal;
8002 SS = getLoc();
8003 if (Parser.parseExpression(ImmVal))
8004 return ParseStatus::Failure;
8005
8006 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
8007 if (!MCE)
8008 return TokError("invalid operand for instruction");
8009
8010 Pattern = MCE->getValue();
8011 } else {
8012 // Parse the pattern
8013 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
8014 if (!Pat)
8015 return ParseStatus::NoMatch;
8016
8017 Lex();
8018 Pattern = Pat->Encoding;
8019 assert(Pattern >= 0 && Pattern < 32);
8020 }
8021
8022 Operands.push_back(
8023 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
8024 SS, getLoc(), getContext()));
8025
8026 return ParseStatus::Success;
8027}
8028
8030AArch64AsmParser::tryParseSVEVecLenSpecifier(OperandVector &Operands) {
8031 int64_t Pattern;
8032 SMLoc SS = getLoc();
8033 const AsmToken &TokE = getTok();
8034 // Parse the pattern
8035 auto Pat = AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByName(
8036 TokE.getString());
8037 if (!Pat)
8038 return ParseStatus::NoMatch;
8039
8040 Lex();
8041 Pattern = Pat->Encoding;
8042 assert(Pattern >= 0 && Pattern <= 1 && "Pattern does not exist");
8043
8044 Operands.push_back(
8045 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
8046 SS, getLoc(), getContext()));
8047
8048 return ParseStatus::Success;
8049}
8050
8051ParseStatus AArch64AsmParser::tryParseGPR64x8(OperandVector &Operands) {
8052 SMLoc SS = getLoc();
8053
8054 MCRegister XReg;
8055 if (!tryParseScalarRegister(XReg).isSuccess())
8056 return ParseStatus::NoMatch;
8057
8058 MCContext &ctx = getContext();
8059 const MCRegisterInfo *RI = ctx.getRegisterInfo();
8060 int X8Reg = RI->getMatchingSuperReg(
8061 XReg, AArch64::x8sub_0,
8062 &AArch64MCRegisterClasses[AArch64::GPR64x8ClassRegClassID]);
8063 if (!X8Reg)
8064 return Error(SS,
8065 "expected an even-numbered x-register in the range [x0,x22]");
8066
8067 Operands.push_back(
8068 AArch64Operand::CreateReg(X8Reg, RegKind::Scalar, SS, getLoc(), ctx));
8069 return ParseStatus::Success;
8070}
8071
8072ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
8073 SMLoc S = getLoc();
8074
8075 if (getTok().isNot(AsmToken::Integer))
8076 return ParseStatus::NoMatch;
8077
8078 if (getLexer().peekTok().isNot(AsmToken::Colon))
8079 return ParseStatus::NoMatch;
8080
8081 const MCExpr *ImmF;
8082 if (getParser().parseExpression(ImmF))
8083 return ParseStatus::NoMatch;
8084
8085 if (getTok().isNot(AsmToken::Colon))
8086 return ParseStatus::NoMatch;
8087
8088 Lex(); // Eat ':'
8089 if (getTok().isNot(AsmToken::Integer))
8090 return ParseStatus::NoMatch;
8091
8092 SMLoc E = getTok().getLoc();
8093 const MCExpr *ImmL;
8094 if (getParser().parseExpression(ImmL))
8095 return ParseStatus::NoMatch;
8096
8097 unsigned ImmFVal = cast<MCConstantExpr>(ImmF)->getValue();
8098 unsigned ImmLVal = cast<MCConstantExpr>(ImmL)->getValue();
8099
8100 Operands.push_back(
8101 AArch64Operand::CreateImmRange(ImmFVal, ImmLVal, S, E, getContext()));
8102 return ParseStatus::Success;
8103}
#define MATCH_HASH_MINUS(N)
static unsigned matchSVEDataVectorRegName(StringRef Name)
static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind)
static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo, SmallVector< StringRef, 4 > &RequestedExtensions)
static unsigned matchSVEPredicateAsCounterRegName(StringRef Name)
static MCRegister MatchRegisterName(StringRef Name)
static bool isMatchingOrAlias(unsigned ZReg, unsigned Reg)
static const char * getSubtargetFeatureName(uint64_t Val)
static unsigned MatchNeonVectorRegName(StringRef Name)
}
static std::optional< std::pair< int, int > > parseVectorKind(StringRef Suffix, RegKind VectorKind)
Returns an optional pair of (#elements, element-width) if Suffix is a valid vector kind.
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmParser()
Force static initialization.
static unsigned matchMatrixRegName(StringRef Name)
static unsigned matchMatrixTileListRegName(StringRef Name)
static std::string AArch64MnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID=0)
static SMLoc incrementLoc(SMLoc L, int Offset)
#define MATCH_HASH(N)
static const struct Extension ExtensionMap[]
static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str)
static unsigned matchSVEPredicateVectorRegName(StringRef Name)
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Given that RA is a live value
@ Default
Definition: DwarfDebug.cpp:87
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define check(cond)
static LVOptions Options
Definition: LVOptions.cpp:25
Live Register Matrix
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
static MSP430CC::CondCodes getCondCode(unsigned Cond)
unsigned Reg
#define T
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallSet class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx)
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
APInt bitcastToAPInt() const
Definition: APFloat.h:1254
Class for arbitrary precision integers.
Definition: APInt.h:77
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
Definition: APInt.h:414
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition: APInt.h:411
int64_t getSExtValue() const
Get sign extended value.
Definition: APInt.h:1521
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
int64_t getIntVal() const
Definition: MCAsmMacro.h:115
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:83
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:99
This class represents an Operation in the Expression.
Base class for user error types.
Definition: Error.h:355
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Container class for subtarget features.
constexpr size_t size() const
void UnLex(AsmToken const &Token)
Definition: MCAsmLexer.h:93
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
Definition: MCAsmLexer.h:111
virtual size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)=0
Look ahead an arbitrary number of tokens.
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, AsmTypeInfo *TypeInfo)=0
Parse a primary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual MCAsmLexer & getLexer()=0
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
int64_t getValue() const
Definition: MCExpr.h:173
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:212
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:803
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getNumOperands() const
Definition: MCInst.h:208
void setLoc(SMLoc loc)
Definition: MCInst.h:203
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Definition: MCInstrDesc.h:219
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
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual MCRegister getReg() const =0
MCRegisterClass - Base class of TargetRegisterClass.
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx, const MCRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg.
const char * getName(MCRegister RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register.
uint16_t getEncodingValue(MCRegister RegNo) const
Returns the encoding for RegNo.
bool isSubRegisterEq(MCRegister RegA, MCRegister RegB) const
Returns true if RegB is a sub-register of RegA or if RegB == RegA.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Streaming machine code generation interface.
Definition: MCStreamer.h:213
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:313
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
const FeatureBitset & getFeatureBits() const
FeatureBitset SetFeatureBitsTransitively(const FeatureBitset &FB)
Set/clear additional feature bits, including all other bits they imply.
void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
Set the features to the default for the given CPU and TuneCPU, with ano appended feature string.
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:397
VariantKind getKind() const
Definition: MCExpr.h:412
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual bool ParseDirective(AsmToken DirectiveID)
ParseDirective - Parse a target specific assembler directive This method is deprecated,...
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc)
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
virtual bool areEqualRegs(const MCParsedAsmOperand &Op1, const MCParsedAsmOperand &Op2) const
Returns whether two operands are registers and are equal.
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 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 ...
Target specific streamer interface.
Definition: MCStreamer.h:94
This represents an "assembler immediate".
Definition: MCValue.h:36
int64_t getConstant() const
Definition: MCValue.h:43
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:45
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:44
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
constexpr bool isNoMatch() const
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
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
bool contains(const T &V) const
Check if the SmallSet contains the given element.
Definition: SmallSet.h:236
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:179
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void resize(size_type N)
Definition: SmallVector.h:651
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
iterator end()
Definition: StringMap.h:220
iterator find(StringRef Key)
Definition: StringMap.h:233
void erase(iterator I)
Definition: StringMap.h:416
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:308
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:693
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:463
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:258
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:602
std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:116
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:417
StringRef take_back(size_t N=1) const
Return a StringRef equal to 'this' but with only the last N elements remaining.
Definition: StringRef.h:582
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:808
std::string lower() const
Definition: StringRef.cpp:111
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:270
static constexpr size_t npos
Definition: StringRef.h:52
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:609
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:171
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
Definition: Triple.h:390
bool isWindowsArm64EC() const
Definition: Triple.h:640
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
uint32_t parseGenericRegister(StringRef Name)
const SysReg * lookupSysRegByName(StringRef)
static bool isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth)
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
static float getFPImmFloat(unsigned Imm)
static uint8_t encodeAdvSIMDModImmType10(uint64_t Imm)
static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth)
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static const char * getShiftExtendName(AArch64_AM::ShiftExtendType ST)
getShiftName - Get the string encoding for the shift type.
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static bool isAdvSIMDModImmType10(uint64_t Imm)
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
const ArchInfo * parseArch(StringRef Arch)
const ArchInfo * getArchForCpu(StringRef CPU)
bool getExtensionFeatures(const AArch64::ExtensionBitset &Extensions, std::vector< StringRef > &Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
bool isPredicated(const MCInst &MI, const MCInstrInfo *MCII)
@ Entry
Definition: COFF.h:811
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition: CallingConv.h:76
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1554
float getFPImm(unsigned Imm)
@ CE
Windows NT (Windows on ARM)
@ SS
Definition: X86.h:207
Reg
All possible values of the reg field in the ModR/M byte.
constexpr double e
Definition: MathExtras.h:31
NodeAddr< CodeNode * > Code
Definition: RDFGraph.h:388
Format
The format used for serializing/deserializing remarks.
Definition: RemarkFormat.h:25
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
static std::optional< AArch64PACKey::ID > AArch64StringToPACKeyID(StringRef Name)
Return numeric key ID for 2-letter identifier string.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1099
@ Offset
Definition: DWP.cpp:480
@ Length
Definition: DWP.cpp:480
static int MCLOHNameToId(StringRef Name)
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:170
Target & getTheAArch64beTarget()
static StringRef MCLOHDirectiveName()
static bool isValidMCLOHType(unsigned Kind)
Target & getTheAArch64leTarget()
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition: bit.h:215
static unsigned getXRegFromWReg(unsigned Reg)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:324
Target & getTheAArch64_32Target()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
Target & getTheARM64_32Target()
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
static int MCLOHIdToNbArgs(MCLOHType Kind)
MCLOHType
Linker Optimization Hint Type.
static unsigned getWRegFromXReg(unsigned Reg)
Target & getTheARM64Target()
DWARFExpression::Operation Op
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1879
#define N
const FeatureBitset Features
const char * Name
A record for a potential prefetch made during the initial scan of the loop.
AArch64::ExtensionBitset DefaultExts
Description of the encoding of one expression Op.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
bool haveFeatures(FeatureBitset ActiveFeatures) const
FeatureBitset getRequiredFeatures() const
const char * Name
FeatureBitset FeaturesRequired