Bug Summary

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