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