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