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