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