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