Bug Summary

File:lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Warning:line 2604, column 3
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

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