LLVM  7.0.0svn
AMDGPUAsmParser.cpp
Go to the documentation of this file.
1 //===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "AMDGPU.h"
11 #include "AMDKernelCodeT.h"
14 #include "SIDefines.h"
15 #include "SIInstrInfo.h"
16 #include "Utils/AMDGPUAsmUtils.h"
17 #include "Utils/AMDGPUBaseInfo.h"
19 #include "llvm/ADT/APFloat.h"
20 #include "llvm/ADT/APInt.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/StringSwitch.h"
27 #include "llvm/ADT/Twine.h"
28 #include "llvm/BinaryFormat/ELF.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCContext.h"
31 #include "llvm/MC/MCExpr.h"
32 #include "llvm/MC/MCInst.h"
33 #include "llvm/MC/MCInstrDesc.h"
34 #include "llvm/MC/MCInstrInfo.h"
40 #include "llvm/MC/MCRegisterInfo.h"
41 #include "llvm/MC/MCStreamer.h"
43 #include "llvm/MC/MCSymbol.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/Compiler.h"
50 #include "llvm/Support/SMLoc.h"
53 #include <algorithm>
54 #include <cassert>
55 #include <cstdint>
56 #include <cstring>
57 #include <iterator>
58 #include <map>
59 #include <memory>
60 #include <string>
61 
62 using namespace llvm;
63 using namespace llvm::AMDGPU;
64 
65 namespace {
66 
67 class AMDGPUAsmParser;
68 
69 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
70 
71 //===----------------------------------------------------------------------===//
72 // Operand
73 //===----------------------------------------------------------------------===//
74 
75 class AMDGPUOperand : public MCParsedAsmOperand {
76  enum KindTy {
77  Token,
78  Immediate,
79  Register,
80  Expression
81  } Kind;
82 
83  SMLoc StartLoc, EndLoc;
84  const AMDGPUAsmParser *AsmParser;
85 
86 public:
87  AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
88  : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
89 
90  using Ptr = std::unique_ptr<AMDGPUOperand>;
91 
92  struct Modifiers {
93  bool Abs = false;
94  bool Neg = false;
95  bool Sext = false;
96 
97  bool hasFPModifiers() const { return Abs || Neg; }
98  bool hasIntModifiers() const { return Sext; }
99  bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
100 
101  int64_t getFPModifiersOperand() const {
102  int64_t Operand = 0;
103  Operand |= Abs ? SISrcMods::ABS : 0;
104  Operand |= Neg ? SISrcMods::NEG : 0;
105  return Operand;
106  }
107 
108  int64_t getIntModifiersOperand() const {
109  int64_t Operand = 0;
110  Operand |= Sext ? SISrcMods::SEXT : 0;
111  return Operand;
112  }
113 
114  int64_t getModifiersOperand() const {
115  assert(!(hasFPModifiers() && hasIntModifiers())
116  && "fp and int modifiers should not be used simultaneously");
117  if (hasFPModifiers()) {
118  return getFPModifiersOperand();
119  } else if (hasIntModifiers()) {
120  return getIntModifiersOperand();
121  } else {
122  return 0;
123  }
124  }
125 
126  friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
127  };
128 
129  enum ImmTy {
130  ImmTyNone,
131  ImmTyGDS,
132  ImmTyLDS,
133  ImmTyOffen,
134  ImmTyIdxen,
135  ImmTyAddr64,
136  ImmTyOffset,
137  ImmTyInstOffset,
138  ImmTyOffset0,
139  ImmTyOffset1,
140  ImmTyGLC,
141  ImmTySLC,
142  ImmTyTFE,
143  ImmTyD16,
144  ImmTyClampSI,
145  ImmTyOModSI,
146  ImmTyDppCtrl,
147  ImmTyDppRowMask,
148  ImmTyDppBankMask,
149  ImmTyDppBoundCtrl,
150  ImmTySdwaDstSel,
151  ImmTySdwaSrc0Sel,
152  ImmTySdwaSrc1Sel,
153  ImmTySdwaDstUnused,
154  ImmTyDMask,
155  ImmTyUNorm,
156  ImmTyDA,
157  ImmTyR128,
158  ImmTyLWE,
159  ImmTyExpTgt,
160  ImmTyExpCompr,
161  ImmTyExpVM,
162  ImmTyDFMT,
163  ImmTyNFMT,
164  ImmTyHwreg,
165  ImmTyOff,
166  ImmTySendMsg,
167  ImmTyInterpSlot,
168  ImmTyInterpAttr,
169  ImmTyAttrChan,
170  ImmTyOpSel,
171  ImmTyOpSelHi,
172  ImmTyNegLo,
173  ImmTyNegHi,
174  ImmTySwizzle,
175  ImmTyHigh
176  };
177 
178  struct TokOp {
179  const char *Data;
180  unsigned Length;
181  };
182 
183  struct ImmOp {
184  int64_t Val;
185  ImmTy Type;
186  bool IsFPImm;
187  Modifiers Mods;
188  };
189 
190  struct RegOp {
191  unsigned RegNo;
192  bool IsForcedVOP3;
193  Modifiers Mods;
194  };
195 
196  union {
197  TokOp Tok;
198  ImmOp Imm;
199  RegOp Reg;
200  const MCExpr *Expr;
201  };
202 
203  bool isToken() const override {
204  if (Kind == Token)
205  return true;
206 
207  if (Kind != Expression || !Expr)
208  return false;
209 
210  // When parsing operands, we can't always tell if something was meant to be
211  // a token, like 'gds', or an expression that references a global variable.
212  // In this case, we assume the string is an expression, and if we need to
213  // interpret is a token, then we treat the symbol name as the token.
214  return isa<MCSymbolRefExpr>(Expr);
215  }
216 
217  bool isImm() const override {
218  return Kind == Immediate;
219  }
220 
221  bool isInlinableImm(MVT type) const;
222  bool isLiteralImm(MVT type) const;
223 
224  bool isRegKind() const {
225  return Kind == Register;
226  }
227 
228  bool isReg() const override {
229  return isRegKind() && !hasModifiers();
230  }
231 
232  bool isRegOrImmWithInputMods(MVT type) const {
233  return isRegKind() || isInlinableImm(type);
234  }
235 
236  bool isRegOrImmWithInt16InputMods() const {
238  }
239 
240  bool isRegOrImmWithInt32InputMods() const {
242  }
243 
244  bool isRegOrImmWithInt64InputMods() const {
246  }
247 
248  bool isRegOrImmWithFP16InputMods() const {
250  }
251 
252  bool isRegOrImmWithFP32InputMods() const {
254  }
255 
256  bool isRegOrImmWithFP64InputMods() const {
258  }
259 
260  bool isVReg() const {
261  return isRegClass(AMDGPU::VGPR_32RegClassID) ||
262  isRegClass(AMDGPU::VReg_64RegClassID) ||
263  isRegClass(AMDGPU::VReg_96RegClassID) ||
264  isRegClass(AMDGPU::VReg_128RegClassID) ||
265  isRegClass(AMDGPU::VReg_256RegClassID) ||
266  isRegClass(AMDGPU::VReg_512RegClassID);
267  }
268 
269  bool isVReg32OrOff() const {
270  return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
271  }
272 
273  bool isSDWAOperand(MVT type) const;
274  bool isSDWAFP16Operand() const;
275  bool isSDWAFP32Operand() const;
276  bool isSDWAInt16Operand() const;
277  bool isSDWAInt32Operand() const;
278 
279  bool isImmTy(ImmTy ImmT) const {
280  return isImm() && Imm.Type == ImmT;
281  }
282 
283  bool isImmModifier() const {
284  return isImm() && Imm.Type != ImmTyNone;
285  }
286 
287  bool isClampSI() const { return isImmTy(ImmTyClampSI); }
288  bool isOModSI() const { return isImmTy(ImmTyOModSI); }
289  bool isDMask() const { return isImmTy(ImmTyDMask); }
290  bool isUNorm() const { return isImmTy(ImmTyUNorm); }
291  bool isDA() const { return isImmTy(ImmTyDA); }
292  bool isR128() const { return isImmTy(ImmTyR128); }
293  bool isLWE() const { return isImmTy(ImmTyLWE); }
294  bool isOff() const { return isImmTy(ImmTyOff); }
295  bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
296  bool isExpVM() const { return isImmTy(ImmTyExpVM); }
297  bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
298  bool isOffen() const { return isImmTy(ImmTyOffen); }
299  bool isIdxen() const { return isImmTy(ImmTyIdxen); }
300  bool isAddr64() const { return isImmTy(ImmTyAddr64); }
301  bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
302  bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
303  bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
304 
305  bool isOffsetU12() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isUInt<12>(getImm()); }
306  bool isOffsetS13() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isInt<13>(getImm()); }
307  bool isGDS() const { return isImmTy(ImmTyGDS); }
308  bool isLDS() const { return isImmTy(ImmTyLDS); }
309  bool isGLC() const { return isImmTy(ImmTyGLC); }
310  bool isSLC() const { return isImmTy(ImmTySLC); }
311  bool isTFE() const { return isImmTy(ImmTyTFE); }
312  bool isD16() const { return isImmTy(ImmTyD16); }
313  bool isDFMT() const { return isImmTy(ImmTyDFMT) && isUInt<8>(getImm()); }
314  bool isNFMT() const { return isImmTy(ImmTyNFMT) && isUInt<8>(getImm()); }
315  bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
316  bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
317  bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
318  bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
319  bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
320  bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
321  bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
322  bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
323  bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
324  bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
325  bool isOpSel() const { return isImmTy(ImmTyOpSel); }
326  bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
327  bool isNegLo() const { return isImmTy(ImmTyNegLo); }
328  bool isNegHi() const { return isImmTy(ImmTyNegHi); }
329  bool isHigh() const { return isImmTy(ImmTyHigh); }
330 
331  bool isMod() const {
332  return isClampSI() || isOModSI();
333  }
334 
335  bool isRegOrImm() const {
336  return isReg() || isImm();
337  }
338 
339  bool isRegClass(unsigned RCID) const;
340 
341  bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
342  return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
343  }
344 
345  bool isSCSrcB16() const {
346  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
347  }
348 
349  bool isSCSrcV2B16() const {
350  return isSCSrcB16();
351  }
352 
353  bool isSCSrcB32() const {
354  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
355  }
356 
357  bool isSCSrcB64() const {
358  return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
359  }
360 
361  bool isSCSrcF16() const {
362  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
363  }
364 
365  bool isSCSrcV2F16() const {
366  return isSCSrcF16();
367  }
368 
369  bool isSCSrcF32() const {
370  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
371  }
372 
373  bool isSCSrcF64() const {
374  return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
375  }
376 
377  bool isSSrcB32() const {
378  return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
379  }
380 
381  bool isSSrcB16() const {
382  return isSCSrcB16() || isLiteralImm(MVT::i16);
383  }
384 
385  bool isSSrcV2B16() const {
386  llvm_unreachable("cannot happen");
387  return isSSrcB16();
388  }
389 
390  bool isSSrcB64() const {
391  // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
392  // See isVSrc64().
393  return isSCSrcB64() || isLiteralImm(MVT::i64);
394  }
395 
396  bool isSSrcF32() const {
397  return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
398  }
399 
400  bool isSSrcF64() const {
401  return isSCSrcB64() || isLiteralImm(MVT::f64);
402  }
403 
404  bool isSSrcF16() const {
405  return isSCSrcB16() || isLiteralImm(MVT::f16);
406  }
407 
408  bool isSSrcV2F16() const {
409  llvm_unreachable("cannot happen");
410  return isSSrcF16();
411  }
412 
413  bool isVCSrcB32() const {
414  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
415  }
416 
417  bool isVCSrcB64() const {
418  return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
419  }
420 
421  bool isVCSrcB16() const {
422  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
423  }
424 
425  bool isVCSrcV2B16() const {
426  return isVCSrcB16();
427  }
428 
429  bool isVCSrcF32() const {
430  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
431  }
432 
433  bool isVCSrcF64() const {
434  return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
435  }
436 
437  bool isVCSrcF16() const {
438  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
439  }
440 
441  bool isVCSrcV2F16() const {
442  return isVCSrcF16();
443  }
444 
445  bool isVSrcB32() const {
446  return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr();
447  }
448 
449  bool isVSrcB64() const {
450  return isVCSrcF64() || isLiteralImm(MVT::i64);
451  }
452 
453  bool isVSrcB16() const {
454  return isVCSrcF16() || isLiteralImm(MVT::i16);
455  }
456 
457  bool isVSrcV2B16() const {
458  llvm_unreachable("cannot happen");
459  return isVSrcB16();
460  }
461 
462  bool isVSrcF32() const {
463  return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr();
464  }
465 
466  bool isVSrcF64() const {
467  return isVCSrcF64() || isLiteralImm(MVT::f64);
468  }
469 
470  bool isVSrcF16() const {
471  return isVCSrcF16() || isLiteralImm(MVT::f16);
472  }
473 
474  bool isVSrcV2F16() const {
475  llvm_unreachable("cannot happen");
476  return isVSrcF16();
477  }
478 
479  bool isKImmFP32() const {
480  return isLiteralImm(MVT::f32);
481  }
482 
483  bool isKImmFP16() const {
484  return isLiteralImm(MVT::f16);
485  }
486 
487  bool isMem() const override {
488  return false;
489  }
490 
491  bool isExpr() const {
492  return Kind == Expression;
493  }
494 
495  bool isSoppBrTarget() const {
496  return isExpr() || isImm();
497  }
498 
499  bool isSWaitCnt() const;
500  bool isHwreg() const;
501  bool isSendMsg() const;
502  bool isSwizzle() const;
503  bool isSMRDOffset8() const;
504  bool isSMRDOffset20() const;
505  bool isSMRDLiteralOffset() const;
506  bool isDPPCtrl() const;
507  bool isGPRIdxMode() const;
508  bool isS16Imm() const;
509  bool isU16Imm() const;
510 
511  StringRef getExpressionAsToken() const {
512  assert(isExpr());
513  const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
514  return S->getSymbol().getName();
515  }
516 
517  StringRef getToken() const {
518  assert(isToken());
519 
520  if (Kind == Expression)
521  return getExpressionAsToken();
522 
523  return StringRef(Tok.Data, Tok.Length);
524  }
525 
526  int64_t getImm() const {
527  assert(isImm());
528  return Imm.Val;
529  }
530 
531  ImmTy getImmTy() const {
532  assert(isImm());
533  return Imm.Type;
534  }
535 
536  unsigned getReg() const override {
537  return Reg.RegNo;
538  }
539 
540  SMLoc getStartLoc() const override {
541  return StartLoc;
542  }
543 
544  SMLoc getEndLoc() const override {
545  return EndLoc;
546  }
547 
548  SMRange getLocRange() const {
549  return SMRange(StartLoc, EndLoc);
550  }
551 
552  Modifiers getModifiers() const {
553  assert(isRegKind() || isImmTy(ImmTyNone));
554  return isRegKind() ? Reg.Mods : Imm.Mods;
555  }
556 
557  void setModifiers(Modifiers Mods) {
558  assert(isRegKind() || isImmTy(ImmTyNone));
559  if (isRegKind())
560  Reg.Mods = Mods;
561  else
562  Imm.Mods = Mods;
563  }
564 
565  bool hasModifiers() const {
566  return getModifiers().hasModifiers();
567  }
568 
569  bool hasFPModifiers() const {
570  return getModifiers().hasFPModifiers();
571  }
572 
573  bool hasIntModifiers() const {
574  return getModifiers().hasIntModifiers();
575  }
576 
577  uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
578 
579  void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
580 
581  void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
582 
583  template <unsigned Bitwidth>
584  void addKImmFPOperands(MCInst &Inst, unsigned N) const;
585 
586  void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
587  addKImmFPOperands<16>(Inst, N);
588  }
589 
590  void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
591  addKImmFPOperands<32>(Inst, N);
592  }
593 
594  void addRegOperands(MCInst &Inst, unsigned N) const;
595 
596  void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
597  if (isRegKind())
598  addRegOperands(Inst, N);
599  else if (isExpr())
600  Inst.addOperand(MCOperand::createExpr(Expr));
601  else
602  addImmOperands(Inst, N);
603  }
604 
605  void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
606  Modifiers Mods = getModifiers();
607  Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
608  if (isRegKind()) {
609  addRegOperands(Inst, N);
610  } else {
611  addImmOperands(Inst, N, false);
612  }
613  }
614 
615  void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
616  assert(!hasIntModifiers());
617  addRegOrImmWithInputModsOperands(Inst, N);
618  }
619 
620  void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
621  assert(!hasFPModifiers());
622  addRegOrImmWithInputModsOperands(Inst, N);
623  }
624 
625  void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
626  Modifiers Mods = getModifiers();
627  Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
628  assert(isRegKind());
629  addRegOperands(Inst, N);
630  }
631 
632  void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
633  assert(!hasIntModifiers());
634  addRegWithInputModsOperands(Inst, N);
635  }
636 
637  void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
638  assert(!hasFPModifiers());
639  addRegWithInputModsOperands(Inst, N);
640  }
641 
642  void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
643  if (isImm())
644  addImmOperands(Inst, N);
645  else {
646  assert(isExpr());
647  Inst.addOperand(MCOperand::createExpr(Expr));
648  }
649  }
650 
651  static void printImmTy(raw_ostream& OS, ImmTy Type) {
652  switch (Type) {
653  case ImmTyNone: OS << "None"; break;
654  case ImmTyGDS: OS << "GDS"; break;
655  case ImmTyLDS: OS << "LDS"; break;
656  case ImmTyOffen: OS << "Offen"; break;
657  case ImmTyIdxen: OS << "Idxen"; break;
658  case ImmTyAddr64: OS << "Addr64"; break;
659  case ImmTyOffset: OS << "Offset"; break;
660  case ImmTyInstOffset: OS << "InstOffset"; break;
661  case ImmTyOffset0: OS << "Offset0"; break;
662  case ImmTyOffset1: OS << "Offset1"; break;
663  case ImmTyGLC: OS << "GLC"; break;
664  case ImmTySLC: OS << "SLC"; break;
665  case ImmTyTFE: OS << "TFE"; break;
666  case ImmTyD16: OS << "D16"; break;
667  case ImmTyDFMT: OS << "DFMT"; break;
668  case ImmTyNFMT: OS << "NFMT"; break;
669  case ImmTyClampSI: OS << "ClampSI"; break;
670  case ImmTyOModSI: OS << "OModSI"; break;
671  case ImmTyDppCtrl: OS << "DppCtrl"; break;
672  case ImmTyDppRowMask: OS << "DppRowMask"; break;
673  case ImmTyDppBankMask: OS << "DppBankMask"; break;
674  case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
675  case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
676  case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
677  case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
678  case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
679  case ImmTyDMask: OS << "DMask"; break;
680  case ImmTyUNorm: OS << "UNorm"; break;
681  case ImmTyDA: OS << "DA"; break;
682  case ImmTyR128: OS << "R128"; break;
683  case ImmTyLWE: OS << "LWE"; break;
684  case ImmTyOff: OS << "Off"; break;
685  case ImmTyExpTgt: OS << "ExpTgt"; break;
686  case ImmTyExpCompr: OS << "ExpCompr"; break;
687  case ImmTyExpVM: OS << "ExpVM"; break;
688  case ImmTyHwreg: OS << "Hwreg"; break;
689  case ImmTySendMsg: OS << "SendMsg"; break;
690  case ImmTyInterpSlot: OS << "InterpSlot"; break;
691  case ImmTyInterpAttr: OS << "InterpAttr"; break;
692  case ImmTyAttrChan: OS << "AttrChan"; break;
693  case ImmTyOpSel: OS << "OpSel"; break;
694  case ImmTyOpSelHi: OS << "OpSelHi"; break;
695  case ImmTyNegLo: OS << "NegLo"; break;
696  case ImmTyNegHi: OS << "NegHi"; break;
697  case ImmTySwizzle: OS << "Swizzle"; break;
698  case ImmTyHigh: OS << "High"; break;
699  }
700  }
701 
702  void print(raw_ostream &OS) const override {
703  switch (Kind) {
704  case Register:
705  OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
706  break;
707  case Immediate:
708  OS << '<' << getImm();
709  if (getImmTy() != ImmTyNone) {
710  OS << " type: "; printImmTy(OS, getImmTy());
711  }
712  OS << " mods: " << Imm.Mods << '>';
713  break;
714  case Token:
715  OS << '\'' << getToken() << '\'';
716  break;
717  case Expression:
718  OS << "<expr " << *Expr << '>';
719  break;
720  }
721  }
722 
723  static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
724  int64_t Val, SMLoc Loc,
725  ImmTy Type = ImmTyNone,
726  bool IsFPImm = false) {
727  auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
728  Op->Imm.Val = Val;
729  Op->Imm.IsFPImm = IsFPImm;
730  Op->Imm.Type = Type;
731  Op->Imm.Mods = Modifiers();
732  Op->StartLoc = Loc;
733  Op->EndLoc = Loc;
734  return Op;
735  }
736 
737  static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
738  StringRef Str, SMLoc Loc,
739  bool HasExplicitEncodingSize = true) {
740  auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
741  Res->Tok.Data = Str.data();
742  Res->Tok.Length = Str.size();
743  Res->StartLoc = Loc;
744  Res->EndLoc = Loc;
745  return Res;
746  }
747 
748  static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
749  unsigned RegNo, SMLoc S,
750  SMLoc E,
751  bool ForceVOP3) {
752  auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
753  Op->Reg.RegNo = RegNo;
754  Op->Reg.Mods = Modifiers();
755  Op->Reg.IsForcedVOP3 = ForceVOP3;
756  Op->StartLoc = S;
757  Op->EndLoc = E;
758  return Op;
759  }
760 
761  static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
762  const class MCExpr *Expr, SMLoc S) {
763  auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
764  Op->Expr = Expr;
765  Op->StartLoc = S;
766  Op->EndLoc = S;
767  return Op;
768  }
769 };
770 
771 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
772  OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
773  return OS;
774 }
775 
776 //===----------------------------------------------------------------------===//
777 // AsmParser
778 //===----------------------------------------------------------------------===//
779 
780 // Holds info related to the current kernel, e.g. count of SGPRs used.
781 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
782 // .amdgpu_hsa_kernel or at EOF.
783 class KernelScopeInfo {
784  int SgprIndexUnusedMin = -1;
785  int VgprIndexUnusedMin = -1;
786  MCContext *Ctx = nullptr;
787 
788  void usesSgprAt(int i) {
789  if (i >= SgprIndexUnusedMin) {
790  SgprIndexUnusedMin = ++i;
791  if (Ctx) {
792  MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
793  Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
794  }
795  }
796  }
797 
798  void usesVgprAt(int i) {
799  if (i >= VgprIndexUnusedMin) {
800  VgprIndexUnusedMin = ++i;
801  if (Ctx) {
802  MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
803  Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
804  }
805  }
806  }
807 
808 public:
809  KernelScopeInfo() = default;
810 
811  void initialize(MCContext &Context) {
812  Ctx = &Context;
813  usesSgprAt(SgprIndexUnusedMin = -1);
814  usesVgprAt(VgprIndexUnusedMin = -1);
815  }
816 
817  void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
818  switch (RegKind) {
819  case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
820  case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
821  default: break;
822  }
823  }
824 };
825 
826 class AMDGPUAsmParser : public MCTargetAsmParser {
827  MCAsmParser &Parser;
828 
829  // Number of extra operands parsed after the first optional operand.
830  // This may be necessary to skip hardcoded mandatory operands.
831  static const unsigned MAX_OPR_LOOKAHEAD = 8;
832 
833  unsigned ForcedEncodingSize = 0;
834  bool ForcedDPP = false;
835  bool ForcedSDWA = false;
836  KernelScopeInfo KernelScope;
837 
838  /// @name Auto-generated Match Functions
839  /// {
840 
841 #define GET_ASSEMBLER_HEADER
842 #include "AMDGPUGenAsmMatcher.inc"
843 
844  /// }
845 
846 private:
847  bool ParseAsAbsoluteExpression(uint32_t &Ret);
848  bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
849  bool ParseDirectiveHSACodeObjectVersion();
850  bool ParseDirectiveHSACodeObjectISA();
851  bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
852  bool ParseDirectiveAMDKernelCodeT();
853  bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
854  bool ParseDirectiveAMDGPUHsaKernel();
855 
856  bool ParseDirectiveISAVersion();
857  bool ParseDirectiveHSAMetadata();
858  bool ParseDirectivePALMetadata();
859 
860  bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
861  RegisterKind RegKind, unsigned Reg1,
862  unsigned RegNum);
863  bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
864  unsigned& RegNum, unsigned& RegWidth,
865  unsigned *DwordRegIndex);
866  void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
867  bool IsAtomic, bool IsAtomicReturn, bool IsLds = false);
868  void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
869  bool IsGdsHardcoded);
870 
871 public:
872  enum AMDGPUMatchResultTy {
873  Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
874  };
875 
876  using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
877 
878  AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
879  const MCInstrInfo &MII,
880  const MCTargetOptions &Options)
881  : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
882  MCAsmParserExtension::Initialize(Parser);
883 
884  if (getFeatureBits().none()) {
885  // Set default features.
886  copySTI().ToggleFeature("SOUTHERN_ISLANDS");
887  }
888 
889  setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
890 
891  {
892  // TODO: make those pre-defined variables read-only.
893  // Currently there is none suitable machinery in the core llvm-mc for this.
894  // MCSymbol::isRedefinable is intended for another purpose, and
895  // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
896  AMDGPU::IsaInfo::IsaVersion ISA =
897  AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
898  MCContext &Ctx = getContext();
899  MCSymbol *Sym =
900  Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
901  Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
902  Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
903  Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
904  Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
905  Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
906  }
907  KernelScope.initialize(getContext());
908  }
909 
910  bool hasXNACK() const {
911  return AMDGPU::hasXNACK(getSTI());
912  }
913 
914  bool hasMIMG_R128() const {
915  return AMDGPU::hasMIMG_R128(getSTI());
916  }
917 
918  bool hasPackedD16() const {
919  return AMDGPU::hasPackedD16(getSTI());
920  }
921 
922  bool isSI() const {
923  return AMDGPU::isSI(getSTI());
924  }
925 
926  bool isCI() const {
927  return AMDGPU::isCI(getSTI());
928  }
929 
930  bool isVI() const {
931  return AMDGPU::isVI(getSTI());
932  }
933 
934  bool isGFX9() const {
935  return AMDGPU::isGFX9(getSTI());
936  }
937 
938  bool hasInv2PiInlineImm() const {
939  return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
940  }
941 
942  bool hasFlatOffsets() const {
943  return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
944  }
945 
946  bool hasSGPR102_SGPR103() const {
947  return !isVI();
948  }
949 
950  bool hasIntClamp() const {
951  return getFeatureBits()[AMDGPU::FeatureIntClamp];
952  }
953 
954  AMDGPUTargetStreamer &getTargetStreamer() {
955  MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
956  return static_cast<AMDGPUTargetStreamer &>(TS);
957  }
958 
959  const MCRegisterInfo *getMRI() const {
960  // We need this const_cast because for some reason getContext() is not const
961  // in MCAsmParser.
962  return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
963  }
964 
965  const MCInstrInfo *getMII() const {
966  return &MII;
967  }
968 
969  const FeatureBitset &getFeatureBits() const {
970  return getSTI().getFeatureBits();
971  }
972 
973  void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
974  void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
975  void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
976 
977  unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
978  bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
979  bool isForcedDPP() const { return ForcedDPP; }
980  bool isForcedSDWA() const { return ForcedSDWA; }
981  ArrayRef<unsigned> getMatchedVariants() const;
982 
983  std::unique_ptr<AMDGPUOperand> parseRegister();
984  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
985  unsigned checkTargetMatchPredicate(MCInst &Inst) override;
986  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
987  unsigned Kind) override;
988  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
989  OperandVector &Operands, MCStreamer &Out,
990  uint64_t &ErrorInfo,
991  bool MatchingInlineAsm) override;
992  bool ParseDirective(AsmToken DirectiveID) override;
993  OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
994  StringRef parseMnemonicSuffix(StringRef Name);
995  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
996  SMLoc NameLoc, OperandVector &Operands) override;
997  //bool ProcessInstruction(MCInst &Inst);
998 
999  OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
1000 
1001  OperandMatchResultTy
1002  parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1003  AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1004  bool (*ConvertResult)(int64_t &) = nullptr);
1005 
1006  OperandMatchResultTy parseOperandArrayWithPrefix(
1007  const char *Prefix,
1008  OperandVector &Operands,
1009  AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1010  bool (*ConvertResult)(int64_t&) = nullptr);
1011 
1012  OperandMatchResultTy
1013  parseNamedBit(const char *Name, OperandVector &Operands,
1014  AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
1015  OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
1016  StringRef &Value);
1017 
1018  bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
1019  OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
1020  OperandMatchResultTy parseReg(OperandVector &Operands);
1021  OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
1022  OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1023  OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1024  OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1025  OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
1026  OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
1027 
1028  void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
1029  void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1030  void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
1031  void cvtExp(MCInst &Inst, const OperandVector &Operands);
1032 
1033  bool parseCnt(int64_t &IntVal);
1034  OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
1035  OperandMatchResultTy parseHwreg(OperandVector &Operands);
1036 
1037 private:
1038  struct OperandInfoTy {
1039  int64_t Id;
1040  bool IsSymbolic = false;
1041 
1042  OperandInfoTy(int64_t Id_) : Id(Id_) {}
1043  };
1044 
1045  bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
1046  bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1047 
1048  void errorExpTgt();
1049  OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1050 
1051  bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
1052  bool validateConstantBusLimitations(const MCInst &Inst);
1053  bool validateEarlyClobberLimitations(const MCInst &Inst);
1054  bool validateIntClampSupported(const MCInst &Inst);
1055  bool validateMIMGAtomicDMask(const MCInst &Inst);
1056  bool validateMIMGGatherDMask(const MCInst &Inst);
1057  bool validateMIMGDataSize(const MCInst &Inst);
1058  bool validateMIMGR128(const MCInst &Inst);
1059  bool validateMIMGD16(const MCInst &Inst);
1060  bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1061  bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1062  unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1063 
1064  bool trySkipId(const StringRef Id);
1065  bool trySkipToken(const AsmToken::TokenKind Kind);
1066  bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1067  bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1068  bool parseExpr(int64_t &Imm);
1069 
1070 public:
1071  OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1072  OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
1073 
1074  OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1075  OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1076  OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1077  OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1078  OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1079 
1080  bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1081  const unsigned MinVal,
1082  const unsigned MaxVal,
1083  const StringRef ErrMsg);
1084  OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1085  bool parseSwizzleOffset(int64_t &Imm);
1086  bool parseSwizzleMacro(int64_t &Imm);
1087  bool parseSwizzleQuadPerm(int64_t &Imm);
1088  bool parseSwizzleBitmaskPerm(int64_t &Imm);
1089  bool parseSwizzleBroadcast(int64_t &Imm);
1090  bool parseSwizzleSwap(int64_t &Imm);
1091  bool parseSwizzleReverse(int64_t &Imm);
1092 
1093  void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1094  void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1095  void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1096  void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); }
1097  void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1098 
1099  AMDGPUOperand::Ptr defaultGLC() const;
1100  AMDGPUOperand::Ptr defaultSLC() const;
1101  AMDGPUOperand::Ptr defaultTFE() const;
1102 
1103  AMDGPUOperand::Ptr defaultD16() const;
1104  AMDGPUOperand::Ptr defaultDMask() const;
1105  AMDGPUOperand::Ptr defaultUNorm() const;
1106  AMDGPUOperand::Ptr defaultDA() const;
1107  AMDGPUOperand::Ptr defaultR128() const;
1108  AMDGPUOperand::Ptr defaultLWE() const;
1109  AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1110  AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1111  AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1112  AMDGPUOperand::Ptr defaultOffsetU12() const;
1113  AMDGPUOperand::Ptr defaultOffsetS13() const;
1114 
1115  OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1116 
1117  void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1118  OptionalImmIndexMap &OptionalIdx);
1119  void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1120  void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1121  void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1122 
1123  void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1124 
1125  void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1126  bool IsAtomic = false);
1127  void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1128 
1129  OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1130  AMDGPUOperand::Ptr defaultRowMask() const;
1131  AMDGPUOperand::Ptr defaultBankMask() const;
1132  AMDGPUOperand::Ptr defaultBoundCtrl() const;
1133  void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1134 
1135  OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1136  AMDGPUOperand::ImmTy Type);
1137  OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1138  void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1139  void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1140  void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1141  void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1142  void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1143  uint64_t BasicInstType, bool skipVcc = false);
1144 };
1145 
1146 struct OptionalOperand {
1147  const char *Name;
1148  AMDGPUOperand::ImmTy Type;
1149  bool IsBit;
1150  bool (*ConvertResult)(int64_t&);
1151 };
1152 
1153 } // end anonymous namespace
1154 
1155 // May be called with integer type with equivalent bitwidth.
1156 static const fltSemantics *getFltSemantics(unsigned Size) {
1157  switch (Size) {
1158  case 4:
1159  return &APFloat::IEEEsingle();
1160  case 8:
1161  return &APFloat::IEEEdouble();
1162  case 2:
1163  return &APFloat::IEEEhalf();
1164  default:
1165  llvm_unreachable("unsupported fp type");
1166  }
1167 }
1168 
1169 static const fltSemantics *getFltSemantics(MVT VT) {
1170  return getFltSemantics(VT.getSizeInBits() / 8);
1171 }
1172 
1173 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1174  switch (OperandType) {
1175  case AMDGPU::OPERAND_REG_IMM_INT32:
1176  case AMDGPU::OPERAND_REG_IMM_FP32:
1177  case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1178  case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1179  return &APFloat::IEEEsingle();
1180  case AMDGPU::OPERAND_REG_IMM_INT64:
1181  case AMDGPU::OPERAND_REG_IMM_FP64:
1182  case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1183  case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1184  return &APFloat::IEEEdouble();
1185  case AMDGPU::OPERAND_REG_IMM_INT16:
1186  case AMDGPU::OPERAND_REG_IMM_FP16:
1187  case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1188  case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1189  case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1190  case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1191  return &APFloat::IEEEhalf();
1192  default:
1193  llvm_unreachable("unsupported fp type");
1194  }
1195 }
1196 
1197 //===----------------------------------------------------------------------===//
1198 // Operand
1199 //===----------------------------------------------------------------------===//
1200 
1201 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1202  bool Lost;
1203 
1204  // Convert literal to single precision
1205  APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1206  APFloat::rmNearestTiesToEven,
1207  &Lost);
1208  // We allow precision lost but not overflow or underflow
1209  if (Status != APFloat::opOK &&
1210  Lost &&
1211  ((Status & APFloat::opOverflow) != 0 ||
1212  (Status & APFloat::opUnderflow) != 0)) {
1213  return false;
1214  }
1215 
1216  return true;
1217 }
1218 
1219 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1220  if (!isImmTy(ImmTyNone)) {
1221  // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1222  return false;
1223  }
1224  // TODO: We should avoid using host float here. It would be better to
1225  // check the float bit values which is what a few other places do.
1226  // We've had bot failures before due to weird NaN support on mips hosts.
1227 
1228  APInt Literal(64, Imm.Val);
1229 
1230  if (Imm.IsFPImm) { // We got fp literal token
1231  if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1232  return AMDGPU::isInlinableLiteral64(Imm.Val,
1233  AsmParser->hasInv2PiInlineImm());
1234  }
1235 
1236  APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1237  if (!canLosslesslyConvertToFPType(FPLiteral, type))
1238  return false;
1239 
1240  if (type.getScalarSizeInBits() == 16) {
1242  static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1243  AsmParser->hasInv2PiInlineImm());
1244  }
1245 
1246  // Check if single precision literal is inlinable
1248  static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1249  AsmParser->hasInv2PiInlineImm());
1250  }
1251 
1252  // We got int literal token.
1253  if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1254  return AMDGPU::isInlinableLiteral64(Imm.Val,
1255  AsmParser->hasInv2PiInlineImm());
1256  }
1257 
1258  if (type.getScalarSizeInBits() == 16) {
1260  static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1261  AsmParser->hasInv2PiInlineImm());
1262  }
1263 
1265  static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1266  AsmParser->hasInv2PiInlineImm());
1267 }
1268 
1269 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1270  // Check that this immediate can be added as literal
1271  if (!isImmTy(ImmTyNone)) {
1272  return false;
1273  }
1274 
1275  if (!Imm.IsFPImm) {
1276  // We got int literal token.
1277 
1278  if (type == MVT::f64 && hasFPModifiers()) {
1279  // Cannot apply fp modifiers to int literals preserving the same semantics
1280  // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1281  // disable these cases.
1282  return false;
1283  }
1284 
1285  unsigned Size = type.getSizeInBits();
1286  if (Size == 64)
1287  Size = 32;
1288 
1289  // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1290  // types.
1291  return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1292  }
1293 
1294  // We got fp literal token
1295  if (type == MVT::f64) { // Expected 64-bit fp operand
1296  // We would set low 64-bits of literal to zeroes but we accept this literals
1297  return true;
1298  }
1299 
1300  if (type == MVT::i64) { // Expected 64-bit int operand
1301  // We don't allow fp literals in 64-bit integer instructions. It is
1302  // unclear how we should encode them.
1303  return false;
1304  }
1305 
1306  APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1307  return canLosslesslyConvertToFPType(FPLiteral, type);
1308 }
1309 
1310 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1311  return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1312 }
1313 
1314 bool AMDGPUOperand::isSDWAOperand(MVT type) const {
1315  if (AsmParser->isVI())
1316  return isVReg();
1317  else if (AsmParser->isGFX9())
1318  return isRegKind() || isInlinableImm(type);
1319  else
1320  return false;
1321 }
1322 
1323 bool AMDGPUOperand::isSDWAFP16Operand() const {
1324  return isSDWAOperand(MVT::f16);
1325 }
1326 
1327 bool AMDGPUOperand::isSDWAFP32Operand() const {
1328  return isSDWAOperand(MVT::f32);
1329 }
1330 
1331 bool AMDGPUOperand::isSDWAInt16Operand() const {
1332  return isSDWAOperand(MVT::i16);
1333 }
1334 
1335 bool AMDGPUOperand::isSDWAInt32Operand() const {
1336  return isSDWAOperand(MVT::i32);
1337 }
1338 
1339 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1340 {
1341  assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1342  assert(Size == 2 || Size == 4 || Size == 8);
1343 
1344  const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1345 
1346  if (Imm.Mods.Abs) {
1347  Val &= ~FpSignMask;
1348  }
1349  if (Imm.Mods.Neg) {
1350  Val ^= FpSignMask;
1351  }
1352 
1353  return Val;
1354 }
1355 
1356 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1357  if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1358  Inst.getNumOperands())) {
1359  addLiteralImmOperand(Inst, Imm.Val,
1360  ApplyModifiers &
1361  isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1362  } else {
1363  assert(!isImmTy(ImmTyNone) || !hasModifiers());
1364  Inst.addOperand(MCOperand::createImm(Imm.Val));
1365  }
1366 }
1367 
1368 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1369  const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1370  auto OpNum = Inst.getNumOperands();
1371  // Check that this operand accepts literals
1372  assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1373 
1374  if (ApplyModifiers) {
1375  assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1376  const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1377  Val = applyInputFPModifiers(Val, Size);
1378  }
1379 
1380  APInt Literal(64, Val);
1381  uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1382 
1383  if (Imm.IsFPImm) { // We got fp literal token
1384  switch (OpTy) {
1389  if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1390  AsmParser->hasInv2PiInlineImm())) {
1391  Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1392  return;
1393  }
1394 
1395  // Non-inlineable
1396  if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1397  // For fp operands we check if low 32 bits are zeros
1398  if (Literal.getLoBits(32) != 0) {
1399  const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1400  "Can't encode literal as exact 64-bit floating-point operand. "
1401  "Low 32-bits will be set to zero");
1402  }
1403 
1404  Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1405  return;
1406  }
1407 
1408  // We don't allow fp literals in 64-bit integer instructions. It is
1409  // unclear how we should encode them. This case should be checked earlier
1410  // in predicate methods (isLiteralImm())
1411  llvm_unreachable("fp literal in 64-bit integer instruction.");
1412 
1423  bool lost;
1424  APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1425  // Convert literal to single precision
1426  FPLiteral.convert(*getOpFltSemantics(OpTy),
1428  // We allow precision lost but not overflow or underflow. This should be
1429  // checked earlier in isLiteralImm()
1430 
1431  uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1434  ImmVal |= (ImmVal << 16);
1435  }
1436 
1437  Inst.addOperand(MCOperand::createImm(ImmVal));
1438  return;
1439  }
1440  default:
1441  llvm_unreachable("invalid operand size");
1442  }
1443 
1444  return;
1445  }
1446 
1447  // We got int literal token.
1448  // Only sign extend inline immediates.
1449  // FIXME: No errors on truncation
1450  switch (OpTy) {
1455  if (isInt<32>(Val) &&
1456  AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1457  AsmParser->hasInv2PiInlineImm())) {
1458  Inst.addOperand(MCOperand::createImm(Val));
1459  return;
1460  }
1461 
1462  Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1463  return;
1464 
1469  if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1470  Inst.addOperand(MCOperand::createImm(Val));
1471  return;
1472  }
1473 
1475  return;
1476 
1481  if (isInt<16>(Val) &&
1482  AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1483  AsmParser->hasInv2PiInlineImm())) {
1484  Inst.addOperand(MCOperand::createImm(Val));
1485  return;
1486  }
1487 
1488  Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1489  return;
1490 
1493  auto LiteralVal = static_cast<uint16_t>(Literal.getLoBits(16).getZExtValue());
1495  AsmParser->hasInv2PiInlineImm()));
1496 
1497  uint32_t ImmVal = static_cast<uint32_t>(LiteralVal) << 16 |
1498  static_cast<uint32_t>(LiteralVal);
1499  Inst.addOperand(MCOperand::createImm(ImmVal));
1500  return;
1501  }
1502  default:
1503  llvm_unreachable("invalid operand size");
1504  }
1505 }
1506 
1507 template <unsigned Bitwidth>
1508 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1509  APInt Literal(64, Imm.Val);
1510 
1511  if (!Imm.IsFPImm) {
1512  // We got int literal token.
1513  Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1514  return;
1515  }
1516 
1517  bool Lost;
1518  APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1519  FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1521  Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1522 }
1523 
1524 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1525  Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1526 }
1527 
1528 //===----------------------------------------------------------------------===//
1529 // AsmParser
1530 //===----------------------------------------------------------------------===//
1531 
1532 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1533  if (Is == IS_VGPR) {
1534  switch (RegWidth) {
1535  default: return -1;
1536  case 1: return AMDGPU::VGPR_32RegClassID;
1537  case 2: return AMDGPU::VReg_64RegClassID;
1538  case 3: return AMDGPU::VReg_96RegClassID;
1539  case 4: return AMDGPU::VReg_128RegClassID;
1540  case 8: return AMDGPU::VReg_256RegClassID;
1541  case 16: return AMDGPU::VReg_512RegClassID;
1542  }
1543  } else if (Is == IS_TTMP) {
1544  switch (RegWidth) {
1545  default: return -1;
1546  case 1: return AMDGPU::TTMP_32RegClassID;
1547  case 2: return AMDGPU::TTMP_64RegClassID;
1548  case 4: return AMDGPU::TTMP_128RegClassID;
1549  case 8: return AMDGPU::TTMP_256RegClassID;
1550  case 16: return AMDGPU::TTMP_512RegClassID;
1551  }
1552  } else if (Is == IS_SGPR) {
1553  switch (RegWidth) {
1554  default: return -1;
1555  case 1: return AMDGPU::SGPR_32RegClassID;
1556  case 2: return AMDGPU::SGPR_64RegClassID;
1557  case 4: return AMDGPU::SGPR_128RegClassID;
1558  case 8: return AMDGPU::SGPR_256RegClassID;
1559  case 16: return AMDGPU::SGPR_512RegClassID;
1560  }
1561  }
1562  return -1;
1563 }
1564 
1565 static unsigned getSpecialRegForName(StringRef RegName) {
1566  return StringSwitch<unsigned>(RegName)
1567  .Case("exec", AMDGPU::EXEC)
1568  .Case("vcc", AMDGPU::VCC)
1569  .Case("flat_scratch", AMDGPU::FLAT_SCR)
1570  .Case("xnack_mask", AMDGPU::XNACK_MASK)
1571  .Case("m0", AMDGPU::M0)
1572  .Case("scc", AMDGPU::SCC)
1573  .Case("tba", AMDGPU::TBA)
1574  .Case("tma", AMDGPU::TMA)
1575  .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1576  .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1577  .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
1578  .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
1579  .Case("vcc_lo", AMDGPU::VCC_LO)
1580  .Case("vcc_hi", AMDGPU::VCC_HI)
1581  .Case("exec_lo", AMDGPU::EXEC_LO)
1582  .Case("exec_hi", AMDGPU::EXEC_HI)
1583  .Case("tma_lo", AMDGPU::TMA_LO)
1584  .Case("tma_hi", AMDGPU::TMA_HI)
1585  .Case("tba_lo", AMDGPU::TBA_LO)
1586  .Case("tba_hi", AMDGPU::TBA_HI)
1587  .Default(0);
1588 }
1589 
1590 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1591  SMLoc &EndLoc) {
1592  auto R = parseRegister();
1593  if (!R) return true;
1594  assert(R->isReg());
1595  RegNo = R->getReg();
1596  StartLoc = R->getStartLoc();
1597  EndLoc = R->getEndLoc();
1598  return false;
1599 }
1600 
1601 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1602  RegisterKind RegKind, unsigned Reg1,
1603  unsigned RegNum) {
1604  switch (RegKind) {
1605  case IS_SPECIAL:
1606  if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1607  Reg = AMDGPU::EXEC;
1608  RegWidth = 2;
1609  return true;
1610  }
1611  if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1612  Reg = AMDGPU::FLAT_SCR;
1613  RegWidth = 2;
1614  return true;
1615  }
1616  if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
1617  Reg = AMDGPU::XNACK_MASK;
1618  RegWidth = 2;
1619  return true;
1620  }
1621  if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1622  Reg = AMDGPU::VCC;
1623  RegWidth = 2;
1624  return true;
1625  }
1626  if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1627  Reg = AMDGPU::TBA;
1628  RegWidth = 2;
1629  return true;
1630  }
1631  if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1632  Reg = AMDGPU::TMA;
1633  RegWidth = 2;
1634  return true;
1635  }
1636  return false;
1637  case IS_VGPR:
1638  case IS_SGPR:
1639  case IS_TTMP:
1640  if (Reg1 != Reg + RegWidth) {
1641  return false;
1642  }
1643  RegWidth++;
1644  return true;
1645  default:
1646  llvm_unreachable("unexpected register kind");
1647  }
1648 }
1649 
1650 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1651  unsigned &RegNum, unsigned &RegWidth,
1652  unsigned *DwordRegIndex) {
1653  if (DwordRegIndex) { *DwordRegIndex = 0; }
1654  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1655  if (getLexer().is(AsmToken::Identifier)) {
1656  StringRef RegName = Parser.getTok().getString();
1657  if ((Reg = getSpecialRegForName(RegName))) {
1658  Parser.Lex();
1659  RegKind = IS_SPECIAL;
1660  } else {
1661  unsigned RegNumIndex = 0;
1662  if (RegName[0] == 'v') {
1663  RegNumIndex = 1;
1664  RegKind = IS_VGPR;
1665  } else if (RegName[0] == 's') {
1666  RegNumIndex = 1;
1667  RegKind = IS_SGPR;
1668  } else if (RegName.startswith("ttmp")) {
1669  RegNumIndex = strlen("ttmp");
1670  RegKind = IS_TTMP;
1671  } else {
1672  return false;
1673  }
1674  if (RegName.size() > RegNumIndex) {
1675  // Single 32-bit register: vXX.
1676  if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1677  return false;
1678  Parser.Lex();
1679  RegWidth = 1;
1680  } else {
1681  // Range of registers: v[XX:YY]. ":YY" is optional.
1682  Parser.Lex();
1683  int64_t RegLo, RegHi;
1684  if (getLexer().isNot(AsmToken::LBrac))
1685  return false;
1686  Parser.Lex();
1687 
1688  if (getParser().parseAbsoluteExpression(RegLo))
1689  return false;
1690 
1691  const bool isRBrace = getLexer().is(AsmToken::RBrac);
1692  if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1693  return false;
1694  Parser.Lex();
1695 
1696  if (isRBrace) {
1697  RegHi = RegLo;
1698  } else {
1699  if (getParser().parseAbsoluteExpression(RegHi))
1700  return false;
1701 
1702  if (getLexer().isNot(AsmToken::RBrac))
1703  return false;
1704  Parser.Lex();
1705  }
1706  RegNum = (unsigned) RegLo;
1707  RegWidth = (RegHi - RegLo) + 1;
1708  }
1709  }
1710  } else if (getLexer().is(AsmToken::LBrac)) {
1711  // List of consecutive registers: [s0,s1,s2,s3]
1712  Parser.Lex();
1713  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1714  return false;
1715  if (RegWidth != 1)
1716  return false;
1717  RegisterKind RegKind1;
1718  unsigned Reg1, RegNum1, RegWidth1;
1719  do {
1720  if (getLexer().is(AsmToken::Comma)) {
1721  Parser.Lex();
1722  } else if (getLexer().is(AsmToken::RBrac)) {
1723  Parser.Lex();
1724  break;
1725  } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1726  if (RegWidth1 != 1) {
1727  return false;
1728  }
1729  if (RegKind1 != RegKind) {
1730  return false;
1731  }
1732  if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1733  return false;
1734  }
1735  } else {
1736  return false;
1737  }
1738  } while (true);
1739  } else {
1740  return false;
1741  }
1742  switch (RegKind) {
1743  case IS_SPECIAL:
1744  RegNum = 0;
1745  RegWidth = 1;
1746  break;
1747  case IS_VGPR:
1748  case IS_SGPR:
1749  case IS_TTMP:
1750  {
1751  unsigned Size = 1;
1752  if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1753  // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1754  Size = std::min(RegWidth, 4u);
1755  }
1756  if (RegNum % Size != 0)
1757  return false;
1758  if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1759  RegNum = RegNum / Size;
1760  int RCID = getRegClass(RegKind, RegWidth);
1761  if (RCID == -1)
1762  return false;
1763  const MCRegisterClass RC = TRI->getRegClass(RCID);
1764  if (RegNum >= RC.getNumRegs())
1765  return false;
1766  Reg = RC.getRegister(RegNum);
1767  break;
1768  }
1769 
1770  default:
1771  llvm_unreachable("unexpected register kind");
1772  }
1773 
1774  if (!subtargetHasRegister(*TRI, Reg))
1775  return false;
1776  return true;
1777 }
1778 
1779 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1780  const auto &Tok = Parser.getTok();
1781  SMLoc StartLoc = Tok.getLoc();
1782  SMLoc EndLoc = Tok.getEndLoc();
1784  unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1785 
1786  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1787  return nullptr;
1788  }
1789  KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1790  return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1791 }
1792 
1793 bool
1794 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) {
1795  if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) &&
1796  (getLexer().getKind() == AsmToken::Integer ||
1797  getLexer().getKind() == AsmToken::Real)) {
1798  // This is a workaround for handling operands like these:
1799  // |1.0|
1800  // |-1|
1801  // This syntax is not compatible with syntax of standard
1802  // MC expressions (due to the trailing '|').
1803 
1804  SMLoc EndLoc;
1805  const MCExpr *Expr;
1806 
1807  if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1808  return true;
1809  }
1810 
1811  return !Expr->evaluateAsAbsolute(Val);
1812  }
1813 
1814  return getParser().parseAbsoluteExpression(Val);
1815 }
1816 
1818 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
1819  // TODO: add syntactic sugar for 1/(2*PI)
1820  bool Minus = false;
1821  if (getLexer().getKind() == AsmToken::Minus) {
1822  const AsmToken NextToken = getLexer().peekTok();
1823  if (!NextToken.is(AsmToken::Integer) &&
1824  !NextToken.is(AsmToken::Real)) {
1825  return MatchOperand_NoMatch;
1826  }
1827  Minus = true;
1828  Parser.Lex();
1829  }
1830 
1831  SMLoc S = Parser.getTok().getLoc();
1832  switch(getLexer().getKind()) {
1833  case AsmToken::Integer: {
1834  int64_t IntVal;
1835  if (parseAbsoluteExpr(IntVal, AbsMod))
1836  return MatchOperand_ParseFail;
1837  if (Minus)
1838  IntVal *= -1;
1839  Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1840  return MatchOperand_Success;
1841  }
1842  case AsmToken::Real: {
1843  int64_t IntVal;
1844  if (parseAbsoluteExpr(IntVal, AbsMod))
1845  return MatchOperand_ParseFail;
1846 
1847  APFloat F(BitsToDouble(IntVal));
1848  if (Minus)
1849  F.changeSign();
1850  Operands.push_back(
1851  AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1852  AMDGPUOperand::ImmTyNone, true));
1853  return MatchOperand_Success;
1854  }
1855  default:
1856  return MatchOperand_NoMatch;
1857  }
1858 }
1859 
1861 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1862  if (auto R = parseRegister()) {
1863  assert(R->isReg());
1864  R->Reg.IsForcedVOP3 = isForcedVOP3();
1865  Operands.push_back(std::move(R));
1866  return MatchOperand_Success;
1867  }
1868  return MatchOperand_NoMatch;
1869 }
1870 
1872 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
1873  auto res = parseImm(Operands, AbsMod);
1874  if (res != MatchOperand_NoMatch) {
1875  return res;
1876  }
1877 
1878  return parseReg(Operands);
1879 }
1880 
1882 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
1883  bool AllowImm) {
1884  bool Negate = false, Negate2 = false, Abs = false, Abs2 = false;
1885 
1886  if (getLexer().getKind()== AsmToken::Minus) {
1887  const AsmToken NextToken = getLexer().peekTok();
1888 
1889  // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
1890  if (NextToken.is(AsmToken::Minus)) {
1891  Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier");
1892  return MatchOperand_ParseFail;
1893  }
1894 
1895  // '-' followed by an integer literal N should be interpreted as integer
1896  // negation rather than a floating-point NEG modifier applied to N.
1897  // Beside being contr-intuitive, such use of floating-point NEG modifier
1898  // results in different meaning of integer literals used with VOP1/2/C
1899  // and VOP3, for example:
1900  // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
1901  // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
1902  // Negative fp literals should be handled likewise for unifomtity
1903  if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) {
1904  Parser.Lex();
1905  Negate = true;
1906  }
1907  }
1908 
1909  if (getLexer().getKind() == AsmToken::Identifier &&
1910  Parser.getTok().getString() == "neg") {
1911  if (Negate) {
1912  Error(Parser.getTok().getLoc(), "expected register or immediate");
1913  return MatchOperand_ParseFail;
1914  }
1915  Parser.Lex();
1916  Negate2 = true;
1917  if (getLexer().isNot(AsmToken::LParen)) {
1918  Error(Parser.getTok().getLoc(), "expected left paren after neg");
1919  return MatchOperand_ParseFail;
1920  }
1921  Parser.Lex();
1922  }
1923 
1924  if (getLexer().getKind() == AsmToken::Identifier &&
1925  Parser.getTok().getString() == "abs") {
1926  Parser.Lex();
1927  Abs2 = true;
1928  if (getLexer().isNot(AsmToken::LParen)) {
1929  Error(Parser.getTok().getLoc(), "expected left paren after abs");
1930  return MatchOperand_ParseFail;
1931  }
1932  Parser.Lex();
1933  }
1934 
1935  if (getLexer().getKind() == AsmToken::Pipe) {
1936  if (Abs2) {
1937  Error(Parser.getTok().getLoc(), "expected register or immediate");
1938  return MatchOperand_ParseFail;
1939  }
1940  Parser.Lex();
1941  Abs = true;
1942  }
1943 
1945  if (AllowImm) {
1946  Res = parseRegOrImm(Operands, Abs);
1947  } else {
1948  Res = parseReg(Operands);
1949  }
1950  if (Res != MatchOperand_Success) {
1951  return Res;
1952  }
1953 
1954  AMDGPUOperand::Modifiers Mods;
1955  if (Abs) {
1956  if (getLexer().getKind() != AsmToken::Pipe) {
1957  Error(Parser.getTok().getLoc(), "expected vertical bar");
1958  return MatchOperand_ParseFail;
1959  }
1960  Parser.Lex();
1961  Mods.Abs = true;
1962  }
1963  if (Abs2) {
1964  if (getLexer().isNot(AsmToken::RParen)) {
1965  Error(Parser.getTok().getLoc(), "expected closing parentheses");
1966  return MatchOperand_ParseFail;
1967  }
1968  Parser.Lex();
1969  Mods.Abs = true;
1970  }
1971 
1972  if (Negate) {
1973  Mods.Neg = true;
1974  } else if (Negate2) {
1975  if (getLexer().isNot(AsmToken::RParen)) {
1976  Error(Parser.getTok().getLoc(), "expected closing parentheses");
1977  return MatchOperand_ParseFail;
1978  }
1979  Parser.Lex();
1980  Mods.Neg = true;
1981  }
1982 
1983  if (Mods.hasFPModifiers()) {
1984  AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1985  Op.setModifiers(Mods);
1986  }
1987  return MatchOperand_Success;
1988 }
1989 
1991 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
1992  bool AllowImm) {
1993  bool Sext = false;
1994 
1995  if (getLexer().getKind() == AsmToken::Identifier &&
1996  Parser.getTok().getString() == "sext") {
1997  Parser.Lex();
1998  Sext = true;
1999  if (getLexer().isNot(AsmToken::LParen)) {
2000  Error(Parser.getTok().getLoc(), "expected left paren after sext");
2001  return MatchOperand_ParseFail;
2002  }
2003  Parser.Lex();
2004  }
2005 
2007  if (AllowImm) {
2008  Res = parseRegOrImm(Operands);
2009  } else {
2010  Res = parseReg(Operands);
2011  }
2012  if (Res != MatchOperand_Success) {
2013  return Res;
2014  }
2015 
2016  AMDGPUOperand::Modifiers Mods;
2017  if (Sext) {
2018  if (getLexer().isNot(AsmToken::RParen)) {
2019  Error(Parser.getTok().getLoc(), "expected closing parentheses");
2020  return MatchOperand_ParseFail;
2021  }
2022  Parser.Lex();
2023  Mods.Sext = true;
2024  }
2025 
2026  if (Mods.hasIntModifiers()) {
2027  AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
2028  Op.setModifiers(Mods);
2029  }
2030 
2031  return MatchOperand_Success;
2032 }
2033 
2035 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
2036  return parseRegOrImmWithFPInputMods(Operands, false);
2037 }
2038 
2040 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
2041  return parseRegOrImmWithIntInputMods(Operands, false);
2042 }
2043 
2044 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
2045  std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
2046  if (Reg) {
2047  Operands.push_back(std::move(Reg));
2048  return MatchOperand_Success;
2049  }
2050 
2051  const AsmToken &Tok = Parser.getTok();
2052  if (Tok.getString() == "off") {
2053  Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
2054  AMDGPUOperand::ImmTyOff, false));
2055  Parser.Lex();
2056  return MatchOperand_Success;
2057  }
2058 
2059  return MatchOperand_NoMatch;
2060 }
2061 
2062 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2063  uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2064 
2065  if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
2066  (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
2067  (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
2068  (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
2069  return Match_InvalidOperand;
2070 
2071  if ((TSFlags & SIInstrFlags::VOP3) &&
2072  (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
2073  getForcedEncodingSize() != 64)
2074  return Match_PreferE32;
2075 
2076  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2077  Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
2078  // v_mac_f32/16 allow only dst_sel == DWORD;
2079  auto OpNum =
2080  AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
2081  const auto &Op = Inst.getOperand(OpNum);
2082  if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
2083  return Match_InvalidOperand;
2084  }
2085  }
2086 
2087  if ((TSFlags & SIInstrFlags::FLAT) && !hasFlatOffsets()) {
2088  // FIXME: Produces error without correct column reported.
2089  auto OpNum =
2090  AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::offset);
2091  const auto &Op = Inst.getOperand(OpNum);
2092  if (Op.getImm() != 0)
2093  return Match_InvalidOperand;
2094  }
2095 
2096  return Match_Success;
2097 }
2098 
2099 // What asm variants we should check
2100 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2101  if (getForcedEncodingSize() == 32) {
2102  static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2103  return makeArrayRef(Variants);
2104  }
2105 
2106  if (isForcedVOP3()) {
2107  static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2108  return makeArrayRef(Variants);
2109  }
2110 
2111  if (isForcedSDWA()) {
2112  static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2114  return makeArrayRef(Variants);
2115  }
2116 
2117  if (isForcedDPP()) {
2118  static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2119  return makeArrayRef(Variants);
2120  }
2121 
2122  static const unsigned Variants[] = {
2125  };
2126 
2127  return makeArrayRef(Variants);
2128 }
2129 
2130 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2131  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2132  const unsigned Num = Desc.getNumImplicitUses();
2133  for (unsigned i = 0; i < Num; ++i) {
2134  unsigned Reg = Desc.ImplicitUses[i];
2135  switch (Reg) {
2136  case AMDGPU::FLAT_SCR:
2137  case AMDGPU::VCC:
2138  case AMDGPU::M0:
2139  return Reg;
2140  default:
2141  break;
2142  }
2143  }
2144  return AMDGPU::NoRegister;
2145 }
2146 
2147 // NB: This code is correct only when used to check constant
2148 // bus limitations because GFX7 support no f16 inline constants.
2149 // Note that there are no cases when a GFX7 opcode violates
2150 // constant bus limitations due to the use of an f16 constant.
2151 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2152  unsigned OpIdx) const {
2153  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2154 
2155  if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2156  return false;
2157  }
2158 
2159  const MCOperand &MO = Inst.getOperand(OpIdx);
2160 
2161  int64_t Val = MO.getImm();
2162  auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2163 
2164  switch (OpSize) { // expected operand size
2165  case 8:
2166  return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2167  case 4:
2168  return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2169  case 2: {
2170  const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2171  if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2172  OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
2173  return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2174  } else {
2175  return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2176  }
2177  }
2178  default:
2179  llvm_unreachable("invalid operand size");
2180  }
2181 }
2182 
2183 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2184  const MCOperand &MO = Inst.getOperand(OpIdx);
2185  if (MO.isImm()) {
2186  return !isInlineConstant(Inst, OpIdx);
2187  }
2188  return !MO.isReg() ||
2189  isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
2190 }
2191 
2192 bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
2193  const unsigned Opcode = Inst.getOpcode();
2194  const MCInstrDesc &Desc = MII.get(Opcode);
2195  unsigned ConstantBusUseCount = 0;
2196 
2197  if (Desc.TSFlags &
2201  SIInstrFlags::SDWA)) {
2202  // Check special imm operands (used by madmk, etc)
2203  if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2204  ++ConstantBusUseCount;
2205  }
2206 
2207  unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2208  if (SGPRUsed != AMDGPU::NoRegister) {
2209  ++ConstantBusUseCount;
2210  }
2211 
2212  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2213  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2214  const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2215 
2216  const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2217 
2218  for (int OpIdx : OpIndices) {
2219  if (OpIdx == -1) break;
2220 
2221  const MCOperand &MO = Inst.getOperand(OpIdx);
2222  if (usesConstantBus(Inst, OpIdx)) {
2223  if (MO.isReg()) {
2224  const unsigned Reg = mc2PseudoReg(MO.getReg());
2225  // Pairs of registers with a partial intersections like these
2226  // s0, s[0:1]
2227  // flat_scratch_lo, flat_scratch
2228  // flat_scratch_lo, flat_scratch_hi
2229  // are theoretically valid but they are disabled anyway.
2230  // Note that this code mimics SIInstrInfo::verifyInstruction
2231  if (Reg != SGPRUsed) {
2232  ++ConstantBusUseCount;
2233  }
2234  SGPRUsed = Reg;
2235  } else { // Expression or a literal
2236  ++ConstantBusUseCount;
2237  }
2238  }
2239  }
2240  }
2241 
2242  return ConstantBusUseCount <= 1;
2243 }
2244 
2245 bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
2246  const unsigned Opcode = Inst.getOpcode();
2247  const MCInstrDesc &Desc = MII.get(Opcode);
2248 
2249  const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2250  if (DstIdx == -1 ||
2251  Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2252  return true;
2253  }
2254 
2255  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2256 
2257  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2258  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2259  const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2260 
2261  assert(DstIdx != -1);
2262  const MCOperand &Dst = Inst.getOperand(DstIdx);
2263  assert(Dst.isReg());
2264  const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2265 
2266  const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2267 
2268  for (int SrcIdx : SrcIndices) {
2269  if (SrcIdx == -1) break;
2270  const MCOperand &Src = Inst.getOperand(SrcIdx);
2271  if (Src.isReg()) {
2272  const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2273  if (isRegIntersect(DstReg, SrcReg, TRI)) {
2274  return false;
2275  }
2276  }
2277  }
2278 
2279  return true;
2280 }
2281 
2282 bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
2283 
2284  const unsigned Opc = Inst.getOpcode();
2285  const MCInstrDesc &Desc = MII.get(Opc);
2286 
2287  if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) {
2288  int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
2289  assert(ClampIdx != -1);
2290  return Inst.getOperand(ClampIdx).getImm() == 0;
2291  }
2292 
2293  return true;
2294 }
2295 
2296 bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) {
2297 
2298  const unsigned Opc = Inst.getOpcode();
2299  const MCInstrDesc &Desc = MII.get(Opc);
2300 
2301  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2302  return true;
2303 
2304  // Gather4 instructions do not need validation: dst size is hardcoded.
2305  if (Desc.TSFlags & SIInstrFlags::Gather4)
2306  return true;
2307 
2308  int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
2309  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2310  int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe);
2311 
2312  assert(VDataIdx != -1);
2313  assert(DMaskIdx != -1);
2314  assert(TFEIdx != -1);
2315 
2316  unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx);
2317  unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0;
2318  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2319  if (DMask == 0)
2320  DMask = 1;
2321 
2322  unsigned DataSize = countPopulation(DMask);
2323  if ((Desc.TSFlags & SIInstrFlags::D16) != 0 && hasPackedD16()) {
2324  DataSize = (DataSize + 1) / 2;
2325  }
2326 
2327  return (VDataSize / 4) == DataSize + TFESize;
2328 }
2329 
2330 bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) {
2331 
2332  const unsigned Opc = Inst.getOpcode();
2333  const MCInstrDesc &Desc = MII.get(Opc);
2334 
2335  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2336  return true;
2337  if (!Desc.mayLoad() || !Desc.mayStore())
2338  return true; // Not atomic
2339 
2340  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2341  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2342 
2343  // This is an incomplete check because image_atomic_cmpswap
2344  // may only use 0x3 and 0xf while other atomic operations
2345  // may use 0x1 and 0x3. However these limitations are
2346  // verified when we check that dmask matches dst size.
2347  return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
2348 }
2349 
2350 bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) {
2351 
2352  const unsigned Opc = Inst.getOpcode();
2353  const MCInstrDesc &Desc = MII.get(Opc);
2354 
2355  if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0)
2356  return true;
2357 
2358  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2359  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2360 
2361  // GATHER4 instructions use dmask in a different fashion compared to
2362  // other MIMG instructions. The only useful DMASK values are
2363  // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
2364  // (red,red,red,red) etc.) The ISA document doesn't mention
2365  // this.
2366  return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
2367 }
2368 
2369 bool AMDGPUAsmParser::validateMIMGR128(const MCInst &Inst) {
2370 
2371  const unsigned Opc = Inst.getOpcode();
2372  const MCInstrDesc &Desc = MII.get(Opc);
2373 
2374  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2375  return true;
2376 
2377  int Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::r128);
2378  assert(Idx != -1);
2379 
2380  bool R128 = (Inst.getOperand(Idx).getImm() != 0);
2381 
2382  return !R128 || hasMIMG_R128();
2383 }
2384 
2385 bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) {
2386 
2387  const unsigned Opc = Inst.getOpcode();
2388  const MCInstrDesc &Desc = MII.get(Opc);
2389 
2390  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2391  return true;
2392  if ((Desc.TSFlags & SIInstrFlags::D16) == 0)
2393  return true;
2394 
2395  return !isCI() && !isSI();
2396 }
2397 
2398 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
2399  const SMLoc &IDLoc) {
2400  if (!validateConstantBusLimitations(Inst)) {
2401  Error(IDLoc,
2402  "invalid operand (violates constant bus restrictions)");
2403  return false;
2404  }
2405  if (!validateEarlyClobberLimitations(Inst)) {
2406  Error(IDLoc,
2407  "destination must be different than all sources");
2408  return false;
2409  }
2410  if (!validateIntClampSupported(Inst)) {
2411  Error(IDLoc,
2412  "integer clamping is not supported on this GPU");
2413  return false;
2414  }
2415  if (!validateMIMGR128(Inst)) {
2416  Error(IDLoc,
2417  "r128 modifier is not supported on this GPU");
2418  return false;
2419  }
2420  // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
2421  if (!validateMIMGD16(Inst)) {
2422  Error(IDLoc,
2423  "d16 modifier is not supported on this GPU");
2424  return false;
2425  }
2426  if (!validateMIMGDataSize(Inst)) {
2427  Error(IDLoc,
2428  "image data size does not match dmask and tfe");
2429  return false;
2430  }
2431  if (!validateMIMGAtomicDMask(Inst)) {
2432  Error(IDLoc,
2433  "invalid atomic image dmask");
2434  return false;
2435  }
2436  if (!validateMIMGGatherDMask(Inst)) {
2437  Error(IDLoc,
2438  "invalid image_gather dmask: only one bit must be set");
2439  return false;
2440  }
2441 
2442  return true;
2443 }
2444 
2445 static std::string AMDGPUMnemonicSpellCheck(StringRef S, uint64_t FBS,
2446  unsigned VariantID = 0);
2447 
2448 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2449  OperandVector &Operands,
2450  MCStreamer &Out,
2451  uint64_t &ErrorInfo,
2452  bool MatchingInlineAsm) {
2453  MCInst Inst;
2454  unsigned Result = Match_Success;
2455  for (auto Variant : getMatchedVariants()) {
2456  uint64_t EI;
2457  auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2458  Variant);
2459  // We order match statuses from least to most specific. We use most specific
2460  // status as resulting
2461  // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
2462  if ((R == Match_Success) ||
2463  (R == Match_PreferE32) ||
2464  (R == Match_MissingFeature && Result != Match_PreferE32) ||
2465  (R == Match_InvalidOperand && Result != Match_MissingFeature
2466  && Result != Match_PreferE32) ||
2467  (R == Match_MnemonicFail && Result != Match_InvalidOperand
2468  && Result != Match_MissingFeature
2469  && Result != Match_PreferE32)) {
2470  Result = R;
2471  ErrorInfo = EI;
2472  }
2473  if (R == Match_Success)
2474  break;
2475  }
2476 
2477  switch (Result) {
2478  default: break;
2479  case Match_Success:
2480  if (!validateInstruction(Inst, IDLoc)) {
2481  return true;
2482  }
2483  Inst.setLoc(IDLoc);
2484  Out.EmitInstruction(Inst, getSTI());
2485  return false;
2486 
2487  case Match_MissingFeature:
2488  return Error(IDLoc, "instruction not supported on this GPU");
2489 
2490  case Match_MnemonicFail: {
2491  uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
2492  std::string Suggestion = AMDGPUMnemonicSpellCheck(
2493  ((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
2494  return Error(IDLoc, "invalid instruction" + Suggestion,
2495  ((AMDGPUOperand &)*Operands[0]).getLocRange());
2496  }
2497 
2498  case Match_InvalidOperand: {
2499  SMLoc ErrorLoc = IDLoc;
2500  if (ErrorInfo != ~0ULL) {
2501  if (ErrorInfo >= Operands.size()) {
2502  return Error(IDLoc, "too few operands for instruction");
2503  }
2504  ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2505  if (ErrorLoc == SMLoc())
2506  ErrorLoc = IDLoc;
2507  }
2508  return Error(ErrorLoc, "invalid operand for instruction");
2509  }
2510 
2511  case Match_PreferE32:
2512  return Error(IDLoc, "internal error: instruction without _e64 suffix "
2513  "should be encoded as e32");
2514  }
2515  llvm_unreachable("Implement any new match types added!");
2516 }
2517 
2518 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
2519  int64_t Tmp = -1;
2520  if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
2521  return true;
2522  }
2523  if (getParser().parseAbsoluteExpression(Tmp)) {
2524  return true;
2525  }
2526  Ret = static_cast<uint32_t>(Tmp);
2527  return false;
2528 }
2529 
2530 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
2531  uint32_t &Minor) {
2532  if (ParseAsAbsoluteExpression(Major))
2533  return TokError("invalid major version");
2534 
2535  if (getLexer().isNot(AsmToken::Comma))
2536  return TokError("minor version number required, comma expected");
2537  Lex();
2538 
2539  if (ParseAsAbsoluteExpression(Minor))
2540  return TokError("invalid minor version");
2541 
2542  return false;
2543 }
2544 
2545 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2546  uint32_t Major;
2547  uint32_t Minor;
2548 
2549  if (ParseDirectiveMajorMinor(Major, Minor))
2550  return true;
2551 
2552  getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2553  return false;
2554 }
2555 
2556 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2557  uint32_t Major;
2558  uint32_t Minor;
2559  uint32_t Stepping;
2560  StringRef VendorName;
2561  StringRef ArchName;
2562 
2563  // If this directive has no arguments, then use the ISA version for the
2564  // targeted GPU.
2565  if (getLexer().is(AsmToken::EndOfStatement)) {
2567  AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2568  getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2569  ISA.Stepping,
2570  "AMD", "AMDGPU");
2571  return false;
2572  }
2573 
2574  if (ParseDirectiveMajorMinor(Major, Minor))
2575  return true;
2576 
2577  if (getLexer().isNot(AsmToken::Comma))
2578  return TokError("stepping version number required, comma expected");
2579  Lex();
2580 
2581  if (ParseAsAbsoluteExpression(Stepping))
2582  return TokError("invalid stepping version");
2583 
2584  if (getLexer().isNot(AsmToken::Comma))
2585  return TokError("vendor name required, comma expected");
2586  Lex();
2587 
2588  if (getLexer().isNot(AsmToken::String))
2589  return TokError("invalid vendor name");
2590 
2591  VendorName = getLexer().getTok().getStringContents();
2592  Lex();
2593 
2594  if (getLexer().isNot(AsmToken::Comma))
2595  return TokError("arch name required, comma expected");
2596  Lex();
2597 
2598  if (getLexer().isNot(AsmToken::String))
2599  return TokError("invalid arch name");
2600 
2601  ArchName = getLexer().getTok().getStringContents();
2602  Lex();
2603 
2604  getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2605  VendorName, ArchName);
2606  return false;
2607 }
2608 
2609 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
2610  amd_kernel_code_t &Header) {
2611  // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
2612  // assembly for backwards compatibility.
2613  if (ID == "max_scratch_backing_memory_byte_size") {
2614  Parser.eatToEndOfStatement();
2615  return false;
2616  }
2617 
2618  SmallString<40> ErrStr;
2619  raw_svector_ostream Err(ErrStr);
2620  if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
2621  return TokError(Err.str());
2622  }
2623  Lex();
2624  return false;
2625 }
2626 
2627 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
2628  amd_kernel_code_t Header;
2629  AMDGPU::initDefaultAMDKernelCodeT(Header, getFeatureBits());
2630 
2631  while (true) {
2632  // Lex EndOfStatement. This is in a while loop, because lexing a comment
2633  // will set the current token to EndOfStatement.
2634  while(getLexer().is(AsmToken::EndOfStatement))
2635  Lex();
2636 
2637  if (getLexer().isNot(AsmToken::Identifier))
2638  return TokError("expected value identifier or .end_amd_kernel_code_t");
2639 
2640  StringRef ID = getLexer().getTok().getIdentifier();
2641  Lex();
2642 
2643  if (ID == ".end_amd_kernel_code_t")
2644  break;
2645 
2646  if (ParseAMDKernelCodeTValue(ID, Header))
2647  return true;
2648  }
2649 
2650  getTargetStreamer().EmitAMDKernelCodeT(Header);
2651 
2652  return false;
2653 }
2654 
2655 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
2656  if (getLexer().isNot(AsmToken::Identifier))
2657  return TokError("expected symbol name");
2658 
2659  StringRef KernelName = Parser.getTok().getString();
2660 
2661  getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
2663  Lex();
2664  KernelScope.initialize(getContext());
2665  return false;
2666 }
2667 
2668 bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
2669  if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) {
2670  return Error(getParser().getTok().getLoc(),
2671  ".amd_amdgpu_isa directive is not available on non-amdgcn "
2672  "architectures");
2673  }
2674 
2675  auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
2676 
2677  std::string ISAVersionStringFromSTI;
2678  raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI);
2679  IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI);
2680 
2681  if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) {
2682  return Error(getParser().getTok().getLoc(),
2683  ".amd_amdgpu_isa directive does not match triple and/or mcpu "
2684  "arguments specified through the command line");
2685  }
2686 
2687  getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str());
2688  Lex();
2689 
2690  return false;
2691 }
2692 
2693 bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
2694  if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) {
2695  return Error(getParser().getTok().getLoc(),
2696  (Twine(HSAMD::AssemblerDirectiveBegin) + Twine(" directive is "
2697  "not available on non-amdhsa OSes")).str());
2698  }
2699 
2700  std::string HSAMetadataString;
2701  raw_string_ostream YamlStream(HSAMetadataString);
2702 
2703  getLexer().setSkipSpace(false);
2704 
2705  bool FoundEnd = false;
2706  while (!getLexer().is(AsmToken::Eof)) {
2707  while (getLexer().is(AsmToken::Space)) {
2708  YamlStream << getLexer().getTok().getString();
2709  Lex();
2710  }
2711 
2712  if (getLexer().is(AsmToken::Identifier)) {
2713  StringRef ID = getLexer().getTok().getIdentifier();
2715  Lex();
2716  FoundEnd = true;
2717  break;
2718  }
2719  }
2720 
2721  YamlStream << Parser.parseStringToEndOfStatement()
2722  << getContext().getAsmInfo()->getSeparatorString();
2723 
2724  Parser.eatToEndOfStatement();
2725  }
2726 
2727  getLexer().setSkipSpace(true);
2728 
2729  if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
2730  return TokError(Twine("expected directive ") +
2731  Twine(HSAMD::AssemblerDirectiveEnd) + Twine(" not found"));
2732  }
2733 
2734  YamlStream.flush();
2735 
2736  if (!getTargetStreamer().EmitHSAMetadata(HSAMetadataString))
2737  return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
2738 
2739  return false;
2740 }
2741 
2742 bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
2743  if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
2744  return Error(getParser().getTok().getLoc(),
2745  (Twine(PALMD::AssemblerDirective) + Twine(" directive is "
2746  "not available on non-amdpal OSes")).str());
2747  }
2748 
2749  PALMD::Metadata PALMetadata;
2750  for (;;) {
2751  uint32_t Value;
2752  if (ParseAsAbsoluteExpression(Value)) {
2753  return TokError(Twine("invalid value in ") +
2755  }
2756  PALMetadata.push_back(Value);
2757  if (getLexer().isNot(AsmToken::Comma))
2758  break;
2759  Lex();
2760  }
2761  getTargetStreamer().EmitPALMetadata(PALMetadata);
2762  return false;
2763 }
2764 
2765 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2766  StringRef IDVal = DirectiveID.getString();
2767 
2768  if (IDVal == ".hsa_code_object_version")
2769  return ParseDirectiveHSACodeObjectVersion();
2770 
2771  if (IDVal == ".hsa_code_object_isa")
2772  return ParseDirectiveHSACodeObjectISA();
2773 
2774  if (IDVal == ".amd_kernel_code_t")
2775  return ParseDirectiveAMDKernelCodeT();
2776 
2777  if (IDVal == ".amdgpu_hsa_kernel")
2778  return ParseDirectiveAMDGPUHsaKernel();
2779 
2780  if (IDVal == ".amd_amdgpu_isa")
2781  return ParseDirectiveISAVersion();
2782 
2784  return ParseDirectiveHSAMetadata();
2785 
2786  if (IDVal == PALMD::AssemblerDirective)
2787  return ParseDirectivePALMetadata();
2788 
2789  return true;
2790 }
2791 
2792 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2793  unsigned RegNo) const {
2794 
2795  for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true);
2796  R.isValid(); ++R) {
2797  if (*R == RegNo)
2798  return isGFX9();
2799  }
2800 
2801  switch (RegNo) {
2802  case AMDGPU::TBA:
2803  case AMDGPU::TBA_LO:
2804  case AMDGPU::TBA_HI:
2805  case AMDGPU::TMA:
2806  case AMDGPU::TMA_LO:
2807  case AMDGPU::TMA_HI:
2808  return !isGFX9();
2809  case AMDGPU::XNACK_MASK:
2810  case AMDGPU::XNACK_MASK_LO:
2811  case AMDGPU::XNACK_MASK_HI:
2812  return !isCI() && !isSI() && hasXNACK();
2813  default:
2814  break;
2815  }
2816 
2817  if (isCI())
2818  return true;
2819 
2820  if (isSI()) {
2821  // No flat_scr
2822  switch (RegNo) {
2823  case AMDGPU::FLAT_SCR:
2824  case AMDGPU::FLAT_SCR_LO:
2825  case AMDGPU::FLAT_SCR_HI:
2826  return false;
2827  default:
2828  return true;
2829  }
2830  }
2831 
2832  // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2833  // SI/CI have.
2834  for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2835  R.isValid(); ++R) {
2836  if (*R == RegNo)
2837  return false;
2838  }
2839 
2840  return true;
2841 }
2842 
2844 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2845  // Try to parse with a custom parser
2846  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2847 
2848  // If we successfully parsed the operand or if there as an error parsing,
2849  // we are done.
2850  //
2851  // If we are parsing after we reach EndOfStatement then this means we
2852  // are appending default values to the Operands list. This is only done
2853  // by custom parser, so we shouldn't continue on to the generic parsing.
2854  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2855  getLexer().is(AsmToken::EndOfStatement))
2856  return ResTy;
2857 
2858  ResTy = parseRegOrImm(Operands);
2859 
2860  if (ResTy == MatchOperand_Success)
2861  return ResTy;
2862 
2863  const auto &Tok = Parser.getTok();
2864  SMLoc S = Tok.getLoc();
2865 
2866  const MCExpr *Expr = nullptr;
2867  if (!Parser.parseExpression(Expr)) {
2868  Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2869  return MatchOperand_Success;
2870  }
2871 
2872  // Possibly this is an instruction flag like 'gds'.
2873  if (Tok.getKind() == AsmToken::Identifier) {
2874  Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), S));
2875  Parser.Lex();
2876  return MatchOperand_Success;
2877  }
2878 
2879  return MatchOperand_NoMatch;
2880 }
2881 
2882 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2883  // Clear any forced encodings from the previous instruction.
2884  setForcedEncodingSize(0);
2885  setForcedDPP(false);
2886  setForcedSDWA(false);
2887 
2888  if (Name.endswith("_e64")) {
2889  setForcedEncodingSize(64);
2890  return Name.substr(0, Name.size() - 4);
2891  } else if (Name.endswith("_e32")) {
2892  setForcedEncodingSize(32);
2893  return Name.substr(0, Name.size() - 4);
2894  } else if (Name.endswith("_dpp")) {
2895  setForcedDPP(true);
2896  return Name.substr(0, Name.size() - 4);
2897  } else if (Name.endswith("_sdwa")) {
2898  setForcedSDWA(true);
2899  return Name.substr(0, Name.size() - 5);
2900  }
2901  return Name;
2902 }
2903 
2904 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2905  StringRef Name,
2906  SMLoc NameLoc, OperandVector &Operands) {
2907  // Add the instruction mnemonic
2908  Name = parseMnemonicSuffix(Name);
2909  Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2910 
2911  while (!getLexer().is(AsmToken::EndOfStatement)) {
2912  OperandMatchResultTy Res = parseOperand(Operands, Name);
2913 
2914  // Eat the comma or space if there is one.
2915  if (getLexer().is(AsmToken::Comma))
2916  Parser.Lex();
2917 
2918  switch (Res) {
2919  case MatchOperand_Success: break;
2921  Error(getLexer().getLoc(), "failed parsing operand.");
2922  while (!getLexer().is(AsmToken::EndOfStatement)) {
2923  Parser.Lex();
2924  }
2925  return true;
2926  case MatchOperand_NoMatch:
2927  Error(getLexer().getLoc(), "not a valid operand.");
2928  while (!getLexer().is(AsmToken::EndOfStatement)) {
2929  Parser.Lex();
2930  }
2931  return true;
2932  }
2933  }
2934 
2935  return false;
2936 }
2937 
2938 //===----------------------------------------------------------------------===//
2939 // Utility functions
2940 //===----------------------------------------------------------------------===//
2941 
2943 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2944  switch(getLexer().getKind()) {
2945  default: return MatchOperand_NoMatch;
2946  case AsmToken::Identifier: {
2947  StringRef Name = Parser.getTok().getString();
2948  if (!Name.equals(Prefix)) {
2949  return MatchOperand_NoMatch;
2950  }
2951 
2952  Parser.Lex();
2953  if (getLexer().isNot(AsmToken::Colon))
2954  return MatchOperand_ParseFail;
2955 
2956  Parser.Lex();
2957 
2958  bool IsMinus = false;
2959  if (getLexer().getKind() == AsmToken::Minus) {
2960  Parser.Lex();
2961  IsMinus = true;
2962  }
2963 
2964  if (getLexer().isNot(AsmToken::Integer))
2965  return MatchOperand_ParseFail;
2966 
2967  if (getParser().parseAbsoluteExpression(Int))
2968  return MatchOperand_ParseFail;
2969 
2970  if (IsMinus)
2971  Int = -Int;
2972  break;
2973  }
2974  }
2975  return MatchOperand_Success;
2976 }
2977 
2979 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2980  AMDGPUOperand::ImmTy ImmTy,
2981  bool (*ConvertResult)(int64_t&)) {
2982  SMLoc S = Parser.getTok().getLoc();
2983  int64_t Value = 0;
2984 
2985  OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2986  if (Res != MatchOperand_Success)
2987  return Res;
2988 
2989  if (ConvertResult && !ConvertResult(Value)) {
2990  return MatchOperand_ParseFail;
2991  }
2992 
2993  Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2994  return MatchOperand_Success;
2995 }
2996 
2997 OperandMatchResultTy AMDGPUAsmParser::parseOperandArrayWithPrefix(
2998  const char *Prefix,
2999  OperandVector &Operands,
3000  AMDGPUOperand::ImmTy ImmTy,
3001  bool (*ConvertResult)(int64_t&)) {
3002  StringRef Name = Parser.getTok().getString();
3003  if (!Name.equals(Prefix))
3004  return MatchOperand_NoMatch;
3005 
3006  Parser.Lex();
3007  if (getLexer().isNot(AsmToken::Colon))
3008  return MatchOperand_ParseFail;
3009 
3010  Parser.Lex();
3011  if (getLexer().isNot(AsmToken::LBrac))
3012  return MatchOperand_ParseFail;
3013  Parser.Lex();
3014 
3015  unsigned Val = 0;
3016  SMLoc S = Parser.getTok().getLoc();
3017 
3018  // FIXME: How to verify the number of elements matches the number of src
3019  // operands?
3020  for (int I = 0; I < 4; ++I) {
3021  if (I != 0) {
3022  if (getLexer().is(AsmToken::RBrac))
3023  break;
3024 
3025  if (getLexer().isNot(AsmToken::Comma))
3026  return MatchOperand_ParseFail;
3027  Parser.Lex();
3028  }
3029 
3030  if (getLexer().isNot(AsmToken::Integer))
3031  return MatchOperand_ParseFail;
3032 
3033  int64_t Op;
3034  if (getParser().parseAbsoluteExpression(Op))
3035  return MatchOperand_ParseFail;
3036 
3037  if (Op != 0 && Op != 1)
3038  return MatchOperand_ParseFail;
3039  Val |= (Op << I);
3040  }
3041 
3042  Parser.Lex();
3043  Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
3044  return MatchOperand_Success;
3045 }
3046 
3048 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
3049  AMDGPUOperand::ImmTy ImmTy) {
3050  int64_t Bit = 0;
3051  SMLoc S = Parser.getTok().getLoc();
3052 
3053  // We are at the end of the statement, and this is a default argument, so
3054  // use a default value.
3055  if (getLexer().isNot(AsmToken::EndOfStatement)) {
3056  switch(getLexer().getKind()) {
3057  case AsmToken::Identifier: {
3058  StringRef Tok = Parser.getTok().getString();
3059  if (Tok == Name) {
3060  Bit = 1;
3061  Parser.Lex();
3062  } else if (Tok.startswith("no") && Tok.endswith(Name)) {
3063  Bit = 0;
3064  Parser.Lex();
3065  } else {
3066  return MatchOperand_NoMatch;
3067  }
3068  break;
3069  }
3070  default:
3071  return MatchOperand_NoMatch;
3072  }
3073  }
3074 
3075  Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
3076  return MatchOperand_Success;
3077 }
3078 
3080  MCInst& Inst, const OperandVector& Operands,
3081  AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
3082  AMDGPUOperand::ImmTy ImmT,
3083  int64_t Default = 0) {
3084  auto i = OptionalIdx.find(ImmT);
3085  if (i != OptionalIdx.end()) {
3086  unsigned Idx = i->second;
3087  ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
3088  } else {
3089  Inst.addOperand(MCOperand::createImm(Default));
3090  }
3091 }
3092 
3094 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
3095  if (getLexer().isNot(AsmToken::Identifier)) {
3096  return MatchOperand_NoMatch;
3097  }
3098  StringRef Tok = Parser.getTok().getString();
3099  if (Tok != Prefix) {
3100  return MatchOperand_NoMatch;
3101  }
3102 
3103  Parser.Lex();
3104  if (getLexer().isNot(AsmToken::Colon)) {
3105  return MatchOperand_ParseFail;
3106  }
3107 
3108  Parser.Lex();
3109  if (getLexer().isNot(AsmToken::Identifier)) {
3110  return MatchOperand_ParseFail;
3111  }
3112 
3113  Value = Parser.getTok().getString();
3114  return MatchOperand_Success;
3115 }
3116 
3117 //===----------------------------------------------------------------------===//
3118 // ds
3119 //===----------------------------------------------------------------------===//
3120 
3121 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
3122  const OperandVector &Operands) {
3123  OptionalImmIndexMap OptionalIdx;
3124 
3125  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3126  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3127 
3128  // Add the register arguments
3129  if (Op.isReg()) {
3130  Op.addRegOperands(Inst, 1);
3131  continue;
3132  }
3133 
3134  // Handle optional arguments
3135  OptionalIdx[Op.getImmTy()] = i;
3136  }
3137 
3138  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
3139  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
3140  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
3141 
3142  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
3143 }
3144 
3145 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
3146  bool IsGdsHardcoded) {
3147  OptionalImmIndexMap OptionalIdx;
3148 
3149  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3150  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3151 
3152  // Add the register arguments
3153  if (Op.isReg()) {
3154  Op.addRegOperands(Inst, 1);
3155  continue;
3156  }
3157 
3158  if (Op.isToken() && Op.getToken() == "gds") {
3159  IsGdsHardcoded = true;
3160  continue;
3161  }
3162 
3163  // Handle optional arguments
3164  OptionalIdx[Op.getImmTy()] = i;
3165  }
3166 
3167  AMDGPUOperand::ImmTy OffsetType =
3168  (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
3169  Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
3170  AMDGPUOperand::ImmTyOffset;
3171 
3172  addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
3173 
3174  if (!IsGdsHardcoded) {
3175  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
3176  }
3177  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
3178 }
3179 
3180 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
3181  OptionalImmIndexMap OptionalIdx;
3182 
3183  unsigned OperandIdx[4];
3184  unsigned EnMask = 0;
3185  int SrcIdx = 0;
3186 
3187  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3188  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3189 
3190  // Add the register arguments
3191  if (Op.isReg()) {
3192  assert(SrcIdx < 4);
3193  OperandIdx[SrcIdx] = Inst.size();
3194  Op.addRegOperands(Inst, 1);
3195  ++SrcIdx;
3196  continue;
3197  }
3198 
3199  if (Op.isOff()) {
3200  assert(SrcIdx < 4);
3201  OperandIdx[SrcIdx] = Inst.size();
3202  Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
3203  ++SrcIdx;
3204  continue;
3205  }
3206 
3207  if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
3208  Op.addImmOperands(Inst, 1);
3209  continue;
3210  }
3211 
3212  if (Op.isToken() && Op.getToken() == "done")
3213  continue;
3214 
3215  // Handle optional arguments
3216  OptionalIdx[Op.getImmTy()] = i;
3217  }
3218 
3219  assert(SrcIdx == 4);
3220 
3221  bool Compr = false;
3222  if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
3223  Compr = true;
3224  Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
3225  Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
3226  Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
3227  }
3228 
3229  for (auto i = 0; i < SrcIdx; ++i) {
3230  if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
3231  EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
3232  }
3233  }
3234 
3235  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
3236  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
3237 
3238  Inst.addOperand(MCOperand::createImm(EnMask));
3239 }
3240 
3241 //===----------------------------------------------------------------------===//
3242 // s_waitcnt
3243 //===----------------------------------------------------------------------===//
3244 
3245 static bool
3247  const AMDGPU::IsaInfo::IsaVersion ISA,
3248  int64_t &IntVal,
3249  int64_t CntVal,
3250  bool Saturate,
3251  unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned),
3252  unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned))
3253 {
3254  bool Failed = false;
3255 
3256  IntVal = encode(ISA, IntVal, CntVal);
3257  if (CntVal != decode(ISA, IntVal)) {
3258  if (Saturate) {
3259  IntVal = encode(ISA, IntVal, -1);
3260  } else {
3261  Failed = true;
3262  }
3263  }
3264  return Failed;
3265 }
3266 
3267 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
3268  StringRef CntName = Parser.getTok().getString();
3269  int64_t CntVal;
3270 
3271  Parser.Lex();
3272  if (getLexer().isNot(AsmToken::LParen))
3273  return true;
3274 
3275  Parser.Lex();
3276  if (getLexer().isNot(AsmToken::Integer))
3277  return true;
3278 
3279  SMLoc ValLoc = Parser.getTok().getLoc();
3280  if (getParser().parseAbsoluteExpression(CntVal))
3281  return true;
3282 
3284  AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
3285 
3286  bool Failed = true;
3287  bool Sat = CntName.endswith("_sat");
3288 
3289  if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
3290  Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
3291  } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
3292  Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
3293  } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
3294  Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
3295  }
3296 
3297  if (Failed) {
3298  Error(ValLoc, "too large value for " + CntName);
3299  return true;
3300  }
3301 
3302  if (getLexer().isNot(AsmToken::RParen)) {
3303  return true;
3304  }
3305 
3306  Parser.Lex();
3307  if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) {
3308  const AsmToken NextToken = getLexer().peekTok();
3309  if (NextToken.is(AsmToken::Identifier)) {
3310  Parser.Lex();
3311  }
3312  }
3313 
3314  return false;
3315 }
3316 
3318 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
3320  AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
3321  int64_t Waitcnt = getWaitcntBitMask(ISA);
3322  SMLoc S = Parser.getTok().getLoc();
3323 
3324  switch(getLexer().getKind()) {
3325  default: return MatchOperand_ParseFail;
3326  case AsmToken::Integer:
3327  // The operand can be an integer value.
3328  if (getParser().parseAbsoluteExpression(Waitcnt))
3329  return MatchOperand_ParseFail;
3330  break;
3331 
3332  case AsmToken::Identifier:
3333  do {
3334  if (parseCnt(Waitcnt))
3335  return MatchOperand_ParseFail;
3336  } while(getLexer().isNot(AsmToken::EndOfStatement));
3337  break;
3338  }
3339  Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
3340  return MatchOperand_Success;
3341 }
3342 
3343 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset,
3344  int64_t &Width) {
3345  using namespace llvm::AMDGPU::Hwreg;
3346 
3347  if (Parser.getTok().getString() != "hwreg")
3348  return true;
3349  Parser.Lex();
3350 
3351  if (getLexer().isNot(AsmToken::LParen))
3352  return true;
3353  Parser.Lex();
3354 
3355  if (getLexer().is(AsmToken::Identifier)) {
3356  HwReg.IsSymbolic = true;
3357  HwReg.Id = ID_UNKNOWN_;
3358  const StringRef tok = Parser.getTok().getString();
3359  int Last = ID_SYMBOLIC_LAST_;
3360  if (isSI() || isCI() || isVI())
3361  Last = ID_SYMBOLIC_FIRST_GFX9_;
3362  for (int i = ID_SYMBOLIC_FIRST_; i < Last; ++i) {
3363  if (tok == IdSymbolic[i]) {
3364  HwReg.Id = i;
3365  break;
3366  }
3367  }
3368  Parser.Lex();
3369  } else {
3370  HwReg.IsSymbolic = false;
3371  if (getLexer().isNot(AsmToken::Integer))
3372  return true;
3373  if (getParser().parseAbsoluteExpression(HwReg.Id))
3374  return true;
3375  }
3376 
3377  if (getLexer().is(AsmToken::RParen)) {
3378  Parser.Lex();
3379  return false;
3380  }
3381 
3382  // optional params
3383  if (getLexer().isNot(AsmToken::Comma))
3384  return true;
3385  Parser.Lex();
3386 
3387  if (getLexer().isNot(AsmToken::Integer))
3388  return true;
3389  if (getParser().parseAbsoluteExpression(Offset))
3390  return true;
3391 
3392  if (getLexer().isNot(AsmToken::Comma))
3393  return true;
3394  Parser.Lex();
3395 
3396  if (getLexer().isNot(AsmToken::Integer))
3397  return true;
3398  if (getParser().parseAbsoluteExpression(Width))
3399  return true;
3400 
3401  if (getLexer().isNot(AsmToken::RParen))
3402  return true;
3403  Parser.Lex();
3404 
3405  return false;
3406 }
3407 
3408 OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
3409  using namespace llvm::AMDGPU::Hwreg;
3410 
3411  int64_t Imm16Val = 0;
3412  SMLoc S = Parser.getTok().getLoc();
3413 
3414  switch(getLexer().getKind()) {
3415  default: return MatchOperand_NoMatch;
3416  case AsmToken::Integer:
3417  // The operand can be an integer value.
3418  if (getParser().parseAbsoluteExpression(Imm16Val))
3419  return MatchOperand_NoMatch;
3420  if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3421  Error(S, "invalid immediate: only 16-bit values are legal");
3422  // Do not return error code, but create an imm operand anyway and proceed
3423  // to the next operand, if any. That avoids unneccessary error messages.
3424  }
3425  break;
3426 
3427  case AsmToken::Identifier: {
3428  OperandInfoTy HwReg(ID_UNKNOWN_);
3429  int64_t Offset = OFFSET_DEFAULT_;
3430  int64_t Width = WIDTH_M1_DEFAULT_ + 1;
3431  if (parseHwregConstruct(HwReg, Offset, Width))
3432  return MatchOperand_ParseFail;
3433  if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3434  if (HwReg.IsSymbolic)
3435  Error(S, "invalid symbolic name of hardware register");
3436  else
3437  Error(S, "invalid code of hardware register: only 6-bit values are legal");
3438  }
3439  if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3440  Error(S, "invalid bit offset: only 5-bit values are legal");
3441  if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3442  Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
3443  Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
3444  }
3445  break;
3446  }
3447  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3448  return MatchOperand_Success;
3449 }
3450 
3451 bool AMDGPUOperand::isSWaitCnt() const {
3452  return isImm();
3453 }
3454 
3455 bool AMDGPUOperand::isHwreg() const {
3456  return isImmTy(ImmTyHwreg);
3457 }
3458 
3459 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
3460  using namespace llvm::AMDGPU::SendMsg;
3461 
3462  if (Parser.getTok().getString() != "sendmsg")
3463  return true;
3464  Parser.Lex();
3465 
3466  if (getLexer().isNot(AsmToken::LParen))
3467  return true;
3468  Parser.Lex();
3469 
3470  if (getLexer().is(AsmToken::Identifier)) {
3471  Msg.IsSymbolic = true;
3472  Msg.Id = ID_UNKNOWN_;
3473  const std::string tok = Parser.getTok().getString();
3474  for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
3475  switch(i) {
3476  default: continue; // Omit gaps.
3477  case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
3478  }
3479  if (tok == IdSymbolic[i]) {
3480  Msg.Id = i;
3481  break;
3482  }
3483  }
3484  Parser.Lex();
3485  } else {
3486  Msg.IsSymbolic = false;
3487  if (getLexer().isNot(AsmToken::Integer))
3488  return true;
3489  if (getParser().parseAbsoluteExpression(Msg.Id))
3490  return true;
3491  if (getLexer().is(AsmToken::Integer))
3492  if (getParser().parseAbsoluteExpression(Msg.Id))
3493  Msg.Id = ID_UNKNOWN_;
3494  }
3495  if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
3496  return false;
3497 
3498  if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
3499  if (getLexer().isNot(AsmToken::RParen))
3500  return true;
3501  Parser.Lex();
3502  return false;
3503  }
3504 
3505  if (getLexer().isNot(AsmToken::Comma))
3506  return true;
3507  Parser.Lex();
3508 
3509  assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
3510  Operation.Id = ID_UNKNOWN_;
3511  if (getLexer().is(AsmToken::Identifier)) {
3512  Operation.IsSymbolic = true;
3513  const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
3514  const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
3515  const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
3516  const StringRef Tok = Parser.getTok().getString();
3517  for (int i = F; i < L; ++i) {
3518  if (Tok == S[i]) {
3519  Operation.Id = i;
3520  break;
3521  }
3522  }
3523  Parser.Lex();
3524  } else {
3525  Operation.IsSymbolic = false;
3526  if (getLexer().isNot(AsmToken::Integer))
3527  return true;
3528  if (getParser().parseAbsoluteExpression(Operation.Id))
3529  return true;
3530  }
3531 
3532  if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3533  // Stream id is optional.
3534  if (getLexer().is(AsmToken::RParen)) {
3535  Parser.Lex();
3536  return false;
3537  }
3538 
3539  if (getLexer().isNot(AsmToken::Comma))
3540  return true;
3541  Parser.Lex();
3542 
3543  if (getLexer().isNot(AsmToken::Integer))
3544  return true;
3545  if (getParser().parseAbsoluteExpression(StreamId))
3546  return true;
3547  }
3548 
3549  if (getLexer().isNot(AsmToken::RParen))
3550  return true;
3551  Parser.Lex();
3552  return false;
3553 }
3554 
3555 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
3556  if (getLexer().getKind() != AsmToken::Identifier)
3557  return MatchOperand_NoMatch;
3558 
3559  StringRef Str = Parser.getTok().getString();
3560  int Slot = StringSwitch<int>(Str)
3561  .Case("p10", 0)
3562  .Case("p20", 1)
3563  .Case("p0", 2)
3564  .Default(-1);
3565 
3566  SMLoc S = Parser.getTok().getLoc();
3567  if (Slot == -1)
3568  return MatchOperand_ParseFail;
3569 
3570  Parser.Lex();
3571  Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
3572  AMDGPUOperand::ImmTyInterpSlot));
3573  return MatchOperand_Success;
3574 }
3575 
3576 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
3577  if (getLexer().getKind() != AsmToken::Identifier)
3578  return MatchOperand_NoMatch;
3579 
3580  StringRef Str = Parser.getTok().getString();
3581  if (!Str.startswith("attr"))
3582  return MatchOperand_NoMatch;
3583 
3584  StringRef Chan = Str.take_back(2);
3585  int AttrChan = StringSwitch<int>(Chan)
3586  .Case(".x", 0)
3587  .Case(".y", 1)
3588  .Case(".z", 2)
3589  .Case(".w", 3)
3590  .Default(-1);
3591  if (AttrChan == -1)
3592  return MatchOperand_ParseFail;
3593 
3594  Str = Str.drop_back(2).drop_front(4);
3595 
3596  uint8_t Attr;
3597  if (Str.getAsInteger(10, Attr))
3598  return MatchOperand_ParseFail;
3599 
3600  SMLoc S = Parser.getTok().getLoc();
3601  Parser.Lex();
3602  if (Attr > 63) {
3603  Error(S, "out of bounds attr");
3604  return MatchOperand_Success;
3605  }
3606 
3607  SMLoc SChan = SMLoc::getFromPointer(Chan.data());
3608 
3609  Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
3610  AMDGPUOperand::ImmTyInterpAttr));
3611  Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
3612  AMDGPUOperand::ImmTyAttrChan));
3613  return MatchOperand_Success;
3614 }
3615 
3616 void AMDGPUAsmParser::errorExpTgt() {
3617  Error(Parser.getTok().getLoc(), "invalid exp target");
3618 }
3619 
3620 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
3621  uint8_t &Val) {
3622  if (Str == "null") {
3623  Val = 9;
3624  return MatchOperand_Success;
3625  }
3626 
3627  if (Str.startswith("mrt")) {
3628  Str = Str.drop_front(3);
3629  if (Str == "z") { // == mrtz
3630  Val = 8;
3631  return MatchOperand_Success;
3632  }
3633 
3634  if (Str.getAsInteger(10, Val))
3635  return MatchOperand_ParseFail;
3636 
3637  if (Val > 7)
3638  errorExpTgt();
3639 
3640  return MatchOperand_Success;
3641  }
3642 
3643  if (Str.startswith("pos")) {
3644  Str = Str.drop_front(3);
3645  if (Str.getAsInteger(10, Val))
3646  return MatchOperand_ParseFail;
3647 
3648  if (Val > 3)
3649  errorExpTgt();
3650 
3651  Val += 12;
3652  return MatchOperand_Success;
3653  }
3654 
3655  if (Str.startswith("param")) {
3656  Str = Str.drop_front(5);
3657  if (Str.getAsInteger(10, Val))
3658  return MatchOperand_ParseFail;
3659 
3660  if (Val >= 32)
3661  errorExpTgt();
3662 
3663  Val += 32;
3664  return MatchOperand_Success;
3665  }
3666 
3667  if (Str.startswith("invalid_target_")) {
3668  Str = Str.drop_front(15);
3669  if (Str.getAsInteger(10, Val))
3670  return MatchOperand_ParseFail;
3671 
3672  errorExpTgt();
3673  return MatchOperand_Success;
3674  }
3675 
3676  return MatchOperand_NoMatch;
3677 }
3678 
3679 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
3680  uint8_t Val;
3681  StringRef Str = Parser.getTok().getString();
3682 
3683  auto Res = parseExpTgtImpl(Str, Val);
3684  if (Res != MatchOperand_Success)
3685  return Res;
3686 
3687  SMLoc S = Parser.getTok().getLoc();
3688  Parser.Lex();
3689 
3690  Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
3691  AMDGPUOperand::ImmTyExpTgt));
3692  return MatchOperand_Success;
3693 }
3694 
3696 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
3697  using namespace llvm::AMDGPU::SendMsg;
3698 
3699  int64_t Imm16Val = 0;
3700  SMLoc S = Parser.getTok().getLoc();
3701 
3702  switch(getLexer().getKind()) {
3703  default:
3704  return MatchOperand_NoMatch;
3705  case AsmToken::Integer:
3706  // The operand can be an integer value.
3707  if (getParser().parseAbsoluteExpression(Imm16Val))
3708  return MatchOperand_NoMatch;
3709  if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3710  Error(S, "invalid immediate: only 16-bit values are legal");
3711  // Do not return error code, but create an imm operand anyway and proceed
3712  // to the next operand, if any. That avoids unneccessary error messages.
3713  }
3714  break;
3715  case AsmToken::Identifier: {
3716  OperandInfoTy Msg(ID_UNKNOWN_);
3717  OperandInfoTy Operation(OP_UNKNOWN_);
3718  int64_t StreamId = STREAM_ID_DEFAULT_;
3719  if (parseSendMsgConstruct(Msg, Operation, StreamId))
3720  return MatchOperand_ParseFail;
3721  do {
3722  // Validate and encode message ID.
3723  if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
3724  || Msg.Id == ID_SYSMSG)) {
3725  if (Msg.IsSymbolic)
3726  Error(S, "invalid/unsupported symbolic name of message");
3727  else
3728  Error(S, "invalid/unsupported code of message");
3729  break;
3730  }
3731  Imm16Val = (Msg.Id << ID_SHIFT_);
3732  // Validate and encode operation ID.
3733  if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
3734  if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
3735  if (Operation.IsSymbolic)
3736  Error(S, "invalid symbolic name of GS_OP");
3737  else
3738  Error(S, "invalid code of GS_OP: only 2-bit values are legal");
3739  break;
3740  }
3741  if (Operation.Id == OP_GS_NOP
3742  && Msg.Id != ID_GS_DONE) {
3743  Error(S, "invalid GS_OP: NOP is for GS_DONE only");
3744  break;
3745  }
3746  Imm16Val |= (Operation.Id << OP_SHIFT_);
3747  }
3748  if (Msg.Id == ID_SYSMSG) {
3749  if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
3750  if (Operation.IsSymbolic)
3751  Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
3752  else
3753  Error(S, "invalid/unsupported code of SYSMSG_OP");
3754  break;
3755  }
3756  Imm16Val |= (Operation.Id << OP_SHIFT_);
3757  }
3758  // Validate and encode stream ID.
3759  if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3760  if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
3761  Error(S, "invalid stream id: only 2-bit values are legal");
3762  break;
3763  }
3764  Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
3765  }
3766  } while (false);
3767  }
3768  break;
3769  }
3770  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
3771  return MatchOperand_Success;
3772 }
3773 
3774 bool AMDGPUOperand::isSendMsg() const {
3775  return isImmTy(ImmTySendMsg);
3776 }
3777 
3778 //===----------------------------------------------------------------------===//
3779 // parser helpers
3780 //===----------------------------------------------------------------------===//
3781 
3782 bool
3783 AMDGPUAsmParser::trySkipId(const StringRef Id) {
3784  if (getLexer().getKind() == AsmToken::Identifier &&
3785  Parser.getTok().getString() == Id) {
3786  Parser.Lex();
3787  return true;
3788  }
3789  return false;
3790 }
3791 
3792 bool
3793 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
3794  if (getLexer().getKind() == Kind) {
3795  Parser.Lex();
3796  return true;
3797  }
3798  return false;
3799 }
3800 
3801 bool
3802 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
3803  const StringRef ErrMsg) {
3804  if (!trySkipToken(Kind)) {
3805  Error(Parser.getTok().getLoc(), ErrMsg);
3806  return false;
3807  }
3808  return true;
3809 }
3810 
3811 bool
3812 AMDGPUAsmParser::parseExpr(int64_t &Imm) {
3813  return !getParser().parseAbsoluteExpression(Imm);
3814 }
3815 
3816 bool
3817 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
3818  SMLoc S = Parser.getTok().getLoc();
3819  if (getLexer().getKind() == AsmToken::String) {
3820  Val = Parser.getTok().getStringContents();
3821  Parser.Lex();
3822  return true;
3823  } else {
3824  Error(S, ErrMsg);
3825  return false;
3826  }
3827 }
3828 
3829 //===----------------------------------------------------------------------===//
3830 // swizzle
3831 //===----------------------------------------------------------------------===//
3832 
3834 static unsigned
3835 encodeBitmaskPerm(const unsigned AndMask,
3836  const unsigned OrMask,
3837  const unsigned XorMask) {
3838  using namespace llvm::AMDGPU::Swizzle;
3839 
3840  return BITMASK_PERM_ENC |
3841  (AndMask << BITMASK_AND_SHIFT) |
3842  (OrMask << BITMASK_OR_SHIFT) |
3843  (XorMask << BITMASK_XOR_SHIFT);
3844 }
3845 
3846 bool
3847 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
3848  const unsigned MinVal,
3849  const unsigned MaxVal,
3850  const StringRef ErrMsg) {
3851  for (unsigned i = 0; i < OpNum; ++i) {
3852  if (!skipToken(AsmToken::Comma, "expected a comma")){
3853  return false;
3854  }
3855  SMLoc ExprLoc = Parser.getTok().getLoc();
3856  if (!parseExpr(Op[i])) {
3857  return false;
3858  }
3859  if (Op[i] < MinVal || Op[i] > MaxVal) {
3860  Error(ExprLoc, ErrMsg);
3861  return false;
3862  }
3863  }
3864 
3865  return true;
3866 }
3867 
3868 bool
3869 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
3870  using namespace llvm::AMDGPU::Swizzle;
3871 
3872  int64_t Lane[LANE_NUM];
3873  if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
3874  "expected a 2-bit lane id")) {
3875  Imm = QUAD_PERM_ENC;
3876  for (auto i = 0; i < LANE_NUM; ++i) {
3877  Imm |= Lane[i] << (LANE_SHIFT * i);
3878  }
3879  return true;
3880  }
3881  return false;
3882 }
3883 
3884 bool
3885 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
3886  using namespace llvm::AMDGPU::Swizzle;
3887 
3888  SMLoc S = Parser.getTok().getLoc();
3889  int64_t GroupSize;
3890  int64_t LaneIdx;
3891 
3892  if (!parseSwizzleOperands(1, &GroupSize,
3893  2, 32,
3894  "group size must be in the interval [2,32]")) {
3895  return false;
3896  }
3897  if (!isPowerOf2_64(GroupSize)) {
3898  Error(S, "group size must be a power of two");
3899  return false;
3900  }
3901  if (parseSwizzleOperands(1, &LaneIdx,
3902  0, GroupSize - 1,
3903  "lane id must be in the interval [0,group size - 1]")) {
3904  Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
3905  return true;
3906  }
3907  return false;
3908 }
3909 
3910 bool
3911 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
3912  using namespace llvm::AMDGPU::Swizzle;
3913 
3914  SMLoc S = Parser.getTok().getLoc();
3915  int64_t GroupSize;
3916 
3917  if (!parseSwizzleOperands(1, &GroupSize,
3918  2, 32, "group size must be in the interval [2,32]")) {
3919  return false;
3920  }
3921  if (!isPowerOf2_64(GroupSize)) {
3922  Error(S, "group size must be a power of two");
3923  return false;
3924  }
3925 
3926  Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
3927  return true;
3928 }
3929 
3930 bool
3931 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
3932  using namespace llvm::AMDGPU::Swizzle;
3933 
3934  SMLoc S = Parser.getTok().getLoc();
3935  int64_t GroupSize;
3936 
3937  if (!parseSwizzleOperands(1, &GroupSize,
3938  1, 16, "group size must be in the interval [1,16]")) {
3939  return false;
3940  }
3941  if (!isPowerOf2_64(GroupSize)) {
3942  Error(S, "group size must be a power of two");
3943  return false;
3944  }
3945 
3946  Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
3947  return true;
3948 }
3949 
3950 bool
3951 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
3952  using namespace llvm::AMDGPU::Swizzle;
3953 
3954  if (!skipToken(AsmToken::Comma, "expected a comma")) {
3955  return false;
3956  }
3957 
3958  StringRef Ctl;
3959  SMLoc StrLoc = Parser.getTok().getLoc();
3960  if (!parseString(Ctl)) {
3961  return false;
3962  }
3963  if (Ctl.size() != BITMASK_WIDTH) {
3964  Error(StrLoc, "expected a 5-character mask");
3965  return false;
3966  }
3967 
3968  unsigned AndMask = 0;
3969  unsigned OrMask = 0;
3970  unsigned XorMask = 0;
3971 
3972  for (size_t i = 0; i < Ctl.size(); ++i) {
3973  unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
3974  switch(Ctl[i]) {
3975  default:
3976  Error(StrLoc, "invalid mask");
3977  return false;
3978  case '0':
3979  break;
3980  case '1':
3981  OrMask |= Mask;
3982  break;
3983  case 'p':
3984  AndMask |= Mask;
3985  break;
3986  case 'i':
3987  AndMask |= Mask;
3988  XorMask |= Mask;
3989  break;
3990  }
3991  }
3992 
3993  Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
3994  return true;
3995 }
3996 
3997 bool
3998 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
3999 
4000  SMLoc OffsetLoc = Parser.getTok().getLoc();
4001 
4002  if (!parseExpr(Imm)) {
4003  return false;
4004  }
4005  if (!isUInt<16>(Imm)) {
4006  Error(OffsetLoc, "expected a 16-bit offset");
4007  return false;
4008  }
4009  return true;
4010 }
4011 
4012 bool
4013 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
4014  using namespace llvm::AMDGPU::Swizzle;
4015 
4016  if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
4017 
4018  SMLoc ModeLoc = Parser.getTok().getLoc();
4019  bool Ok = false;
4020 
4021  if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
4022  Ok = parseSwizzleQuadPerm(Imm);
4023  } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
4024  Ok = parseSwizzleBitmaskPerm(Imm);
4025  } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
4026  Ok = parseSwizzleBroadcast(Imm);
4027  } else if (trySkipId(IdSymbolic[ID_SWAP])) {
4028  Ok = parseSwizzleSwap(Imm);
4029  } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
4030  Ok = parseSwizzleReverse(Imm);
4031  } else {
4032  Error(ModeLoc, "expected a swizzle mode");
4033  }
4034 
4035  return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
4036  }
4037 
4038  return false;
4039 }
4040 
4042 AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
4043  SMLoc S = Parser.getTok().getLoc();
4044  int64_t Imm = 0;
4045 
4046  if (trySkipId("offset")) {
4047 
4048  bool Ok = false;
4049  if (skipToken(AsmToken::Colon, "expected a colon")) {
4050  if (trySkipId("swizzle")) {
4051  Ok = parseSwizzleMacro(Imm);
4052  } else {
4053  Ok = parseSwizzleOffset(Imm);
4054  }
4055  }
4056 
4057  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
4058 
4060  } else {
4061  // Swizzle "offset" operand is optional.
4062  // If it is omitted, try parsing other optional operands.
4063  return parseOptionalOpr(Operands);
4064  }
4065 }
4066 
4067 bool
4068 AMDGPUOperand::isSwizzle() const {
4069  return isImmTy(ImmTySwizzle);
4070 }
4071 
4072 //===----------------------------------------------------------------------===//
4073 // sopp branch targets
4074 //===----------------------------------------------------------------------===//
4075 
4077 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
4078  SMLoc S = Parser.getTok().getLoc();
4079 
4080  switch (getLexer().getKind()) {
4081  default: return MatchOperand_ParseFail;
4082  case AsmToken::Integer: {
4083  int64_t Imm;
4084  if (getParser().parseAbsoluteExpression(Imm))
4085  return MatchOperand_ParseFail;
4086  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
4087  return MatchOperand_Success;
4088  }
4089 
4090  case AsmToken::Identifier:
4091  Operands.push_back(AMDGPUOperand::CreateExpr(this,
4092  MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
4093  Parser.getTok().getString()), getContext()), S));
4094  Parser.Lex();
4095  return MatchOperand_Success;
4096  }
4097 }
4098 
4099 //===----------------------------------------------------------------------===//
4100 // mubuf
4101 //===----------------------------------------------------------------------===//
4102 
4103 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
4104  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
4105 }
4106 
4107 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
4108  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
4109 }
4110 
4111 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
4112  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
4113 }
4114 
4115 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
4116  const OperandVector &Operands,
4117  bool IsAtomic,
4118  bool IsAtomicReturn,
4119  bool IsLds) {
4120  bool IsLdsOpcode = IsLds;
4121  bool HasLdsModifier = false;
4122  OptionalImmIndexMap OptionalIdx;
4123  assert(IsAtomicReturn ? IsAtomic : true);
4124 
4125  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4126  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4127 
4128  // Add the register arguments
4129  if (Op.isReg()) {
4130  Op.addRegOperands(Inst, 1);
4131  continue;
4132  }
4133 
4134  // Handle the case where soffset is an immediate
4135  if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
4136  Op.addImmOperands(Inst, 1);
4137  continue;
4138  }
4139 
4140  HasLdsModifier = Op.isLDS();
4141 
4142  // Handle tokens like 'offen' which are sometimes hard-coded into the
4143  // asm string. There are no MCInst operands for these.
4144  if (Op.isToken()) {
4145  continue;
4146  }
4147  assert(Op.isImm());
4148 
4149  // Handle optional arguments
4150  OptionalIdx[Op.getImmTy()] = i;
4151  }
4152 
4153  // This is a workaround for an llvm quirk which may result in an
4154  // incorrect instruction selection. Lds and non-lds versions of
4155  // MUBUF instructions are identical except that lds versions
4156  // have mandatory 'lds' modifier. However this modifier follows
4157  // optional modifiers and llvm asm matcher regards this 'lds'
4158  // modifier as an optional one. As a result, an lds version
4159  // of opcode may be selected even if it has no 'lds' modifier.
4160  if (IsLdsOpcode && !HasLdsModifier) {
4161  int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode());
4162  if (NoLdsOpcode != -1) { // Got lds version - correct it.
4163  Inst.setOpcode(NoLdsOpcode);
4164  IsLdsOpcode = false;
4165  }
4166  }
4167 
4168  // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
4169  if (IsAtomicReturn) {
4170  MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
4171  Inst.insert(I, *I);
4172  }
4173 
4174  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
4175  if (!IsAtomic) { // glc is hard-coded.
4176  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
4177  }
4178  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
4179 
4180  if (!IsLdsOpcode) { // tfe is not legal with lds opcodes
4181  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
4182  }
4183 }
4184 
4185 void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
4186  OptionalImmIndexMap OptionalIdx;
4187 
4188  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4189  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4190 
4191  // Add the register arguments
4192  if (Op.isReg()) {
4193  Op.addRegOperands(Inst, 1);
4194  continue;
4195  }
4196 
4197  // Handle the case where soffset is an immediate
4198  if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
4199  Op.addImmOperands(Inst, 1);
4200  continue;
4201  }
4202 
4203  // Handle tokens like 'offen' which are sometimes hard-coded into the
4204  // asm string. There are no MCInst operands for these.
4205  if (Op.isToken()) {
4206  continue;
4207  }
4208  assert(Op.isImm());
4209 
4210  // Handle optional arguments
4211  OptionalIdx[Op.getImmTy()] = i;
4212  }
4213 
4214  addOptionalImmOperand(Inst, Operands, OptionalIdx,
4215  AMDGPUOperand::ImmTyOffset);
4216  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDFMT);
4217  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyNFMT);
4218  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
4219  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
4220  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
4221 }
4222 
4223 //===----------------------------------------------------------------------===//
4224 // mimg
4225 //===----------------------------------------------------------------------===//
4226 
4227 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands,
4228  bool IsAtomic) {
4229  unsigned I = 1;
4230  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4231  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4232  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4233  }
4234 
4235  if (IsAtomic) {
4236  // Add src, same as dst
4237  assert(Desc.getNumDefs() == 1);
4238  ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1);
4239  }
4240 
4241  OptionalImmIndexMap OptionalIdx;
4242 
4243  for (unsigned E = Operands.size(); I != E; ++I) {
4244  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4245 
4246  // Add the register arguments
4247  if (Op.isReg()) {
4248  Op.addRegOperands(Inst, 1);
4249  } else if (Op.isImmModifier()) {
4250  OptionalIdx[Op.getImmTy()] = I;
4251  } else {
4252  llvm_unreachable("unexpected operand type");
4253  }
4254  }
4255 
4256  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
4257  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
4258  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
4259  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
4260  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
4261  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
4262  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
4263  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
4264 }
4265 
4266 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
4267  cvtMIMG(Inst, Operands, true);
4268 }
4269 
4270 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
4271  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
4272 }
4273 
4274 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
4275  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
4276 }
4277 
4278 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
4279  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
4280 }
4281 
4282 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
4283  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
4284 }
4285 
4286 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
4287  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
4288 }
4289 
4290 //===----------------------------------------------------------------------===//
4291 // smrd
4292 //===----------------------------------------------------------------------===//
4293 
4294 bool AMDGPUOperand::isSMRDOffset8() const {
4295  return isImm() && isUInt<8>(getImm());
4296 }
4297 
4298 bool AMDGPUOperand::isSMRDOffset20() const {
4299  return isImm() && isUInt<20>(getImm());
4300 }
4301 
4302 bool AMDGPUOperand::isSMRDLiteralOffset() const {
4303  // 32-bit literals are only supported on CI and we only want to use them
4304  // when the offset is > 8-bits.
4305  return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
4306 }
4307 
4308 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
4309  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4310 }
4311 
4312 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
4313  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4314 }
4315 
4316 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
4317  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4318 }
4319 
4320 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const {
4321  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4322 }
4323 
4324 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetS13() const {
4325  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4326 }
4327 
4328 //===----------------------------------------------------------------------===//
4329 // vop3
4330 //===----------------------------------------------------------------------===//
4331 
4332 static bool ConvertOmodMul(int64_t &Mul) {
4333  if (Mul != 1 && Mul != 2 && Mul != 4)
4334  return false;
4335 
4336  Mul >>= 1;
4337  return true;
4338 }
4339 
4340 static bool ConvertOmodDiv(int64_t &Div) {
4341  if (Div == 1) {
4342  Div = 0;
4343  return true;
4344  }
4345 
4346  if (Div == 2) {
4347  Div = 3;
4348  return true;
4349  }
4350 
4351  return false;
4352 }
4353 
4354 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
4355  if (BoundCtrl == 0) {
4356  BoundCtrl = 1;
4357  return true;
4358  }
4359 
4360  if (BoundCtrl == -1) {
4361  BoundCtrl = 0;
4362  return true;
4363  }
4364 
4365  return false;
4366 }
4367 
4368 // Note: the order in this table matches the order of operands in AsmString.
4369 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
4370  {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
4371  {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
4372  {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
4373  {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
4374  {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
4375  {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
4376  {"lds", AMDGPUOperand::ImmTyLDS, true, nullptr},
4377  {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
4378  {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
4379  {"dfmt", AMDGPUOperand::ImmTyDFMT, false, nullptr},
4380  {"nfmt", AMDGPUOperand::ImmTyNFMT, false, nullptr},
4381  {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
4382  {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
4383  {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
4384  {"d16", AMDGPUOperand::ImmTyD16, true, nullptr},
4385  {"high", AMDGPUOperand::ImmTyHigh, true, nullptr},
4386  {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
4387  {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
4388  {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
4389  {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
4390  {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
4391  {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
4392  {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
4393  {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
4394  {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
4395  {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
4396  {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
4397  {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
4398  {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
4399  {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
4400  {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
4401  {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
4402  {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
4403  {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
4404  {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
4405  {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
4406 };
4407 
4408 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
4409  unsigned size = Operands.size();
4410  assert(size > 0);
4411 
4412  OperandMatchResultTy res = parseOptionalOpr(Operands);
4413 
4414  // This is a hack to enable hardcoded mandatory operands which follow
4415  // optional operands.
4416  //
4417  // Current design assumes that all operands after the first optional operand
4418  // are also optional. However implementation of some instructions violates
4419  // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands).
4420  //
4421  // To alleviate this problem, we have to (implicitly) parse extra operands
4422  // to make sure autogenerated parser of custom operands never hit hardcoded
4423  // mandatory operands.
4424 
4425  if (size == 1 || ((AMDGPUOperand &)*Operands[size - 1]).isRegKind()) {
4426 
4427  // We have parsed the first optional operand.
4428  // Parse as many operands as necessary to skip all mandatory operands.
4429 
4430  for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
4431  if (res != MatchOperand_Success ||
4432  getLexer().is(AsmToken::EndOfStatement)) break;
4433  if (getLexer().is(AsmToken::Comma)) Parser.Lex();
4434  res = parseOptionalOpr(Operands);
4435  }
4436  }
4437 
4438  return res;
4439 }
4440 
4441 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) {
4443  for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
4444  // try to parse any optional operand here
4445  if (Op.IsBit) {
4446  res = parseNamedBit(Op.Name, Operands, Op.Type);
4447  } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
4448  res = parseOModOperand(Operands);
4449  } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
4450  Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
4451  Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
4452  res = parseSDWASel(Operands, Op.Name, Op.Type);
4453  } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
4454  res = parseSDWADstUnused(Operands);
4455  } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
4456  Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
4457  Op.Type == AMDGPUOperand::ImmTyNegLo ||
4458  Op.Type == AMDGPUOperand::ImmTyNegHi) {
4459  res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
4460  Op.ConvertResult);
4461  } else {
4462  res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
4463  }
4464  if (res != MatchOperand_NoMatch) {
4465  return res;
4466  }
4467  }
4468  return MatchOperand_NoMatch;
4469 }
4470 
4471 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
4472  StringRef Name = Parser.getTok().getString();
4473  if (Name == "mul") {
4474  return parseIntWithPrefix("mul", Operands,
4475  AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
4476  }
4477 
4478  if (Name == "div") {
4479  return parseIntWithPrefix("div", Operands,
4480  AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
4481  }
4482 
4483  return MatchOperand_NoMatch;
4484 }
4485 
4486 void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) {
4487  cvtVOP3P(Inst, Operands);
4488 
4489  int Opc = Inst.getOpcode();
4490 
4491  int SrcNum;
4492  const int Ops[] = { AMDGPU::OpName::src0,
4493  AMDGPU::OpName::src1,
4494  AMDGPU::OpName::src2 };
4495  for (SrcNum = 0;
4496  SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1;
4497  ++SrcNum);
4498  assert(SrcNum > 0);
4499 
4500  int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4501  unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4502 
4503  if ((OpSel & (1 << SrcNum)) != 0) {
4504  int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
4505  uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
4506  Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL);
4507  }
4508 }
4509 
4510 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
4511  // 1. This operand is input modifiers
4512  return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
4513  // 2. This is not last operand
4514  && Desc.NumOperands > (OpNum + 1)
4515  // 3. Next operand is register class
4516  && Desc.OpInfo[OpNum + 1].RegClass != -1
4517  // 4. Next register is not tied to any other operand
4518  && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
4519 }
4520 
4521 void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands)
4522 {
4523  OptionalImmIndexMap OptionalIdx;
4524  unsigned Opc = Inst.getOpcode();
4525 
4526  unsigned I = 1;
4527  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4528  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4529  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4530  }
4531 
4532  for (unsigned E = Operands.size(); I != E; ++I) {
4533  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4534  if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4535  Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4536  } else if (Op.isInterpSlot() ||
4537  Op.isInterpAttr() ||
4538  Op.isAttrChan()) {
4539  Inst.addOperand(MCOperand::createImm(Op.Imm.Val));
4540  } else if (Op.isImmModifier()) {
4541  OptionalIdx[Op.getImmTy()] = I;
4542  } else {
4543  llvm_unreachable("unhandled operand type");
4544  }
4545  }
4546 
4547  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) {
4548  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh);
4549  }
4550 
4551  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4552  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4553  }
4554 
4555  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
4556  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4557  }
4558 }
4559 
4560 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
4561  OptionalImmIndexMap &OptionalIdx) {
4562  unsigned Opc = Inst.getOpcode();
4563 
4564  unsigned I = 1;
4565  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4566  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4567  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4568  }
4569 
4570  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) {
4571  // This instruction has src modifiers
4572  for (unsigned E = Operands.size(); I != E; ++I) {
4573  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4574  if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4575  Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4576  } else if (Op.isImmModifier()) {
4577  OptionalIdx[Op.getImmTy()] = I;
4578  } else if (Op.isRegOrImm()) {
4579  Op.addRegOrImmOperands(Inst, 1);
4580  } else {
4581  llvm_unreachable("unhandled operand type");
4582  }
4583  }
4584  } else {
4585  // No src modifiers
4586  for (unsigned E = Operands.size(); I != E; ++I) {
4587  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4588  if (Op.isMod()) {
4589  OptionalIdx[Op.getImmTy()] = I;
4590  } else {
4591  Op.addRegOrImmOperands(Inst, 1);
4592  }
4593  }
4594  }
4595 
4596  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4597  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4598  }
4599 
4600  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
4601  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4602  }
4603 
4604  // Special case v_mac_{f16, f32} and v_fmac_f32 (gfx906):
4605  // it has src2 register operand that is tied to dst operand
4606  // we don't allow modifiers for this operand in assembler so src2_modifiers
4607  // should be 0.
4608  if (Opc == AMDGPU::V_MAC_F32_e64_si ||
4609  Opc == AMDGPU::V_MAC_F32_e64_vi ||
4610  Opc == AMDGPU::V_MAC_F16_e64_vi ||
4611  Opc == AMDGPU::V_FMAC_F32_e64_vi) {
4612  auto it = Inst.begin();
4613  std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
4614  it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
4615  ++it;
4616  Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4617  }
4618 }
4619 
4620 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
4621  OptionalImmIndexMap OptionalIdx;
4622  cvtVOP3(Inst, Operands, OptionalIdx);
4623 }
4624 
4625 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst,
4626  const OperandVector &Operands) {
4627  OptionalImmIndexMap OptIdx;
4628  const int Opc = Inst.getOpcode();
4629  const MCInstrDesc &Desc = MII.get(Opc);
4630 
4631  const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0;
4632 
4633  cvtVOP3(Inst, Operands, OptIdx);
4634 
4635  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) {
4636  assert(!IsPacked);
4637  Inst.addOperand(Inst.getOperand(0));
4638  }
4639 
4640  // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
4641  // instruction, and then figure out where to actually put the modifiers
4642 
4643  addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
4644 
4645  int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4646  if (OpSelHiIdx != -1) {
4647  int DefaultVal = IsPacked ? -1 : 0;
4648  addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
4649  DefaultVal);
4650  }
4651 
4652  int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
4653  if (NegLoIdx != -1) {
4654  assert(IsPacked);
4655  addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
4656  addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
4657  }
4658 
4659  const int Ops[] = { AMDGPU::OpName::src0,
4660  AMDGPU::OpName::src1,
4661  AMDGPU::OpName::src2 };
4662  const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
4663  AMDGPU::OpName::src1_modifiers,
4664  AMDGPU::OpName::src2_modifiers };
4665 
4666  int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4667 
4668  unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4669  unsigned OpSelHi = 0;
4670  unsigned NegLo = 0;
4671  unsigned NegHi = 0;
4672 
4673  if (OpSelHiIdx != -1) {
4674  OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
4675  }
4676 
4677  if (NegLoIdx != -1) {
4678  int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
4679  NegLo = Inst.getOperand(NegLoIdx).getImm();
4680  NegHi = Inst.getOperand(NegHiIdx).getImm();
4681  }
4682 
4683  for (int J = 0; J < 3; ++J) {
4684  int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
4685  if (OpIdx == -1)
4686  break;
4687 
4688  uint32_t ModVal = 0;
4689 
4690  if ((OpSel & (1 << J)) != 0)
4691  ModVal |= SISrcMods::OP_SEL_0;
4692 
4693  if ((OpSelHi & (1 << J)) != 0)
4694  ModVal |= SISrcMods::OP_SEL_1;
4695 
4696  if ((NegLo & (1 << J)) != 0)
4697  ModVal |= SISrcMods::NEG;
4698 
4699  if ((NegHi & (1 << J)) != 0)
4700  ModVal |= SISrcMods::NEG_HI;
4701 
4702  int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
4703 
4704  Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
4705  }
4706 }
4707 
4708 //===----------------------------------------------------------------------===//
4709 // dpp
4710 //===----------------------------------------------------------------------===//
4711 
4712 bool AMDGPUOperand::isDPPCtrl() const {
4713  using namespace AMDGPU::DPP;
4714 
4715  bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
4716  if (result) {
4717  int64_t Imm = getImm();
4718  return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) ||
4719  (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
4720  (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
4721  (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
4722  (Imm == DppCtrl::WAVE_SHL1) ||
4723  (Imm == DppCtrl::WAVE_ROL1) ||
4724  (Imm == DppCtrl::WAVE_SHR1) ||
4725  (Imm == DppCtrl::WAVE_ROR1) ||
4726  (Imm == DppCtrl::ROW_MIRROR) ||
4727  (Imm == DppCtrl::ROW_HALF_MIRROR) ||
4728  (Imm == DppCtrl::BCAST15) ||
4729  (Imm == DppCtrl::BCAST31);
4730  }
4731  return false;
4732 }
4733 
4734 bool AMDGPUOperand::isGPRIdxMode() const {
4735  return isImm() && isUInt<4>(getImm());
4736 }
4737 
4738 bool AMDGPUOperand::isS16Imm() const {
4739  return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
4740 }
4741 
4742 bool AMDGPUOperand::isU16Imm() const {
4743  return isImm() && isUInt<16>(getImm());
4744 }
4745 
4747 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
4748  using namespace AMDGPU::DPP;
4749 
4750  SMLoc S = Parser.getTok().getLoc();
4751  StringRef Prefix;
4752  int64_t Int;
4753 
4754  if (getLexer().getKind() == AsmToken::Identifier) {
4755  Prefix = Parser.getTok().getString();
4756  } else {
4757  return MatchOperand_NoMatch;
4758  }
4759 
4760  if (Prefix == "row_mirror") {
4761  Int = DppCtrl::ROW_MIRROR;
4762  Parser.Lex();
4763  } else if (Prefix == "row_half_mirror") {
4765  Parser.Lex();
4766  } else {
4767  // Check to prevent parseDPPCtrlOps from eating invalid tokens
4768  if (Prefix != "quad_perm"
4769  && Prefix != "row_shl"
4770  && Prefix != "row_shr"
4771  && Prefix != "row_ror"
4772  && Prefix != "wave_shl"
4773  && Prefix != "wave_rol"
4774  && Prefix != "wave_shr"
4775  && Prefix != "wave_ror"
4776  && Prefix != "row_bcast") {
4777  return MatchOperand_NoMatch;
4778  }
4779 
4780  Parser.Lex();
4781  if (getLexer().isNot(AsmToken::Colon))
4782  return MatchOperand_ParseFail;
4783 
4784  if (Prefix == "quad_perm") {
4785  // quad_perm:[%d,%d,%d,%d]
4786  Parser.Lex();
4787  if (getLexer().isNot(AsmToken::LBrac))
4788  return MatchOperand_ParseFail;
4789  Parser.Lex();
4790 
4791  if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
4792  return MatchOperand_ParseFail;
4793 
4794  for (int i = 0; i < 3; ++i) {
4795  if (getLexer().isNot(AsmToken::Comma))
4796  return MatchOperand_ParseFail;
4797  Parser.Lex();
4798 
4799  int64_t Temp;
4800  if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
4801  return MatchOperand_ParseFail;
4802  const int shift = i*2 + 2;
4803  Int += (Temp << shift);
4804  }
4805 
4806  if (getLexer().isNot(AsmToken::RBrac))
4807  return MatchOperand_ParseFail;
4808  Parser.Lex();
4809  } else {
4810  // sel:%d
4811  Parser.Lex();
4812  if (getParser().parseAbsoluteExpression(Int))
4813  return MatchOperand_ParseFail;
4814 
4815  if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
4816  Int |= DppCtrl::ROW_SHL0;
4817  } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
4818  Int |= DppCtrl::ROW_SHR0;
4819  } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
4820  Int |= DppCtrl::ROW_ROR0;
4821  } else if (Prefix == "wave_shl" && 1 == Int) {
4822  Int = DppCtrl::WAVE_SHL1;
4823  } else if (Prefix == "wave_rol" && 1 == Int) {
4824  Int = DppCtrl::WAVE_ROL1;
4825  } else if (Prefix == "wave_shr" && 1 == Int) {
4826  Int = DppCtrl::WAVE_SHR1;
4827  } else if (Prefix == "wave_ror" && 1 == Int) {
4828  Int = DppCtrl::WAVE_ROR1;
4829  } else if (Prefix == "row_bcast") {
4830  if (Int == 15) {
4831  Int = DppCtrl::BCAST15;
4832  } else if (Int == 31) {
4833  Int = DppCtrl::BCAST31;
4834  } else {
4835  return MatchOperand_ParseFail;
4836  }
4837  } else {
4838  return MatchOperand_ParseFail;
4839  }
4840  }
4841  }
4842 
4843  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
4844  return MatchOperand_Success;
4845 }
4846 
4847 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
4848  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
4849 }
4850 
4851 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
4852  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
4853 }
4854 
4855 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
4856  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
4857 }
4858 
4859 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
4860  OptionalImmIndexMap OptionalIdx;
4861 
4862  unsigned I = 1;
4863  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4864  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4865  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4866  }
4867 
4868  // All DPP instructions with at least one source operand have a fake "old"
4869  // source at the beginning that's tied to the dst operand. Handle it here.
4870  if (Desc.getNumOperands() >= 2)
4871  Inst.addOperand(Inst.getOperand(0));
4872 
4873  for (unsigned E = Operands.size(); I != E; ++I) {
4874  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4875  // Add the register arguments
4876  if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4877  // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
4878  // Skip it.
4879  continue;
4880  } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4881  Op.addRegWithFPInputModsOperands(Inst, 2);
4882  } else if (Op.isDPPCtrl()) {
4883  Op.addImmOperands(Inst, 1);
4884  } else if (Op.isImm()) {
4885  // Handle optional arguments
4886  OptionalIdx[Op.getImmTy()] = I;
4887  } else {
4888  llvm_unreachable("Invalid operand type");
4889  }
4890  }
4891 
4892  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
4893  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
4894  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
4895 }
4896 
4897 //===----------------------------------------------------------------------===//
4898 // sdwa
4899 //===----------------------------------------------------------------------===//
4900 
4902 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
4903  AMDGPUOperand::ImmTy Type) {
4904  using namespace llvm::AMDGPU::SDWA;
4905 
4906  SMLoc S = Parser.getTok().getLoc();
4907  StringRef Value;
4909 
4910  res = parseStringWithPrefix(Prefix, Value);
4911  if (res != MatchOperand_Success) {
4912  return res;
4913  }
4914 
4915  int64_t Int;
4916  Int = StringSwitch<int64_t>(Value)
4917  .Case("BYTE_0", SdwaSel::BYTE_0)
4918  .Case("BYTE_1", SdwaSel::BYTE_1)
4919  .Case("BYTE_2", SdwaSel::BYTE_2)
4920  .Case("BYTE_3", SdwaSel::BYTE_3)
4921  .Case("WORD_0", SdwaSel::WORD_0)
4922  .Case("WORD_1", SdwaSel::WORD_1)
4923  .Case("DWORD", SdwaSel::DWORD)
4924  .Default(0xffffffff);
4925  Parser.Lex(); // eat last token
4926 
4927  if (Int == 0xffffffff) {
4928  return MatchOperand_ParseFail;
4929  }
4930 
4931  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
4932  return MatchOperand_Success;
4933 }
4934 
4936 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
4937  using namespace llvm::AMDGPU::SDWA;
4938 
4939  SMLoc S = Parser.getTok().getLoc();
4940  StringRef Value;
4942 
4943  res = parseStringWithPrefix("dst_unused", Value);
4944  if (res != MatchOperand_Success) {
4945  return res;
4946  }
4947 
4948  int64_t Int;
4949  Int = StringSwitch<int64_t>(Value)
4950  .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
4951  .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
4952  .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
4953  .Default(0xffffffff);
4954  Parser.Lex(); // eat last token
4955 
4956  if (Int == 0xffffffff) {
4957  return MatchOperand_ParseFail;
4958  }
4959 
4960  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
4961  return MatchOperand_Success;
4962 }
4963 
4964 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
4965  cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
4966 }
4967 
4968 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
4969  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
4970 }
4971 
4972 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
4973  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
4974 }
4975 
4976 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
4977  cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
4978 }
4979 
4980 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
4981  uint64_t BasicInstType, bool skipVcc) {
4982  using namespace llvm::AMDGPU::SDWA;
4983 
4984  OptionalImmIndexMap OptionalIdx;
4985  bool skippedVcc = false;
4986 
4987  unsigned I = 1;
4988  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4989  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4990  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4991  }
4992 
4993  for (unsigned E = Operands.size(); I != E; ++I) {
4994  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4995  if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4996  // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
4997  // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
4998  // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
4999  // Skip VCC only if we didn't skip it on previous iteration.
5000  if (BasicInstType == SIInstrFlags::VOP2 &&
5001  (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
5002  skippedVcc = true;
5003  continue;
5004  } else if (BasicInstType == SIInstrFlags::VOPC &&
5005  Inst.getNumOperands() == 0) {
5006  skippedVcc = true;
5007  continue;
5008  }
5009  }
5010  if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
5011  Op.addRegOrImmWithInputModsOperands(Inst, 2);
5012  } else if (Op.isImm()) {
5013  // Handle optional arguments
5014  OptionalIdx[Op.getImmTy()] = I;
5015  } else {
5016  llvm_unreachable("Invalid operand type");
5017  }
5018  skippedVcc = false;
5019  }
5020 
5021  if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
5022  Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
5023  // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
5024  switch (BasicInstType) {
5025  case SIInstrFlags::VOP1:
5026  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
5027  if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
5028  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
5029  }
5030  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
5031  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
5032  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
5033  break;
5034 
5035  case SIInstrFlags::VOP2:
5036  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
5037  if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
5038  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
5039  }
5040  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
5041  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
5042  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
5043  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
5044  break;
5045 
5046  case SIInstrFlags::VOPC:
5047  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
5048  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
5049  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
5050  break;
5051 
5052  default:
5053  llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
5054  }
5055  }
5056 
5057  // special case v_mac_{f16, f32}:
5058  // it has src2 register operand that is tied to dst operand
5059  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
5060  Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
5061  auto it = Inst.begin();
5062  std::advance(
5063  it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
5064  Inst.insert(it, Inst.getOperand(0)); // src2 = dst
5065  }
5066 }
5067 
5068 /// Force static initialization.
5072 }
5073 
5074 #define GET_REGISTER_MATCHER
5075 #define GET_MATCHER_IMPLEMENTATION
5076 #define GET_MNEMONIC_SPELL_CHECKER
5077 #include "AMDGPUGenAsmMatcher.inc"
5078 
5079 // This fuction should be defined after auto-generated include so that we have
5080 // MatchClassKind enum defined
5081 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
5082  unsigned Kind) {
5083  // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
5084  // But MatchInstructionImpl() expects to meet token and fails to validate
5085  // operand. This method checks if we are given immediate operand but expect to
5086  // get corresponding token.
5087  AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
5088  switch (Kind) {
5089  case MCK_addr64:
5090  return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
5091  case MCK_gds:
5092  return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
5093  case MCK_lds:
5094  return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
5095  case MCK_glc:
5096  return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
5097  case MCK_d16:
5098  return Operand.isD16() ? Match_Success : Match_InvalidOperand;
5099  case MCK_idxen:
5100  return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
5101  case MCK_offen:
5102  return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
5103  case MCK_SSrcB32:
5104  // When operands have expression values, they will return true for isToken,
5105  // because it is not possible to distinguish between a token and an
5106  // expression at parse time. MatchInstructionImpl() will always try to
5107  // match an operand as a token, when isToken returns true, and when the
5108  // name of the expression is not a valid token, the match will fail,
5109  // so we need to handle it here.
5110  return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
5111  case MCK_SSrcF32:
5112  return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
5113  case MCK_SoppBrTarget:
5114  return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
5115  case MCK_VReg32OrOff:
5116  return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
5117  case MCK_InterpSlot:
5118  return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
5119  case MCK_Attr:
5120  return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
5121  case MCK_AttrChan:
5122  return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
5123  default:
5124  return Match_InvalidOperand;
5125  }
5126 }
static bool isReg(const MCInst &MI, unsigned OpNo)
unsigned getNumImplicitUses() const
Return the number of implicit uses this instruction has.
Definition: MCInstrDesc.h:516
constexpr bool isUInt< 32 >(uint64_t x)
Definition: MathExtras.h:341
Represents a range in source code.
Definition: SMLoc.h:49
void push_back(const T &Elt)
Definition: SmallVector.h:213
iterator begin()
Definition: MCInst.h:194
bool isImm() const
Definition: MCInst.h:59
unsigned mc2PseudoReg(unsigned Reg)
Convert hardware register Reg to a pseudo register.
Target & getTheGCNTarget()
The target for GCN GPUs.
bool hasPackedD16(const MCSubtargetInfo &STI)
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:111
static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum)
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1547
static const fltSemantics * getOpFltSemantics(uint8_t OperandType)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:321
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:137
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition: MathExtras.h:281
Target & getTheAMDGPUTarget()
The target which supports all AMD GPUs.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:161
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
unsigned Reg
bool isReg() const
Definition: MCInst.h:58
static unsigned getSpecialRegForName(StringRef RegName)
static InstrUID decode(OpcodeType type, InstructionContext insnContext, uint8_t opcode, uint8_t modRM)
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:504
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:298
unsigned const TargetRegisterInfo * TRI
F(f)
bool isInlinableLiteralV216(int32_t Literal, bool HasInv2Pi)
void changeSign()
Definition: APFloat.h:1050
static void addOptionalImmOperand(MCInst &Inst, const OperandVector &Operands, AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx, AMDGPUOperand::ImmTy ImmT, int64_t Default=0)
bool mayLoad() const
Return true if this instruction could possibly read memory.
Definition: MCInstrDesc.h:388
static bool ConvertOmodDiv(int64_t &Div)
bool parseAmdKernelCodeField(StringRef ID, MCAsmParser &Parser, amd_kernel_code_t &C, raw_ostream &Err)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
static LLVM_READNONE unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask, const unsigned XorMask)
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo=false)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:892
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_back(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with only the last N elements remaining.
Definition: StringRef.h:619
bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:279
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
bool isRegIntersect(unsigned Reg0, unsigned Reg1, const MCRegisterInfo *TRI)
Is there any intersection between registers.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:208
RegisterKind
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
AMD Kernel Code Object (amd_kernel_code_t).
unsigned getRegOperandSize(const MCRegisterInfo *MRI, const MCInstrDesc &Desc, unsigned OpNo)
Get size of register operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:22
static int getRegClass(RegisterKind Is, unsigned RegWidth)
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:166
unsigned encodeLgkmcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt, unsigned Lgkmcnt)
unsigned decodeLgkmcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
Definition: StringSwitch.h:203
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:156
unsigned encodeExpcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt, unsigned Expcnt)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand...
This file implements a class to represent arbitrary precision integral constant values and operations...
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:65
unsigned getSizeInBits() const
unsigned getWaitcntBitMask(const IsaInfo::IsaVersion &Version)
std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \\\)
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:79
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:267
static bool encodeCnt(const AMDGPU::IsaInfo::IsaVersion ISA, int64_t &IntVal, int64_t CntVal, bool Saturate, unsigned(*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned), unsigned(*decode)(const IsaInfo::IsaVersion &Version, unsigned))
RegisterMCAsmParser - Helper template for registering a target specific assembly parser, for use in the target machine initialization function.
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:28
static const fltSemantics & IEEEdouble() LLVM_READNONE
Definition: APFloat.cpp:123
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
MCRegisterClass - Base class of TargetRegisterClass.
iterator insert(iterator I, const MCOperand &Op)
Definition: MCInst.h:199
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
unsigned short NumOperands
Definition: MCInstrDesc.h:164
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this floating-point operand?
int64_t getImm() const
Definition: MCInst.h:76
void setImm(int64_t Val)
Definition: MCInst.h:81
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
Streaming machine code generation interface.
Definition: MCStreamer.h:183
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
bool isSI(const MCSubtargetInfo &STI)
constexpr bool isUInt< 8 >(uint64_t x)
Definition: MathExtras.h:335
unsigned const MachineRegisterInfo * MRI
constexpr char AssemblerDirectiveBegin[]
HSA metadata beginning assembler directive.
Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
PowerPC Reduce CR logical Operation
bool hasMIMG_R128(const MCSubtargetInfo &STI)
unsigned getScalarSizeInBits() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const char *const IdSymbolic[]
MCRegAliasIterator enumerates all registers aliasing Reg.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:426
This file declares a class to represent arbitrary precision floating point values and provide a varie...
Instruction set architecture version.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
unsigned getNumOperands() const
Definition: MCInst.h:184
static const OptionalOperand AMDGPUOptionalOperandTable[]
SmallVectorImpl< MCOperand >::iterator iterator
Definition: MCInst.h:188
constexpr char AssemblerDirectiveEnd[]
HSA metadata ending assembler directive.
constexpr char AssemblerDirective[]
PAL metadata assembler directive.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:390
void setLoc(SMLoc loc)
Definition: MCInst.h:179
std::string & str()
Flushes the stream contents to the target string and returns the string&#39;s reference.
Definition: raw_ostream.h:493
void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, const FeatureBitset &Features)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Operands with register or inline constant.
Definition: SIDefines.h:121
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the last N elements dropped.
Definition: StringRef.h:654
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:497
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the first N elements dropped.
Definition: StringRef.h:645
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set.
Definition: MCInstrDesc.h:185
static bool ConvertBoundCtrl(int64_t &BoundCtrl)
unsigned decodeVmcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt)
void setOpcode(unsigned Op)
Definition: MCInst.h:173
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:512
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1032
LLVM_READONLY int getMUBUFNoLdsInst(uint16_t Opcode)
constexpr bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:301
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition: Error.h:148
const MCSymbol & getSymbol() const
Definition: MCExpr.h:334
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:182
Promote Memory to Register
Definition: Mem2Reg.cpp:110
static bool ConvertOmodMul(int64_t &Mul)
StringRef str()
Return a StringRef for the vector contents.
Definition: raw_ostream.h:529
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:223
unsigned encodeVmcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt, unsigned Vmcnt)
double BitsToDouble(uint64_t Bits)
This function takes a 64-bit integer and returns the bit equivalent double.
Definition: MathExtras.h:565
void LLVMInitializeAMDGPUAsmParser()
Force static initialization.
bool is(TokenKind K) const
Definition: MCAsmMacro.h:83
Class for arbitrary precision integers.
Definition: APInt.h:69
SMLoc getLoc() const
Definition: MCInst.h:180
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const char *const OpSysSymbolic[]
Base class for user error types.
Definition: Error.h:331
bool mayStore() const
Return true if this instruction could possibly modify memory.
Definition: MCInstrDesc.h:394
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:70
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:169
static std::string AMDGPUMnemonicSpellCheck(StringRef S, uint64_t FBS, unsigned VariantID=0)
bool isCI(const MCSubtargetInfo &STI)
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:37
bool isGFX9(const MCSubtargetInfo &STI)
const char *const OpGsSymbolic[]
Provides AMDGPU specific target descriptions.
Interface definition for SIInstrInfo.
static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT)
bool isVI(const MCSubtargetInfo &STI)
size_t size() const
Definition: MCInst.h:193
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:73
unsigned decodeExpcnt(const IsaInfo::IsaVersion &Version, unsigned Waitcnt)
bool hasXNACK(const MCSubtargetInfo &STI)
#define LLVM_READNONE
Definition: Compiler.h:161
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
constexpr bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:338
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Definition: APInt.h:2023
Operands with register or 32-bit immediate.
Definition: SIDefines.h:113
void setReg(unsigned Reg)
Set the register number.
Definition: MCInst.h:71
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:203
const unsigned Kind
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Can this operand also contain immediate values?
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:477
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM Value Representation.
Definition: Value.h:73
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:172
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg...
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
static const fltSemantics * getFltSemantics(unsigned Size)
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
AMDGPU metadata definitions and in-memory representations.
APInt bitcastToAPInt() const
Definition: APFloat.h:1094
bool isSGPR(unsigned Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
Represents a location in source code.
Definition: SMLoc.h:24
unsigned getOpcode() const
Definition: MCInst.h:174
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:385
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
const uint64_t Version
Definition: InstrProf.h:895
IsaVersion getIsaVersion(const FeatureBitset &Features)
std::vector< uint32_t > Metadata
PAL metadata represented as a vector.
void streamIsaVersion(const MCSubtargetInfo *STI, raw_ostream &Stream)
Streams isa version string for given subtarget STI into Stream.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
const MCPhysReg * ImplicitUses
Definition: MCInstrDesc.h:170