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 isTypedVectorListMultiple() 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_InvalidLookupTable:
6416 return Error(Loc, "Invalid lookup table, expected zt0");
6417 case Match_InvalidSVEVectorListStrided2x8:
6418 case Match_InvalidSVEVectorListStrided2x16:
6419 case Match_InvalidSVEVectorListStrided2x32:
6420 case Match_InvalidSVEVectorListStrided2x64:
6421 return Error(
6422 Loc,
6423 "Invalid vector list, expected list with each SVE vector in the list "
6424 "8 registers apart, and the first register in the range [z0, z7] or "
6425 "[z16, z23] and with correct element type");
6426 case Match_InvalidSVEVectorListStrided4x8:
6427 case Match_InvalidSVEVectorListStrided4x16:
6428 case Match_InvalidSVEVectorListStrided4x32:
6429 case Match_InvalidSVEVectorListStrided4x64:
6430 return Error(
6431 Loc,
6432 "Invalid vector list, expected list with each SVE vector in the list "
6433 "4 registers apart, and the first register in the range [z0, z3] or "
6434 "[z16, z19] and with correct element type");
6435 case Match_AddSubLSLImm3ShiftLarge:
6436 return Error(Loc,
6437 "expected 'lsl' with optional integer in range [0, 7]");
6438 default:
6439 llvm_unreachable("unexpected error code!");
6440 }
6441}
6442
6443static const char *getSubtargetFeatureName(uint64_t Val);
6444
6445bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
6446 OperandVector &Operands,
6447 MCStreamer &Out,
6449 bool MatchingInlineAsm) {
6450 assert(!Operands.empty() && "Unexpected empty operand list!");
6451 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
6452 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
6453
6454 StringRef Tok = Op.getToken();
6455 unsigned NumOperands = Operands.size();
6456
6457 if (NumOperands == 4 && Tok == "lsl") {
6458 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6459 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6460 if (Op2.isScalarReg() && Op3.isImm()) {
6461 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6462 if (Op3CE) {
6463 uint64_t Op3Val = Op3CE->getValue();
6464 uint64_t NewOp3Val = 0;
6465 uint64_t NewOp4Val = 0;
6466 if (getAArch64MCRegisterClass(AArch64::GPR32allRegClassID)
6467 .contains(Op2.getReg())) {
6468 NewOp3Val = (32 - Op3Val) & 0x1f;
6469 NewOp4Val = 31 - Op3Val;
6470 } else {
6471 NewOp3Val = (64 - Op3Val) & 0x3f;
6472 NewOp4Val = 63 - Op3Val;
6473 }
6474
6475 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
6476 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
6477
6478 Operands[0] =
6479 AArch64Operand::CreateToken("ubfm", Op.getStartLoc(), getContext());
6480 Operands.push_back(AArch64Operand::CreateImm(
6481 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
6482 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
6483 Op3.getEndLoc(), getContext());
6484 }
6485 }
6486 } else if (NumOperands == 4 && Tok == "bfc") {
6487 // FIXME: Horrible hack to handle BFC->BFM alias.
6488 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6489 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
6490 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
6491
6492 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
6493 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
6494 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
6495
6496 if (LSBCE && WidthCE) {
6497 uint64_t LSB = LSBCE->getValue();
6498 uint64_t Width = WidthCE->getValue();
6499
6500 uint64_t RegWidth = 0;
6501 if (getAArch64MCRegisterClass(AArch64::GPR64allRegClassID)
6502 .contains(Op1.getReg()))
6503 RegWidth = 64;
6504 else
6505 RegWidth = 32;
6506
6507 if (LSB >= RegWidth)
6508 return Error(LSBOp.getStartLoc(),
6509 "expected integer in range [0, 31]");
6510 if (Width < 1 || Width > RegWidth)
6511 return Error(WidthOp.getStartLoc(),
6512 "expected integer in range [1, 32]");
6513
6514 uint64_t ImmR = 0;
6515 if (RegWidth == 32)
6516 ImmR = (32 - LSB) & 0x1f;
6517 else
6518 ImmR = (64 - LSB) & 0x3f;
6519
6520 uint64_t ImmS = Width - 1;
6521
6522 if (ImmR != 0 && ImmS >= ImmR)
6523 return Error(WidthOp.getStartLoc(),
6524 "requested insert overflows register");
6525
6526 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
6527 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
6528 Operands[0] =
6529 AArch64Operand::CreateToken("bfm", Op.getStartLoc(), getContext());
6530 Operands[2] = AArch64Operand::CreateReg(
6531 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
6532 SMLoc(), SMLoc(), getContext());
6533 Operands[3] = AArch64Operand::CreateImm(
6534 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
6535 Operands.emplace_back(
6536 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
6537 WidthOp.getEndLoc(), getContext()));
6538 }
6539 }
6540 } else if (NumOperands == 5) {
6541 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
6542 // UBFIZ -> UBFM aliases.
6543 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
6544 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6545 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6546 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6547
6548 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6549 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6550 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
6551
6552 if (Op3CE && Op4CE) {
6553 uint64_t Op3Val = Op3CE->getValue();
6554 uint64_t Op4Val = Op4CE->getValue();
6555
6556 uint64_t RegWidth = 0;
6557 if (getAArch64MCRegisterClass(AArch64::GPR64allRegClassID)
6558 .contains(Op1.getReg()))
6559 RegWidth = 64;
6560 else
6561 RegWidth = 32;
6562
6563 if (Op3Val >= RegWidth)
6564 return Error(Op3.getStartLoc(),
6565 "expected integer in range [0, 31]");
6566 if (Op4Val < 1 || Op4Val > RegWidth)
6567 return Error(Op4.getStartLoc(),
6568 "expected integer in range [1, 32]");
6569
6570 uint64_t NewOp3Val = 0;
6571 if (RegWidth == 32)
6572 NewOp3Val = (32 - Op3Val) & 0x1f;
6573 else
6574 NewOp3Val = (64 - Op3Val) & 0x3f;
6575
6576 uint64_t NewOp4Val = Op4Val - 1;
6577
6578 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
6579 return Error(Op4.getStartLoc(),
6580 "requested insert overflows register");
6581
6582 const MCExpr *NewOp3 =
6583 MCConstantExpr::create(NewOp3Val, getContext());
6584 const MCExpr *NewOp4 =
6585 MCConstantExpr::create(NewOp4Val, getContext());
6586 Operands[3] = AArch64Operand::CreateImm(
6587 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
6588 Operands[4] = AArch64Operand::CreateImm(
6589 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
6590 if (Tok == "bfi")
6591 Operands[0] = AArch64Operand::CreateToken("bfm", Op.getStartLoc(),
6592 getContext());
6593 else if (Tok == "sbfiz")
6594 Operands[0] = AArch64Operand::CreateToken("sbfm", Op.getStartLoc(),
6595 getContext());
6596 else if (Tok == "ubfiz")
6597 Operands[0] = AArch64Operand::CreateToken("ubfm", Op.getStartLoc(),
6598 getContext());
6599 else
6600 llvm_unreachable("No valid mnemonic for alias?");
6601 }
6602 }
6603
6604 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
6605 // UBFX -> UBFM aliases.
6606 } else if (NumOperands == 5 &&
6607 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
6608 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6609 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6610 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6611
6612 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6613 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
6614 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
6615
6616 if (Op3CE && Op4CE) {
6617 uint64_t Op3Val = Op3CE->getValue();
6618 uint64_t Op4Val = Op4CE->getValue();
6619
6620 uint64_t RegWidth = 0;
6621 if (getAArch64MCRegisterClass(AArch64::GPR64allRegClassID)
6622 .contains(Op1.getReg()))
6623 RegWidth = 64;
6624 else
6625 RegWidth = 32;
6626
6627 if (Op3Val >= RegWidth)
6628 return Error(Op3.getStartLoc(),
6629 "expected integer in range [0, 31]");
6630 if (Op4Val < 1 || Op4Val > RegWidth)
6631 return Error(Op4.getStartLoc(),
6632 "expected integer in range [1, 32]");
6633
6634 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
6635
6636 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
6637 return Error(Op4.getStartLoc(),
6638 "requested extract overflows register");
6639
6640 const MCExpr *NewOp4 =
6641 MCConstantExpr::create(NewOp4Val, getContext());
6642 Operands[4] = AArch64Operand::CreateImm(
6643 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
6644 if (Tok == "bfxil")
6645 Operands[0] = AArch64Operand::CreateToken("bfm", Op.getStartLoc(),
6646 getContext());
6647 else if (Tok == "sbfx")
6648 Operands[0] = AArch64Operand::CreateToken("sbfm", Op.getStartLoc(),
6649 getContext());
6650 else if (Tok == "ubfx")
6651 Operands[0] = AArch64Operand::CreateToken("ubfm", Op.getStartLoc(),
6652 getContext());
6653 else
6654 llvm_unreachable("No valid mnemonic for alias?");
6655 }
6656 }
6657 }
6658 }
6659
6660 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
6661 // instruction for FP registers correctly in some rare circumstances. Convert
6662 // it to a safe instruction and warn (because silently changing someone's
6663 // assembly is rude).
6664 if (getSTI().hasFeature(AArch64::FeatureZCZeroingFPWorkaround) &&
6665 NumOperands == 4 && Tok == "movi") {
6666 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6667 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6668 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6669 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
6670 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
6671 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
6672 if (Suffix.lower() == ".2d" &&
6673 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
6674 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
6675 " correctly on this CPU, converting to equivalent movi.16b");
6676 // Switch the suffix to .16b.
6677 unsigned Idx = Op1.isToken() ? 1 : 2;
6678 Operands[Idx] =
6679 AArch64Operand::CreateToken(".16b", IDLoc, getContext());
6680 }
6681 }
6682 }
6683
6684 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
6685 // InstAlias can't quite handle this since the reg classes aren't
6686 // subclasses.
6687 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
6688 // The source register can be Wn here, but the matcher expects a
6689 // GPR64. Twiddle it here if necessary.
6690 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6691 if (Op.isScalarReg()) {
6692 MCRegister Reg = getXRegFromWReg(Op.getReg());
6693 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6694 Op.getStartLoc(), Op.getEndLoc(),
6695 getContext());
6696 }
6697 }
6698 // FIXME: Likewise for sxt[bh] with a Xd dst operand
6699 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
6700 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6701 if (Op.isScalarReg() &&
6702 getAArch64MCRegisterClass(AArch64::GPR64allRegClassID)
6703 .contains(Op.getReg())) {
6704 // The source register can be Wn here, but the matcher expects a
6705 // GPR64. Twiddle it here if necessary.
6706 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6707 if (Op.isScalarReg()) {
6708 MCRegister Reg = getXRegFromWReg(Op.getReg());
6709 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6710 Op.getStartLoc(),
6711 Op.getEndLoc(), getContext());
6712 }
6713 }
6714 }
6715 // FIXME: Likewise for uxt[bh] with a Xd dst operand
6716 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
6717 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6718 if (Op.isScalarReg() &&
6719 getAArch64MCRegisterClass(AArch64::GPR64allRegClassID)
6720 .contains(Op.getReg())) {
6721 // The source register can be Wn here, but the matcher expects a
6722 // GPR32. Twiddle it here if necessary.
6723 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6724 if (Op.isScalarReg()) {
6725 MCRegister Reg = getWRegFromXReg(Op.getReg());
6726 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
6727 Op.getStartLoc(),
6728 Op.getEndLoc(), getContext());
6729 }
6730 }
6731 }
6732
6733 MCInst Inst;
6734 FeatureBitset MissingFeatures;
6735 // First try to match against the secondary set of tables containing the
6736 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
6737 unsigned MatchResult =
6738 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6739 MatchingInlineAsm, 1);
6740
6741 // If that fails, try against the alternate table containing long-form NEON:
6742 // "fadd v0.2s, v1.2s, v2.2s"
6743 if (MatchResult != Match_Success) {
6744 // But first, save the short-form match result: we can use it in case the
6745 // long-form match also fails.
6746 auto ShortFormNEONErrorInfo = ErrorInfo;
6747 auto ShortFormNEONMatchResult = MatchResult;
6748 auto ShortFormNEONMissingFeatures = MissingFeatures;
6749
6750 MatchResult =
6751 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6752 MatchingInlineAsm, 0);
6753
6754 // Now, both matches failed, and the long-form match failed on the mnemonic
6755 // suffix token operand. The short-form match failure is probably more
6756 // relevant: use it instead.
6757 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
6758 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
6759 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
6760 MatchResult = ShortFormNEONMatchResult;
6761 ErrorInfo = ShortFormNEONErrorInfo;
6762 MissingFeatures = ShortFormNEONMissingFeatures;
6763 }
6764 }
6765
6766 switch (MatchResult) {
6767 case Match_Success: {
6768 // Perform range checking and other semantic validations
6769 SmallVector<SMLoc, 8> OperandLocs;
6770 NumOperands = Operands.size();
6771 for (unsigned i = 1; i < NumOperands; ++i)
6772 OperandLocs.push_back(Operands[i]->getStartLoc());
6773 if (validateInstruction(Inst, IDLoc, OperandLocs))
6774 return true;
6775
6776 Inst.setLoc(IDLoc);
6777 Out.emitInstruction(Inst, getSTI());
6778 return false;
6779 }
6780 case Match_MissingFeature: {
6781 assert(MissingFeatures.any() && "Unknown missing feature!");
6782 // Special case the error message for the very common case where only
6783 // a single subtarget feature is missing (neon, e.g.).
6784 std::string Msg = "instruction requires:";
6785 for (unsigned Feature : MissingFeatures) {
6786 Msg += " ";
6787 Msg += getSubtargetFeatureName(Feature);
6788 }
6789 return Error(IDLoc, Msg);
6790 }
6791 case Match_MnemonicFail:
6792 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
6793 case Match_InvalidOperand: {
6794 SMLoc ErrorLoc = IDLoc;
6795
6796 if (ErrorInfo != ~0ULL) {
6797 if (ErrorInfo >= Operands.size())
6798 return Error(IDLoc, "too few operands for instruction",
6799 SMRange(IDLoc, getTok().getLoc()));
6800
6801 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
6802 if (ErrorLoc == SMLoc())
6803 ErrorLoc = IDLoc;
6804 }
6805 // If the match failed on a suffix token operand, tweak the diagnostic
6806 // accordingly.
6807 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
6808 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
6809 MatchResult = Match_InvalidSuffix;
6810
6811 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
6812 }
6813 case Match_InvalidTiedOperand:
6814 case Match_InvalidMemoryIndexed1:
6815 case Match_InvalidMemoryIndexed2:
6816 case Match_InvalidMemoryIndexed4:
6817 case Match_InvalidMemoryIndexed8:
6818 case Match_InvalidMemoryIndexed16:
6819 case Match_InvalidCondCode:
6820 case Match_AddSubLSLImm3ShiftLarge:
6821 case Match_AddSubRegExtendSmall:
6822 case Match_AddSubRegExtendLarge:
6823 case Match_AddSubSecondSource:
6824 case Match_LogicalSecondSource:
6825 case Match_AddSubRegShift32:
6826 case Match_AddSubRegShift64:
6827 case Match_InvalidMovImm32Shift:
6828 case Match_InvalidMovImm64Shift:
6829 case Match_InvalidFPImm:
6830 case Match_InvalidMemoryWExtend8:
6831 case Match_InvalidMemoryWExtend16:
6832 case Match_InvalidMemoryWExtend32:
6833 case Match_InvalidMemoryWExtend64:
6834 case Match_InvalidMemoryWExtend128:
6835 case Match_InvalidMemoryXExtend8:
6836 case Match_InvalidMemoryXExtend16:
6837 case Match_InvalidMemoryXExtend32:
6838 case Match_InvalidMemoryXExtend64:
6839 case Match_InvalidMemoryXExtend128:
6840 case Match_InvalidMemoryIndexed1SImm4:
6841 case Match_InvalidMemoryIndexed2SImm4:
6842 case Match_InvalidMemoryIndexed3SImm4:
6843 case Match_InvalidMemoryIndexed4SImm4:
6844 case Match_InvalidMemoryIndexed1SImm6:
6845 case Match_InvalidMemoryIndexed16SImm4:
6846 case Match_InvalidMemoryIndexed32SImm4:
6847 case Match_InvalidMemoryIndexed4SImm7:
6848 case Match_InvalidMemoryIndexed8SImm7:
6849 case Match_InvalidMemoryIndexed16SImm7:
6850 case Match_InvalidMemoryIndexed8UImm5:
6851 case Match_InvalidMemoryIndexed8UImm3:
6852 case Match_InvalidMemoryIndexed4UImm5:
6853 case Match_InvalidMemoryIndexed2UImm5:
6854 case Match_InvalidMemoryIndexed1UImm6:
6855 case Match_InvalidMemoryIndexed2UImm6:
6856 case Match_InvalidMemoryIndexed4UImm6:
6857 case Match_InvalidMemoryIndexed8UImm6:
6858 case Match_InvalidMemoryIndexed16UImm6:
6859 case Match_InvalidMemoryIndexedSImm6:
6860 case Match_InvalidMemoryIndexedSImm5:
6861 case Match_InvalidMemoryIndexedSImm8:
6862 case Match_InvalidMemoryIndexedSImm9:
6863 case Match_InvalidMemoryIndexed16SImm9:
6864 case Match_InvalidMemoryIndexed8SImm10:
6865 case Match_InvalidImm0_0:
6866 case Match_InvalidImm0_1:
6867 case Match_InvalidImm0_3:
6868 case Match_InvalidImm0_7:
6869 case Match_InvalidImm0_15:
6870 case Match_InvalidImm0_31:
6871 case Match_InvalidImm0_63:
6872 case Match_InvalidImm0_127:
6873 case Match_InvalidImm0_255:
6874 case Match_InvalidImm0_65535:
6875 case Match_InvalidHinteUImm16:
6876 case Match_InvalidImm1_8:
6877 case Match_InvalidImm1_16:
6878 case Match_InvalidImm1_32:
6879 case Match_InvalidImm1_64:
6880 case Match_InvalidImmM1_62:
6881 case Match_InvalidMemoryIndexedRange2UImm0:
6882 case Match_InvalidMemoryIndexedRange2UImm1:
6883 case Match_InvalidMemoryIndexedRange2UImm2:
6884 case Match_InvalidMemoryIndexedRange2UImm3:
6885 case Match_InvalidMemoryIndexedRange4UImm0:
6886 case Match_InvalidMemoryIndexedRange4UImm1:
6887 case Match_InvalidMemoryIndexedRange4UImm2:
6888 case Match_InvalidSVEAddSubImm8:
6889 case Match_InvalidSVEAddSubImm16:
6890 case Match_InvalidSVEAddSubImm32:
6891 case Match_InvalidSVEAddSubImm64:
6892 case Match_InvalidSVECpyImm8:
6893 case Match_InvalidSVECpyImm16:
6894 case Match_InvalidSVECpyImm32:
6895 case Match_InvalidSVECpyImm64:
6896 case Match_InvalidIndexRange0_0:
6897 case Match_InvalidIndexRange1_1:
6898 case Match_InvalidIndexRange0_15:
6899 case Match_InvalidIndexRange0_7:
6900 case Match_InvalidIndexRange0_3:
6901 case Match_InvalidIndexRange0_1:
6902 case Match_InvalidSVEIndexRange0_63:
6903 case Match_InvalidSVEIndexRange0_31:
6904 case Match_InvalidSVEIndexRange0_15:
6905 case Match_InvalidSVEIndexRange0_7:
6906 case Match_InvalidSVEIndexRange0_3:
6907 case Match_InvalidLabel:
6908 case Match_InvalidComplexRotationEven:
6909 case Match_InvalidComplexRotationOdd:
6910 case Match_InvalidGPR64shifted8:
6911 case Match_InvalidGPR64shifted16:
6912 case Match_InvalidGPR64shifted32:
6913 case Match_InvalidGPR64shifted64:
6914 case Match_InvalidGPR64shifted128:
6915 case Match_InvalidGPR64NoXZRshifted8:
6916 case Match_InvalidGPR64NoXZRshifted16:
6917 case Match_InvalidGPR64NoXZRshifted32:
6918 case Match_InvalidGPR64NoXZRshifted64:
6919 case Match_InvalidGPR64NoXZRshifted128:
6920 case Match_InvalidZPR32UXTW8:
6921 case Match_InvalidZPR32UXTW16:
6922 case Match_InvalidZPR32UXTW32:
6923 case Match_InvalidZPR32UXTW64:
6924 case Match_InvalidZPR32SXTW8:
6925 case Match_InvalidZPR32SXTW16:
6926 case Match_InvalidZPR32SXTW32:
6927 case Match_InvalidZPR32SXTW64:
6928 case Match_InvalidZPR64UXTW8:
6929 case Match_InvalidZPR64SXTW8:
6930 case Match_InvalidZPR64UXTW16:
6931 case Match_InvalidZPR64SXTW16:
6932 case Match_InvalidZPR64UXTW32:
6933 case Match_InvalidZPR64SXTW32:
6934 case Match_InvalidZPR64UXTW64:
6935 case Match_InvalidZPR64SXTW64:
6936 case Match_InvalidZPR32LSL8:
6937 case Match_InvalidZPR32LSL16:
6938 case Match_InvalidZPR32LSL32:
6939 case Match_InvalidZPR32LSL64:
6940 case Match_InvalidZPR64LSL8:
6941 case Match_InvalidZPR64LSL16:
6942 case Match_InvalidZPR64LSL32:
6943 case Match_InvalidZPR64LSL64:
6944 case Match_InvalidZPR0:
6945 case Match_InvalidZPR8:
6946 case Match_InvalidZPR16:
6947 case Match_InvalidZPR32:
6948 case Match_InvalidZPR64:
6949 case Match_InvalidZPR128:
6950 case Match_InvalidZPR_3b8:
6951 case Match_InvalidZPR_3b16:
6952 case Match_InvalidZPR_3b32:
6953 case Match_InvalidZPR_4b8:
6954 case Match_InvalidZPR_4b16:
6955 case Match_InvalidZPR_4b32:
6956 case Match_InvalidZPR_4b64:
6957 case Match_InvalidSVEPPRorPNRAnyReg:
6958 case Match_InvalidSVEPPRorPNRBReg:
6959 case Match_InvalidSVEPredicateAnyReg:
6960 case Match_InvalidSVEPattern:
6961 case Match_InvalidSVEVecLenSpecifier:
6962 case Match_InvalidSVEPredicateBReg:
6963 case Match_InvalidSVEPredicateHReg:
6964 case Match_InvalidSVEPredicateSReg:
6965 case Match_InvalidSVEPredicateDReg:
6966 case Match_InvalidSVEPredicate3bAnyReg:
6967 case Match_InvalidSVEPNPredicateB_p8to15Reg:
6968 case Match_InvalidSVEPNPredicateH_p8to15Reg:
6969 case Match_InvalidSVEPNPredicateS_p8to15Reg:
6970 case Match_InvalidSVEPNPredicateD_p8to15Reg:
6971 case Match_InvalidSVEPNPredicateAny_p8to15Reg:
6972 case Match_InvalidSVEPNPredicateBReg:
6973 case Match_InvalidSVEPNPredicateHReg:
6974 case Match_InvalidSVEPNPredicateSReg:
6975 case Match_InvalidSVEPNPredicateDReg:
6976 case Match_InvalidSVEPredicateListMul2x8:
6977 case Match_InvalidSVEPredicateListMul2x16:
6978 case Match_InvalidSVEPredicateListMul2x32:
6979 case Match_InvalidSVEPredicateListMul2x64:
6980 case Match_InvalidSVEExactFPImmOperandHalfOne:
6981 case Match_InvalidSVEExactFPImmOperandHalfTwo:
6982 case Match_InvalidSVEExactFPImmOperandZeroOne:
6983 case Match_InvalidMatrixTile16:
6984 case Match_InvalidMatrixTile32:
6985 case Match_InvalidMatrixTile64:
6986 case Match_InvalidMatrix:
6987 case Match_InvalidMatrix8:
6988 case Match_InvalidMatrix16:
6989 case Match_InvalidMatrix32:
6990 case Match_InvalidMatrix64:
6991 case Match_InvalidMatrixTileVectorH8:
6992 case Match_InvalidMatrixTileVectorH16:
6993 case Match_InvalidMatrixTileVectorH32:
6994 case Match_InvalidMatrixTileVectorH64:
6995 case Match_InvalidMatrixTileVectorH128:
6996 case Match_InvalidMatrixTileVectorV8:
6997 case Match_InvalidMatrixTileVectorV16:
6998 case Match_InvalidMatrixTileVectorV32:
6999 case Match_InvalidMatrixTileVectorV64:
7000 case Match_InvalidMatrixTileVectorV128:
7001 case Match_InvalidSVCR:
7002 case Match_InvalidMatrixIndexGPR32_12_15:
7003 case Match_InvalidMatrixIndexGPR32_8_11:
7004 case Match_InvalidLookupTable:
7005 case Match_InvalidZPRMul2_Lo8:
7006 case Match_InvalidZPRMul2_Hi8:
7007 case Match_InvalidZPRMul2_Lo16:
7008 case Match_InvalidZPRMul2_Hi16:
7009 case Match_InvalidZPRMul2_Lo32:
7010 case Match_InvalidZPRMul2_Hi32:
7011 case Match_InvalidZPRMul2_Lo64:
7012 case Match_InvalidZPRMul2_Hi64:
7013 case Match_InvalidZPR_K0:
7014 case Match_InvalidSVEVectorList2x8Mul2:
7015 case Match_InvalidSVEVectorList2x16Mul2:
7016 case Match_InvalidSVEVectorList2x32Mul2:
7017 case Match_InvalidSVEVectorList2x64Mul2:
7018 case Match_InvalidSVEVectorList2x128Mul2:
7019 case Match_InvalidSVEVectorList4x8Mul4:
7020 case Match_InvalidSVEVectorList4x16Mul4:
7021 case Match_InvalidSVEVectorList4x32Mul4:
7022 case Match_InvalidSVEVectorList4x64Mul4:
7023 case Match_InvalidSVEVectorList4x128Mul4:
7024 case Match_InvalidSVEVectorList2x8Mul2_Lo:
7025 case Match_InvalidSVEVectorList2x16Mul2_Lo:
7026 case Match_InvalidSVEVectorList2x32Mul2_Lo:
7027 case Match_InvalidSVEVectorList2x64Mul2_Lo:
7028 case Match_InvalidSVEVectorList2x8Mul2_Hi:
7029 case Match_InvalidSVEVectorList2x16Mul2_Hi:
7030 case Match_InvalidSVEVectorList2x32Mul2_Hi:
7031 case Match_InvalidSVEVectorList2x64Mul2_Hi:
7032 case Match_InvalidSVEVectorListStrided2x8:
7033 case Match_InvalidSVEVectorListStrided2x16:
7034 case Match_InvalidSVEVectorListStrided2x32:
7035 case Match_InvalidSVEVectorListStrided2x64:
7036 case Match_InvalidSVEVectorListStrided4x8:
7037 case Match_InvalidSVEVectorListStrided4x16:
7038 case Match_InvalidSVEVectorListStrided4x32:
7039 case Match_InvalidSVEVectorListStrided4x64:
7040 case Match_MSR:
7041 case Match_MRS: {
7042 if (ErrorInfo >= Operands.size())
7043 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
7044 // Any time we get here, there's nothing fancy to do. Just get the
7045 // operand SMLoc and display the diagnostic.
7046 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
7047 if (ErrorLoc == SMLoc())
7048 ErrorLoc = IDLoc;
7049 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
7050 }
7051 }
7052
7053 llvm_unreachable("Implement any new match types added!");
7054}
7055
7056/// ParseDirective parses the arm specific directives
7057bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
7058 const MCContext::Environment Format = getContext().getObjectFileType();
7059 bool IsMachO = Format == MCContext::IsMachO;
7060 bool IsCOFF = Format == MCContext::IsCOFF;
7061 bool IsELF = Format == MCContext::IsELF;
7062
7063 auto IDVal = DirectiveID.getIdentifier().lower();
7064 SMLoc Loc = DirectiveID.getLoc();
7065 if (IDVal == ".arch")
7066 parseDirectiveArch(Loc);
7067 else if (IDVal == ".cpu")
7068 parseDirectiveCPU(Loc);
7069 else if (IDVal == ".tlsdesccall")
7070 parseDirectiveTLSDescCall(Loc);
7071 else if (IDVal == ".ltorg" || IDVal == ".pool")
7072 parseDirectiveLtorg(Loc);
7073 else if (IDVal == ".unreq")
7074 parseDirectiveUnreq(Loc);
7075 else if (IDVal == ".inst")
7076 parseDirectiveInst(Loc);
7077 else if (IDVal == ".cfi_negate_ra_state")
7078 parseDirectiveCFINegateRAState();
7079 else if (IDVal == ".cfi_negate_ra_state_with_pc")
7080 parseDirectiveCFINegateRAStateWithPC();
7081 else if (IDVal == ".cfi_b_key_frame")
7082 parseDirectiveCFIBKeyFrame();
7083 else if (IDVal == ".cfi_mte_tagged_frame")
7084 parseDirectiveCFIMTETaggedFrame();
7085 else if (IDVal == ".arch_extension")
7086 parseDirectiveArchExtension(Loc);
7087 else if (IDVal == ".variant_pcs")
7088 parseDirectiveVariantPCS(Loc);
7089 else if (IsMachO) {
7090 if (IDVal == MCLOHDirectiveName())
7091 parseDirectiveLOH(IDVal, Loc);
7092 else
7093 return true;
7094 } else if (IsCOFF) {
7095 if (IDVal == ".seh_stackalloc")
7096 parseDirectiveSEHAllocStack(Loc);
7097 else if (IDVal == ".seh_endprologue")
7098 parseDirectiveSEHPrologEnd(Loc);
7099 else if (IDVal == ".seh_save_r19r20_x")
7100 parseDirectiveSEHSaveR19R20X(Loc);
7101 else if (IDVal == ".seh_save_fplr")
7102 parseDirectiveSEHSaveFPLR(Loc);
7103 else if (IDVal == ".seh_save_fplr_x")
7104 parseDirectiveSEHSaveFPLRX(Loc);
7105 else if (IDVal == ".seh_save_reg")
7106 parseDirectiveSEHSaveReg(Loc);
7107 else if (IDVal == ".seh_save_reg_x")
7108 parseDirectiveSEHSaveRegX(Loc);
7109 else if (IDVal == ".seh_save_regp")
7110 parseDirectiveSEHSaveRegP(Loc);
7111 else if (IDVal == ".seh_save_regp_x")
7112 parseDirectiveSEHSaveRegPX(Loc);
7113 else if (IDVal == ".seh_save_lrpair")
7114 parseDirectiveSEHSaveLRPair(Loc);
7115 else if (IDVal == ".seh_save_freg")
7116 parseDirectiveSEHSaveFReg(Loc);
7117 else if (IDVal == ".seh_save_freg_x")
7118 parseDirectiveSEHSaveFRegX(Loc);
7119 else if (IDVal == ".seh_save_fregp")
7120 parseDirectiveSEHSaveFRegP(Loc);
7121 else if (IDVal == ".seh_save_fregp_x")
7122 parseDirectiveSEHSaveFRegPX(Loc);
7123 else if (IDVal == ".seh_set_fp")
7124 parseDirectiveSEHSetFP(Loc);
7125 else if (IDVal == ".seh_add_fp")
7126 parseDirectiveSEHAddFP(Loc);
7127 else if (IDVal == ".seh_nop")
7128 parseDirectiveSEHNop(Loc);
7129 else if (IDVal == ".seh_save_next")
7130 parseDirectiveSEHSaveNext(Loc);
7131 else if (IDVal == ".seh_startepilogue")
7132 parseDirectiveSEHEpilogStart(Loc);
7133 else if (IDVal == ".seh_endepilogue")
7134 parseDirectiveSEHEpilogEnd(Loc);
7135 else if (IDVal == ".seh_trap_frame")
7136 parseDirectiveSEHTrapFrame(Loc);
7137 else if (IDVal == ".seh_pushframe")
7138 parseDirectiveSEHMachineFrame(Loc);
7139 else if (IDVal == ".seh_context")
7140 parseDirectiveSEHContext(Loc);
7141 else if (IDVal == ".seh_ec_context")
7142 parseDirectiveSEHECContext(Loc);
7143 else if (IDVal == ".seh_clear_unwound_to_call")
7144 parseDirectiveSEHClearUnwoundToCall(Loc);
7145 else if (IDVal == ".seh_pac_sign_lr")
7146 parseDirectiveSEHPACSignLR(Loc);
7147 else if (IDVal == ".seh_save_any_reg")
7148 parseDirectiveSEHSaveAnyReg(Loc, false, false);
7149 else if (IDVal == ".seh_save_any_reg_p")
7150 parseDirectiveSEHSaveAnyReg(Loc, true, false);
7151 else if (IDVal == ".seh_save_any_reg_x")
7152 parseDirectiveSEHSaveAnyReg(Loc, false, true);
7153 else if (IDVal == ".seh_save_any_reg_px")
7154 parseDirectiveSEHSaveAnyReg(Loc, true, true);
7155 else if (IDVal == ".seh_allocz")
7156 parseDirectiveSEHAllocZ(Loc);
7157 else if (IDVal == ".seh_save_zreg")
7158 parseDirectiveSEHSaveZReg(Loc);
7159 else if (IDVal == ".seh_save_preg")
7160 parseDirectiveSEHSavePReg(Loc);
7161 else
7162 return true;
7163 } else if (IsELF) {
7164 if (IDVal == ".aeabi_subsection")
7165 parseDirectiveAeabiSubSectionHeader(Loc);
7166 else if (IDVal == ".aeabi_attribute")
7167 parseDirectiveAeabiAArch64Attr(Loc);
7168 else
7169 return true;
7170 } else
7171 return true;
7172 return false;
7173}
7174
7175static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
7176 SmallVector<StringRef, 4> &RequestedExtensions) {
7177 const bool NoCrypto = llvm::is_contained(RequestedExtensions, "nocrypto");
7178 const bool Crypto = llvm::is_contained(RequestedExtensions, "crypto");
7179
7180 if (!NoCrypto && Crypto) {
7181 // Map 'generic' (and others) to sha2 and aes, because
7182 // that was the traditional meaning of crypto.
7183 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
7184 ArchInfo == AArch64::ARMV8_3A) {
7185 RequestedExtensions.push_back("sha2");
7186 RequestedExtensions.push_back("aes");
7187 }
7188 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
7189 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
7190 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
7191 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
7192 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
7193 ArchInfo == AArch64::ARMV9_4A || ArchInfo == AArch64::ARMV8R) {
7194 RequestedExtensions.push_back("sm4");
7195 RequestedExtensions.push_back("sha3");
7196 RequestedExtensions.push_back("sha2");
7197 RequestedExtensions.push_back("aes");
7198 }
7199 } else if (NoCrypto) {
7200 // Map 'generic' (and others) to sha2 and aes, because
7201 // that was the traditional meaning of crypto.
7202 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
7203 ArchInfo == AArch64::ARMV8_3A) {
7204 RequestedExtensions.push_back("nosha2");
7205 RequestedExtensions.push_back("noaes");
7206 }
7207 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
7208 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
7209 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
7210 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
7211 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
7212 ArchInfo == AArch64::ARMV9_4A) {
7213 RequestedExtensions.push_back("nosm4");
7214 RequestedExtensions.push_back("nosha3");
7215 RequestedExtensions.push_back("nosha2");
7216 RequestedExtensions.push_back("noaes");
7217 }
7218 }
7219}
7220
7222 return SMLoc::getFromPointer(L.getPointer() + Offset);
7223}
7224
7225/// parseDirectiveArch
7226/// ::= .arch token
7227bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
7228 SMLoc CurLoc = getLoc();
7229
7230 StringRef Name = getParser().parseStringToEndOfStatement().trim();
7231 StringRef Arch, ExtensionString;
7232 std::tie(Arch, ExtensionString) = Name.split('+');
7233
7234 const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch);
7235 if (!ArchInfo)
7236 return Error(CurLoc, "unknown arch name");
7237
7238 if (parseToken(AsmToken::EndOfStatement))
7239 return true;
7240
7241 // Get the architecture and extension features.
7242 std::vector<StringRef> AArch64Features;
7243 AArch64Features.push_back(AArch64::StrTab[ArchInfo->ArchFeature]);
7244 AArch64::getExtensionFeatures(ArchInfo->DefaultExts, AArch64Features);
7245
7246 MCSubtargetInfo &STI = copySTI();
7247 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
7248 STI.setDefaultFeatures("generic", /*TuneCPU*/ "generic",
7249 join(ArchFeatures.begin(), ArchFeatures.end(), ","));
7250
7251 SmallVector<StringRef, 4> RequestedExtensions;
7252 if (!ExtensionString.empty())
7253 ExtensionString.split(RequestedExtensions, '+');
7254
7255 ExpandCryptoAEK(*ArchInfo, RequestedExtensions);
7256 CurLoc = incrementLoc(CurLoc, Arch.size());
7257
7258 for (auto Name : RequestedExtensions) {
7259 // Advance source location past '+'.
7260 CurLoc = incrementLoc(CurLoc, 1);
7261
7262 bool EnableFeature = !Name.consume_front_insensitive("no");
7263
7264 auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7265 return Extension.name() == Name;
7266 });
7267
7268 if (It == std::end(ExtensionMap))
7269 return Error(CurLoc, "unsupported architectural extension: " + Name);
7270
7271 if (EnableFeature)
7272 STI.SetFeatureBitsTransitively(It->value());
7273 else
7274 STI.ClearFeatureBitsTransitively(It->value());
7275 CurLoc = incrementLoc(CurLoc, Name.size());
7276 }
7277 FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7278 setAvailableFeatures(Features);
7279
7280 getTargetStreamer().emitDirectiveArch(Name);
7281 return false;
7282}
7283
7284/// parseDirectiveArchExtension
7285/// ::= .arch_extension [no]feature
7286bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
7287 SMLoc ExtLoc = getLoc();
7288
7289 StringRef FullName = getParser().parseStringToEndOfStatement().trim();
7290
7291 if (parseEOL())
7292 return true;
7293
7294 bool EnableFeature = true;
7295 StringRef Name = FullName;
7296 if (Name.starts_with_insensitive("no")) {
7297 EnableFeature = false;
7298 Name = Name.substr(2);
7299 }
7300
7301 auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7302 return Extension.name() == Name;
7303 });
7304
7305 if (It == std::end(ExtensionMap))
7306 return Error(ExtLoc, "unsupported architectural extension: " + Name);
7307
7308 MCSubtargetInfo &STI = copySTI();
7309 if (EnableFeature)
7310 STI.SetFeatureBitsTransitively(It->value());
7311 else
7312 STI.ClearFeatureBitsTransitively(It->value());
7313 FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7314 setAvailableFeatures(Features);
7315
7316 getTargetStreamer().emitDirectiveArchExtension(FullName);
7317 return false;
7318}
7319
7320/// parseDirectiveCPU
7321/// ::= .cpu id
7322bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
7323 SMLoc CurLoc = getLoc();
7324
7325 StringRef CPU, ExtensionString;
7326 std::tie(CPU, ExtensionString) =
7327 getParser().parseStringToEndOfStatement().trim().split('+');
7328
7329 if (parseToken(AsmToken::EndOfStatement))
7330 return true;
7331
7332 SmallVector<StringRef, 4> RequestedExtensions;
7333 if (!ExtensionString.empty())
7334 ExtensionString.split(RequestedExtensions, '+');
7335
7336 const llvm::AArch64::ArchInfo *CpuArch = llvm::AArch64::getArchForCpu(CPU);
7337 if (!CpuArch) {
7338 Error(CurLoc, "unknown CPU name");
7339 return false;
7340 }
7341 ExpandCryptoAEK(*CpuArch, RequestedExtensions);
7342
7343 MCSubtargetInfo &STI = copySTI();
7344 STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
7345 CurLoc = incrementLoc(CurLoc, CPU.size());
7346
7347 for (auto Name : RequestedExtensions) {
7348 // Advance source location past '+'.
7349 CurLoc = incrementLoc(CurLoc, 1);
7350
7351 bool EnableFeature = !Name.consume_front_insensitive("no");
7352
7353 auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7354 return Extension.name() == Name;
7355 });
7356
7357 if (It == std::end(ExtensionMap))
7358 return Error(CurLoc, "unsupported architectural extension: " + Name);
7359
7360 if (EnableFeature)
7361 STI.SetFeatureBitsTransitively(It->value());
7362 else
7363 STI.ClearFeatureBitsTransitively(It->value());
7364 CurLoc = incrementLoc(CurLoc, Name.size());
7365 }
7366 FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7367 setAvailableFeatures(Features);
7368 return false;
7369}
7370
7371/// parseDirectiveInst
7372/// ::= .inst opcode [, ...]
7373bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
7374 if (getLexer().is(AsmToken::EndOfStatement))
7375 return Error(Loc, "expected expression following '.inst' directive");
7376
7377 auto parseOp = [&]() -> bool {
7378 SMLoc L = getLoc();
7379 const MCExpr *Expr = nullptr;
7380 if (check(getParser().parseExpression(Expr), L, "expected expression"))
7381 return true;
7382 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
7383 if (check(!Value, L, "expected constant expression"))
7384 return true;
7385 getTargetStreamer().emitInst(Value->getValue());
7386 return false;
7387 };
7388
7389 return parseMany(parseOp);
7390}
7391
7392// parseDirectiveTLSDescCall:
7393// ::= .tlsdesccall symbol
7394bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
7395 StringRef Name;
7396 if (check(getParser().parseIdentifier(Name), L, "expected symbol") ||
7397 parseToken(AsmToken::EndOfStatement))
7398 return true;
7399
7400 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
7401 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
7403
7404 MCInst Inst;
7405 Inst.setOpcode(AArch64::TLSDESCCALL);
7407
7408 getParser().getStreamer().emitInstruction(Inst, getSTI());
7409 return false;
7410}
7411
7412/// ::= .loh <lohName | lohId> label1, ..., labelN
7413/// The number of arguments depends on the loh identifier.
7414bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
7416 if (getTok().isNot(AsmToken::Identifier)) {
7417 if (getTok().isNot(AsmToken::Integer))
7418 return TokError("expected an identifier or a number in directive");
7419 // We successfully get a numeric value for the identifier.
7420 // Check if it is valid.
7421 int64_t Id = getTok().getIntVal();
7422 if (Id <= -1U && !isValidMCLOHType(Id))
7423 return TokError("invalid numeric identifier in directive");
7424 Kind = (MCLOHType)Id;
7425 } else {
7426 StringRef Name = getTok().getIdentifier();
7427 // We successfully parse an identifier.
7428 // Check if it is a recognized one.
7429 int Id = MCLOHNameToId(Name);
7430
7431 if (Id == -1)
7432 return TokError("invalid identifier in directive");
7433 Kind = (MCLOHType)Id;
7434 }
7435 // Consume the identifier.
7436 Lex();
7437 // Get the number of arguments of this LOH.
7438 int NbArgs = MCLOHIdToNbArgs(Kind);
7439
7440 assert(NbArgs != -1 && "Invalid number of arguments");
7441
7443 for (int Idx = 0; Idx < NbArgs; ++Idx) {
7444 StringRef Name;
7445 if (getParser().parseIdentifier(Name))
7446 return TokError("expected identifier in directive");
7447 Args.push_back(getContext().getOrCreateSymbol(Name));
7448
7449 if (Idx + 1 == NbArgs)
7450 break;
7451 if (parseComma())
7452 return true;
7453 }
7454 if (parseEOL())
7455 return true;
7456
7457 getStreamer().emitLOHDirective(Kind, Args);
7458 return false;
7459}
7460
7461/// parseDirectiveLtorg
7462/// ::= .ltorg | .pool
7463bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
7464 if (parseEOL())
7465 return true;
7466 getTargetStreamer().emitCurrentConstantPool();
7467 return false;
7468}
7469
7470/// parseDirectiveReq
7471/// ::= name .req registername
7472bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7473 Lex(); // Eat the '.req' token.
7474 SMLoc SRegLoc = getLoc();
7475 RegKind RegisterKind = RegKind::Scalar;
7476 MCRegister RegNum;
7477 ParseStatus ParseRes = tryParseScalarRegister(RegNum);
7478
7479 if (!ParseRes.isSuccess()) {
7480 StringRef Kind;
7481 RegisterKind = RegKind::NeonVector;
7482 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
7483
7484 if (ParseRes.isFailure())
7485 return true;
7486
7487 if (ParseRes.isSuccess() && !Kind.empty())
7488 return Error(SRegLoc, "vector register without type specifier expected");
7489 }
7490
7491 if (!ParseRes.isSuccess()) {
7492 StringRef Kind;
7493 RegisterKind = RegKind::SVEDataVector;
7494 ParseRes =
7495 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
7496
7497 if (ParseRes.isFailure())
7498 return true;
7499
7500 if (ParseRes.isSuccess() && !Kind.empty())
7501 return Error(SRegLoc,
7502 "sve vector register without type specifier expected");
7503 }
7504
7505 if (!ParseRes.isSuccess()) {
7506 StringRef Kind;
7507 RegisterKind = RegKind::SVEPredicateVector;
7508 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
7509
7510 if (ParseRes.isFailure())
7511 return true;
7512
7513 if (ParseRes.isSuccess() && !Kind.empty())
7514 return Error(SRegLoc,
7515 "sve predicate register without type specifier expected");
7516 }
7517
7518 if (!ParseRes.isSuccess())
7519 return Error(SRegLoc, "register name or alias expected");
7520
7521 // Shouldn't be anything else.
7522 if (parseEOL())
7523 return true;
7524
7525 auto pair = std::make_pair(RegisterKind, RegNum);
7526 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
7527 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
7528
7529 return false;
7530}
7531
7532/// parseDirectiveUneq
7533/// ::= .unreq registername
7534bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
7535 if (getTok().isNot(AsmToken::Identifier))
7536 return TokError("unexpected input in .unreq directive.");
7537 RegisterReqs.erase(getTok().getIdentifier().lower());
7538 Lex(); // Eat the identifier.
7539 return parseToken(AsmToken::EndOfStatement);
7540}
7541
7542bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
7543 if (parseEOL())
7544 return true;
7545 getStreamer().emitCFINegateRAState();
7546 return false;
7547}
7548
7549bool AArch64AsmParser::parseDirectiveCFINegateRAStateWithPC() {
7550 if (parseEOL())
7551 return true;
7552 getStreamer().emitCFINegateRAStateWithPC();
7553 return false;
7554}
7555
7556/// parseDirectiveCFIBKeyFrame
7557/// ::= .cfi_b_key
7558bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
7559 if (parseEOL())
7560 return true;
7561 getStreamer().emitCFIBKeyFrame();
7562 return false;
7563}
7564
7565/// parseDirectiveCFIMTETaggedFrame
7566/// ::= .cfi_mte_tagged_frame
7567bool AArch64AsmParser::parseDirectiveCFIMTETaggedFrame() {
7568 if (parseEOL())
7569 return true;
7570 getStreamer().emitCFIMTETaggedFrame();
7571 return false;
7572}
7573
7574/// parseDirectiveVariantPCS
7575/// ::= .variant_pcs symbolname
7576bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L) {
7577 StringRef Name;
7578 if (getParser().parseIdentifier(Name))
7579 return TokError("expected symbol name");
7580 if (parseEOL())
7581 return true;
7582 getTargetStreamer().emitDirectiveVariantPCS(
7583 getContext().getOrCreateSymbol(Name));
7584 return false;
7585}
7586
7587/// parseDirectiveSEHAllocStack
7588/// ::= .seh_stackalloc
7589bool AArch64AsmParser::parseDirectiveSEHAllocStack(SMLoc L) {
7590 int64_t Size;
7591 if (parseImmExpr(Size))
7592 return true;
7593 getTargetStreamer().emitARM64WinCFIAllocStack(Size);
7594 return false;
7595}
7596
7597/// parseDirectiveSEHPrologEnd
7598/// ::= .seh_endprologue
7599bool AArch64AsmParser::parseDirectiveSEHPrologEnd(SMLoc L) {
7600 getTargetStreamer().emitARM64WinCFIPrologEnd();
7601 return false;
7602}
7603
7604/// parseDirectiveSEHSaveR19R20X
7605/// ::= .seh_save_r19r20_x
7606bool AArch64AsmParser::parseDirectiveSEHSaveR19R20X(SMLoc L) {
7607 int64_t Offset;
7608 if (parseImmExpr(Offset))
7609 return true;
7610 getTargetStreamer().emitARM64WinCFISaveR19R20X(Offset);
7611 return false;
7612}
7613
7614/// parseDirectiveSEHSaveFPLR
7615/// ::= .seh_save_fplr
7616bool AArch64AsmParser::parseDirectiveSEHSaveFPLR(SMLoc L) {
7617 int64_t Offset;
7618 if (parseImmExpr(Offset))
7619 return true;
7620 getTargetStreamer().emitARM64WinCFISaveFPLR(Offset);
7621 return false;
7622}
7623
7624/// parseDirectiveSEHSaveFPLRX
7625/// ::= .seh_save_fplr_x
7626bool AArch64AsmParser::parseDirectiveSEHSaveFPLRX(SMLoc L) {
7627 int64_t Offset;
7628 if (parseImmExpr(Offset))
7629 return true;
7630 getTargetStreamer().emitARM64WinCFISaveFPLRX(Offset);
7631 return false;
7632}
7633
7634/// parseDirectiveSEHSaveReg
7635/// ::= .seh_save_reg
7636bool AArch64AsmParser::parseDirectiveSEHSaveReg(SMLoc L) {
7637 unsigned Reg;
7638 int64_t Offset;
7639 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7640 parseComma() || parseImmExpr(Offset))
7641 return true;
7642 getTargetStreamer().emitARM64WinCFISaveReg(Reg, Offset);
7643 return false;
7644}
7645
7646/// parseDirectiveSEHSaveRegX
7647/// ::= .seh_save_reg_x
7648bool AArch64AsmParser::parseDirectiveSEHSaveRegX(SMLoc L) {
7649 unsigned Reg;
7650 int64_t Offset;
7651 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7652 parseComma() || parseImmExpr(Offset))
7653 return true;
7654 getTargetStreamer().emitARM64WinCFISaveRegX(Reg, Offset);
7655 return false;
7656}
7657
7658/// parseDirectiveSEHSaveRegP
7659/// ::= .seh_save_regp
7660bool AArch64AsmParser::parseDirectiveSEHSaveRegP(SMLoc L) {
7661 unsigned Reg;
7662 int64_t Offset;
7663 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::FP) ||
7664 parseComma() || parseImmExpr(Offset))
7665 return true;
7666 getTargetStreamer().emitARM64WinCFISaveRegP(Reg, Offset);
7667 return false;
7668}
7669
7670/// parseDirectiveSEHSaveRegPX
7671/// ::= .seh_save_regp_x
7672bool AArch64AsmParser::parseDirectiveSEHSaveRegPX(SMLoc L) {
7673 unsigned Reg;
7674 int64_t Offset;
7675 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::FP) ||
7676 parseComma() || parseImmExpr(Offset))
7677 return true;
7678 getTargetStreamer().emitARM64WinCFISaveRegPX(Reg, Offset);
7679 return false;
7680}
7681
7682/// parseDirectiveSEHSaveLRPair
7683/// ::= .seh_save_lrpair
7684bool AArch64AsmParser::parseDirectiveSEHSaveLRPair(SMLoc L) {
7685 unsigned Reg;
7686 int64_t Offset;
7687 L = getLoc();
7688 if (parseRegisterInRange(Reg, AArch64::X0, AArch64::X19, AArch64::LR) ||
7689 parseComma() || parseImmExpr(Offset))
7690 return true;
7691 if (check(((Reg - 19) % 2 != 0), L,
7692 "expected register with even offset from x19"))
7693 return true;
7694 getTargetStreamer().emitARM64WinCFISaveLRPair(Reg, Offset);
7695 return false;
7696}
7697
7698/// parseDirectiveSEHSaveFReg
7699/// ::= .seh_save_freg
7700bool AArch64AsmParser::parseDirectiveSEHSaveFReg(SMLoc L) {
7701 unsigned Reg;
7702 int64_t Offset;
7703 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D15) ||
7704 parseComma() || parseImmExpr(Offset))
7705 return true;
7706 getTargetStreamer().emitARM64WinCFISaveFReg(Reg, Offset);
7707 return false;
7708}
7709
7710/// parseDirectiveSEHSaveFRegX
7711/// ::= .seh_save_freg_x
7712bool AArch64AsmParser::parseDirectiveSEHSaveFRegX(SMLoc L) {
7713 unsigned Reg;
7714 int64_t Offset;
7715 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D15) ||
7716 parseComma() || parseImmExpr(Offset))
7717 return true;
7718 getTargetStreamer().emitARM64WinCFISaveFRegX(Reg, Offset);
7719 return false;
7720}
7721
7722/// parseDirectiveSEHSaveFRegP
7723/// ::= .seh_save_fregp
7724bool AArch64AsmParser::parseDirectiveSEHSaveFRegP(SMLoc L) {
7725 unsigned Reg;
7726 int64_t Offset;
7727 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D14) ||
7728 parseComma() || parseImmExpr(Offset))
7729 return true;
7730 getTargetStreamer().emitARM64WinCFISaveFRegP(Reg, Offset);
7731 return false;
7732}
7733
7734/// parseDirectiveSEHSaveFRegPX
7735/// ::= .seh_save_fregp_x
7736bool AArch64AsmParser::parseDirectiveSEHSaveFRegPX(SMLoc L) {
7737 unsigned Reg;
7738 int64_t Offset;
7739 if (parseRegisterInRange(Reg, AArch64::D0, AArch64::D8, AArch64::D14) ||
7740 parseComma() || parseImmExpr(Offset))
7741 return true;
7742 getTargetStreamer().emitARM64WinCFISaveFRegPX(Reg, Offset);
7743 return false;
7744}
7745
7746/// parseDirectiveSEHSetFP
7747/// ::= .seh_set_fp
7748bool AArch64AsmParser::parseDirectiveSEHSetFP(SMLoc L) {
7749 getTargetStreamer().emitARM64WinCFISetFP();
7750 return false;
7751}
7752
7753/// parseDirectiveSEHAddFP
7754/// ::= .seh_add_fp
7755bool AArch64AsmParser::parseDirectiveSEHAddFP(SMLoc L) {
7756 int64_t Size;
7757 if (parseImmExpr(Size))
7758 return true;
7759 getTargetStreamer().emitARM64WinCFIAddFP(Size);
7760 return false;
7761}
7762
7763/// parseDirectiveSEHNop
7764/// ::= .seh_nop
7765bool AArch64AsmParser::parseDirectiveSEHNop(SMLoc L) {
7766 getTargetStreamer().emitARM64WinCFINop();
7767 return false;
7768}
7769
7770/// parseDirectiveSEHSaveNext
7771/// ::= .seh_save_next
7772bool AArch64AsmParser::parseDirectiveSEHSaveNext(SMLoc L) {
7773 getTargetStreamer().emitARM64WinCFISaveNext();
7774 return false;
7775}
7776
7777/// parseDirectiveSEHEpilogStart
7778/// ::= .seh_startepilogue
7779bool AArch64AsmParser::parseDirectiveSEHEpilogStart(SMLoc L) {
7780 getTargetStreamer().emitARM64WinCFIEpilogStart();
7781 return false;
7782}
7783
7784/// parseDirectiveSEHEpilogEnd
7785/// ::= .seh_endepilogue
7786bool AArch64AsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) {
7787 getTargetStreamer().emitARM64WinCFIEpilogEnd();
7788 return false;
7789}
7790
7791/// parseDirectiveSEHTrapFrame
7792/// ::= .seh_trap_frame
7793bool AArch64AsmParser::parseDirectiveSEHTrapFrame(SMLoc L) {
7794 getTargetStreamer().emitARM64WinCFITrapFrame();
7795 return false;
7796}
7797
7798/// parseDirectiveSEHMachineFrame
7799/// ::= .seh_pushframe
7800bool AArch64AsmParser::parseDirectiveSEHMachineFrame(SMLoc L) {
7801 getTargetStreamer().emitARM64WinCFIMachineFrame();
7802 return false;
7803}
7804
7805/// parseDirectiveSEHContext
7806/// ::= .seh_context
7807bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L) {
7808 getTargetStreamer().emitARM64WinCFIContext();
7809 return false;
7810}
7811
7812/// parseDirectiveSEHECContext
7813/// ::= .seh_ec_context
7814bool AArch64AsmParser::parseDirectiveSEHECContext(SMLoc L) {
7815 getTargetStreamer().emitARM64WinCFIECContext();
7816 return false;
7817}
7818
7819/// parseDirectiveSEHClearUnwoundToCall
7820/// ::= .seh_clear_unwound_to_call
7821bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
7822 getTargetStreamer().emitARM64WinCFIClearUnwoundToCall();
7823 return false;
7824}
7825
7826/// parseDirectiveSEHPACSignLR
7827/// ::= .seh_pac_sign_lr
7828bool AArch64AsmParser::parseDirectiveSEHPACSignLR(SMLoc L) {
7829 getTargetStreamer().emitARM64WinCFIPACSignLR();
7830 return false;
7831}
7832
7833/// parseDirectiveSEHSaveAnyReg
7834/// ::= .seh_save_any_reg
7835/// ::= .seh_save_any_reg_p
7836/// ::= .seh_save_any_reg_x
7837/// ::= .seh_save_any_reg_px
7838bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
7839 bool Writeback) {
7840 MCRegister Reg;
7841 SMLoc Start, End;
7842 int64_t Offset;
7843 if (check(parseRegister(Reg, Start, End), getLoc(), "expected register") ||
7844 parseComma() || parseImmExpr(Offset))
7845 return true;
7846
7847 if (Reg == AArch64::FP || Reg == AArch64::LR ||
7848 (Reg >= AArch64::X0 && Reg <= AArch64::X28)) {
7849 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7850 return Error(L, "invalid save_any_reg offset");
7851 unsigned EncodedReg;
7852 if (Reg == AArch64::FP)
7853 EncodedReg = 29;
7854 else if (Reg == AArch64::LR)
7855 EncodedReg = 30;
7856 else
7857 EncodedReg = Reg - AArch64::X0;
7858 if (Paired) {
7859 if (Reg == AArch64::LR)
7860 return Error(Start, "lr cannot be paired with another register");
7861 if (Writeback)
7862 getTargetStreamer().emitARM64WinCFISaveAnyRegIPX(EncodedReg, Offset);
7863 else
7864 getTargetStreamer().emitARM64WinCFISaveAnyRegIP(EncodedReg, Offset);
7865 } else {
7866 if (Writeback)
7867 getTargetStreamer().emitARM64WinCFISaveAnyRegIX(EncodedReg, Offset);
7868 else
7869 getTargetStreamer().emitARM64WinCFISaveAnyRegI(EncodedReg, Offset);
7870 }
7871 } else if (Reg >= AArch64::D0 && Reg <= AArch64::D31) {
7872 unsigned EncodedReg = Reg - AArch64::D0;
7873 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7874 return Error(L, "invalid save_any_reg offset");
7875 if (Paired) {
7876 if (Reg == AArch64::D31)
7877 return Error(Start, "d31 cannot be paired with another register");
7878 if (Writeback)
7879 getTargetStreamer().emitARM64WinCFISaveAnyRegDPX(EncodedReg, Offset);
7880 else
7881 getTargetStreamer().emitARM64WinCFISaveAnyRegDP(EncodedReg, Offset);
7882 } else {
7883 if (Writeback)
7884 getTargetStreamer().emitARM64WinCFISaveAnyRegDX(EncodedReg, Offset);
7885 else
7886 getTargetStreamer().emitARM64WinCFISaveAnyRegD(EncodedReg, Offset);
7887 }
7888 } else if (Reg >= AArch64::Q0 && Reg <= AArch64::Q31) {
7889 unsigned EncodedReg = Reg - AArch64::Q0;
7890 if (Offset < 0 || Offset % 16)
7891 return Error(L, "invalid save_any_reg offset");
7892 if (Paired) {
7893 if (Reg == AArch64::Q31)
7894 return Error(Start, "q31 cannot be paired with another register");
7895 if (Writeback)
7896 getTargetStreamer().emitARM64WinCFISaveAnyRegQPX(EncodedReg, Offset);
7897 else
7898 getTargetStreamer().emitARM64WinCFISaveAnyRegQP(EncodedReg, Offset);
7899 } else {
7900 if (Writeback)
7901 getTargetStreamer().emitARM64WinCFISaveAnyRegQX(EncodedReg, Offset);
7902 else
7903 getTargetStreamer().emitARM64WinCFISaveAnyRegQ(EncodedReg, Offset);
7904 }
7905 } else {
7906 return Error(Start, "save_any_reg register must be x, q or d register");
7907 }
7908 return false;
7909}
7910
7911/// parseDirectiveAllocZ
7912/// ::= .seh_allocz
7913bool AArch64AsmParser::parseDirectiveSEHAllocZ(SMLoc L) {
7914 int64_t Offset;
7915 if (parseImmExpr(Offset))
7916 return true;
7917 getTargetStreamer().emitARM64WinCFIAllocZ(Offset);
7918 return false;
7919}
7920
7921/// parseDirectiveSEHSaveZReg
7922/// ::= .seh_save_zreg
7923bool AArch64AsmParser::parseDirectiveSEHSaveZReg(SMLoc L) {
7924 MCRegister RegNum;
7925 StringRef Kind;
7926 int64_t Offset;
7927 ParseStatus Res =
7928 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
7929 if (!Res.isSuccess())
7930 return true;
7931 if (check(RegNum < AArch64::Z8 || RegNum > AArch64::Z23, L,
7932 "expected register in range z8 to z23"))
7933 return true;
7934 if (parseComma() || parseImmExpr(Offset))
7935 return true;
7936 getTargetStreamer().emitARM64WinCFISaveZReg(RegNum - AArch64::Z0, Offset);
7937 return false;
7938}
7939
7940/// parseDirectiveSEHSavePReg
7941/// ::= .seh_save_preg
7942bool AArch64AsmParser::parseDirectiveSEHSavePReg(SMLoc L) {
7943 MCRegister RegNum;
7944 StringRef Kind;
7945 int64_t Offset;
7946 ParseStatus Res =
7947 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
7948 if (!Res.isSuccess())
7949 return true;
7950 if (check(RegNum < AArch64::P4 || RegNum > AArch64::P15, L,
7951 "expected register in range p4 to p15"))
7952 return true;
7953 if (parseComma() || parseImmExpr(Offset))
7954 return true;
7955 getTargetStreamer().emitARM64WinCFISavePReg(RegNum - AArch64::P0, Offset);
7956 return false;
7957}
7958
7959bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
7960 // Handle parsing of .aeabi_subsection directives
7961 // - On first declaration of a subsection, expect exactly three identifiers
7962 // after `.aeabi_subsection`: the subsection name and two parameters.
7963 // - When switching to an existing subsection, it is valid to provide only
7964 // the subsection name, or the name together with the two parameters.
7965 MCAsmParser &Parser = getParser();
7966
7967 // Consume the name (subsection name)
7968 StringRef SubsectionName;
7969 AArch64BuildAttributes::VendorID SubsectionNameID;
7970 if (Parser.getTok().is(AsmToken::Identifier)) {
7971 SubsectionName = Parser.getTok().getIdentifier();
7972 SubsectionNameID = AArch64BuildAttributes::getVendorID(SubsectionName);
7973 } else {
7974 Error(Parser.getTok().getLoc(), "subsection name not found");
7975 return true;
7976 }
7977 Parser.Lex();
7978
7979 std::unique_ptr<MCELFStreamer::AttributeSubSection> SubsectionExists =
7980 getTargetStreamer().getAttributesSubsectionByName(SubsectionName);
7981 // Check whether only the subsection name was provided.
7982 // If so, the user is trying to switch to a subsection that should have been
7983 // declared before.
7985 if (SubsectionExists) {
7986 getTargetStreamer().emitAttributesSubsection(
7987 SubsectionName,
7989 SubsectionExists->IsOptional),
7991 SubsectionExists->ParameterType));
7992 return false;
7993 }
7994 // If subsection does not exists, report error.
7995 else {
7996 Error(Parser.getTok().getLoc(),
7997 "Could not switch to subsection '" + SubsectionName +
7998 "' using subsection name, subsection has not been defined");
7999 return true;
8000 }
8001 }
8002
8003 // Otherwise, expecting 2 more parameters: consume a comma
8004 // parseComma() return *false* on success, and call Lex(), no need to call
8005 // Lex() again.
8006 if (Parser.parseComma()) {
8007 return true;
8008 }
8009
8010 // Consume the first parameter (optionality parameter)
8012 // options: optional/required
8013 if (Parser.getTok().is(AsmToken::Identifier)) {
8014 StringRef Optionality = Parser.getTok().getIdentifier();
8015 IsOptional = AArch64BuildAttributes::getOptionalID(Optionality);
8017 Error(Parser.getTok().getLoc(),
8019 return true;
8020 }
8021 if (SubsectionExists) {
8022 if (IsOptional != SubsectionExists->IsOptional) {
8023 Error(Parser.getTok().getLoc(),
8024 "optionality mismatch! subsection '" + SubsectionName +
8025 "' already exists with optionality defined as '" +
8027 SubsectionExists->IsOptional) +
8028 "' and not '" +
8029 AArch64BuildAttributes::getOptionalStr(IsOptional) + "'");
8030 return true;
8031 }
8032 }
8033 } else {
8034 Error(Parser.getTok().getLoc(),
8035 "optionality parameter not found, expected required|optional");
8036 return true;
8037 }
8038 // Check for possible IsOptional unaccepted values for known subsections
8039 if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID) {
8040 if (AArch64BuildAttributes::REQUIRED == IsOptional) {
8041 Error(Parser.getTok().getLoc(),
8042 "aeabi_feature_and_bits must be marked as optional");
8043 return true;
8044 }
8045 }
8046 if (AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) {
8047 if (AArch64BuildAttributes::OPTIONAL == IsOptional) {
8048 Error(Parser.getTok().getLoc(),
8049 "aeabi_pauthabi must be marked as required");
8050 return true;
8051 }
8052 }
8053 Parser.Lex();
8054 // consume a comma
8055 if (Parser.parseComma()) {
8056 return true;
8057 }
8058
8059 // Consume the second parameter (type parameter)
8061 if (Parser.getTok().is(AsmToken::Identifier)) {
8062 StringRef Name = Parser.getTok().getIdentifier();
8065 Error(Parser.getTok().getLoc(),
8067 return true;
8068 }
8069 if (SubsectionExists) {
8070 if (Type != SubsectionExists->ParameterType) {
8071 Error(Parser.getTok().getLoc(),
8072 "type mismatch! subsection '" + SubsectionName +
8073 "' already exists with type defined as '" +
8075 SubsectionExists->ParameterType) +
8076 "' and not '" + AArch64BuildAttributes::getTypeStr(Type) +
8077 "'");
8078 return true;
8079 }
8080 }
8081 } else {
8082 Error(Parser.getTok().getLoc(),
8083 "type parameter not found, expected uleb128|ntbs");
8084 return true;
8085 }
8086 // Check for possible unaccepted 'type' values for known subsections
8087 if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID ||
8088 AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) {
8090 Error(Parser.getTok().getLoc(),
8091 SubsectionName + " must be marked as ULEB128");
8092 return true;
8093 }
8094 }
8095 Parser.Lex();
8096
8097 // Parsing finished, check for trailing tokens.
8099 Error(Parser.getTok().getLoc(), "unexpected token for AArch64 build "
8100 "attributes subsection header directive");
8101 return true;
8102 }
8103
8104 getTargetStreamer().emitAttributesSubsection(SubsectionName, IsOptional, Type);
8105
8106 return false;
8107}
8108
8109bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
8110 // Expecting 2 Tokens: after '.aeabi_attribute', e.g.:
8111 // .aeabi_attribute (1)Tag_Feature_BTI, (2)[uleb128|ntbs]
8112 // separated by a comma.
8113 MCAsmParser &Parser = getParser();
8114
8115 std::unique_ptr<MCELFStreamer::AttributeSubSection> ActiveSubsection =
8116 getTargetStreamer().getActiveAttributesSubsection();
8117 if (nullptr == ActiveSubsection) {
8118 Error(Parser.getTok().getLoc(),
8119 "no active subsection, build attribute can not be added");
8120 return true;
8121 }
8122 StringRef ActiveSubsectionName = ActiveSubsection->VendorName;
8123 unsigned ActiveSubsectionType = ActiveSubsection->ParameterType;
8124
8125 unsigned ActiveSubsectionID = AArch64BuildAttributes::VENDOR_UNKNOWN;
8127 AArch64BuildAttributes::AEABI_PAUTHABI) == ActiveSubsectionName)
8128 ActiveSubsectionID = AArch64BuildAttributes::AEABI_PAUTHABI;
8131 ActiveSubsectionName)
8133
8134 StringRef TagStr = "";
8135 unsigned Tag;
8136 if (Parser.getTok().is(AsmToken::Integer)) {
8137 Tag = getTok().getIntVal();
8138 } else if (Parser.getTok().is(AsmToken::Identifier)) {
8139 TagStr = Parser.getTok().getIdentifier();
8140 switch (ActiveSubsectionID) {
8142 // Tag was provided as an unrecognized string instead of an unsigned
8143 // integer
8144 Error(Parser.getTok().getLoc(), "unrecognized Tag: '" + TagStr +
8145 "' \nExcept for public subsections, "
8146 "tags have to be an unsigned int.");
8147 return true;
8148 break;
8152 Error(Parser.getTok().getLoc(), "unknown AArch64 build attribute '" +
8153 TagStr + "' for subsection '" +
8154 ActiveSubsectionName + "'");
8155 return true;
8156 }
8157 break;
8161 Error(Parser.getTok().getLoc(), "unknown AArch64 build attribute '" +
8162 TagStr + "' for subsection '" +
8163 ActiveSubsectionName + "'");
8164 return true;
8165 }
8166 break;
8167 }
8168 } else {
8169 Error(Parser.getTok().getLoc(), "AArch64 build attributes tag not found");
8170 return true;
8171 }
8172 Parser.Lex();
8173 // consume a comma
8174 // parseComma() return *false* on success, and call Lex(), no need to call
8175 // Lex() again.
8176 if (Parser.parseComma()) {
8177 return true;
8178 }
8179
8180 // Consume the second parameter (attribute value)
8181 unsigned ValueInt = unsigned(-1);
8182 std::string ValueStr = "";
8183 if (Parser.getTok().is(AsmToken::Integer)) {
8184 if (AArch64BuildAttributes::NTBS == ActiveSubsectionType) {
8185 Error(
8186 Parser.getTok().getLoc(),
8187 "active subsection type is NTBS (string), found ULEB128 (unsigned)");
8188 return true;
8189 }
8190 ValueInt = getTok().getIntVal();
8191 } else if (Parser.getTok().is(AsmToken::Identifier)) {
8192 if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) {
8193 Error(
8194 Parser.getTok().getLoc(),
8195 "active subsection type is ULEB128 (unsigned), found NTBS (string)");
8196 return true;
8197 }
8198 ValueStr = Parser.getTok().getIdentifier();
8199 } else if (Parser.getTok().is(AsmToken::String)) {
8200 if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) {
8201 Error(
8202 Parser.getTok().getLoc(),
8203 "active subsection type is ULEB128 (unsigned), found NTBS (string)");
8204 return true;
8205 }
8206 ValueStr = Parser.getTok().getString();
8207 } else {
8208 Error(Parser.getTok().getLoc(), "AArch64 build attributes value not found");
8209 return true;
8210 }
8211 // Check for possible unaccepted values for known tags
8212 // (AEABI_FEATURE_AND_BITS)
8213 if (ActiveSubsectionID == AArch64BuildAttributes::AEABI_FEATURE_AND_BITS) {
8214 if (0 != ValueInt && 1 != ValueInt) {
8215 Error(Parser.getTok().getLoc(),
8216 "unknown AArch64 build attributes Value for Tag '" + TagStr +
8217 "' options are 0|1");
8218 return true;
8219 }
8220 }
8221 Parser.Lex();
8222
8223 // Parsing finished. Check for trailing tokens.
8225 Error(Parser.getTok().getLoc(),
8226 "unexpected token for AArch64 build attributes tag and value "
8227 "attribute directive");
8228 return true;
8229 }
8230
8231 if (unsigned(-1) != ValueInt) {
8232 getTargetStreamer().emitAttribute(ActiveSubsectionName, Tag, ValueInt, "");
8233 }
8234 if ("" != ValueStr) {
8235 getTargetStreamer().emitAttribute(ActiveSubsectionName, Tag, unsigned(-1),
8236 ValueStr);
8237 }
8238 return false;
8239}
8240
8241bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
8242 SMLoc Loc = getLoc();
8243 if (getLexer().getKind() != AsmToken::Identifier)
8244 return TokError("expected '%' relocation specifier");
8245 StringRef Identifier = getParser().getTok().getIdentifier();
8246 auto Spec = AArch64::parsePercentSpecifierName(Identifier);
8247 if (!Spec)
8248 return TokError("invalid relocation specifier");
8249
8250 getParser().Lex(); // Eat the identifier
8251 if (parseToken(AsmToken::LParen, "expected '('"))
8252 return true;
8253
8254 const MCExpr *SubExpr;
8255 if (getParser().parseParenExpression(SubExpr, E))
8256 return true;
8257
8258 Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);
8259 return false;
8260}
8261
8262bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
8263 SMLoc EndLoc;
8264 if (parseOptionalToken(AsmToken::Percent))
8265 return parseExprWithSpecifier(Res, EndLoc);
8266
8267 if (getParser().parseExpression(Res))
8268 return true;
8269 MCAsmParser &Parser = getParser();
8270 if (!parseOptionalToken(AsmToken::At))
8271 return false;
8272 if (getLexer().getKind() != AsmToken::Identifier)
8273 return Error(getLoc(), "expected relocation specifier");
8274
8275 std::string Identifier = Parser.getTok().getIdentifier().lower();
8276 SMLoc Loc = getLoc();
8277 Lex();
8278 if (Identifier == "auth")
8279 return parseAuthExpr(Res, EndLoc);
8280
8281 auto Spec = AArch64::S_None;
8282 if (STI->getTargetTriple().isOSBinFormatMachO()) {
8283 if (Identifier == "got")
8284 Spec = AArch64::S_MACHO_GOT;
8285 }
8286 if (Spec == AArch64::S_None)
8287 return Error(Loc, "invalid relocation specifier");
8288 if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Res))
8289 Res = MCSymbolRefExpr::create(&SRE->getSymbol(), Spec, getContext(),
8290 SRE->getLoc());
8291 else
8292 return Error(Loc, "@ specifier only allowed after a symbol");
8293
8294 for (;;) {
8295 std::optional<MCBinaryExpr::Opcode> Opcode;
8296 if (parseOptionalToken(AsmToken::Plus))
8297 Opcode = MCBinaryExpr::Add;
8298 else if (parseOptionalToken(AsmToken::Minus))
8299 Opcode = MCBinaryExpr::Sub;
8300 else
8301 break;
8302 const MCExpr *Term;
8303 if (getParser().parsePrimaryExpr(Term, EndLoc, nullptr))
8304 return true;
8305 Res = MCBinaryExpr::create(*Opcode, Res, Term, getContext(), Res->getLoc());
8306 }
8307 return false;
8308}
8309
8310/// parseAuthExpr
8311/// ::= _sym@AUTH(ib,123[,addr])
8312/// ::= (_sym + 5)@AUTH(ib,123[,addr])
8313/// ::= (_sym - 5)@AUTH(ib,123[,addr])
8314bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
8315 MCAsmParser &Parser = getParser();
8316 MCContext &Ctx = getContext();
8317 AsmToken Tok = Parser.getTok();
8318
8319 // At this point, we encountered "<id>@AUTH". There is no fallback anymore.
8320 if (parseToken(AsmToken::LParen, "expected '('"))
8321 return true;
8322
8323 if (Parser.getTok().isNot(AsmToken::Identifier))
8324 return TokError("expected key name");
8325
8326 StringRef KeyStr = Parser.getTok().getIdentifier();
8327 auto KeyIDOrNone = AArch64StringToPACKeyID(KeyStr);
8328 if (!KeyIDOrNone)
8329 return TokError("invalid key '" + KeyStr + "'");
8330 Parser.Lex();
8331
8332 if (parseToken(AsmToken::Comma, "expected ','"))
8333 return true;
8334
8335 if (Parser.getTok().isNot(AsmToken::Integer))
8336 return TokError("expected integer discriminator");
8337 int64_t Discriminator = Parser.getTok().getIntVal();
8338
8339 if (!isUInt<16>(Discriminator))
8340 return TokError("integer discriminator " + Twine(Discriminator) +
8341 " out of range [0, 0xFFFF]");
8342 Parser.Lex();
8343
8344 bool UseAddressDiversity = false;
8345 if (Parser.getTok().is(AsmToken::Comma)) {
8346 Parser.Lex();
8347 if (Parser.getTok().isNot(AsmToken::Identifier) ||
8348 Parser.getTok().getIdentifier() != "addr")
8349 return TokError("expected 'addr'");
8350 UseAddressDiversity = true;
8351 Parser.Lex();
8352 }
8353
8354 EndLoc = Parser.getTok().getEndLoc();
8355 if (parseToken(AsmToken::RParen, "expected ')'"))
8356 return true;
8357
8358 Res = AArch64AuthMCExpr::create(Res, Discriminator, *KeyIDOrNone,
8359 UseAddressDiversity, Ctx, Res->getLoc());
8360 return false;
8361}
8362
8363bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
8364 AArch64::Specifier &ELFSpec,
8365 AArch64::Specifier &DarwinSpec,
8366 int64_t &Addend) {
8367 ELFSpec = AArch64::S_INVALID;
8368 DarwinSpec = AArch64::S_None;
8369 Addend = 0;
8370
8371 if (auto *AE = dyn_cast<MCSpecifierExpr>(Expr)) {
8372 ELFSpec = AE->getSpecifier();
8373 Expr = AE->getSubExpr();
8374 }
8375
8376 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
8377 if (SE) {
8378 // It's a simple symbol reference with no addend.
8379 DarwinSpec = AArch64::Specifier(SE->getKind());
8380 return true;
8381 }
8382
8383 // Check that it looks like a symbol + an addend
8384 MCValue Res;
8385 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr);
8386 if (!Relocatable || Res.getSubSym())
8387 return false;
8388
8389 // Treat expressions with an ELFSpec (like ":abs_g1:3", or
8390 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
8391 if (!Res.getAddSym() && ELFSpec == AArch64::S_INVALID)
8392 return false;
8393
8394 if (Res.getAddSym())
8395 DarwinSpec = AArch64::Specifier(Res.getSpecifier());
8396 Addend = Res.getConstant();
8397
8398 // It's some symbol reference + a constant addend, but really
8399 // shouldn't use both Darwin and ELF syntax.
8400 return ELFSpec == AArch64::S_INVALID || DarwinSpec == AArch64::S_None;
8401}
8402
8403/// Force static initialization.
8404extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
8412
8413#define GET_REGISTER_MATCHER
8414#define GET_SUBTARGET_FEATURE_NAME
8415#define GET_MATCHER_IMPLEMENTATION
8416#define GET_MNEMONIC_SPELL_CHECKER
8417#include "AArch64GenAsmMatcher.inc"
8418
8419// Define this matcher function after the auto-generated include so we
8420// have the match class enum definitions.
8421unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
8422 unsigned Kind) {
8423 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
8424
8425 auto MatchesOpImmediate = [&](int64_t ExpectedVal) -> MatchResultTy {
8426 if (!Op.isImm())
8427 return Match_InvalidOperand;
8428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
8429 if (!CE)
8430 return Match_InvalidOperand;
8431 if (CE->getValue() == ExpectedVal)
8432 return Match_Success;
8433 return Match_InvalidOperand;
8434 };
8435
8436 switch (Kind) {
8437 default:
8438 return Match_InvalidOperand;
8439 case MCK_MPR:
8440 // If the Kind is a token for the MPR register class which has the "za"
8441 // register (SME accumulator array), check if the asm is a literal "za"
8442 // token. This is for the "smstart za" alias that defines the register
8443 // as a literal token.
8444 if (Op.isTokenEqual("za"))
8445 return Match_Success;
8446 return Match_InvalidOperand;
8447
8448 // If the kind is a token for a literal immediate, check if our asm operand
8449 // matches. This is for InstAliases which have a fixed-value immediate in
8450 // the asm string, such as hints which are parsed into a specific
8451 // instruction definition.
8452#define MATCH_HASH(N) \
8453 case MCK__HASH_##N: \
8454 return MatchesOpImmediate(N);
8455 MATCH_HASH(0)
8456 MATCH_HASH(1)
8457 MATCH_HASH(2)
8458 MATCH_HASH(3)
8459 MATCH_HASH(4)
8460 MATCH_HASH(6)
8461 MATCH_HASH(7)
8462 MATCH_HASH(8)
8463 MATCH_HASH(10)
8464 MATCH_HASH(12)
8465 MATCH_HASH(14)
8466 MATCH_HASH(16)
8467 MATCH_HASH(24)
8468 MATCH_HASH(25)
8469 MATCH_HASH(26)
8470 MATCH_HASH(27)
8471 MATCH_HASH(28)
8472 MATCH_HASH(29)
8473 MATCH_HASH(30)
8474 MATCH_HASH(31)
8475 MATCH_HASH(32)
8476 MATCH_HASH(40)
8477 MATCH_HASH(48)
8478 MATCH_HASH(64)
8479#undef MATCH_HASH
8480#define MATCH_HASH_MINUS(N) \
8481 case MCK__HASH__MINUS_##N: \
8482 return MatchesOpImmediate(-N);
8486#undef MATCH_HASH_MINUS
8487 }
8488}
8489
8490ParseStatus AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
8491
8492 SMLoc S = getLoc();
8493
8494 if (getTok().isNot(AsmToken::Identifier))
8495 return Error(S, "expected register");
8496
8497 MCRegister FirstReg;
8498 ParseStatus Res = tryParseScalarRegister(FirstReg);
8499 if (!Res.isSuccess())
8500 return Error(S, "expected first even register of a consecutive same-size "
8501 "even/odd register pair");
8502
8503 const MCRegisterClass &WRegClass =
8504 getAArch64MCRegisterClass(AArch64::GPR32RegClassID);
8505 const MCRegisterClass &XRegClass =
8506 getAArch64MCRegisterClass(AArch64::GPR64RegClassID);
8507
8508 bool isXReg = XRegClass.contains(FirstReg),
8509 isWReg = WRegClass.contains(FirstReg);
8510 if (!isXReg && !isWReg)
8511 return Error(S, "expected first even register of a consecutive same-size "
8512 "even/odd register pair");
8513
8514 const MCRegisterInfo *RI = getContext().getRegisterInfo();
8515 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
8516
8517 if (FirstEncoding & 0x1)
8518 return Error(S, "expected first even register of a consecutive same-size "
8519 "even/odd register pair");
8520
8521 if (getTok().isNot(AsmToken::Comma))
8522 return Error(getLoc(), "expected comma");
8523 // Eat the comma
8524 Lex();
8525
8526 SMLoc E = getLoc();
8527 MCRegister SecondReg;
8528 Res = tryParseScalarRegister(SecondReg);
8529 if (!Res.isSuccess())
8530 return Error(E, "expected second odd register of a consecutive same-size "
8531 "even/odd register pair");
8532
8533 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
8534 (isXReg && !XRegClass.contains(SecondReg)) ||
8535 (isWReg && !WRegClass.contains(SecondReg)))
8536 return Error(E, "expected second odd register of a consecutive same-size "
8537 "even/odd register pair");
8538
8539 MCRegister Pair;
8540 if (isXReg) {
8541 Pair = RI->getMatchingSuperReg(
8542 FirstReg, AArch64::sube64,
8543 &getAArch64MCRegisterClass(AArch64::XSeqPairsClassRegClassID));
8544 } else {
8545 Pair = RI->getMatchingSuperReg(
8546 FirstReg, AArch64::sube32,
8547 &getAArch64MCRegisterClass(AArch64::WSeqPairsClassRegClassID));
8548 }
8549
8550 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
8551 getLoc(), getContext()));
8552
8553 return ParseStatus::Success;
8554}
8555
8556template <bool ParseShiftExtend, bool ParseSuffix>
8557ParseStatus AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
8558 const SMLoc S = getLoc();
8559 // Check for a SVE vector register specifier first.
8560 MCRegister RegNum;
8561 StringRef Kind;
8562
8563 ParseStatus Res =
8564 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
8565
8566 if (!Res.isSuccess())
8567 return Res;
8568
8569 if (ParseSuffix && Kind.empty())
8570 return ParseStatus::NoMatch;
8571
8572 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
8573 if (!KindRes)
8574 return ParseStatus::NoMatch;
8575
8576 unsigned ElementWidth = KindRes->second;
8577
8578 // No shift/extend is the default.
8579 if (!ParseShiftExtend || getTok().isNot(AsmToken::Comma)) {
8580 Operands.push_back(AArch64Operand::CreateVectorReg(
8581 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
8582
8583 ParseStatus Res = tryParseVectorIndex(Operands);
8584 if (Res.isFailure())
8585 return ParseStatus::Failure;
8586 return ParseStatus::Success;
8587 }
8588
8589 // Eat the comma
8590 Lex();
8591
8592 // Match the shift
8594 Res = tryParseOptionalShiftExtend(ExtOpnd);
8595 if (!Res.isSuccess())
8596 return Res;
8597
8598 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
8599 Operands.push_back(AArch64Operand::CreateVectorReg(
8600 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
8601 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
8602 Ext->hasShiftExtendAmount()));
8603
8604 return ParseStatus::Success;
8605}
8606
8607ParseStatus AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
8608 MCAsmParser &Parser = getParser();
8609
8610 SMLoc SS = getLoc();
8611 const AsmToken &TokE = getTok();
8612 bool IsHash = TokE.is(AsmToken::Hash);
8613
8614 if (!IsHash && TokE.isNot(AsmToken::Identifier))
8615 return ParseStatus::NoMatch;
8616
8617 int64_t Pattern;
8618 if (IsHash) {
8619 Lex(); // Eat hash
8620
8621 // Parse the immediate operand.
8622 const MCExpr *ImmVal;
8623 SS = getLoc();
8624 if (Parser.parseExpression(ImmVal))
8625 return ParseStatus::Failure;
8626
8627 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
8628 if (!MCE)
8629 return TokError("invalid operand for instruction");
8630
8631 Pattern = MCE->getValue();
8632 } else {
8633 // Parse the pattern
8634 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
8635 if (!Pat)
8636 return ParseStatus::NoMatch;
8637
8638 Lex();
8639 Pattern = Pat->Encoding;
8640 assert(Pattern >= 0 && Pattern < 32);
8641 }
8642
8643 Operands.push_back(
8644 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
8645 SS, getLoc(), getContext()));
8646
8647 return ParseStatus::Success;
8648}
8649
8650ParseStatus
8651AArch64AsmParser::tryParseSVEVecLenSpecifier(OperandVector &Operands) {
8652 int64_t Pattern;
8653 SMLoc SS = getLoc();
8654 const AsmToken &TokE = getTok();
8655 // Parse the pattern
8656 auto Pat = AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByName(
8657 TokE.getString());
8658 if (!Pat)
8659 return ParseStatus::NoMatch;
8660
8661 Lex();
8662 Pattern = Pat->Encoding;
8663 assert(Pattern >= 0 && Pattern <= 1 && "Pattern does not exist");
8664
8665 Operands.push_back(
8666 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
8667 SS, getLoc(), getContext()));
8668
8669 return ParseStatus::Success;
8670}
8671
8672ParseStatus AArch64AsmParser::tryParseGPR64x8(OperandVector &Operands) {
8673 SMLoc SS = getLoc();
8674
8675 MCRegister XReg;
8676 if (!tryParseScalarRegister(XReg).isSuccess())
8677 return ParseStatus::NoMatch;
8678
8679 MCContext &ctx = getContext();
8680 const MCRegisterInfo *RI = ctx.getRegisterInfo();
8681 MCRegister X8Reg = RI->getMatchingSuperReg(
8682 XReg, AArch64::x8sub_0,
8683 &getAArch64MCRegisterClass(AArch64::GPR64x8ClassRegClassID));
8684 if (!X8Reg)
8685 return Error(SS,
8686 "expected an even-numbered x-register in the range [x0,x22]");
8687
8688 Operands.push_back(
8689 AArch64Operand::CreateReg(X8Reg, RegKind::Scalar, SS, getLoc(), ctx));
8690 return ParseStatus::Success;
8691}
8692
8693ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
8694 SMLoc S = getLoc();
8695
8696 if (getTok().isNot(AsmToken::Integer))
8697 return ParseStatus::NoMatch;
8698
8699 if (getLexer().peekTok().isNot(AsmToken::Colon))
8700 return ParseStatus::NoMatch;
8701
8702 const MCExpr *ImmF;
8703 if (getParser().parseExpression(ImmF))
8704 return ParseStatus::NoMatch;
8705
8706 if (getTok().isNot(AsmToken::Colon))
8707 return ParseStatus::NoMatch;
8708
8709 Lex(); // Eat ':'
8710 if (getTok().isNot(AsmToken::Integer))
8711 return ParseStatus::NoMatch;
8712
8713 SMLoc E = getTok().getLoc();
8714 const MCExpr *ImmL;
8715 if (getParser().parseExpression(ImmL))
8716 return ParseStatus::NoMatch;
8717
8718 unsigned ImmFVal = cast<MCConstantExpr>(ImmF)->getValue();
8719 unsigned ImmLVal = cast<MCConstantExpr>(ImmL)->getValue();
8720
8721 Operands.push_back(
8722 AArch64Operand::CreateImmRange(ImmFVal, ImmLVal, S, E, getContext()));
8723 return ParseStatus::Success;
8724}
8725
8726template <int Adj>
8727ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
8728 SMLoc S = getLoc();
8729
8730 parseOptionalToken(AsmToken::Hash);
8731 bool IsNegative = parseOptionalToken(AsmToken::Minus);
8732
8733 if (getTok().isNot(AsmToken::Integer))
8734 return ParseStatus::NoMatch;
8735
8736 const MCExpr *Ex;
8737 if (getParser().parseExpression(Ex))
8738 return ParseStatus::NoMatch;
8739
8740 int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
8741 if (IsNegative)
8742 Imm = -Imm;
8743
8744 // We want an adjusted immediate in the range [0, 63]. If we don't have one,
8745 // return a value, which is certain to trigger a error message about invalid
8746 // immediate range instead of a non-descriptive invalid operand error.
8747 static_assert(Adj == 1 || Adj == -1, "Unsafe immediate adjustment");
8748 if (Imm == INT64_MIN || Imm == INT64_MAX || Imm + Adj < 0 || Imm + Adj > 63)
8749 Imm = -2;
8750 else
8751 Imm += Adj;
8752
8753 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
8754 Operands.push_back(AArch64Operand::CreateImm(
8756
8757 return ParseStatus::Success;
8758}
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
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:1436
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:1585
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.
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:786
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:388
Context & getContext() const
Definition BasicBlock.h:99
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