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