Bug Summary

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