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