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