brintos

brintos / llvm-project-archived public Read only

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