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