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