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