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