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