LLVM  4.0.0
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 "AMDKernelCodeT.h"
13 #include "SIDefines.h"
14 #include "Utils/AMDGPUBaseInfo.h"
16 #include "Utils/AMDGPUAsmUtils.h"
17 #include "llvm/ADT/APFloat.h"
18 #include "llvm/ADT/APInt.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCExpr.h"
29 #include "llvm/MC/MCInst.h"
30 #include "llvm/MC/MCInstrDesc.h"
31 #include "llvm/MC/MCInstrInfo.h"
37 #include "llvm/MC/MCRegisterInfo.h"
38 #include "llvm/MC/MCStreamer.h"
40 #include "llvm/MC/MCSymbol.h"
41 #include "llvm/Support/Casting.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Support/ELF.h"
47 #include "llvm/Support/SMLoc.h"
51 #include <algorithm>
52 #include <cassert>
53 #include <cstdint>
54 #include <cstring>
55 #include <iterator>
56 #include <map>
57 #include <memory>
58 #include <string>
59 #include <vector>
60 
61 using namespace llvm;
62 using namespace llvm::AMDGPU;
63 
64 namespace {
65 
66 class AMDGPUAsmParser;
67 
68 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
69 
70 //===----------------------------------------------------------------------===//
71 // Operand
72 //===----------------------------------------------------------------------===//
73 
74 class AMDGPUOperand : public MCParsedAsmOperand {
75  enum KindTy {
76  Token,
77  Immediate,
78  Register,
79  Expression
80  } Kind;
81 
82  SMLoc StartLoc, EndLoc;
83  const AMDGPUAsmParser *AsmParser;
84 
85 public:
86  AMDGPUOperand(enum KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
87  : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
88 
89  typedef std::unique_ptr<AMDGPUOperand> Ptr;
90 
91  struct Modifiers {
92  bool Abs = false;
93  bool Neg = false;
94  bool Sext = false;
95 
96  bool hasFPModifiers() const { return Abs || Neg; }
97  bool hasIntModifiers() const { return Sext; }
98  bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
99 
100  int64_t getFPModifiersOperand() const {
101  int64_t Operand = 0;
102  Operand |= Abs ? SISrcMods::ABS : 0;
103  Operand |= Neg ? SISrcMods::NEG : 0;
104  return Operand;
105  }
106 
107  int64_t getIntModifiersOperand() const {
108  int64_t Operand = 0;
109  Operand |= Sext ? SISrcMods::SEXT : 0;
110  return Operand;
111  }
112 
113  int64_t getModifiersOperand() const {
114  assert(!(hasFPModifiers() && hasIntModifiers())
115  && "fp and int modifiers should not be used simultaneously");
116  if (hasFPModifiers()) {
117  return getFPModifiersOperand();
118  } else if (hasIntModifiers()) {
119  return getIntModifiersOperand();
120  } else {
121  return 0;
122  }
123  }
124 
125  friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
126  };
127 
128  enum ImmTy {
129  ImmTyNone,
130  ImmTyGDS,
131  ImmTyOffen,
132  ImmTyIdxen,
133  ImmTyAddr64,
134  ImmTyOffset,
135  ImmTyOffset0,
136  ImmTyOffset1,
137  ImmTyGLC,
138  ImmTySLC,
139  ImmTyTFE,
140  ImmTyClampSI,
141  ImmTyOModSI,
142  ImmTyDppCtrl,
143  ImmTyDppRowMask,
144  ImmTyDppBankMask,
145  ImmTyDppBoundCtrl,
146  ImmTySdwaDstSel,
147  ImmTySdwaSrc0Sel,
148  ImmTySdwaSrc1Sel,
149  ImmTySdwaDstUnused,
150  ImmTyDMask,
151  ImmTyUNorm,
152  ImmTyDA,
153  ImmTyR128,
154  ImmTyLWE,
155  ImmTyExpTgt,
156  ImmTyExpCompr,
157  ImmTyExpVM,
158  ImmTyHwreg,
159  ImmTyOff,
160  ImmTySendMsg,
161  ImmTyInterpSlot,
162  ImmTyInterpAttr,
163  ImmTyAttrChan
164  };
165 
166  struct TokOp {
167  const char *Data;
168  unsigned Length;
169  };
170 
171  struct ImmOp {
172  int64_t Val;
173  ImmTy Type;
174  bool IsFPImm;
175  Modifiers Mods;
176  };
177 
178  struct RegOp {
179  unsigned RegNo;
180  bool IsForcedVOP3;
181  Modifiers Mods;
182  };
183 
184  union {
185  TokOp Tok;
186  ImmOp Imm;
187  RegOp Reg;
188  const MCExpr *Expr;
189  };
190 
191  bool isToken() const override {
192  if (Kind == Token)
193  return true;
194 
195  if (Kind != Expression || !Expr)
196  return false;
197 
198  // When parsing operands, we can't always tell if something was meant to be
199  // a token, like 'gds', or an expression that references a global variable.
200  // In this case, we assume the string is an expression, and if we need to
201  // interpret is a token, then we treat the symbol name as the token.
202  return isa<MCSymbolRefExpr>(Expr);
203  }
204 
205  bool isImm() const override {
206  return Kind == Immediate;
207  }
208 
209  bool isInlinableImm(MVT type) const;
210  bool isLiteralImm(MVT type) const;
211 
212  bool isRegKind() const {
213  return Kind == Register;
214  }
215 
216  bool isReg() const override {
217  return isRegKind() && !hasModifiers();
218  }
219 
220  bool isRegOrImmWithInputMods(MVT type) const {
221  return isRegKind() || isInlinableImm(type);
222  }
223 
224  bool isRegOrImmWithInt16InputMods() const {
226  }
227 
228  bool isRegOrImmWithInt32InputMods() const {
230  }
231 
232  bool isRegOrImmWithInt64InputMods() const {
234  }
235 
236  bool isRegOrImmWithFP16InputMods() const {
238  }
239 
240  bool isRegOrImmWithFP32InputMods() const {
242  }
243 
244  bool isRegOrImmWithFP64InputMods() const {
246  }
247 
248  bool isVReg() const {
249  return isRegClass(AMDGPU::VGPR_32RegClassID) ||
250  isRegClass(AMDGPU::VReg_64RegClassID) ||
251  isRegClass(AMDGPU::VReg_96RegClassID) ||
252  isRegClass(AMDGPU::VReg_128RegClassID) ||
253  isRegClass(AMDGPU::VReg_256RegClassID) ||
254  isRegClass(AMDGPU::VReg_512RegClassID);
255  }
256 
257  bool isVReg32OrOff() const {
258  return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
259  }
260 
261  bool isImmTy(ImmTy ImmT) const {
262  return isImm() && Imm.Type == ImmT;
263  }
264 
265  bool isImmModifier() const {
266  return isImm() && Imm.Type != ImmTyNone;
267  }
268 
269  bool isClampSI() const { return isImmTy(ImmTyClampSI); }
270  bool isOModSI() const { return isImmTy(ImmTyOModSI); }
271  bool isDMask() const { return isImmTy(ImmTyDMask); }
272  bool isUNorm() const { return isImmTy(ImmTyUNorm); }
273  bool isDA() const { return isImmTy(ImmTyDA); }
274  bool isR128() const { return isImmTy(ImmTyUNorm); }
275  bool isLWE() const { return isImmTy(ImmTyLWE); }
276  bool isOff() const { return isImmTy(ImmTyOff); }
277  bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
278  bool isExpVM() const { return isImmTy(ImmTyExpVM); }
279  bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
280  bool isOffen() const { return isImmTy(ImmTyOffen); }
281  bool isIdxen() const { return isImmTy(ImmTyIdxen); }
282  bool isAddr64() const { return isImmTy(ImmTyAddr64); }
283  bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
284  bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
285  bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
286  bool isGDS() const { return isImmTy(ImmTyGDS); }
287  bool isGLC() const { return isImmTy(ImmTyGLC); }
288  bool isSLC() const { return isImmTy(ImmTySLC); }
289  bool isTFE() const { return isImmTy(ImmTyTFE); }
290  bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
291  bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
292  bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
293  bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
294  bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
295  bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
296  bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
297  bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
298  bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
299  bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
300 
301  bool isMod() const {
302  return isClampSI() || isOModSI();
303  }
304 
305  bool isRegOrImm() const {
306  return isReg() || isImm();
307  }
308 
309  bool isRegClass(unsigned RCID) const;
310 
311  bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
312  return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
313  }
314 
315  bool isSCSrcB16() const {
316  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
317  }
318 
319  bool isSCSrcB32() const {
320  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
321  }
322 
323  bool isSCSrcB64() const {
324  return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
325  }
326 
327  bool isSCSrcF16() const {
328  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
329  }
330 
331  bool isSCSrcF32() const {
332  return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
333  }
334 
335  bool isSCSrcF64() const {
336  return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
337  }
338 
339  bool isSSrcB32() const {
340  return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
341  }
342 
343  bool isSSrcB16() const {
344  return isSCSrcB16() || isLiteralImm(MVT::i16);
345  }
346 
347  bool isSSrcB64() const {
348  // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
349  // See isVSrc64().
350  return isSCSrcB64() || isLiteralImm(MVT::i64);
351  }
352 
353  bool isSSrcF32() const {
354  return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
355  }
356 
357  bool isSSrcF64() const {
358  return isSCSrcB64() || isLiteralImm(MVT::f64);
359  }
360 
361  bool isSSrcF16() const {
362  return isSCSrcB16() || isLiteralImm(MVT::f16);
363  }
364 
365  bool isVCSrcB32() const {
366  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
367  }
368 
369  bool isVCSrcB64() const {
370  return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
371  }
372 
373  bool isVCSrcB16() const {
374  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
375  }
376 
377  bool isVCSrcF32() const {
378  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
379  }
380 
381  bool isVCSrcF64() const {
382  return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
383  }
384 
385  bool isVCSrcF16() const {
386  return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
387  }
388 
389  bool isVSrcB32() const {
390  return isVCSrcF32() || isLiteralImm(MVT::i32);
391  }
392 
393  bool isVSrcB64() const {
394  return isVCSrcF64() || isLiteralImm(MVT::i64);
395  }
396 
397  bool isVSrcB16() const {
398  return isVCSrcF16() || isLiteralImm(MVT::i16);
399  }
400 
401  bool isVSrcF32() const {
402  return isVCSrcF32() || isLiteralImm(MVT::f32);
403  }
404 
405  bool isVSrcF64() const {
406  return isVCSrcF64() || isLiteralImm(MVT::f64);
407  }
408 
409  bool isVSrcF16() const {
410  return isVCSrcF16() || isLiteralImm(MVT::f16);
411  }
412 
413  bool isKImmFP32() const {
414  return isLiteralImm(MVT::f32);
415  }
416 
417  bool isKImmFP16() const {
418  return isLiteralImm(MVT::f16);
419  }
420 
421  bool isMem() const override {
422  return false;
423  }
424 
425  bool isExpr() const {
426  return Kind == Expression;
427  }
428 
429  bool isSoppBrTarget() const {
430  return isExpr() || isImm();
431  }
432 
433  bool isSWaitCnt() const;
434  bool isHwreg() const;
435  bool isSendMsg() const;
436  bool isSMRDOffset8() const;
437  bool isSMRDOffset20() const;
438  bool isSMRDLiteralOffset() const;
439  bool isDPPCtrl() const;
440  bool isGPRIdxMode() const;
441 
442  StringRef getExpressionAsToken() const {
443  assert(isExpr());
444  const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
445  return S->getSymbol().getName();
446  }
447 
448  StringRef getToken() const {
449  assert(isToken());
450 
451  if (Kind == Expression)
452  return getExpressionAsToken();
453 
454  return StringRef(Tok.Data, Tok.Length);
455  }
456 
457  int64_t getImm() const {
458  assert(isImm());
459  return Imm.Val;
460  }
461 
462  enum ImmTy getImmTy() const {
463  assert(isImm());
464  return Imm.Type;
465  }
466 
467  unsigned getReg() const override {
468  return Reg.RegNo;
469  }
470 
471  SMLoc getStartLoc() const override {
472  return StartLoc;
473  }
474 
475  SMLoc getEndLoc() const override {
476  return EndLoc;
477  }
478 
479  Modifiers getModifiers() const {
480  assert(isRegKind() || isImmTy(ImmTyNone));
481  return isRegKind() ? Reg.Mods : Imm.Mods;
482  }
483 
484  void setModifiers(Modifiers Mods) {
485  assert(isRegKind() || isImmTy(ImmTyNone));
486  if (isRegKind())
487  Reg.Mods = Mods;
488  else
489  Imm.Mods = Mods;
490  }
491 
492  bool hasModifiers() const {
493  return getModifiers().hasModifiers();
494  }
495 
496  bool hasFPModifiers() const {
497  return getModifiers().hasFPModifiers();
498  }
499 
500  bool hasIntModifiers() const {
501  return getModifiers().hasIntModifiers();
502  }
503 
504  void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
505 
506  void addLiteralImmOperand(MCInst &Inst, int64_t Val) const;
507 
508  template <unsigned Bitwidth>
509  void addKImmFPOperands(MCInst &Inst, unsigned N) const;
510 
511  void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
512  addKImmFPOperands<16>(Inst, N);
513  }
514 
515  void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
516  addKImmFPOperands<32>(Inst, N);
517  }
518 
519  void addRegOperands(MCInst &Inst, unsigned N) const;
520 
521  void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
522  if (isRegKind())
523  addRegOperands(Inst, N);
524  else if (isExpr())
525  Inst.addOperand(MCOperand::createExpr(Expr));
526  else
527  addImmOperands(Inst, N);
528  }
529 
530  void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
531  Modifiers Mods = getModifiers();
532  Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
533  if (isRegKind()) {
534  addRegOperands(Inst, N);
535  } else {
536  addImmOperands(Inst, N, false);
537  }
538  }
539 
540  void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
541  assert(!hasIntModifiers());
542  addRegOrImmWithInputModsOperands(Inst, N);
543  }
544 
545  void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
546  assert(!hasFPModifiers());
547  addRegOrImmWithInputModsOperands(Inst, N);
548  }
549 
550  void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
551  Modifiers Mods = getModifiers();
552  Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
553  assert(isRegKind());
554  addRegOperands(Inst, N);
555  }
556 
557  void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
558  assert(!hasIntModifiers());
559  addRegWithInputModsOperands(Inst, N);
560  }
561 
562  void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
563  assert(!hasFPModifiers());
564  addRegWithInputModsOperands(Inst, N);
565  }
566 
567  void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
568  if (isImm())
569  addImmOperands(Inst, N);
570  else {
571  assert(isExpr());
572  Inst.addOperand(MCOperand::createExpr(Expr));
573  }
574  }
575 
576  static void printImmTy(raw_ostream& OS, ImmTy Type) {
577  switch (Type) {
578  case ImmTyNone: OS << "None"; break;
579  case ImmTyGDS: OS << "GDS"; break;
580  case ImmTyOffen: OS << "Offen"; break;
581  case ImmTyIdxen: OS << "Idxen"; break;
582  case ImmTyAddr64: OS << "Addr64"; break;
583  case ImmTyOffset: OS << "Offset"; break;
584  case ImmTyOffset0: OS << "Offset0"; break;
585  case ImmTyOffset1: OS << "Offset1"; break;
586  case ImmTyGLC: OS << "GLC"; break;
587  case ImmTySLC: OS << "SLC"; break;
588  case ImmTyTFE: OS << "TFE"; break;
589  case ImmTyClampSI: OS << "ClampSI"; break;
590  case ImmTyOModSI: OS << "OModSI"; break;
591  case ImmTyDppCtrl: OS << "DppCtrl"; break;
592  case ImmTyDppRowMask: OS << "DppRowMask"; break;
593  case ImmTyDppBankMask: OS << "DppBankMask"; break;
594  case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
595  case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
596  case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
597  case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
598  case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
599  case ImmTyDMask: OS << "DMask"; break;
600  case ImmTyUNorm: OS << "UNorm"; break;
601  case ImmTyDA: OS << "DA"; break;
602  case ImmTyR128: OS << "R128"; break;
603  case ImmTyLWE: OS << "LWE"; break;
604  case ImmTyOff: OS << "Off"; break;
605  case ImmTyExpTgt: OS << "ExpTgt"; break;
606  case ImmTyExpCompr: OS << "ExpCompr"; break;
607  case ImmTyExpVM: OS << "ExpVM"; break;
608  case ImmTyHwreg: OS << "Hwreg"; break;
609  case ImmTySendMsg: OS << "SendMsg"; break;
610  case ImmTyInterpSlot: OS << "InterpSlot"; break;
611  case ImmTyInterpAttr: OS << "InterpAttr"; break;
612  case ImmTyAttrChan: OS << "AttrChan"; break;
613  }
614  }
615 
616  void print(raw_ostream &OS) const override {
617  switch (Kind) {
618  case Register:
619  OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
620  break;
621  case Immediate:
622  OS << '<' << getImm();
623  if (getImmTy() != ImmTyNone) {
624  OS << " type: "; printImmTy(OS, getImmTy());
625  }
626  OS << " mods: " << Imm.Mods << '>';
627  break;
628  case Token:
629  OS << '\'' << getToken() << '\'';
630  break;
631  case Expression:
632  OS << "<expr " << *Expr << '>';
633  break;
634  }
635  }
636 
637  static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
638  int64_t Val, SMLoc Loc,
639  enum ImmTy Type = ImmTyNone,
640  bool IsFPImm = false) {
641  auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
642  Op->Imm.Val = Val;
643  Op->Imm.IsFPImm = IsFPImm;
644  Op->Imm.Type = Type;
645  Op->Imm.Mods = Modifiers();
646  Op->StartLoc = Loc;
647  Op->EndLoc = Loc;
648  return Op;
649  }
650 
651  static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
652  StringRef Str, SMLoc Loc,
653  bool HasExplicitEncodingSize = true) {
654  auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
655  Res->Tok.Data = Str.data();
656  Res->Tok.Length = Str.size();
657  Res->StartLoc = Loc;
658  Res->EndLoc = Loc;
659  return Res;
660  }
661 
662  static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
663  unsigned RegNo, SMLoc S,
664  SMLoc E,
665  bool ForceVOP3) {
666  auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
667  Op->Reg.RegNo = RegNo;
668  Op->Reg.Mods = Modifiers();
669  Op->Reg.IsForcedVOP3 = ForceVOP3;
670  Op->StartLoc = S;
671  Op->EndLoc = E;
672  return Op;
673  }
674 
675  static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
676  const class MCExpr *Expr, SMLoc S) {
677  auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
678  Op->Expr = Expr;
679  Op->StartLoc = S;
680  Op->EndLoc = S;
681  return Op;
682  }
683 };
684 
685 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
686  OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
687  return OS;
688 }
689 
690 //===----------------------------------------------------------------------===//
691 // AsmParser
692 //===----------------------------------------------------------------------===//
693 
694 // Holds info related to the current kernel, e.g. count of SGPRs used.
695 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
696 // .amdgpu_hsa_kernel or at EOF.
697 class KernelScopeInfo {
698  int SgprIndexUnusedMin;
699  int VgprIndexUnusedMin;
700  MCContext *Ctx;
701 
702  void usesSgprAt(int i) {
703  if (i >= SgprIndexUnusedMin) {
704  SgprIndexUnusedMin = ++i;
705  if (Ctx) {
706  MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
707  Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
708  }
709  }
710  }
711  void usesVgprAt(int i) {
712  if (i >= VgprIndexUnusedMin) {
713  VgprIndexUnusedMin = ++i;
714  if (Ctx) {
715  MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
716  Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
717  }
718  }
719  }
720 public:
721  KernelScopeInfo() : SgprIndexUnusedMin(-1), VgprIndexUnusedMin(-1), Ctx(nullptr)
722  {}
723  void initialize(MCContext &Context) {
724  Ctx = &Context;
725  usesSgprAt(SgprIndexUnusedMin = -1);
726  usesVgprAt(VgprIndexUnusedMin = -1);
727  }
728  void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
729  switch (RegKind) {
730  case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
731  case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
732  default: break;
733  }
734  }
735 };
736 
737 class AMDGPUAsmParser : public MCTargetAsmParser {
738  const MCInstrInfo &MII;
739  MCAsmParser &Parser;
740 
741  unsigned ForcedEncodingSize;
742  bool ForcedDPP;
743  bool ForcedSDWA;
744  KernelScopeInfo KernelScope;
745 
746  /// @name Auto-generated Match Functions
747  /// {
748 
749 #define GET_ASSEMBLER_HEADER
750 #include "AMDGPUGenAsmMatcher.inc"
751 
752  /// }
753 
754 private:
755  bool ParseAsAbsoluteExpression(uint32_t &Ret);
756  bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
757  bool ParseDirectiveHSACodeObjectVersion();
758  bool ParseDirectiveHSACodeObjectISA();
759  bool ParseDirectiveRuntimeMetadata();
760  bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
761  bool ParseDirectiveAMDKernelCodeT();
762  bool ParseSectionDirectiveHSAText();
763  bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
764  bool ParseDirectiveAMDGPUHsaKernel();
765  bool ParseDirectiveAMDGPUHsaModuleGlobal();
766  bool ParseDirectiveAMDGPUHsaProgramGlobal();
767  bool ParseSectionDirectiveHSADataGlobalAgent();
768  bool ParseSectionDirectiveHSADataGlobalProgram();
769  bool ParseSectionDirectiveHSARodataReadonlyAgent();
770  bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
771  bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex);
772  void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
773 
774 public:
775  enum AMDGPUMatchResultTy {
776  Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
777  };
778 
779  AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
780  const MCInstrInfo &MII,
781  const MCTargetOptions &Options)
782  : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
783  ForcedEncodingSize(0),
784  ForcedDPP(false),
785  ForcedSDWA(false) {
786  MCAsmParserExtension::Initialize(Parser);
787 
788  if (getSTI().getFeatureBits().none()) {
789  // Set default features.
790  copySTI().ToggleFeature("SOUTHERN_ISLANDS");
791  }
792 
793  setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
794 
795  {
796  // TODO: make those pre-defined variables read-only.
797  // Currently there is none suitable machinery in the core llvm-mc for this.
798  // MCSymbol::isRedefinable is intended for another purpose, and
799  // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
800  AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
801  MCContext &Ctx = getContext();
802  MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
803  Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx));
804  Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
805  Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx));
806  Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
807  Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx));
808  }
809  KernelScope.initialize(getContext());
810  }
811 
812  bool isSI() const {
813  return AMDGPU::isSI(getSTI());
814  }
815 
816  bool isCI() const {
817  return AMDGPU::isCI(getSTI());
818  }
819 
820  bool isVI() const {
821  return AMDGPU::isVI(getSTI());
822  }
823 
824  bool hasInv2PiInlineImm() const {
825  return getSTI().getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
826  }
827 
828  bool hasSGPR102_SGPR103() const {
829  return !isVI();
830  }
831 
832  AMDGPUTargetStreamer &getTargetStreamer() {
833  MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
834  return static_cast<AMDGPUTargetStreamer &>(TS);
835  }
836 
837  const MCRegisterInfo *getMRI() const {
838  // We need this const_cast because for some reason getContext() is not const
839  // in MCAsmParser.
840  return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
841  }
842 
843  const MCInstrInfo *getMII() const {
844  return &MII;
845  }
846 
847  void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
848  void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
849  void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
850 
851  unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
852  bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
853  bool isForcedDPP() const { return ForcedDPP; }
854  bool isForcedSDWA() const { return ForcedSDWA; }
855  ArrayRef<unsigned> getMatchedVariants() const;
856 
857  std::unique_ptr<AMDGPUOperand> parseRegister();
858  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
859  unsigned checkTargetMatchPredicate(MCInst &Inst) override;
860  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
861  unsigned Kind) override;
862  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
863  OperandVector &Operands, MCStreamer &Out,
864  uint64_t &ErrorInfo,
865  bool MatchingInlineAsm) override;
866  bool ParseDirective(AsmToken DirectiveID) override;
867  OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
868  StringRef parseMnemonicSuffix(StringRef Name);
869  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
870  SMLoc NameLoc, OperandVector &Operands) override;
871  //bool ProcessInstruction(MCInst &Inst);
872 
873  OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
874  OperandMatchResultTy
875  parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
876  enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
877  bool (*ConvertResult)(int64_t &) = nullptr);
878  OperandMatchResultTy
879  parseNamedBit(const char *Name, OperandVector &Operands,
880  enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
881  OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
882  StringRef &Value);
883 
884  OperandMatchResultTy parseImm(OperandVector &Operands);
885  OperandMatchResultTy parseReg(OperandVector &Operands);
886  OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
887  OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
888  OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
889  OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
890  OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
891  OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
892 
893  void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
894  void cvtDS(MCInst &Inst, const OperandVector &Operands);
895  void cvtExp(MCInst &Inst, const OperandVector &Operands);
896 
897  bool parseCnt(int64_t &IntVal);
898  OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
899  OperandMatchResultTy parseHwreg(OperandVector &Operands);
900 
901 private:
902  struct OperandInfoTy {
903  int64_t Id;
904  bool IsSymbolic;
905  OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
906  };
907 
908  bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
909  bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
910 
911  void errorExpTgt();
912  OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
913 
914 public:
915  OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
916 
917  OperandMatchResultTy parseExpTgt(OperandVector &Operands);
918  OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
919  OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
920  OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
921  OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
922 
923  void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
924  void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
925  void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
926  AMDGPUOperand::Ptr defaultGLC() const;
927  AMDGPUOperand::Ptr defaultSLC() const;
928  AMDGPUOperand::Ptr defaultTFE() const;
929 
930  AMDGPUOperand::Ptr defaultDMask() const;
931  AMDGPUOperand::Ptr defaultUNorm() const;
932  AMDGPUOperand::Ptr defaultDA() const;
933  AMDGPUOperand::Ptr defaultR128() const;
934  AMDGPUOperand::Ptr defaultLWE() const;
935  AMDGPUOperand::Ptr defaultSMRDOffset8() const;
936  AMDGPUOperand::Ptr defaultSMRDOffset20() const;
937  AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
938 
939  OperandMatchResultTy parseOModOperand(OperandVector &Operands);
940 
941  void cvtId(MCInst &Inst, const OperandVector &Operands);
942  void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
943  void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
944 
945  void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
946  void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
947 
948  OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
949  AMDGPUOperand::Ptr defaultRowMask() const;
950  AMDGPUOperand::Ptr defaultBankMask() const;
951  AMDGPUOperand::Ptr defaultBoundCtrl() const;
952  void cvtDPP(MCInst &Inst, const OperandVector &Operands);
953 
954  OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
955  AMDGPUOperand::ImmTy Type);
956  OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
957  void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
958  void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
959  void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
960  void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
961  uint64_t BasicInstType);
962 };
963 
964 struct OptionalOperand {
965  const char *Name;
966  AMDGPUOperand::ImmTy Type;
967  bool IsBit;
968  bool (*ConvertResult)(int64_t&);
969 };
970 
971 } // end anonymous namespace
972 
973 // May be called with integer type with equivalent bitwidth.
974 static const fltSemantics *getFltSemantics(unsigned Size) {
975  switch (Size) {
976  case 4:
977  return &APFloat::IEEEsingle();
978  case 8:
979  return &APFloat::IEEEdouble();
980  case 2:
981  return &APFloat::IEEEhalf();
982  default:
983  llvm_unreachable("unsupported fp type");
984  }
985 }
986 
987 static const fltSemantics *getFltSemantics(MVT VT) {
988  return getFltSemantics(VT.getSizeInBits() / 8);
989 }
990 
991 //===----------------------------------------------------------------------===//
992 // Operand
993 //===----------------------------------------------------------------------===//
994 
995 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
996  bool Lost;
997 
998  // Convert literal to single precision
999  APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1000  APFloat::rmNearestTiesToEven,
1001  &Lost);
1002  // We allow precision lost but not overflow or underflow
1003  if (Status != APFloat::opOK &&
1004  Lost &&
1005  ((Status & APFloat::opOverflow) != 0 ||
1006  (Status & APFloat::opUnderflow) != 0)) {
1007  return false;
1008  }
1009 
1010  return true;
1011 }
1012 
1013 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1014  if (!isImmTy(ImmTyNone)) {
1015  // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1016  return false;
1017  }
1018  // TODO: We should avoid using host float here. It would be better to
1019  // check the float bit values which is what a few other places do.
1020  // We've had bot failures before due to weird NaN support on mips hosts.
1021 
1022  APInt Literal(64, Imm.Val);
1023 
1024  if (Imm.IsFPImm) { // We got fp literal token
1025  if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1026  return AMDGPU::isInlinableLiteral64(Imm.Val,
1027  AsmParser->hasInv2PiInlineImm());
1028  }
1029 
1030  APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1031  if (!canLosslesslyConvertToFPType(FPLiteral, type))
1032  return false;
1033 
1034  // Check if single precision literal is inlinable
1036  static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1037  AsmParser->hasInv2PiInlineImm());
1038  }
1039 
1040 
1041  // We got int literal token.
1042  if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1043  return AMDGPU::isInlinableLiteral64(Imm.Val,
1044  AsmParser->hasInv2PiInlineImm());
1045  }
1046 
1047  if (type.getScalarSizeInBits() == 16) {
1049  static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1050  AsmParser->hasInv2PiInlineImm());
1051  }
1052 
1054  static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1055  AsmParser->hasInv2PiInlineImm());
1056 }
1057 
1058 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1059  // Check that this imediate can be added as literal
1060  if (!isImmTy(ImmTyNone)) {
1061  return false;
1062  }
1063 
1064  if (!Imm.IsFPImm) {
1065  // We got int literal token.
1066 
1067  unsigned Size = type.getSizeInBits();
1068  if (Size == 64)
1069  Size = 32;
1070 
1071  // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1072  // types.
1073  return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1074  }
1075 
1076  // We got fp literal token
1077  if (type == MVT::f64) { // Expected 64-bit fp operand
1078  // We would set low 64-bits of literal to zeroes but we accept this literals
1079  return true;
1080  }
1081 
1082  if (type == MVT::i64) { // Expected 64-bit int operand
1083  // We don't allow fp literals in 64-bit integer instructions. It is
1084  // unclear how we should encode them.
1085  return false;
1086  }
1087 
1088  APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1089  return canLosslesslyConvertToFPType(FPLiteral, type);
1090 }
1091 
1092 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1093  return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1094 }
1095 
1096 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1097  int64_t Val = Imm.Val;
1098  if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers() && Imm.Mods.Neg) {
1099  // Apply modifiers to immediate value. Only negate can get here
1100  if (Imm.IsFPImm) {
1101  APFloat F(BitsToDouble(Val));
1102  F.changeSign();
1103  Val = F.bitcastToAPInt().getZExtValue();
1104  } else {
1105  Val = -Val;
1106  }
1107  }
1108 
1109  if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1110  Inst.getNumOperands())) {
1111  addLiteralImmOperand(Inst, Val);
1112  } else {
1113  Inst.addOperand(MCOperand::createImm(Val));
1114  }
1115 }
1116 
1117 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val) const {
1118  const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1119  auto OpNum = Inst.getNumOperands();
1120  // Check that this operand accepts literals
1121  assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1122 
1123  auto OpSize = AMDGPU::getOperandSize(InstDesc, OpNum); // expected operand size
1124 
1125  if (Imm.IsFPImm) { // We got fp literal token
1126  APInt Literal(64, Val);
1127 
1128  switch (OpSize) {
1129  case 8: {
1130  if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1131  AsmParser->hasInv2PiInlineImm())) {
1132  Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1133  return;
1134  }
1135 
1136  // Non-inlineable
1137  if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1138  // For fp operands we check if low 32 bits are zeros
1139  if (Literal.getLoBits(32) != 0) {
1140  const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1141  "Can't encode literal as exact 64-bit floating-point operand. "
1142  "Low 32-bits will be set to zero");
1143  }
1144 
1145  Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1146  return;
1147  }
1148 
1149  // We don't allow fp literals in 64-bit integer instructions. It is
1150  // unclear how we should encode them. This case should be checked earlier
1151  // in predicate methods (isLiteralImm())
1152  llvm_unreachable("fp literal in 64-bit integer instruction.");
1153  }
1154  case 4:
1155  case 2: {
1156  bool lost;
1157  APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1158  // Convert literal to single precision
1159  FPLiteral.convert(*getFltSemantics(OpSize),
1161  // We allow precision lost but not overflow or underflow. This should be
1162  // checked earlier in isLiteralImm()
1163  Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1164  return;
1165  }
1166  default:
1167  llvm_unreachable("invalid operand size");
1168  }
1169 
1170  return;
1171  }
1172 
1173  // We got int literal token.
1174  // Only sign extend inline immediates.
1175  // FIXME: No errors on truncation
1176  switch (OpSize) {
1177  case 4: {
1178  if (isInt<32>(Val) &&
1179  AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1180  AsmParser->hasInv2PiInlineImm())) {
1181  Inst.addOperand(MCOperand::createImm(Val));
1182  return;
1183  }
1184 
1185  Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1186  return;
1187  }
1188  case 8: {
1190  AsmParser->hasInv2PiInlineImm())) {
1191  Inst.addOperand(MCOperand::createImm(Val));
1192  return;
1193  }
1194 
1196  return;
1197  }
1198  case 2: {
1199  if (isInt<16>(Val) &&
1200  AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1201  AsmParser->hasInv2PiInlineImm())) {
1202  Inst.addOperand(MCOperand::createImm(Val));
1203  return;
1204  }
1205 
1206  Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1207  return;
1208  }
1209  default:
1210  llvm_unreachable("invalid operand size");
1211  }
1212 }
1213 
1214 template <unsigned Bitwidth>
1215 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1216  APInt Literal(64, Imm.Val);
1217 
1218  if (!Imm.IsFPImm) {
1219  // We got int literal token.
1220  Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1221  return;
1222  }
1223 
1224  bool Lost;
1225  APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1226  FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1228  Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1229 }
1230 
1231 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1232  Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1233 }
1234 
1235 //===----------------------------------------------------------------------===//
1236 // AsmParser
1237 //===----------------------------------------------------------------------===//
1238 
1239 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1240  if (Is == IS_VGPR) {
1241  switch (RegWidth) {
1242  default: return -1;
1243  case 1: return AMDGPU::VGPR_32RegClassID;
1244  case 2: return AMDGPU::VReg_64RegClassID;
1245  case 3: return AMDGPU::VReg_96RegClassID;
1246  case 4: return AMDGPU::VReg_128RegClassID;
1247  case 8: return AMDGPU::VReg_256RegClassID;
1248  case 16: return AMDGPU::VReg_512RegClassID;
1249  }
1250  } else if (Is == IS_TTMP) {
1251  switch (RegWidth) {
1252  default: return -1;
1253  case 1: return AMDGPU::TTMP_32RegClassID;
1254  case 2: return AMDGPU::TTMP_64RegClassID;
1255  case 4: return AMDGPU::TTMP_128RegClassID;
1256  }
1257  } else if (Is == IS_SGPR) {
1258  switch (RegWidth) {
1259  default: return -1;
1260  case 1: return AMDGPU::SGPR_32RegClassID;
1261  case 2: return AMDGPU::SGPR_64RegClassID;
1262  case 4: return AMDGPU::SGPR_128RegClassID;
1263  case 8: return AMDGPU::SReg_256RegClassID;
1264  case 16: return AMDGPU::SReg_512RegClassID;
1265  }
1266  }
1267  return -1;
1268 }
1269 
1270 static unsigned getSpecialRegForName(StringRef RegName) {
1271  return StringSwitch<unsigned>(RegName)
1272  .Case("exec", AMDGPU::EXEC)
1273  .Case("vcc", AMDGPU::VCC)
1274  .Case("flat_scratch", AMDGPU::FLAT_SCR)
1275  .Case("m0", AMDGPU::M0)
1276  .Case("scc", AMDGPU::SCC)
1277  .Case("tba", AMDGPU::TBA)
1278  .Case("tma", AMDGPU::TMA)
1279  .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1280  .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1281  .Case("vcc_lo", AMDGPU::VCC_LO)
1282  .Case("vcc_hi", AMDGPU::VCC_HI)
1283  .Case("exec_lo", AMDGPU::EXEC_LO)
1284  .Case("exec_hi", AMDGPU::EXEC_HI)
1285  .Case("tma_lo", AMDGPU::TMA_LO)
1286  .Case("tma_hi", AMDGPU::TMA_HI)
1287  .Case("tba_lo", AMDGPU::TBA_LO)
1288  .Case("tba_hi", AMDGPU::TBA_HI)
1289  .Default(0);
1290 }
1291 
1292 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
1293  auto R = parseRegister();
1294  if (!R) return true;
1295  assert(R->isReg());
1296  RegNo = R->getReg();
1297  StartLoc = R->getStartLoc();
1298  EndLoc = R->getEndLoc();
1299  return false;
1300 }
1301 
1302 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum)
1303 {
1304  switch (RegKind) {
1305  case IS_SPECIAL:
1306  if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; }
1307  if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; }
1308  if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; }
1309  if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; }
1310  if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; }
1311  return false;
1312  case IS_VGPR:
1313  case IS_SGPR:
1314  case IS_TTMP:
1315  if (Reg1 != Reg + RegWidth) { return false; }
1316  RegWidth++;
1317  return true;
1318  default:
1319  llvm_unreachable("unexpected register kind");
1320  }
1321 }
1322 
1323 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex)
1324 {
1325  if (DwordRegIndex) { *DwordRegIndex = 0; }
1326  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1327  if (getLexer().is(AsmToken::Identifier)) {
1328  StringRef RegName = Parser.getTok().getString();
1329  if ((Reg = getSpecialRegForName(RegName))) {
1330  Parser.Lex();
1331  RegKind = IS_SPECIAL;
1332  } else {
1333  unsigned RegNumIndex = 0;
1334  if (RegName[0] == 'v') {
1335  RegNumIndex = 1;
1336  RegKind = IS_VGPR;
1337  } else if (RegName[0] == 's') {
1338  RegNumIndex = 1;
1339  RegKind = IS_SGPR;
1340  } else if (RegName.startswith("ttmp")) {
1341  RegNumIndex = strlen("ttmp");
1342  RegKind = IS_TTMP;
1343  } else {
1344  return false;
1345  }
1346  if (RegName.size() > RegNumIndex) {
1347  // Single 32-bit register: vXX.
1348  if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1349  return false;
1350  Parser.Lex();
1351  RegWidth = 1;
1352  } else {
1353  // Range of registers: v[XX:YY]. ":YY" is optional.
1354  Parser.Lex();
1355  int64_t RegLo, RegHi;
1356  if (getLexer().isNot(AsmToken::LBrac))
1357  return false;
1358  Parser.Lex();
1359 
1360  if (getParser().parseAbsoluteExpression(RegLo))
1361  return false;
1362 
1363  const bool isRBrace = getLexer().is(AsmToken::RBrac);
1364  if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1365  return false;
1366  Parser.Lex();
1367 
1368  if (isRBrace) {
1369  RegHi = RegLo;
1370  } else {
1371  if (getParser().parseAbsoluteExpression(RegHi))
1372  return false;
1373 
1374  if (getLexer().isNot(AsmToken::RBrac))
1375  return false;
1376  Parser.Lex();
1377  }
1378  RegNum = (unsigned) RegLo;
1379  RegWidth = (RegHi - RegLo) + 1;
1380  }
1381  }
1382  } else if (getLexer().is(AsmToken::LBrac)) {
1383  // List of consecutive registers: [s0,s1,s2,s3]
1384  Parser.Lex();
1385  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1386  return false;
1387  if (RegWidth != 1)
1388  return false;
1389  RegisterKind RegKind1;
1390  unsigned Reg1, RegNum1, RegWidth1;
1391  do {
1392  if (getLexer().is(AsmToken::Comma)) {
1393  Parser.Lex();
1394  } else if (getLexer().is(AsmToken::RBrac)) {
1395  Parser.Lex();
1396  break;
1397  } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1398  if (RegWidth1 != 1) {
1399  return false;
1400  }
1401  if (RegKind1 != RegKind) {
1402  return false;
1403  }
1404  if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1405  return false;
1406  }
1407  } else {
1408  return false;
1409  }
1410  } while (true);
1411  } else {
1412  return false;
1413  }
1414  switch (RegKind) {
1415  case IS_SPECIAL:
1416  RegNum = 0;
1417  RegWidth = 1;
1418  break;
1419  case IS_VGPR:
1420  case IS_SGPR:
1421  case IS_TTMP:
1422  {
1423  unsigned Size = 1;
1424  if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1425  // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1426  Size = std::min(RegWidth, 4u);
1427  }
1428  if (RegNum % Size != 0)
1429  return false;
1430  if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1431  RegNum = RegNum / Size;
1432  int RCID = getRegClass(RegKind, RegWidth);
1433  if (RCID == -1)
1434  return false;
1435  const MCRegisterClass RC = TRI->getRegClass(RCID);
1436  if (RegNum >= RC.getNumRegs())
1437  return false;
1438  Reg = RC.getRegister(RegNum);
1439  break;
1440  }
1441 
1442  default:
1443  llvm_unreachable("unexpected register kind");
1444  }
1445 
1446  if (!subtargetHasRegister(*TRI, Reg))
1447  return false;
1448  return true;
1449 }
1450 
1451 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1452  const auto &Tok = Parser.getTok();
1453  SMLoc StartLoc = Tok.getLoc();
1454  SMLoc EndLoc = Tok.getEndLoc();
1455  RegisterKind RegKind;
1456  unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1457 
1458  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1459  return nullptr;
1460  }
1461  KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1462  return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1463 }
1464 
1466 AMDGPUAsmParser::parseImm(OperandVector &Operands) {
1467  // TODO: add syntactic sugar for 1/(2*PI)
1468  bool Minus = false;
1469  if (getLexer().getKind() == AsmToken::Minus) {
1470  Minus = true;
1471  Parser.Lex();
1472  }
1473 
1474  SMLoc S = Parser.getTok().getLoc();
1475  switch(getLexer().getKind()) {
1476  case AsmToken::Integer: {
1477  int64_t IntVal;
1478  if (getParser().parseAbsoluteExpression(IntVal))
1479  return MatchOperand_ParseFail;
1480  if (Minus)
1481  IntVal *= -1;
1482  Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1483  return MatchOperand_Success;
1484  }
1485  case AsmToken::Real: {
1486  int64_t IntVal;
1487  if (getParser().parseAbsoluteExpression(IntVal))
1488  return MatchOperand_ParseFail;
1489 
1490  APFloat F(BitsToDouble(IntVal));
1491  if (Minus)
1492  F.changeSign();
1493  Operands.push_back(
1494  AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1495  AMDGPUOperand::ImmTyNone, true));
1496  return MatchOperand_Success;
1497  }
1498  default:
1500  }
1501 }
1502 
1504 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1505  if (auto R = parseRegister()) {
1506  assert(R->isReg());
1507  R->Reg.IsForcedVOP3 = isForcedVOP3();
1508  Operands.push_back(std::move(R));
1509  return MatchOperand_Success;
1510  }
1511  return MatchOperand_NoMatch;
1512 }
1513 
1515 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) {
1516  auto res = parseImm(Operands);
1517  if (res != MatchOperand_NoMatch) {
1518  return res;
1519  }
1520 
1521  return parseReg(Operands);
1522 }
1523 
1525 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm) {
1526  // XXX: During parsing we can't determine if minus sign means
1527  // negate-modifier or negative immediate value.
1528  // By default we suppose it is modifier.
1529  bool Negate = false, Abs = false, Abs2 = false;
1530 
1531  if (getLexer().getKind()== AsmToken::Minus) {
1532  Parser.Lex();
1533  Negate = true;
1534  }
1535 
1536  if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") {
1537  Parser.Lex();
1538  Abs2 = true;
1539  if (getLexer().isNot(AsmToken::LParen)) {
1540  Error(Parser.getTok().getLoc(), "expected left paren after abs");
1541  return MatchOperand_ParseFail;
1542  }
1543  Parser.Lex();
1544  }
1545 
1546  if (getLexer().getKind() == AsmToken::Pipe) {
1547  if (Abs2) {
1548  Error(Parser.getTok().getLoc(), "expected register or immediate");
1549  return MatchOperand_ParseFail;
1550  }
1551  Parser.Lex();
1552  Abs = true;
1553  }
1554 
1556  if (AllowImm) {
1557  Res = parseRegOrImm(Operands);
1558  } else {
1559  Res = parseReg(Operands);
1560  }
1561  if (Res != MatchOperand_Success) {
1562  return Res;
1563  }
1564 
1565  AMDGPUOperand::Modifiers Mods;
1566  if (Negate) {
1567  Mods.Neg = true;
1568  }
1569  if (Abs) {
1570  if (getLexer().getKind() != AsmToken::Pipe) {
1571  Error(Parser.getTok().getLoc(), "expected vertical bar");
1572  return MatchOperand_ParseFail;
1573  }
1574  Parser.Lex();
1575  Mods.Abs = true;
1576  }
1577  if (Abs2) {
1578  if (getLexer().isNot(AsmToken::RParen)) {
1579  Error(Parser.getTok().getLoc(), "expected closing parentheses");
1580  return MatchOperand_ParseFail;
1581  }
1582  Parser.Lex();
1583  Mods.Abs = true;
1584  }
1585 
1586  if (Mods.hasFPModifiers()) {
1587  AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1588  Op.setModifiers(Mods);
1589  }
1590  return MatchOperand_Success;
1591 }
1592 
1594 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm) {
1595  bool Sext = false;
1596 
1597  if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") {
1598  Parser.Lex();
1599  Sext = true;
1600  if (getLexer().isNot(AsmToken::LParen)) {
1601  Error(Parser.getTok().getLoc(), "expected left paren after sext");
1602  return MatchOperand_ParseFail;
1603  }
1604  Parser.Lex();
1605  }
1606 
1608  if (AllowImm) {
1609  Res = parseRegOrImm(Operands);
1610  } else {
1611  Res = parseReg(Operands);
1612  }
1613  if (Res != MatchOperand_Success) {
1614  return Res;
1615  }
1616 
1617  AMDGPUOperand::Modifiers Mods;
1618  if (Sext) {
1619  if (getLexer().isNot(AsmToken::RParen)) {
1620  Error(Parser.getTok().getLoc(), "expected closing parentheses");
1621  return MatchOperand_ParseFail;
1622  }
1623  Parser.Lex();
1624  Mods.Sext = true;
1625  }
1626 
1627  if (Mods.hasIntModifiers()) {
1628  AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1629  Op.setModifiers(Mods);
1630  }
1631 
1632  return MatchOperand_Success;
1633 }
1634 
1636 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1637  return parseRegOrImmWithFPInputMods(Operands, false);
1638 }
1639 
1641 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1642  return parseRegOrImmWithIntInputMods(Operands, false);
1643 }
1644 
1645 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1646  std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1647  if (Reg) {
1648  Operands.push_back(std::move(Reg));
1649  return MatchOperand_Success;
1650  }
1651 
1652  const AsmToken &Tok = Parser.getTok();
1653  if (Tok.getString() == "off") {
1654  Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1655  AMDGPUOperand::ImmTyOff, false));
1656  Parser.Lex();
1657  return MatchOperand_Success;
1658  }
1659 
1660  return MatchOperand_NoMatch;
1661 }
1662 
1663 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1664 
1665  uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1666 
1667  if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1668  (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1669  (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1670  (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1671  return Match_InvalidOperand;
1672 
1673  if ((TSFlags & SIInstrFlags::VOP3) &&
1674  (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1675  getForcedEncodingSize() != 64)
1676  return Match_PreferE32;
1677 
1678  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1679  Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1680  // v_mac_f32/16 allow only dst_sel == DWORD;
1681  auto OpNum =
1682  AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1683  const auto &Op = Inst.getOperand(OpNum);
1684  if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1685  return Match_InvalidOperand;
1686  }
1687  }
1688 
1689  return Match_Success;
1690 }
1691 
1692 // What asm variants we should check
1693 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
1694  if (getForcedEncodingSize() == 32) {
1695  static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
1696  return makeArrayRef(Variants);
1697  }
1698 
1699  if (isForcedVOP3()) {
1700  static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
1701  return makeArrayRef(Variants);
1702  }
1703 
1704  if (isForcedSDWA()) {
1705  static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA};
1706  return makeArrayRef(Variants);
1707  }
1708 
1709  if (isForcedDPP()) {
1710  static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
1711  return makeArrayRef(Variants);
1712  }
1713 
1714  static const unsigned Variants[] = {
1717  };
1718 
1719  return makeArrayRef(Variants);
1720 }
1721 
1722 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1723  OperandVector &Operands,
1724  MCStreamer &Out,
1725  uint64_t &ErrorInfo,
1726  bool MatchingInlineAsm) {
1727  MCInst Inst;
1728  unsigned Result = Match_Success;
1729  for (auto Variant : getMatchedVariants()) {
1730  uint64_t EI;
1731  auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
1732  Variant);
1733  // We order match statuses from least to most specific. We use most specific
1734  // status as resulting
1735  // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
1736  if ((R == Match_Success) ||
1737  (R == Match_PreferE32) ||
1738  (R == Match_MissingFeature && Result != Match_PreferE32) ||
1739  (R == Match_InvalidOperand && Result != Match_MissingFeature
1740  && Result != Match_PreferE32) ||
1741  (R == Match_MnemonicFail && Result != Match_InvalidOperand
1742  && Result != Match_MissingFeature
1743  && Result != Match_PreferE32)) {
1744  Result = R;
1745  ErrorInfo = EI;
1746  }
1747  if (R == Match_Success)
1748  break;
1749  }
1750 
1751  switch (Result) {
1752  default: break;
1753  case Match_Success:
1754  Inst.setLoc(IDLoc);
1755  Out.EmitInstruction(Inst, getSTI());
1756  return false;
1757 
1758  case Match_MissingFeature:
1759  return Error(IDLoc, "instruction not supported on this GPU");
1760 
1761  case Match_MnemonicFail:
1762  return Error(IDLoc, "unrecognized instruction mnemonic");
1763 
1764  case Match_InvalidOperand: {
1765  SMLoc ErrorLoc = IDLoc;
1766  if (ErrorInfo != ~0ULL) {
1767  if (ErrorInfo >= Operands.size()) {
1768  return Error(IDLoc, "too few operands for instruction");
1769  }
1770  ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
1771  if (ErrorLoc == SMLoc())
1772  ErrorLoc = IDLoc;
1773  }
1774  return Error(ErrorLoc, "invalid operand for instruction");
1775  }
1776 
1777  case Match_PreferE32:
1778  return Error(IDLoc, "internal error: instruction without _e64 suffix "
1779  "should be encoded as e32");
1780  }
1781  llvm_unreachable("Implement any new match types added!");
1782 }
1783 
1784 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
1785  int64_t Tmp = -1;
1786  if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
1787  return true;
1788  }
1789  if (getParser().parseAbsoluteExpression(Tmp)) {
1790  return true;
1791  }
1792  Ret = static_cast<uint32_t>(Tmp);
1793  return false;
1794 }
1795 
1796 
1797 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
1798  uint32_t &Minor) {
1799  if (ParseAsAbsoluteExpression(Major))
1800  return TokError("invalid major version");
1801 
1802  if (getLexer().isNot(AsmToken::Comma))
1803  return TokError("minor version number required, comma expected");
1804  Lex();
1805 
1806  if (ParseAsAbsoluteExpression(Minor))
1807  return TokError("invalid minor version");
1808 
1809  return false;
1810 }
1811 
1812 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
1813 
1814  uint32_t Major;
1815  uint32_t Minor;
1816 
1817  if (ParseDirectiveMajorMinor(Major, Minor))
1818  return true;
1819 
1820  getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
1821  return false;
1822 }
1823 
1824 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
1825  uint32_t Major;
1826  uint32_t Minor;
1827  uint32_t Stepping;
1828  StringRef VendorName;
1829  StringRef ArchName;
1830 
1831  // If this directive has no arguments, then use the ISA version for the
1832  // targeted GPU.
1833  if (getLexer().is(AsmToken::EndOfStatement)) {
1834  AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
1835  getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
1836  Isa.Stepping,
1837  "AMD", "AMDGPU");
1838  return false;
1839  }
1840 
1841  if (ParseDirectiveMajorMinor(Major, Minor))
1842  return true;
1843 
1844  if (getLexer().isNot(AsmToken::Comma))
1845  return TokError("stepping version number required, comma expected");
1846  Lex();
1847 
1848  if (ParseAsAbsoluteExpression(Stepping))
1849  return TokError("invalid stepping version");
1850 
1851  if (getLexer().isNot(AsmToken::Comma))
1852  return TokError("vendor name required, comma expected");
1853  Lex();
1854 
1855  if (getLexer().isNot(AsmToken::String))
1856  return TokError("invalid vendor name");
1857 
1858  VendorName = getLexer().getTok().getStringContents();
1859  Lex();
1860 
1861  if (getLexer().isNot(AsmToken::Comma))
1862  return TokError("arch name required, comma expected");
1863  Lex();
1864 
1865  if (getLexer().isNot(AsmToken::String))
1866  return TokError("invalid arch name");
1867 
1868  ArchName = getLexer().getTok().getStringContents();
1869  Lex();
1870 
1871  getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
1872  VendorName, ArchName);
1873  return false;
1874 }
1875 
1876 bool AMDGPUAsmParser::ParseDirectiveRuntimeMetadata() {
1877  std::string Metadata;
1878  raw_string_ostream MS(Metadata);
1879 
1880  getLexer().setSkipSpace(false);
1881 
1882  bool FoundEnd = false;
1883  while (!getLexer().is(AsmToken::Eof)) {
1884  while (getLexer().is(AsmToken::Space)) {
1885  MS << ' ';
1886  Lex();
1887  }
1888 
1889  if (getLexer().is(AsmToken::Identifier)) {
1890  StringRef ID = getLexer().getTok().getIdentifier();
1891  if (ID == ".end_amdgpu_runtime_metadata") {
1892  Lex();
1893  FoundEnd = true;
1894  break;
1895  }
1896  }
1897 
1898  MS << Parser.parseStringToEndOfStatement()
1899  << getContext().getAsmInfo()->getSeparatorString();
1900 
1901  Parser.eatToEndOfStatement();
1902  }
1903 
1904  getLexer().setSkipSpace(true);
1905 
1906  if (getLexer().is(AsmToken::Eof) && !FoundEnd)
1907  return TokError("expected directive .end_amdgpu_runtime_metadata not found");
1908 
1909  MS.flush();
1910 
1911  getTargetStreamer().EmitRuntimeMetadata(Metadata);
1912 
1913  return false;
1914 }
1915 
1916 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
1917  amd_kernel_code_t &Header) {
1918  SmallString<40> ErrStr;
1919  raw_svector_ostream Err(ErrStr);
1920  if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
1921  return TokError(Err.str());
1922  }
1923  Lex();
1924  return false;
1925 }
1926 
1927 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
1928  amd_kernel_code_t Header;
1929  AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits());
1930 
1931  while (true) {
1932  // Lex EndOfStatement. This is in a while loop, because lexing a comment
1933  // will set the current token to EndOfStatement.
1934  while(getLexer().is(AsmToken::EndOfStatement))
1935  Lex();
1936 
1937  if (getLexer().isNot(AsmToken::Identifier))
1938  return TokError("expected value identifier or .end_amd_kernel_code_t");
1939 
1940  StringRef ID = getLexer().getTok().getIdentifier();
1941  Lex();
1942 
1943  if (ID == ".end_amd_kernel_code_t")
1944  break;
1945 
1946  if (ParseAMDKernelCodeTValue(ID, Header))
1947  return true;
1948  }
1949 
1950  getTargetStreamer().EmitAMDKernelCodeT(Header);
1951 
1952  return false;
1953 }
1954 
1955 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
1956  getParser().getStreamer().SwitchSection(
1957  AMDGPU::getHSATextSection(getContext()));
1958  return false;
1959 }
1960 
1961 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
1962  if (getLexer().isNot(AsmToken::Identifier))
1963  return TokError("expected symbol name");
1964 
1965  StringRef KernelName = Parser.getTok().getString();
1966 
1967  getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
1969  Lex();
1970  KernelScope.initialize(getContext());
1971  return false;
1972 }
1973 
1974 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
1975  if (getLexer().isNot(AsmToken::Identifier))
1976  return TokError("expected symbol name");
1977 
1978  StringRef GlobalName = Parser.getTok().getIdentifier();
1979 
1980  getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
1981  Lex();
1982  return false;
1983 }
1984 
1985 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
1986  if (getLexer().isNot(AsmToken::Identifier))
1987  return TokError("expected symbol name");
1988 
1989  StringRef GlobalName = Parser.getTok().getIdentifier();
1990 
1991  getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
1992  Lex();
1993  return false;
1994 }
1995 
1996 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
1997  getParser().getStreamer().SwitchSection(
1998  AMDGPU::getHSADataGlobalAgentSection(getContext()));
1999  return false;
2000 }
2001 
2002 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
2003  getParser().getStreamer().SwitchSection(
2005  return false;
2006 }
2007 
2008 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
2009  getParser().getStreamer().SwitchSection(
2011  return false;
2012 }
2013 
2014 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2015  StringRef IDVal = DirectiveID.getString();
2016 
2017  if (IDVal == ".hsa_code_object_version")
2018  return ParseDirectiveHSACodeObjectVersion();
2019 
2020  if (IDVal == ".hsa_code_object_isa")
2021  return ParseDirectiveHSACodeObjectISA();
2022 
2023  if (IDVal == ".amdgpu_runtime_metadata")
2024  return ParseDirectiveRuntimeMetadata();
2025 
2026  if (IDVal == ".amd_kernel_code_t")
2027  return ParseDirectiveAMDKernelCodeT();
2028 
2029  if (IDVal == ".hsatext")
2030  return ParseSectionDirectiveHSAText();
2031 
2032  if (IDVal == ".amdgpu_hsa_kernel")
2033  return ParseDirectiveAMDGPUHsaKernel();
2034 
2035  if (IDVal == ".amdgpu_hsa_module_global")
2036  return ParseDirectiveAMDGPUHsaModuleGlobal();
2037 
2038  if (IDVal == ".amdgpu_hsa_program_global")
2039  return ParseDirectiveAMDGPUHsaProgramGlobal();
2040 
2041  if (IDVal == ".hsadata_global_agent")
2042  return ParseSectionDirectiveHSADataGlobalAgent();
2043 
2044  if (IDVal == ".hsadata_global_program")
2045  return ParseSectionDirectiveHSADataGlobalProgram();
2046 
2047  if (IDVal == ".hsarodata_readonly_agent")
2048  return ParseSectionDirectiveHSARodataReadonlyAgent();
2049 
2050  return true;
2051 }
2052 
2053 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2054  unsigned RegNo) const {
2055  if (isCI())
2056  return true;
2057 
2058  if (isSI()) {
2059  // No flat_scr
2060  switch (RegNo) {
2061  case AMDGPU::FLAT_SCR:
2062  case AMDGPU::FLAT_SCR_LO:
2063  case AMDGPU::FLAT_SCR_HI:
2064  return false;
2065  default:
2066  return true;
2067  }
2068  }
2069 
2070  // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2071  // SI/CI have.
2072  for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2073  R.isValid(); ++R) {
2074  if (*R == RegNo)
2075  return false;
2076  }
2077 
2078  return true;
2079 }
2080 
2082 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2083 
2084  // Try to parse with a custom parser
2085  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2086 
2087  // If we successfully parsed the operand or if there as an error parsing,
2088  // we are done.
2089  //
2090  // If we are parsing after we reach EndOfStatement then this means we
2091  // are appending default values to the Operands list. This is only done
2092  // by custom parser, so we shouldn't continue on to the generic parsing.
2093  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2094  getLexer().is(AsmToken::EndOfStatement))
2095  return ResTy;
2096 
2097  ResTy = parseRegOrImm(Operands);
2098 
2099  if (ResTy == MatchOperand_Success)
2100  return ResTy;
2101 
2102  if (getLexer().getKind() == AsmToken::Identifier) {
2103  // If this identifier is a symbol, we want to create an expression for it.
2104  // It is a little difficult to distinguish between a symbol name, and
2105  // an instruction flag like 'gds'. In order to do this, we parse
2106  // all tokens as expressions and then treate the symbol name as the token
2107  // string when we want to interpret the operand as a token.
2108  const auto &Tok = Parser.getTok();
2109  SMLoc S = Tok.getLoc();
2110  const MCExpr *Expr = nullptr;
2111  if (!Parser.parseExpression(Expr)) {
2112  Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2113  return MatchOperand_Success;
2114  }
2115 
2116  Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2117  Parser.Lex();
2118  return MatchOperand_Success;
2119  }
2120  return MatchOperand_NoMatch;
2121 }
2122 
2123 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2124  // Clear any forced encodings from the previous instruction.
2125  setForcedEncodingSize(0);
2126  setForcedDPP(false);
2127  setForcedSDWA(false);
2128 
2129  if (Name.endswith("_e64")) {
2130  setForcedEncodingSize(64);
2131  return Name.substr(0, Name.size() - 4);
2132  } else if (Name.endswith("_e32")) {
2133  setForcedEncodingSize(32);
2134  return Name.substr(0, Name.size() - 4);
2135  } else if (Name.endswith("_dpp")) {
2136  setForcedDPP(true);
2137  return Name.substr(0, Name.size() - 4);
2138  } else if (Name.endswith("_sdwa")) {
2139  setForcedSDWA(true);
2140  return Name.substr(0, Name.size() - 5);
2141  }
2142  return Name;
2143 }
2144 
2145 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2146  StringRef Name,
2147  SMLoc NameLoc, OperandVector &Operands) {
2148  // Add the instruction mnemonic
2149  Name = parseMnemonicSuffix(Name);
2150  Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2151 
2152  while (!getLexer().is(AsmToken::EndOfStatement)) {
2153  OperandMatchResultTy Res = parseOperand(Operands, Name);
2154 
2155  // Eat the comma or space if there is one.
2156  if (getLexer().is(AsmToken::Comma))
2157  Parser.Lex();
2158 
2159  switch (Res) {
2160  case MatchOperand_Success: break;
2162  Error(getLexer().getLoc(), "failed parsing operand.");
2163  while (!getLexer().is(AsmToken::EndOfStatement)) {
2164  Parser.Lex();
2165  }
2166  return true;
2167  case MatchOperand_NoMatch:
2168  Error(getLexer().getLoc(), "not a valid operand.");
2169  while (!getLexer().is(AsmToken::EndOfStatement)) {
2170  Parser.Lex();
2171  }
2172  return true;
2173  }
2174  }
2175 
2176  return false;
2177 }
2178 
2179 //===----------------------------------------------------------------------===//
2180 // Utility functions
2181 //===----------------------------------------------------------------------===//
2182 
2184 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2185  switch(getLexer().getKind()) {
2186  default: return MatchOperand_NoMatch;
2187  case AsmToken::Identifier: {
2188  StringRef Name = Parser.getTok().getString();
2189  if (!Name.equals(Prefix)) {
2190  return MatchOperand_NoMatch;
2191  }
2192 
2193  Parser.Lex();
2194  if (getLexer().isNot(AsmToken::Colon))
2195  return MatchOperand_ParseFail;
2196 
2197  Parser.Lex();
2198  if (getLexer().isNot(AsmToken::Integer))
2199  return MatchOperand_ParseFail;
2200 
2201  if (getParser().parseAbsoluteExpression(Int))
2202  return MatchOperand_ParseFail;
2203  break;
2204  }
2205  }
2206  return MatchOperand_Success;
2207 }
2208 
2210 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2211  enum AMDGPUOperand::ImmTy ImmTy,
2212  bool (*ConvertResult)(int64_t&)) {
2213  SMLoc S = Parser.getTok().getLoc();
2214  int64_t Value = 0;
2215 
2216  OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2217  if (Res != MatchOperand_Success)
2218  return Res;
2219 
2220  if (ConvertResult && !ConvertResult(Value)) {
2221  return MatchOperand_ParseFail;
2222  }
2223 
2224  Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2225  return MatchOperand_Success;
2226 }
2227 
2229 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2230  enum AMDGPUOperand::ImmTy ImmTy) {
2231  int64_t Bit = 0;
2232  SMLoc S = Parser.getTok().getLoc();
2233 
2234  // We are at the end of the statement, and this is a default argument, so
2235  // use a default value.
2236  if (getLexer().isNot(AsmToken::EndOfStatement)) {
2237  switch(getLexer().getKind()) {
2238  case AsmToken::Identifier: {
2239  StringRef Tok = Parser.getTok().getString();
2240  if (Tok == Name) {
2241  Bit = 1;
2242  Parser.Lex();
2243  } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2244  Bit = 0;
2245  Parser.Lex();
2246  } else {
2247  return MatchOperand_NoMatch;
2248  }
2249  break;
2250  }
2251  default:
2252  return MatchOperand_NoMatch;
2253  }
2254  }
2255 
2256  Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2257  return MatchOperand_Success;
2258 }
2259 
2260 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
2261 
2262 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands,
2263  OptionalImmIndexMap& OptionalIdx,
2264  enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) {
2265  auto i = OptionalIdx.find(ImmT);
2266  if (i != OptionalIdx.end()) {
2267  unsigned Idx = i->second;
2268  ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2269  } else {
2270  Inst.addOperand(MCOperand::createImm(Default));
2271  }
2272 }
2273 
2275 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2276  if (getLexer().isNot(AsmToken::Identifier)) {
2277  return MatchOperand_NoMatch;
2278  }
2279  StringRef Tok = Parser.getTok().getString();
2280  if (Tok != Prefix) {
2281  return MatchOperand_NoMatch;
2282  }
2283 
2284  Parser.Lex();
2285  if (getLexer().isNot(AsmToken::Colon)) {
2286  return MatchOperand_ParseFail;
2287  }
2288 
2289  Parser.Lex();
2290  if (getLexer().isNot(AsmToken::Identifier)) {
2291  return MatchOperand_ParseFail;
2292  }
2293 
2294  Value = Parser.getTok().getString();
2295  return MatchOperand_Success;
2296 }
2297 
2298 //===----------------------------------------------------------------------===//
2299 // ds
2300 //===----------------------------------------------------------------------===//
2301 
2302 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2303  const OperandVector &Operands) {
2304  OptionalImmIndexMap OptionalIdx;
2305 
2306  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2307  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2308 
2309  // Add the register arguments
2310  if (Op.isReg()) {
2311  Op.addRegOperands(Inst, 1);
2312  continue;
2313  }
2314 
2315  // Handle optional arguments
2316  OptionalIdx[Op.getImmTy()] = i;
2317  }
2318 
2319  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2320  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2321  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2322 
2323  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2324 }
2325 
2326 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
2327  std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
2328  bool GDSOnly = false;
2329 
2330  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2331  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2332 
2333  // Add the register arguments
2334  if (Op.isReg()) {
2335  Op.addRegOperands(Inst, 1);
2336  continue;
2337  }
2338 
2339  if (Op.isToken() && Op.getToken() == "gds") {
2340  GDSOnly = true;
2341  continue;
2342  }
2343 
2344  // Handle optional arguments
2345  OptionalIdx[Op.getImmTy()] = i;
2346  }
2347 
2348  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2349  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2350 
2351  if (!GDSOnly) {
2352  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2353  }
2354  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2355 }
2356 
2357 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2358  OptionalImmIndexMap OptionalIdx;
2359 
2360  unsigned EnMask = 0;
2361  int SrcIdx = 0;
2362 
2363  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2364  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2365 
2366  // Add the register arguments
2367  if (Op.isReg()) {
2368  EnMask |= (1 << SrcIdx);
2369  Op.addRegOperands(Inst, 1);
2370  ++SrcIdx;
2371  continue;
2372  }
2373 
2374  if (Op.isOff()) {
2375  ++SrcIdx;
2376  Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2377  continue;
2378  }
2379 
2380  if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2381  Op.addImmOperands(Inst, 1);
2382  continue;
2383  }
2384 
2385  if (Op.isToken() && Op.getToken() == "done")
2386  continue;
2387 
2388  // Handle optional arguments
2389  OptionalIdx[Op.getImmTy()] = i;
2390  }
2391 
2392  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2393  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2394 
2395  Inst.addOperand(MCOperand::createImm(EnMask));
2396 }
2397 
2398 //===----------------------------------------------------------------------===//
2399 // s_waitcnt
2400 //===----------------------------------------------------------------------===//
2401 
2402 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2403  StringRef CntName = Parser.getTok().getString();
2404  int64_t CntVal;
2405 
2406  Parser.Lex();
2407  if (getLexer().isNot(AsmToken::LParen))
2408  return true;
2409 
2410  Parser.Lex();
2411  if (getLexer().isNot(AsmToken::Integer))
2412  return true;
2413 
2414  if (getParser().parseAbsoluteExpression(CntVal))
2415  return true;
2416 
2417  if (getLexer().isNot(AsmToken::RParen))
2418  return true;
2419 
2420  Parser.Lex();
2421  if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
2422  Parser.Lex();
2423 
2424  IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2425  if (CntName == "vmcnt")
2426  IntVal = encodeVmcnt(IV, IntVal, CntVal);
2427  else if (CntName == "expcnt")
2428  IntVal = encodeExpcnt(IV, IntVal, CntVal);
2429  else if (CntName == "lgkmcnt")
2430  IntVal = encodeLgkmcnt(IV, IntVal, CntVal);
2431  else
2432  return true;
2433 
2434  return false;
2435 }
2436 
2438 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2439  IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2440  int64_t Waitcnt = getWaitcntBitMask(IV);
2441  SMLoc S = Parser.getTok().getLoc();
2442 
2443  switch(getLexer().getKind()) {
2444  default: return MatchOperand_ParseFail;
2445  case AsmToken::Integer:
2446  // The operand can be an integer value.
2447  if (getParser().parseAbsoluteExpression(Waitcnt))
2448  return MatchOperand_ParseFail;
2449  break;
2450 
2451  case AsmToken::Identifier:
2452  do {
2453  if (parseCnt(Waitcnt))
2454  return MatchOperand_ParseFail;
2455  } while(getLexer().isNot(AsmToken::EndOfStatement));
2456  break;
2457  }
2458  Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
2459  return MatchOperand_Success;
2460 }
2461 
2462 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) {
2463  using namespace llvm::AMDGPU::Hwreg;
2464 
2465  if (Parser.getTok().getString() != "hwreg")
2466  return true;
2467  Parser.Lex();
2468 
2469  if (getLexer().isNot(AsmToken::LParen))
2470  return true;
2471  Parser.Lex();
2472 
2473  if (getLexer().is(AsmToken::Identifier)) {
2474  HwReg.IsSymbolic = true;
2475  HwReg.Id = ID_UNKNOWN_;
2476  const StringRef tok = Parser.getTok().getString();
2477  for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
2478  if (tok == IdSymbolic[i]) {
2479  HwReg.Id = i;
2480  break;
2481  }
2482  }
2483  Parser.Lex();
2484  } else {
2485  HwReg.IsSymbolic = false;
2486  if (getLexer().isNot(AsmToken::Integer))
2487  return true;
2488  if (getParser().parseAbsoluteExpression(HwReg.Id))
2489  return true;
2490  }
2491 
2492  if (getLexer().is(AsmToken::RParen)) {
2493  Parser.Lex();
2494  return false;
2495  }
2496 
2497  // optional params
2498  if (getLexer().isNot(AsmToken::Comma))
2499  return true;
2500  Parser.Lex();
2501 
2502  if (getLexer().isNot(AsmToken::Integer))
2503  return true;
2504  if (getParser().parseAbsoluteExpression(Offset))
2505  return true;
2506 
2507  if (getLexer().isNot(AsmToken::Comma))
2508  return true;
2509  Parser.Lex();
2510 
2511  if (getLexer().isNot(AsmToken::Integer))
2512  return true;
2513  if (getParser().parseAbsoluteExpression(Width))
2514  return true;
2515 
2516  if (getLexer().isNot(AsmToken::RParen))
2517  return true;
2518  Parser.Lex();
2519 
2520  return false;
2521 }
2522 
2524 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
2525  using namespace llvm::AMDGPU::Hwreg;
2526 
2527  int64_t Imm16Val = 0;
2528  SMLoc S = Parser.getTok().getLoc();
2529 
2530  switch(getLexer().getKind()) {
2531  default: return MatchOperand_NoMatch;
2532  case AsmToken::Integer:
2533  // The operand can be an integer value.
2534  if (getParser().parseAbsoluteExpression(Imm16Val))
2535  return MatchOperand_NoMatch;
2536  if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2537  Error(S, "invalid immediate: only 16-bit values are legal");
2538  // Do not return error code, but create an imm operand anyway and proceed
2539  // to the next operand, if any. That avoids unneccessary error messages.
2540  }
2541  break;
2542 
2543  case AsmToken::Identifier: {
2544  OperandInfoTy HwReg(ID_UNKNOWN_);
2545  int64_t Offset = OFFSET_DEFAULT_;
2546  int64_t Width = WIDTH_M1_DEFAULT_ + 1;
2547  if (parseHwregConstruct(HwReg, Offset, Width))
2548  return MatchOperand_ParseFail;
2549  if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
2550  if (HwReg.IsSymbolic)
2551  Error(S, "invalid symbolic name of hardware register");
2552  else
2553  Error(S, "invalid code of hardware register: only 6-bit values are legal");
2554  }
2555  if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
2556  Error(S, "invalid bit offset: only 5-bit values are legal");
2557  if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
2558  Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
2559  Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
2560  }
2561  break;
2562  }
2563  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
2564  return MatchOperand_Success;
2565 }
2566 
2567 bool AMDGPUOperand::isSWaitCnt() const {
2568  return isImm();
2569 }
2570 
2571 bool AMDGPUOperand::isHwreg() const {
2572  return isImmTy(ImmTyHwreg);
2573 }
2574 
2575 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
2576  using namespace llvm::AMDGPU::SendMsg;
2577 
2578  if (Parser.getTok().getString() != "sendmsg")
2579  return true;
2580  Parser.Lex();
2581 
2582  if (getLexer().isNot(AsmToken::LParen))
2583  return true;
2584  Parser.Lex();
2585 
2586  if (getLexer().is(AsmToken::Identifier)) {
2587  Msg.IsSymbolic = true;
2588  Msg.Id = ID_UNKNOWN_;
2589  const std::string tok = Parser.getTok().getString();
2590  for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
2591  switch(i) {
2592  default: continue; // Omit gaps.
2593  case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
2594  }
2595  if (tok == IdSymbolic[i]) {
2596  Msg.Id = i;
2597  break;
2598  }
2599  }
2600  Parser.Lex();
2601  } else {
2602  Msg.IsSymbolic = false;
2603  if (getLexer().isNot(AsmToken::Integer))
2604  return true;
2605  if (getParser().parseAbsoluteExpression(Msg.Id))
2606  return true;
2607  if (getLexer().is(AsmToken::Integer))
2608  if (getParser().parseAbsoluteExpression(Msg.Id))
2609  Msg.Id = ID_UNKNOWN_;
2610  }
2611  if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
2612  return false;
2613 
2614  if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
2615  if (getLexer().isNot(AsmToken::RParen))
2616  return true;
2617  Parser.Lex();
2618  return false;
2619  }
2620 
2621  if (getLexer().isNot(AsmToken::Comma))
2622  return true;
2623  Parser.Lex();
2624 
2625  assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
2626  Operation.Id = ID_UNKNOWN_;
2627  if (getLexer().is(AsmToken::Identifier)) {
2628  Operation.IsSymbolic = true;
2629  const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
2630  const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
2631  const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
2632  const StringRef Tok = Parser.getTok().getString();
2633  for (int i = F; i < L; ++i) {
2634  if (Tok == S[i]) {
2635  Operation.Id = i;
2636  break;
2637  }
2638  }
2639  Parser.Lex();
2640  } else {
2641  Operation.IsSymbolic = false;
2642  if (getLexer().isNot(AsmToken::Integer))
2643  return true;
2644  if (getParser().parseAbsoluteExpression(Operation.Id))
2645  return true;
2646  }
2647 
2648  if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2649  // Stream id is optional.
2650  if (getLexer().is(AsmToken::RParen)) {
2651  Parser.Lex();
2652  return false;
2653  }
2654 
2655  if (getLexer().isNot(AsmToken::Comma))
2656  return true;
2657  Parser.Lex();
2658 
2659  if (getLexer().isNot(AsmToken::Integer))
2660  return true;
2661  if (getParser().parseAbsoluteExpression(StreamId))
2662  return true;
2663  }
2664 
2665  if (getLexer().isNot(AsmToken::RParen))
2666  return true;
2667  Parser.Lex();
2668  return false;
2669 }
2670 
2671 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
2672  if (getLexer().getKind() != AsmToken::Identifier)
2673  return MatchOperand_NoMatch;
2674 
2675  StringRef Str = Parser.getTok().getString();
2676  int Slot = StringSwitch<int>(Str)
2677  .Case("p10", 0)
2678  .Case("p20", 1)
2679  .Case("p0", 2)
2680  .Default(-1);
2681 
2682  SMLoc S = Parser.getTok().getLoc();
2683  if (Slot == -1)
2684  return MatchOperand_ParseFail;
2685 
2686  Parser.Lex();
2687  Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
2688  AMDGPUOperand::ImmTyInterpSlot));
2689  return MatchOperand_Success;
2690 }
2691 
2692 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
2693  if (getLexer().getKind() != AsmToken::Identifier)
2694  return MatchOperand_NoMatch;
2695 
2696  StringRef Str = Parser.getTok().getString();
2697  if (!Str.startswith("attr"))
2698  return MatchOperand_NoMatch;
2699 
2700  StringRef Chan = Str.take_back(2);
2701  int AttrChan = StringSwitch<int>(Chan)
2702  .Case(".x", 0)
2703  .Case(".y", 1)
2704  .Case(".z", 2)
2705  .Case(".w", 3)
2706  .Default(-1);
2707  if (AttrChan == -1)
2708  return MatchOperand_ParseFail;
2709 
2710  Str = Str.drop_back(2).drop_front(4);
2711 
2712  uint8_t Attr;
2713  if (Str.getAsInteger(10, Attr))
2714  return MatchOperand_ParseFail;
2715 
2716  SMLoc S = Parser.getTok().getLoc();
2717  Parser.Lex();
2718  if (Attr > 63) {
2719  Error(S, "out of bounds attr");
2720  return MatchOperand_Success;
2721  }
2722 
2723  SMLoc SChan = SMLoc::getFromPointer(Chan.data());
2724 
2725  Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
2726  AMDGPUOperand::ImmTyInterpAttr));
2727  Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
2728  AMDGPUOperand::ImmTyAttrChan));
2729  return MatchOperand_Success;
2730 }
2731 
2732 void AMDGPUAsmParser::errorExpTgt() {
2733  Error(Parser.getTok().getLoc(), "invalid exp target");
2734 }
2735 
2736 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
2737  uint8_t &Val) {
2738  if (Str == "null") {
2739  Val = 9;
2740  return MatchOperand_Success;
2741  }
2742 
2743  if (Str.startswith("mrt")) {
2744  Str = Str.drop_front(3);
2745  if (Str == "z") { // == mrtz
2746  Val = 8;
2747  return MatchOperand_Success;
2748  }
2749 
2750  if (Str.getAsInteger(10, Val))
2751  return MatchOperand_ParseFail;
2752 
2753  if (Val > 7)
2754  errorExpTgt();
2755 
2756  return MatchOperand_Success;
2757  }
2758 
2759  if (Str.startswith("pos")) {
2760  Str = Str.drop_front(3);
2761  if (Str.getAsInteger(10, Val))
2762  return MatchOperand_ParseFail;
2763 
2764  if (Val > 3)
2765  errorExpTgt();
2766 
2767  Val += 12;
2768  return MatchOperand_Success;
2769  }
2770 
2771  if (Str.startswith("param")) {
2772  Str = Str.drop_front(5);
2773  if (Str.getAsInteger(10, Val))
2774  return MatchOperand_ParseFail;
2775 
2776  if (Val >= 32)
2777  errorExpTgt();
2778 
2779  Val += 32;
2780  return MatchOperand_Success;
2781  }
2782 
2783  if (Str.startswith("invalid_target_")) {
2784  Str = Str.drop_front(15);
2785  if (Str.getAsInteger(10, Val))
2786  return MatchOperand_ParseFail;
2787 
2788  errorExpTgt();
2789  return MatchOperand_Success;
2790  }
2791 
2792  return MatchOperand_NoMatch;
2793 }
2794 
2795 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
2796  uint8_t Val;
2797  StringRef Str = Parser.getTok().getString();
2798 
2799  auto Res = parseExpTgtImpl(Str, Val);
2800  if (Res != MatchOperand_Success)
2801  return Res;
2802 
2803  SMLoc S = Parser.getTok().getLoc();
2804  Parser.Lex();
2805 
2806  Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
2807  AMDGPUOperand::ImmTyExpTgt));
2808  return MatchOperand_Success;
2809 }
2810 
2812 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
2813  using namespace llvm::AMDGPU::SendMsg;
2814 
2815  int64_t Imm16Val = 0;
2816  SMLoc S = Parser.getTok().getLoc();
2817 
2818  switch(getLexer().getKind()) {
2819  default:
2820  return MatchOperand_NoMatch;
2821  case AsmToken::Integer:
2822  // The operand can be an integer value.
2823  if (getParser().parseAbsoluteExpression(Imm16Val))
2824  return MatchOperand_NoMatch;
2825  if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2826  Error(S, "invalid immediate: only 16-bit values are legal");
2827  // Do not return error code, but create an imm operand anyway and proceed
2828  // to the next operand, if any. That avoids unneccessary error messages.
2829  }
2830  break;
2831  case AsmToken::Identifier: {
2832  OperandInfoTy Msg(ID_UNKNOWN_);
2833  OperandInfoTy Operation(OP_UNKNOWN_);
2834  int64_t StreamId = STREAM_ID_DEFAULT_;
2835  if (parseSendMsgConstruct(Msg, Operation, StreamId))
2836  return MatchOperand_ParseFail;
2837  do {
2838  // Validate and encode message ID.
2839  if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
2840  || Msg.Id == ID_SYSMSG)) {
2841  if (Msg.IsSymbolic)
2842  Error(S, "invalid/unsupported symbolic name of message");
2843  else
2844  Error(S, "invalid/unsupported code of message");
2845  break;
2846  }
2847  Imm16Val = (Msg.Id << ID_SHIFT_);
2848  // Validate and encode operation ID.
2849  if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
2850  if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
2851  if (Operation.IsSymbolic)
2852  Error(S, "invalid symbolic name of GS_OP");
2853  else
2854  Error(S, "invalid code of GS_OP: only 2-bit values are legal");
2855  break;
2856  }
2857  if (Operation.Id == OP_GS_NOP
2858  && Msg.Id != ID_GS_DONE) {
2859  Error(S, "invalid GS_OP: NOP is for GS_DONE only");
2860  break;
2861  }
2862  Imm16Val |= (Operation.Id << OP_SHIFT_);
2863  }
2864  if (Msg.Id == ID_SYSMSG) {
2865  if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
2866  if (Operation.IsSymbolic)
2867  Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
2868  else
2869  Error(S, "invalid/unsupported code of SYSMSG_OP");
2870  break;
2871  }
2872  Imm16Val |= (Operation.Id << OP_SHIFT_);
2873  }
2874  // Validate and encode stream ID.
2875  if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2876  if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
2877  Error(S, "invalid stream id: only 2-bit values are legal");
2878  break;
2879  }
2880  Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
2881  }
2882  } while (false);
2883  }
2884  break;
2885  }
2886  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
2887  return MatchOperand_Success;
2888 }
2889 
2890 bool AMDGPUOperand::isSendMsg() const {
2891  return isImmTy(ImmTySendMsg);
2892 }
2893 
2894 //===----------------------------------------------------------------------===//
2895 // sopp branch targets
2896 //===----------------------------------------------------------------------===//
2897 
2899 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
2900  SMLoc S = Parser.getTok().getLoc();
2901 
2902  switch (getLexer().getKind()) {
2903  default: return MatchOperand_ParseFail;
2904  case AsmToken::Integer: {
2905  int64_t Imm;
2906  if (getParser().parseAbsoluteExpression(Imm))
2907  return MatchOperand_ParseFail;
2908  Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
2909  return MatchOperand_Success;
2910  }
2911 
2912  case AsmToken::Identifier:
2913  Operands.push_back(AMDGPUOperand::CreateExpr(this,
2914  MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
2915  Parser.getTok().getString()), getContext()), S));
2916  Parser.Lex();
2917  return MatchOperand_Success;
2918  }
2919 }
2920 
2921 //===----------------------------------------------------------------------===//
2922 // mubuf
2923 //===----------------------------------------------------------------------===//
2924 
2925 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
2926  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
2927 }
2928 
2929 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
2930  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
2931 }
2932 
2933 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2934  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
2935 }
2936 
2937 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
2938  const OperandVector &Operands,
2939  bool IsAtomic, bool IsAtomicReturn) {
2940  OptionalImmIndexMap OptionalIdx;
2941  assert(IsAtomicReturn ? IsAtomic : true);
2942 
2943  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2944  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2945 
2946  // Add the register arguments
2947  if (Op.isReg()) {
2948  Op.addRegOperands(Inst, 1);
2949  continue;
2950  }
2951 
2952  // Handle the case where soffset is an immediate
2953  if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
2954  Op.addImmOperands(Inst, 1);
2955  continue;
2956  }
2957 
2958  // Handle tokens like 'offen' which are sometimes hard-coded into the
2959  // asm string. There are no MCInst operands for these.
2960  if (Op.isToken()) {
2961  continue;
2962  }
2963  assert(Op.isImm());
2964 
2965  // Handle optional arguments
2966  OptionalIdx[Op.getImmTy()] = i;
2967  }
2968 
2969  // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2970  if (IsAtomicReturn) {
2971  MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
2972  Inst.insert(I, *I);
2973  }
2974 
2975  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2976  if (!IsAtomic) { // glc is hard-coded.
2977  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2978  }
2979  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2980  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2981 }
2982 
2983 //===----------------------------------------------------------------------===//
2984 // mimg
2985 //===----------------------------------------------------------------------===//
2986 
2987 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
2988  unsigned I = 1;
2989  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2990  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2991  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2992  }
2993 
2994  OptionalImmIndexMap OptionalIdx;
2995 
2996  for (unsigned E = Operands.size(); I != E; ++I) {
2997  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2998 
2999  // Add the register arguments
3000  if (Op.isRegOrImm()) {
3001  Op.addRegOrImmOperands(Inst, 1);
3002  continue;
3003  } else if (Op.isImmModifier()) {
3004  OptionalIdx[Op.getImmTy()] = I;
3005  } else {
3006  llvm_unreachable("unexpected operand type");
3007  }
3008  }
3009 
3010  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3011  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3012  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3013  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3014  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3015  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3016  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3017  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3018 }
3019 
3020 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
3021  unsigned I = 1;
3022  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3023  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3024  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3025  }
3026 
3027  // Add src, same as dst
3028  ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
3029 
3030  OptionalImmIndexMap OptionalIdx;
3031 
3032  for (unsigned E = Operands.size(); I != E; ++I) {
3033  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3034 
3035  // Add the register arguments
3036  if (Op.isRegOrImm()) {
3037  Op.addRegOrImmOperands(Inst, 1);
3038  continue;
3039  } else if (Op.isImmModifier()) {
3040  OptionalIdx[Op.getImmTy()] = I;
3041  } else {
3042  llvm_unreachable("unexpected operand type");
3043  }
3044  }
3045 
3046  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3047  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3048  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3049  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3050  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3051  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3052  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3053  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3054 }
3055 
3056 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
3057  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
3058 }
3059 
3060 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
3061  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
3062 }
3063 
3064 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
3065  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
3066 }
3067 
3068 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
3069  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3070 }
3071 
3072 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3073  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3074 }
3075 
3076 //===----------------------------------------------------------------------===//
3077 // smrd
3078 //===----------------------------------------------------------------------===//
3079 
3080 bool AMDGPUOperand::isSMRDOffset8() const {
3081  return isImm() && isUInt<8>(getImm());
3082 }
3083 
3084 bool AMDGPUOperand::isSMRDOffset20() const {
3085  return isImm() && isUInt<20>(getImm());
3086 }
3087 
3088 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3089  // 32-bit literals are only supported on CI and we only want to use them
3090  // when the offset is > 8-bits.
3091  return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3092 }
3093 
3094 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3095  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3096 }
3097 
3098 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3099  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3100 }
3101 
3102 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3103  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3104 }
3105 
3106 //===----------------------------------------------------------------------===//
3107 // vop3
3108 //===----------------------------------------------------------------------===//
3109 
3110 static bool ConvertOmodMul(int64_t &Mul) {
3111  if (Mul != 1 && Mul != 2 && Mul != 4)
3112  return false;
3113 
3114  Mul >>= 1;
3115  return true;
3116 }
3117 
3118 static bool ConvertOmodDiv(int64_t &Div) {
3119  if (Div == 1) {
3120  Div = 0;
3121  return true;
3122  }
3123 
3124  if (Div == 2) {
3125  Div = 3;
3126  return true;
3127  }
3128 
3129  return false;
3130 }
3131 
3132 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
3133  if (BoundCtrl == 0) {
3134  BoundCtrl = 1;
3135  return true;
3136  }
3137 
3138  if (BoundCtrl == -1) {
3139  BoundCtrl = 0;
3140  return true;
3141  }
3142 
3143  return false;
3144 }
3145 
3146 // Note: the order in this table matches the order of operands in AsmString.
3147 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
3148  {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
3149  {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
3150  {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
3151  {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
3152  {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
3153  {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
3154  {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
3155  {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
3156  {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
3157  {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
3158  {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
3159  {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
3160  {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
3161  {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
3162  {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
3163  {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
3164  {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
3165  {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
3166  {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
3167  {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
3168  {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
3169  {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
3170  {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
3171  {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
3172  {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
3173 };
3174 
3175 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
3177  for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
3178  // try to parse any optional operand here
3179  if (Op.IsBit) {
3180  res = parseNamedBit(Op.Name, Operands, Op.Type);
3181  } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
3182  res = parseOModOperand(Operands);
3183  } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
3184  Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
3185  Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
3186  res = parseSDWASel(Operands, Op.Name, Op.Type);
3187  } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
3188  res = parseSDWADstUnused(Operands);
3189  } else {
3190  res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
3191  }
3192  if (res != MatchOperand_NoMatch) {
3193  return res;
3194  }
3195  }
3196  return MatchOperand_NoMatch;
3197 }
3198 
3199 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
3200  StringRef Name = Parser.getTok().getString();
3201  if (Name == "mul") {
3202  return parseIntWithPrefix("mul", Operands,
3203  AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
3204  }
3205 
3206  if (Name == "div") {
3207  return parseIntWithPrefix("div", Operands,
3208  AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
3209  }
3210 
3211  return MatchOperand_NoMatch;
3212 }
3213 
3214 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
3215  unsigned I = 1;
3216  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3217  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3218  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3219  }
3220  for (unsigned E = Operands.size(); I != E; ++I)
3221  ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
3222 }
3223 
3224 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
3225  uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3226  if (TSFlags & SIInstrFlags::VOP3) {
3227  cvtVOP3(Inst, Operands);
3228  } else {
3229  cvtId(Inst, Operands);
3230  }
3231 }
3232 
3233 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
3234  // 1. This operand is input modifiers
3235  return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
3236  // 2. This is not last operand
3237  && Desc.NumOperands > (OpNum + 1)
3238  // 3. Next operand is register class
3239  && Desc.OpInfo[OpNum + 1].RegClass != -1
3240  // 4. Next register is not tied to any other operand
3241  && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
3242 }
3243 
3244 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
3245  OptionalImmIndexMap OptionalIdx;
3246  unsigned I = 1;
3247  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3248  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3249  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3250  }
3251 
3252  for (unsigned E = Operands.size(); I != E; ++I) {
3253  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3254  if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3255  Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
3256  } else if (Op.isImm()) {
3257  OptionalIdx[Op.getImmTy()] = I;
3258  } else {
3259  llvm_unreachable("unhandled operand type");
3260  }
3261  }
3262 
3263  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
3264  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
3265 
3266  // special case v_mac_{f16, f32}:
3267  // it has src2 register operand that is tied to dst operand
3268  // we don't allow modifiers for this operand in assembler so src2_modifiers
3269  // should be 0
3270  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
3271  Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
3272  Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
3273  auto it = Inst.begin();
3274  std::advance(
3275  it,
3276  AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
3277  AMDGPU::V_MAC_F16_e64 :
3278  AMDGPU::V_MAC_F32_e64,
3279  AMDGPU::OpName::src2_modifiers));
3280  it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
3281  ++it;
3282  Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3283  }
3284 }
3285 
3286 //===----------------------------------------------------------------------===//
3287 // dpp
3288 //===----------------------------------------------------------------------===//
3289 
3290 bool AMDGPUOperand::isDPPCtrl() const {
3291  bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
3292  if (result) {
3293  int64_t Imm = getImm();
3294  return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
3295  ((Imm >= 0x101) && (Imm <= 0x10f)) ||
3296  ((Imm >= 0x111) && (Imm <= 0x11f)) ||
3297  ((Imm >= 0x121) && (Imm <= 0x12f)) ||
3298  (Imm == 0x130) ||
3299  (Imm == 0x134) ||
3300  (Imm == 0x138) ||
3301  (Imm == 0x13c) ||
3302  (Imm == 0x140) ||
3303  (Imm == 0x141) ||
3304  (Imm == 0x142) ||
3305  (Imm == 0x143);
3306  }
3307  return false;
3308 }
3309 
3310 bool AMDGPUOperand::isGPRIdxMode() const {
3311  return isImm() && isUInt<4>(getImm());
3312 }
3313 
3315 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
3316  SMLoc S = Parser.getTok().getLoc();
3317  StringRef Prefix;
3318  int64_t Int;
3319 
3320  if (getLexer().getKind() == AsmToken::Identifier) {
3321  Prefix = Parser.getTok().getString();
3322  } else {
3323  return MatchOperand_NoMatch;
3324  }
3325 
3326  if (Prefix == "row_mirror") {
3327  Int = 0x140;
3328  Parser.Lex();
3329  } else if (Prefix == "row_half_mirror") {
3330  Int = 0x141;
3331  Parser.Lex();
3332  } else {
3333  // Check to prevent parseDPPCtrlOps from eating invalid tokens
3334  if (Prefix != "quad_perm"
3335  && Prefix != "row_shl"
3336  && Prefix != "row_shr"
3337  && Prefix != "row_ror"
3338  && Prefix != "wave_shl"
3339  && Prefix != "wave_rol"
3340  && Prefix != "wave_shr"
3341  && Prefix != "wave_ror"
3342  && Prefix != "row_bcast") {
3343  return MatchOperand_NoMatch;
3344  }
3345 
3346  Parser.Lex();
3347  if (getLexer().isNot(AsmToken::Colon))
3348  return MatchOperand_ParseFail;
3349 
3350  if (Prefix == "quad_perm") {
3351  // quad_perm:[%d,%d,%d,%d]
3352  Parser.Lex();
3353  if (getLexer().isNot(AsmToken::LBrac))
3354  return MatchOperand_ParseFail;
3355  Parser.Lex();
3356 
3357  if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
3358  return MatchOperand_ParseFail;
3359 
3360  for (int i = 0; i < 3; ++i) {
3361  if (getLexer().isNot(AsmToken::Comma))
3362  return MatchOperand_ParseFail;
3363  Parser.Lex();
3364 
3365  int64_t Temp;
3366  if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
3367  return MatchOperand_ParseFail;
3368  const int shift = i*2 + 2;
3369  Int += (Temp << shift);
3370  }
3371 
3372  if (getLexer().isNot(AsmToken::RBrac))
3373  return MatchOperand_ParseFail;
3374  Parser.Lex();
3375 
3376  } else {
3377  // sel:%d
3378  Parser.Lex();
3379  if (getParser().parseAbsoluteExpression(Int))
3380  return MatchOperand_ParseFail;
3381 
3382  if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
3383  Int |= 0x100;
3384  } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
3385  Int |= 0x110;
3386  } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
3387  Int |= 0x120;
3388  } else if (Prefix == "wave_shl" && 1 == Int) {
3389  Int = 0x130;
3390  } else if (Prefix == "wave_rol" && 1 == Int) {
3391  Int = 0x134;
3392  } else if (Prefix == "wave_shr" && 1 == Int) {
3393  Int = 0x138;
3394  } else if (Prefix == "wave_ror" && 1 == Int) {
3395  Int = 0x13C;
3396  } else if (Prefix == "row_bcast") {
3397  if (Int == 15) {
3398  Int = 0x142;
3399  } else if (Int == 31) {
3400  Int = 0x143;
3401  } else {
3402  return MatchOperand_ParseFail;
3403  }
3404  } else {
3405  return MatchOperand_ParseFail;
3406  }
3407  }
3408  }
3409 
3410  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
3411  return MatchOperand_Success;
3412 }
3413 
3414 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
3415  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
3416 }
3417 
3418 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
3419  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
3420 }
3421 
3422 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
3423  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
3424 }
3425 
3426 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
3427  OptionalImmIndexMap OptionalIdx;
3428 
3429  unsigned I = 1;
3430  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3431  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3432  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3433  }
3434 
3435  for (unsigned E = Operands.size(); I != E; ++I) {
3436  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3437  // Add the register arguments
3438  if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
3439  // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token.
3440  // Skip it.
3441  continue;
3442  } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3443  Op.addRegWithFPInputModsOperands(Inst, 2);
3444  } else if (Op.isDPPCtrl()) {
3445  Op.addImmOperands(Inst, 1);
3446  } else if (Op.isImm()) {
3447  // Handle optional arguments
3448  OptionalIdx[Op.getImmTy()] = I;
3449  } else {
3450  llvm_unreachable("Invalid operand type");
3451  }
3452  }
3453 
3454  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
3455  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
3456  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
3457 
3458  // special case v_mac_{f16, f32}:
3459  // it has src2 register operand that is tied to dst operand
3460  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
3461  Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
3462  auto it = Inst.begin();
3463  std::advance(
3464  it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3465  Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3466  }
3467 }
3468 
3469 //===----------------------------------------------------------------------===//
3470 // sdwa
3471 //===----------------------------------------------------------------------===//
3472 
3474 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
3475  AMDGPUOperand::ImmTy Type) {
3476  using namespace llvm::AMDGPU::SDWA;
3477 
3478  SMLoc S = Parser.getTok().getLoc();
3479  StringRef Value;
3481 
3482  res = parseStringWithPrefix(Prefix, Value);
3483  if (res != MatchOperand_Success) {
3484  return res;
3485  }
3486 
3487  int64_t Int;
3488  Int = StringSwitch<int64_t>(Value)
3489  .Case("BYTE_0", SdwaSel::BYTE_0)
3490  .Case("BYTE_1", SdwaSel::BYTE_1)
3491  .Case("BYTE_2", SdwaSel::BYTE_2)
3492  .Case("BYTE_3", SdwaSel::BYTE_3)
3493  .Case("WORD_0", SdwaSel::WORD_0)
3494  .Case("WORD_1", SdwaSel::WORD_1)
3495  .Case("DWORD", SdwaSel::DWORD)
3496  .Default(0xffffffff);
3497  Parser.Lex(); // eat last token
3498 
3499  if (Int == 0xffffffff) {
3500  return MatchOperand_ParseFail;
3501  }
3502 
3503  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
3504  return MatchOperand_Success;
3505 }
3506 
3508 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
3509  using namespace llvm::AMDGPU::SDWA;
3510 
3511  SMLoc S = Parser.getTok().getLoc();
3512  StringRef Value;
3514 
3515  res = parseStringWithPrefix("dst_unused", Value);
3516  if (res != MatchOperand_Success) {
3517  return res;
3518  }
3519 
3520  int64_t Int;
3521  Int = StringSwitch<int64_t>(Value)
3522  .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
3523  .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
3524  .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
3525  .Default(0xffffffff);
3526  Parser.Lex(); // eat last token
3527 
3528  if (Int == 0xffffffff) {
3529  return MatchOperand_ParseFail;
3530  }
3531 
3532  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
3533  return MatchOperand_Success;
3534 }
3535 
3536 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
3537  cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
3538 }
3539 
3540 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
3541  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
3542 }
3543 
3544 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
3545  cvtSDWA(Inst, Operands, SIInstrFlags::VOPC);
3546 }
3547 
3548 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
3549  uint64_t BasicInstType) {
3550  OptionalImmIndexMap OptionalIdx;
3551 
3552  unsigned I = 1;
3553  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3554  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3555  ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3556  }
3557 
3558  for (unsigned E = Operands.size(); I != E; ++I) {
3559  AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3560  // Add the register arguments
3561  if ((BasicInstType == SIInstrFlags::VOPC ||
3562  BasicInstType == SIInstrFlags::VOP2)&&
3563  Op.isReg() &&
3564  Op.Reg.RegNo == AMDGPU::VCC) {
3565  // VOPC and VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
3566  // Skip it.
3567  continue;
3568  } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3569  Op.addRegWithInputModsOperands(Inst, 2);
3570  } else if (Op.isImm()) {
3571  // Handle optional arguments
3572  OptionalIdx[Op.getImmTy()] = I;
3573  } else {
3574  llvm_unreachable("Invalid operand type");
3575  }
3576  }
3577 
3578  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
3579 
3580  if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
3581  // V_NOP_sdwa_vi has no optional sdwa arguments
3582  switch (BasicInstType) {
3583  case SIInstrFlags::VOP1:
3584  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3585  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3586  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3587  break;
3588 
3589  case SIInstrFlags::VOP2:
3590  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3591  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3592  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3593  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3594  break;
3595 
3596  case SIInstrFlags::VOPC:
3597  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3598  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3599  break;
3600 
3601  default:
3602  llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
3603  }
3604  }
3605 
3606  // special case v_mac_{f16, f32}:
3607  // it has src2 register operand that is tied to dst operand
3608  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
3609  Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
3610  auto it = Inst.begin();
3611  std::advance(
3612  it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3613  Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3614  }
3615 
3616 }
3617 
3618 /// Force static initialization.
3622 }
3623 
3624 #define GET_REGISTER_MATCHER
3625 #define GET_MATCHER_IMPLEMENTATION
3626 #include "AMDGPUGenAsmMatcher.inc"
3627 
3628 // This fuction should be defined after auto-generated include so that we have
3629 // MatchClassKind enum defined
3630 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
3631  unsigned Kind) {
3632  // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
3633  // But MatchInstructionImpl() expects to meet token and fails to validate
3634  // operand. This method checks if we are given immediate operand but expect to
3635  // get corresponding token.
3636  AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
3637  switch (Kind) {
3638  case MCK_addr64:
3639  return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
3640  case MCK_gds:
3641  return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
3642  case MCK_glc:
3643  return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
3644  case MCK_idxen:
3645  return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
3646  case MCK_offen:
3647  return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
3648  case MCK_SSrcB32:
3649  // When operands have expression values, they will return true for isToken,
3650  // because it is not possible to distinguish between a token and an
3651  // expression at parse time. MatchInstructionImpl() will always try to
3652  // match an operand as a token, when isToken returns true, and when the
3653  // name of the expression is not a valid token, the match will fail,
3654  // so we need to handle it here.
3655  return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
3656  case MCK_SSrcF32:
3657  return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
3658  case MCK_SoppBrTarget:
3659  return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
3660  case MCK_VReg32OrOff:
3661  return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
3662  case MCK_InterpSlot:
3663  return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
3664  case MCK_Attr:
3665  return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
3666  case MCK_AttrChan:
3667  return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
3668  default:
3669  return Match_InvalidOperand;
3670  }
3671 }
MachineLoop * L
static bool isReg(const MCInst &MI, unsigned OpNo)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:634
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:494
constexpr bool isUInt< 32 >(uint64_t x)
Definition: MathExtras.h:315
void push_back(const T &Elt)
Definition: SmallVector.h:211
iterator begin()
Definition: MCInst.h:175
Target & getTheGCNTarget()
The target for GCN GPUs.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:276
static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum)
uint64_t Token
const MCSymbol & getSymbol() const
Definition: MCExpr.h:311
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:298
size_t i
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_back(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:608
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:216
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:129
constexpr uint32_t Lo_32(uint64_t Value)
Lo_32 - This function returns the low 32 bits of a 64 bit value.
Definition: MathExtras.h:253
Target & getTheAMDGPUTarget()
The target which suports all AMD GPUs.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:163
MachineInstrBuilder MachineInstrBuilder &DefMI const MCInstrDesc & Desc
unsigned getScalarSizeInBits() const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmLexer.h:114
static unsigned getSpecialRegForName(StringRef RegName)
unsigned getSizeInBits() const
MCSection * getHSATextSection(MCContext &Ctx)
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:490
OperandMatchResultTy
constexpr bool isInt< 16 >(int64_t x)
Definition: MathExtras.h:271
MCSection * getHSARodataReadonlyAgentSection(MCContext &Ctx)
unsigned getWaitcntBitMask(IsaVersion Version)
static bool ConvertOmodDiv(int64_t &Div)
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:765
bool parseAmdKernelCodeField(StringRef ID, MCAsmParser &Parser, amd_kernel_code_t &C, raw_ostream &Err)
bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:111
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
RegisterKind
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:440
std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
AMD Kernel Code Object (amd_kernel_code_t).
static void advance(T &it, size_t Val)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:32
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(const T &Value) const
Definition: StringSwitch.h:244
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:166
Reg
All possible values of the reg field in the ModR/M byte.
Target independent representation for an assembler token.
Definition: MCAsmLexer.h:25
static int getRegClass(RegisterKind Is, unsigned RegWidth)
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:161
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:135
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 encodeExpcnt(IsaVersion Version, unsigned Waitcnt, unsigned Expcnt)
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:82
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:74
#define F(x, y, z)
Definition: MD5.cpp:51
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:264
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
MCRegisterClass - Base class of TargetRegisterClass.
iterator insert(iterator I, const MCOperand &Op)
Definition: MCInst.h:179
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
unsigned short NumOperands
Definition: MCInstrDesc.h:166
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?
MCSection * getHSADataGlobalAgentSection(MCContext &Ctx)
MCSection * getHSADataGlobalProgramSection(MCContext &Ctx)
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:161
bool isSI(const MCSubtargetInfo &STI)
constexpr bool isUInt< 8 >(uint64_t x)
Definition: MathExtras.h:309
unsigned const MachineRegisterInfo * MRI
IsaVersion getIsaVersion(const FeatureBitset &Features)
MVT - Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
const char *const IdSymbolic[]
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:28
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:587
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned encodeLgkmcnt(IsaVersion Version, unsigned Waitcnt, unsigned Lgkmcnt)
MCRegAliasIterator enumerates all registers aliasing Reg.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
uint32_t Offset
static const OptionalOperand AMDGPUOptionalOperandTable[]
void addOptionalImmOperand(MCInst &Inst, const OperandVector &Operands, OptionalImmIndexMap &OptionalIdx, enum AMDGPUOperand::ImmTy ImmT, int64_t Default=0)
SMLoc getLoc() const
Definition: MCInst.h:162
bool isIntN(unsigned N, int64_t x)
isIntN - Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:366
void setLoc(SMLoc loc)
Definition: MCInst.h:161
void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, const FeatureBitset &Features)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set.
Definition: MCInstrDesc.h:187
static bool ConvertBoundCtrl(int64_t &BoundCtrl)
constexpr bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:274
Promote Memory to Register
Definition: Mem2Reg.cpp:100
static bool ConvertOmodMul(int64_t &Mul)
double BitsToDouble(uint64_t Bits)
BitsToDouble - This function takes a 64-bit integer and returns the bit equivalent double...
Definition: MathExtras.h:549
void LLVMInitializeAMDGPUAsmParser()
Force static initialization.
unsigned encodeVmcnt(IsaVersion Version, unsigned Waitcnt, unsigned Vmcnt)
unsigned getOpcode() const
Definition: MCInst.h:159
Class for arbitrary precision integers.
Definition: APInt.h:77
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const char *const OpSysSymbolic[]
Base class for user error types.
bool isCI(const MCSubtargetInfo &STI)
static const fltSemantics & IEEEdouble()
Definition: APFloat.cpp:103
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:37
const char *const OpGsSymbolic[]
Provides AMDGPU specific target descriptions.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser, for use in the target machine initialization function.
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:199
static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT)
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:76
unsigned getNumOperands() const
Definition: MCInst.h:166
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:135
constexpr bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:312
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Definition: APInt.h:1726
const unsigned Kind
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Can this operand also contain immediate values?
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:463
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM Value Representation.
Definition: Value.h:71
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:174
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg...
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
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:125
static const fltSemantics * getFltSemantics(unsigned Size)
void addOperand(const MCOperand &Op)
Definition: MCInst.h:168
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:643
int * Ptr
Represents a location in source code.
Definition: SMLoc.h:24
bool isUIntN(unsigned N, uint64_t x)
isUIntN - Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:360
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
std::map< enum AMDGPUOperand::ImmTy, unsigned > OptionalImmIndexMap
Root of the metadata hierarchy.
Definition: Metadata.h:55
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:117
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:164