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