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