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