1 //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 11 #include "MCTargetDesc/AMDGPUTargetStreamer.h" 12 #include "Utils/AMDGPUBaseInfo.h" 13 #include "AMDKernelCodeT.h" 14 #include "SIDefines.h" 15 #include "llvm/ADT/APFloat.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/StringSwitch.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstrInfo.h" 25 #include "llvm/MC/MCParser/MCAsmLexer.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 28 #include "llvm/MC/MCRegisterInfo.h" 29 #include "llvm/MC/MCStreamer.h" 30 #include "llvm/MC/MCSubtargetInfo.h" 31 #include "llvm/MC/MCTargetAsmParser.h" 32 #include "llvm/Support/SourceMgr.h" 33 #include "llvm/Support/TargetRegistry.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include "llvm/Support/Debug.h" 36 37 using namespace llvm; 38 39 namespace { 40 41 struct OptionalOperand; 42 43 class AMDGPUOperand : public MCParsedAsmOperand { 44 enum KindTy { 45 Token, 46 Immediate, 47 Register, 48 Expression 49 } Kind; 50 51 SMLoc StartLoc, EndLoc; 52 53 public: 54 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {} 55 56 MCContext *Ctx; 57 58 enum ImmTy { 59 ImmTyNone, 60 ImmTyDSOffset0, 61 ImmTyDSOffset1, 62 ImmTyGDS, 63 ImmTyOffset, 64 ImmTyGLC, 65 ImmTySLC, 66 ImmTyTFE, 67 ImmTyClamp, 68 ImmTyOMod 69 }; 70 71 struct TokOp { 72 const char *Data; 73 unsigned Length; 74 }; 75 76 struct ImmOp { 77 bool IsFPImm; 78 ImmTy Type; 79 int64_t Val; 80 }; 81 82 struct RegOp { 83 unsigned RegNo; 84 int Modifiers; 85 const MCRegisterInfo *TRI; 86 bool IsForcedVOP3; 87 }; 88 89 union { 90 TokOp Tok; 91 ImmOp Imm; 92 RegOp Reg; 93 const MCExpr *Expr; 94 }; 95 96 void addImmOperands(MCInst &Inst, unsigned N) const { 97 Inst.addOperand(MCOperand::createImm(getImm())); 98 } 99 100 StringRef getToken() const { 101 return StringRef(Tok.Data, Tok.Length); 102 } 103 104 void addRegOperands(MCInst &Inst, unsigned N) const { 105 Inst.addOperand(MCOperand::createReg(getReg())); 106 } 107 108 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 109 if (isReg()) 110 addRegOperands(Inst, N); 111 else 112 addImmOperands(Inst, N); 113 } 114 115 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 116 Inst.addOperand(MCOperand::createImm( 117 Reg.Modifiers == -1 ? 0 : Reg.Modifiers)); 118 addRegOperands(Inst, N); 119 } 120 121 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 122 if (isImm()) 123 addImmOperands(Inst, N); 124 else { 125 assert(isExpr()); 126 Inst.addOperand(MCOperand::createExpr(Expr)); 127 } 128 } 129 130 bool defaultTokenHasSuffix() const { 131 StringRef Token(Tok.Data, Tok.Length); 132 133 return Token.endswith("_e32") || Token.endswith("_e64"); 134 } 135 136 bool isToken() const override { 137 return Kind == Token; 138 } 139 140 bool isImm() const override { 141 return Kind == Immediate; 142 } 143 144 bool isInlineImm() const { 145 float F = BitsToFloat(Imm.Val); 146 // TODO: Add 0.5pi for VI 147 return isImm() && ((Imm.Val <= 64 && Imm.Val >= -16) || 148 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 || 149 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0)); 150 } 151 152 bool isDSOffset0() const { 153 assert(isImm()); 154 return Imm.Type == ImmTyDSOffset0; 155 } 156 157 bool isDSOffset1() const { 158 assert(isImm()); 159 return Imm.Type == ImmTyDSOffset1; 160 } 161 162 int64_t getImm() const { 163 return Imm.Val; 164 } 165 166 enum ImmTy getImmTy() const { 167 assert(isImm()); 168 return Imm.Type; 169 } 170 171 bool isRegKind() const { 172 return Kind == Register; 173 } 174 175 bool isReg() const override { 176 return Kind == Register && Reg.Modifiers == -1; 177 } 178 179 bool isRegWithInputMods() const { 180 return Kind == Register && (Reg.IsForcedVOP3 || Reg.Modifiers != -1); 181 } 182 183 void setModifiers(unsigned Mods) { 184 assert(isReg()); 185 Reg.Modifiers = Mods; 186 } 187 188 bool hasModifiers() const { 189 assert(isRegKind()); 190 return Reg.Modifiers != -1; 191 } 192 193 unsigned getReg() const override { 194 return Reg.RegNo; 195 } 196 197 bool isRegOrImm() const { 198 return isReg() || isImm(); 199 } 200 201 bool isRegClass(unsigned RCID) const { 202 return Reg.TRI->getRegClass(RCID).contains(getReg()); 203 } 204 205 bool isSCSrc32() const { 206 return isInlineImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); 207 } 208 209 bool isSSrc32() const { 210 return isImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); 211 } 212 213 bool isSSrc64() const { 214 return isImm() || isInlineImm() || 215 (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)); 216 } 217 218 bool isSCSrc64() const { 219 return (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)) || isInlineImm(); 220 } 221 222 bool isVCSrc32() const { 223 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); 224 } 225 226 bool isVCSrc64() const { 227 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); 228 } 229 230 bool isVSrc32() const { 231 return isImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); 232 } 233 234 bool isVSrc64() const { 235 return isImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); 236 } 237 238 bool isMem() const override { 239 return false; 240 } 241 242 bool isExpr() const { 243 return Kind == Expression; 244 } 245 246 bool isSoppBrTarget() const { 247 return isExpr() || isImm(); 248 } 249 250 SMLoc getStartLoc() const override { 251 return StartLoc; 252 } 253 254 SMLoc getEndLoc() const override { 255 return EndLoc; 256 } 257 258 void print(raw_ostream &OS) const override { 259 switch (Kind) { 260 case Register: 261 OS << "<register " << getReg() << " mods: " << Reg.Modifiers << '>'; 262 break; 263 case Immediate: 264 OS << getImm(); 265 break; 266 case Token: 267 OS << '\'' << getToken() << '\''; 268 break; 269 case Expression: 270 OS << "<expr " << *Expr << '>'; 271 break; 272 } 273 } 274 275 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val, SMLoc Loc, 276 enum ImmTy Type = ImmTyNone, 277 bool IsFPImm = false) { 278 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate); 279 Op->Imm.Val = Val; 280 Op->Imm.IsFPImm = IsFPImm; 281 Op->Imm.Type = Type; 282 Op->StartLoc = Loc; 283 Op->EndLoc = Loc; 284 return Op; 285 } 286 287 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc, 288 bool HasExplicitEncodingSize = true) { 289 auto Res = llvm::make_unique<AMDGPUOperand>(Token); 290 Res->Tok.Data = Str.data(); 291 Res->Tok.Length = Str.size(); 292 Res->StartLoc = Loc; 293 Res->EndLoc = Loc; 294 return Res; 295 } 296 297 static std::unique_ptr<AMDGPUOperand> CreateReg(unsigned RegNo, SMLoc S, 298 SMLoc E, 299 const MCRegisterInfo *TRI, 300 bool ForceVOP3) { 301 auto Op = llvm::make_unique<AMDGPUOperand>(Register); 302 Op->Reg.RegNo = RegNo; 303 Op->Reg.TRI = TRI; 304 Op->Reg.Modifiers = -1; 305 Op->Reg.IsForcedVOP3 = ForceVOP3; 306 Op->StartLoc = S; 307 Op->EndLoc = E; 308 return Op; 309 } 310 311 static std::unique_ptr<AMDGPUOperand> CreateExpr(const class MCExpr *Expr, SMLoc S) { 312 auto Op = llvm::make_unique<AMDGPUOperand>(Expression); 313 Op->Expr = Expr; 314 Op->StartLoc = S; 315 Op->EndLoc = S; 316 return Op; 317 } 318 319 bool isDSOffset() const; 320 bool isDSOffset01() const; 321 bool isSWaitCnt() const; 322 bool isMubufOffset() const; 323 bool isSMRDOffset() const; 324 bool isSMRDLiteralOffset() const; 325 }; 326 327 class AMDGPUAsmParser : public MCTargetAsmParser { 328 MCSubtargetInfo &STI; 329 const MCInstrInfo &MII; 330 MCAsmParser &Parser; 331 332 unsigned ForcedEncodingSize; 333 /// @name Auto-generated Match Functions 334 /// { 335 336 #define GET_ASSEMBLER_HEADER 337 #include "AMDGPUGenAsmMatcher.inc" 338 339 /// } 340 341 private: 342 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 343 bool ParseDirectiveHSACodeObjectVersion(); 344 bool ParseDirectiveHSACodeObjectISA(); 345 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 346 bool ParseDirectiveAMDKernelCodeT(); 347 bool ParseSectionDirectiveHSAText(); 348 349 public: 350 public: 351 enum AMDGPUMatchResultTy { 352 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 353 }; 354 355 AMDGPUAsmParser(MCSubtargetInfo &STI, MCAsmParser &_Parser, 356 const MCInstrInfo &MII, 357 const MCTargetOptions &Options) 358 : MCTargetAsmParser(Options), STI(STI), MII(MII), Parser(_Parser), 359 ForcedEncodingSize(0){ 360 361 if (STI.getFeatureBits().none()) { 362 // Set default features. 363 STI.ToggleFeature("SOUTHERN_ISLANDS"); 364 } 365 366 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 367 } 368 369 AMDGPUTargetStreamer &getTargetStreamer() { 370 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 371 return static_cast<AMDGPUTargetStreamer &>(TS); 372 } 373 374 unsigned getForcedEncodingSize() const { 375 return ForcedEncodingSize; 376 } 377 378 void setForcedEncodingSize(unsigned Size) { 379 ForcedEncodingSize = Size; 380 } 381 382 bool isForcedVOP3() const { 383 return ForcedEncodingSize == 64; 384 } 385 386 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 387 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 388 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 389 OperandVector &Operands, MCStreamer &Out, 390 uint64_t &ErrorInfo, 391 bool MatchingInlineAsm) override; 392 bool ParseDirective(AsmToken DirectiveID) override; 393 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); 394 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 395 SMLoc NameLoc, OperandVector &Operands) override; 396 397 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int, 398 int64_t Default = 0); 399 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, 400 OperandVector &Operands, 401 enum AMDGPUOperand::ImmTy ImmTy = 402 AMDGPUOperand::ImmTyNone); 403 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands, 404 enum AMDGPUOperand::ImmTy ImmTy = 405 AMDGPUOperand::ImmTyNone); 406 OperandMatchResultTy parseOptionalOps( 407 const ArrayRef<OptionalOperand> &OptionalOps, 408 OperandVector &Operands); 409 410 411 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 412 void cvtDS(MCInst &Inst, const OperandVector &Operands); 413 OperandMatchResultTy parseDSOptionalOps(OperandVector &Operands); 414 OperandMatchResultTy parseDSOff01OptionalOps(OperandVector &Operands); 415 OperandMatchResultTy parseDSOffsetOptional(OperandVector &Operands); 416 417 bool parseCnt(int64_t &IntVal); 418 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 419 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 420 421 OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands); 422 OperandMatchResultTy parseFlatAtomicOptionalOps(OperandVector &Operands); 423 void cvtFlat(MCInst &Inst, const OperandVector &Operands); 424 425 void cvtMubuf(MCInst &Inst, const OperandVector &Operands); 426 OperandMatchResultTy parseOffset(OperandVector &Operands); 427 OperandMatchResultTy parseMubufOptionalOps(OperandVector &Operands); 428 OperandMatchResultTy parseGLC(OperandVector &Operands); 429 OperandMatchResultTy parseSLC(OperandVector &Operands); 430 OperandMatchResultTy parseTFE(OperandVector &Operands); 431 432 OperandMatchResultTy parseDMask(OperandVector &Operands); 433 OperandMatchResultTy parseUNorm(OperandVector &Operands); 434 OperandMatchResultTy parseR128(OperandVector &Operands); 435 436 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 437 OperandMatchResultTy parseVOP3OptionalOps(OperandVector &Operands); 438 }; 439 440 struct OptionalOperand { 441 const char *Name; 442 AMDGPUOperand::ImmTy Type; 443 bool IsBit; 444 int64_t Default; 445 bool (*ConvertResult)(int64_t&); 446 }; 447 448 } 449 450 static unsigned getRegClass(bool IsVgpr, unsigned RegWidth) { 451 if (IsVgpr) { 452 switch (RegWidth) { 453 default: llvm_unreachable("Unknown register width"); 454 case 1: return AMDGPU::VGPR_32RegClassID; 455 case 2: return AMDGPU::VReg_64RegClassID; 456 case 3: return AMDGPU::VReg_96RegClassID; 457 case 4: return AMDGPU::VReg_128RegClassID; 458 case 8: return AMDGPU::VReg_256RegClassID; 459 case 16: return AMDGPU::VReg_512RegClassID; 460 } 461 } 462 463 switch (RegWidth) { 464 default: llvm_unreachable("Unknown register width"); 465 case 1: return AMDGPU::SGPR_32RegClassID; 466 case 2: return AMDGPU::SGPR_64RegClassID; 467 case 4: return AMDGPU::SReg_128RegClassID; 468 case 8: return AMDGPU::SReg_256RegClassID; 469 case 16: return AMDGPU::SReg_512RegClassID; 470 } 471 } 472 473 static unsigned getRegForName(StringRef RegName) { 474 475 return StringSwitch<unsigned>(RegName) 476 .Case("exec", AMDGPU::EXEC) 477 .Case("vcc", AMDGPU::VCC) 478 .Case("flat_scr", AMDGPU::FLAT_SCR) 479 .Case("m0", AMDGPU::M0) 480 .Case("scc", AMDGPU::SCC) 481 .Case("flat_scr_lo", AMDGPU::FLAT_SCR_LO) 482 .Case("flat_scr_hi", AMDGPU::FLAT_SCR_HI) 483 .Case("vcc_lo", AMDGPU::VCC_LO) 484 .Case("vcc_hi", AMDGPU::VCC_HI) 485 .Case("exec_lo", AMDGPU::EXEC_LO) 486 .Case("exec_hi", AMDGPU::EXEC_HI) 487 .Default(0); 488 } 489 490 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { 491 const AsmToken Tok = Parser.getTok(); 492 StartLoc = Tok.getLoc(); 493 EndLoc = Tok.getEndLoc(); 494 StringRef RegName = Tok.getString(); 495 RegNo = getRegForName(RegName); 496 497 if (RegNo) { 498 Parser.Lex(); 499 return false; 500 } 501 502 // Match vgprs and sgprs 503 if (RegName[0] != 's' && RegName[0] != 'v') 504 return true; 505 506 bool IsVgpr = RegName[0] == 'v'; 507 unsigned RegWidth; 508 unsigned RegIndexInClass; 509 if (RegName.size() > 1) { 510 // We have a 32-bit register 511 RegWidth = 1; 512 if (RegName.substr(1).getAsInteger(10, RegIndexInClass)) 513 return true; 514 Parser.Lex(); 515 } else { 516 // We have a register greater than 32-bits. 517 518 int64_t RegLo, RegHi; 519 Parser.Lex(); 520 if (getLexer().isNot(AsmToken::LBrac)) 521 return true; 522 523 Parser.Lex(); 524 if (getParser().parseAbsoluteExpression(RegLo)) 525 return true; 526 527 if (getLexer().isNot(AsmToken::Colon)) 528 return true; 529 530 Parser.Lex(); 531 if (getParser().parseAbsoluteExpression(RegHi)) 532 return true; 533 534 if (getLexer().isNot(AsmToken::RBrac)) 535 return true; 536 537 Parser.Lex(); 538 RegWidth = (RegHi - RegLo) + 1; 539 if (IsVgpr) { 540 // VGPR registers aren't aligned. 541 RegIndexInClass = RegLo; 542 } else { 543 // SGPR registers are aligned. Max alignment is 4 dwords. 544 RegIndexInClass = RegLo / std::min(RegWidth, 4u); 545 } 546 } 547 548 const MCRegisterInfo *TRC = getContext().getRegisterInfo(); 549 unsigned RC = getRegClass(IsVgpr, RegWidth); 550 if (RegIndexInClass > TRC->getRegClass(RC).getNumRegs()) 551 return true; 552 RegNo = TRC->getRegClass(RC).getRegister(RegIndexInClass); 553 return false; 554 } 555 556 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 557 558 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 559 560 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 561 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3))) 562 return Match_InvalidOperand; 563 564 if ((TSFlags & SIInstrFlags::VOP3) && 565 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 566 getForcedEncodingSize() != 64) 567 return Match_PreferE32; 568 569 return Match_Success; 570 } 571 572 573 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 574 OperandVector &Operands, 575 MCStreamer &Out, 576 uint64_t &ErrorInfo, 577 bool MatchingInlineAsm) { 578 MCInst Inst; 579 580 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 581 default: break; 582 case Match_Success: 583 Inst.setLoc(IDLoc); 584 Out.EmitInstruction(Inst, STI); 585 return false; 586 case Match_MissingFeature: 587 return Error(IDLoc, "instruction not supported on this GPU"); 588 589 case Match_MnemonicFail: 590 return Error(IDLoc, "unrecognized instruction mnemonic"); 591 592 case Match_InvalidOperand: { 593 SMLoc ErrorLoc = IDLoc; 594 if (ErrorInfo != ~0ULL) { 595 if (ErrorInfo >= Operands.size()) { 596 if (isForcedVOP3()) { 597 // If 64-bit encoding has been forced we can end up with no 598 // clamp or omod operands if none of the registers have modifiers, 599 // so we need to add these to the operand list. 600 AMDGPUOperand &LastOp = 601 ((AMDGPUOperand &)*Operands[Operands.size() - 1]); 602 if (LastOp.isRegKind() || 603 (LastOp.isImm() && 604 LastOp.getImmTy() != AMDGPUOperand::ImmTyNone)) { 605 SMLoc S = Parser.getTok().getLoc(); 606 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 607 AMDGPUOperand::ImmTyClamp)); 608 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 609 AMDGPUOperand::ImmTyOMod)); 610 bool Res = MatchAndEmitInstruction(IDLoc, Opcode, Operands, 611 Out, ErrorInfo, 612 MatchingInlineAsm); 613 if (!Res) 614 return Res; 615 } 616 617 } 618 return Error(IDLoc, "too few operands for instruction"); 619 } 620 621 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 622 if (ErrorLoc == SMLoc()) 623 ErrorLoc = IDLoc; 624 } 625 return Error(ErrorLoc, "invalid operand for instruction"); 626 } 627 case Match_PreferE32: 628 return Error(IDLoc, "internal error: instruction without _e64 suffix " 629 "should be encoded as e32"); 630 } 631 llvm_unreachable("Implement any new match types added!"); 632 } 633 634 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 635 uint32_t &Minor) { 636 if (getLexer().isNot(AsmToken::Integer)) 637 return TokError("invalid major version"); 638 639 Major = getLexer().getTok().getIntVal(); 640 Lex(); 641 642 if (getLexer().isNot(AsmToken::Comma)) 643 return TokError("minor version number required, comma expected"); 644 Lex(); 645 646 if (getLexer().isNot(AsmToken::Integer)) 647 return TokError("invalid minor version"); 648 649 Minor = getLexer().getTok().getIntVal(); 650 Lex(); 651 652 return false; 653 } 654 655 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 656 657 uint32_t Major; 658 uint32_t Minor; 659 660 if (ParseDirectiveMajorMinor(Major, Minor)) 661 return true; 662 663 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 664 return false; 665 } 666 667 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 668 669 uint32_t Major; 670 uint32_t Minor; 671 uint32_t Stepping; 672 StringRef VendorName; 673 StringRef ArchName; 674 675 // If this directive has no arguments, then use the ISA version for the 676 // targeted GPU. 677 if (getLexer().is(AsmToken::EndOfStatement)) { 678 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(STI.getFeatureBits()); 679 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor, 680 Isa.Stepping, 681 "AMD", "AMDGPU"); 682 return false; 683 } 684 685 686 if (ParseDirectiveMajorMinor(Major, Minor)) 687 return true; 688 689 if (getLexer().isNot(AsmToken::Comma)) 690 return TokError("stepping version number required, comma expected"); 691 Lex(); 692 693 if (getLexer().isNot(AsmToken::Integer)) 694 return TokError("invalid stepping version"); 695 696 Stepping = getLexer().getTok().getIntVal(); 697 Lex(); 698 699 if (getLexer().isNot(AsmToken::Comma)) 700 return TokError("vendor name required, comma expected"); 701 Lex(); 702 703 if (getLexer().isNot(AsmToken::String)) 704 return TokError("invalid vendor name"); 705 706 VendorName = getLexer().getTok().getStringContents(); 707 Lex(); 708 709 if (getLexer().isNot(AsmToken::Comma)) 710 return TokError("arch name required, comma expected"); 711 Lex(); 712 713 if (getLexer().isNot(AsmToken::String)) 714 return TokError("invalid arch name"); 715 716 ArchName = getLexer().getTok().getStringContents(); 717 Lex(); 718 719 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 720 VendorName, ArchName); 721 return false; 722 } 723 724 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 725 amd_kernel_code_t &Header) { 726 727 if (getLexer().isNot(AsmToken::Equal)) 728 return TokError("expected '='"); 729 Lex(); 730 731 if (getLexer().isNot(AsmToken::Integer)) 732 return TokError("amd_kernel_code_t values must be integers"); 733 734 uint64_t Value = getLexer().getTok().getIntVal(); 735 Lex(); 736 737 if (ID == "kernel_code_version_major") 738 Header.amd_kernel_code_version_major = Value; 739 else if (ID == "kernel_code_version_minor") 740 Header.amd_kernel_code_version_minor = Value; 741 else if (ID == "machine_kind") 742 Header.amd_machine_kind = Value; 743 else if (ID == "machine_version_major") 744 Header.amd_machine_version_major = Value; 745 else if (ID == "machine_version_minor") 746 Header.amd_machine_version_minor = Value; 747 else if (ID == "machine_version_stepping") 748 Header.amd_machine_version_stepping = Value; 749 else if (ID == "kernel_code_entry_byte_offset") 750 Header.kernel_code_entry_byte_offset = Value; 751 else if (ID == "kernel_code_prefetch_byte_size") 752 Header.kernel_code_prefetch_byte_size = Value; 753 else if (ID == "max_scratch_backing_memory_byte_size") 754 Header.max_scratch_backing_memory_byte_size = Value; 755 else if (ID == "compute_pgm_rsrc1_vgprs") 756 Header.compute_pgm_resource_registers |= S_00B848_VGPRS(Value); 757 else if (ID == "compute_pgm_rsrc1_sgprs") 758 Header.compute_pgm_resource_registers |= S_00B848_SGPRS(Value); 759 else if (ID == "compute_pgm_rsrc1_priority") 760 Header.compute_pgm_resource_registers |= S_00B848_PRIORITY(Value); 761 else if (ID == "compute_pgm_rsrc1_float_mode") 762 Header.compute_pgm_resource_registers |= S_00B848_FLOAT_MODE(Value); 763 else if (ID == "compute_pgm_rsrc1_priv") 764 Header.compute_pgm_resource_registers |= S_00B848_PRIV(Value); 765 else if (ID == "compute_pgm_rsrc1_dx10_clamp") 766 Header.compute_pgm_resource_registers |= S_00B848_DX10_CLAMP(Value); 767 else if (ID == "compute_pgm_rsrc1_debug_mode") 768 Header.compute_pgm_resource_registers |= S_00B848_DEBUG_MODE(Value); 769 else if (ID == "compute_pgm_rsrc1_ieee_mode") 770 Header.compute_pgm_resource_registers |= S_00B848_IEEE_MODE(Value); 771 else if (ID == "compute_pgm_rsrc2_scratch_en") 772 Header.compute_pgm_resource_registers |= (S_00B84C_SCRATCH_EN(Value) << 32); 773 else if (ID == "compute_pgm_rsrc2_user_sgpr") 774 Header.compute_pgm_resource_registers |= (S_00B84C_USER_SGPR(Value) << 32); 775 else if (ID == "compute_pgm_rsrc2_tgid_x_en") 776 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_X_EN(Value) << 32); 777 else if (ID == "compute_pgm_rsrc2_tgid_y_en") 778 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Y_EN(Value) << 32); 779 else if (ID == "compute_pgm_rsrc2_tgid_z_en") 780 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Z_EN(Value) << 32); 781 else if (ID == "compute_pgm_rsrc2_tg_size_en") 782 Header.compute_pgm_resource_registers |= (S_00B84C_TG_SIZE_EN(Value) << 32); 783 else if (ID == "compute_pgm_rsrc2_tidig_comp_cnt") 784 Header.compute_pgm_resource_registers |= 785 (S_00B84C_TIDIG_COMP_CNT(Value) << 32); 786 else if (ID == "compute_pgm_rsrc2_excp_en_msb") 787 Header.compute_pgm_resource_registers |= 788 (S_00B84C_EXCP_EN_MSB(Value) << 32); 789 else if (ID == "compute_pgm_rsrc2_lds_size") 790 Header.compute_pgm_resource_registers |= (S_00B84C_LDS_SIZE(Value) << 32); 791 else if (ID == "compute_pgm_rsrc2_excp_en") 792 Header.compute_pgm_resource_registers |= (S_00B84C_EXCP_EN(Value) << 32); 793 else if (ID == "compute_pgm_resource_registers") 794 Header.compute_pgm_resource_registers = Value; 795 else if (ID == "enable_sgpr_private_segment_buffer") 796 Header.code_properties |= 797 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER_SHIFT); 798 else if (ID == "enable_sgpr_dispatch_ptr") 799 Header.code_properties |= 800 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR_SHIFT); 801 else if (ID == "enable_sgpr_queue_ptr") 802 Header.code_properties |= 803 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR_SHIFT); 804 else if (ID == "enable_sgpr_kernarg_segment_ptr") 805 Header.code_properties |= 806 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR_SHIFT); 807 else if (ID == "enable_sgpr_dispatch_id") 808 Header.code_properties |= 809 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID_SHIFT); 810 else if (ID == "enable_sgpr_flat_scratch_init") 811 Header.code_properties |= 812 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT_SHIFT); 813 else if (ID == "enable_sgpr_private_segment_size") 814 Header.code_properties |= 815 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE_SHIFT); 816 else if (ID == "enable_sgpr_grid_workgroup_count_x") 817 Header.code_properties |= 818 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_X_SHIFT); 819 else if (ID == "enable_sgpr_grid_workgroup_count_y") 820 Header.code_properties |= 821 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Y_SHIFT); 822 else if (ID == "enable_sgpr_grid_workgroup_count_z") 823 Header.code_properties |= 824 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Z_SHIFT); 825 else if (ID == "enable_ordered_append_gds") 826 Header.code_properties |= 827 (Value << AMD_CODE_PROPERTY_ENABLE_ORDERED_APPEND_GDS_SHIFT); 828 else if (ID == "private_element_size") 829 Header.code_properties |= 830 (Value << AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE_SHIFT); 831 else if (ID == "is_ptr64") 832 Header.code_properties |= 833 (Value << AMD_CODE_PROPERTY_IS_PTR64_SHIFT); 834 else if (ID == "is_dynamic_callstack") 835 Header.code_properties |= 836 (Value << AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_SHIFT); 837 else if (ID == "is_debug_enabled") 838 Header.code_properties |= 839 (Value << AMD_CODE_PROPERTY_IS_DEBUG_SUPPORTED_SHIFT); 840 else if (ID == "is_xnack_enabled") 841 Header.code_properties |= 842 (Value << AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED_SHIFT); 843 else if (ID == "workitem_private_segment_byte_size") 844 Header.workitem_private_segment_byte_size = Value; 845 else if (ID == "workgroup_group_segment_byte_size") 846 Header.workgroup_group_segment_byte_size = Value; 847 else if (ID == "gds_segment_byte_size") 848 Header.gds_segment_byte_size = Value; 849 else if (ID == "kernarg_segment_byte_size") 850 Header.kernarg_segment_byte_size = Value; 851 else if (ID == "workgroup_fbarrier_count") 852 Header.workgroup_fbarrier_count = Value; 853 else if (ID == "wavefront_sgpr_count") 854 Header.wavefront_sgpr_count = Value; 855 else if (ID == "workitem_vgpr_count") 856 Header.workitem_vgpr_count = Value; 857 else if (ID == "reserved_vgpr_first") 858 Header.reserved_vgpr_first = Value; 859 else if (ID == "reserved_vgpr_count") 860 Header.reserved_vgpr_count = Value; 861 else if (ID == "reserved_sgpr_first") 862 Header.reserved_sgpr_first = Value; 863 else if (ID == "reserved_sgpr_count") 864 Header.reserved_sgpr_count = Value; 865 else if (ID == "debug_wavefront_private_segment_offset_sgpr") 866 Header.debug_wavefront_private_segment_offset_sgpr = Value; 867 else if (ID == "debug_private_segment_buffer_sgpr") 868 Header.debug_private_segment_buffer_sgpr = Value; 869 else if (ID == "kernarg_segment_alignment") 870 Header.kernarg_segment_alignment = Value; 871 else if (ID == "group_segment_alignment") 872 Header.group_segment_alignment = Value; 873 else if (ID == "private_segment_alignment") 874 Header.private_segment_alignment = Value; 875 else if (ID == "wavefront_size") 876 Header.wavefront_size = Value; 877 else if (ID == "call_convention") 878 Header.call_convention = Value; 879 else if (ID == "runtime_loader_kernel_symbol") 880 Header.runtime_loader_kernel_symbol = Value; 881 else 882 return TokError("amd_kernel_code_t value not recognized."); 883 884 return false; 885 } 886 887 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 888 889 amd_kernel_code_t Header; 890 AMDGPU::initDefaultAMDKernelCodeT(Header, STI.getFeatureBits()); 891 892 while (true) { 893 894 if (getLexer().isNot(AsmToken::EndOfStatement)) 895 return TokError("amd_kernel_code_t values must begin on a new line"); 896 897 // Lex EndOfStatement. This is in a while loop, because lexing a comment 898 // will set the current token to EndOfStatement. 899 while(getLexer().is(AsmToken::EndOfStatement)) 900 Lex(); 901 902 if (getLexer().isNot(AsmToken::Identifier)) 903 return TokError("expected value identifier or .end_amd_kernel_code_t"); 904 905 StringRef ID = getLexer().getTok().getIdentifier(); 906 Lex(); 907 908 if (ID == ".end_amd_kernel_code_t") 909 break; 910 911 if (ParseAMDKernelCodeTValue(ID, Header)) 912 return true; 913 } 914 915 getTargetStreamer().EmitAMDKernelCodeT(Header); 916 917 return false; 918 } 919 920 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() { 921 getParser().getStreamer().SwitchSection( 922 AMDGPU::getHSATextSection(getContext())); 923 return false; 924 } 925 926 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 927 StringRef IDVal = DirectiveID.getString(); 928 929 if (IDVal == ".hsa_code_object_version") 930 return ParseDirectiveHSACodeObjectVersion(); 931 932 if (IDVal == ".hsa_code_object_isa") 933 return ParseDirectiveHSACodeObjectISA(); 934 935 if (IDVal == ".amd_kernel_code_t") 936 return ParseDirectiveAMDKernelCodeT(); 937 938 if (IDVal == ".hsatext" || IDVal == ".text") 939 return ParseSectionDirectiveHSAText(); 940 941 return true; 942 } 943 944 static bool operandsHaveModifiers(const OperandVector &Operands) { 945 946 for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 947 const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 948 if (Op.isRegKind() && Op.hasModifiers()) 949 return true; 950 if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOMod || 951 Op.getImmTy() == AMDGPUOperand::ImmTyClamp)) 952 return true; 953 } 954 return false; 955 } 956 957 AMDGPUAsmParser::OperandMatchResultTy 958 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 959 960 // Try to parse with a custom parser 961 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 962 963 // If we successfully parsed the operand or if there as an error parsing, 964 // we are done. 965 // 966 // If we are parsing after we reach EndOfStatement then this means we 967 // are appending default values to the Operands list. This is only done 968 // by custom parser, so we shouldn't continue on to the generic parsing. 969 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail || 970 getLexer().is(AsmToken::EndOfStatement)) 971 return ResTy; 972 973 bool Negate = false, Abs = false; 974 if (getLexer().getKind()== AsmToken::Minus) { 975 Parser.Lex(); 976 Negate = true; 977 } 978 979 if (getLexer().getKind() == AsmToken::Pipe) { 980 Parser.Lex(); 981 Abs = true; 982 } 983 984 switch(getLexer().getKind()) { 985 case AsmToken::Integer: { 986 SMLoc S = Parser.getTok().getLoc(); 987 int64_t IntVal; 988 if (getParser().parseAbsoluteExpression(IntVal)) 989 return MatchOperand_ParseFail; 990 if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) { 991 Error(S, "invalid immediate: only 32-bit values are legal"); 992 return MatchOperand_ParseFail; 993 } 994 995 if (Negate) 996 IntVal *= -1; 997 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S)); 998 return MatchOperand_Success; 999 } 1000 case AsmToken::Real: { 1001 // FIXME: We should emit an error if a double precisions floating-point 1002 // value is used. I'm not sure the best way to detect this. 1003 SMLoc S = Parser.getTok().getLoc(); 1004 int64_t IntVal; 1005 if (getParser().parseAbsoluteExpression(IntVal)) 1006 return MatchOperand_ParseFail; 1007 1008 APFloat F((float)BitsToDouble(IntVal)); 1009 if (Negate) 1010 F.changeSign(); 1011 Operands.push_back( 1012 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); 1013 return MatchOperand_Success; 1014 } 1015 case AsmToken::Identifier: { 1016 SMLoc S, E; 1017 unsigned RegNo; 1018 if (!ParseRegister(RegNo, S, E)) { 1019 1020 bool HasModifiers = operandsHaveModifiers(Operands); 1021 unsigned Modifiers = 0; 1022 1023 if (Negate) 1024 Modifiers |= 0x1; 1025 1026 if (Abs) { 1027 if (getLexer().getKind() != AsmToken::Pipe) 1028 return MatchOperand_ParseFail; 1029 Parser.Lex(); 1030 Modifiers |= 0x2; 1031 } 1032 1033 if (Modifiers && !HasModifiers) { 1034 // We are adding a modifier to src1 or src2 and previous sources 1035 // don't have modifiers, so we need to go back and empty modifers 1036 // for each previous source. 1037 for (unsigned PrevRegIdx = Operands.size() - 1; PrevRegIdx > 1; 1038 --PrevRegIdx) { 1039 1040 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[PrevRegIdx]); 1041 RegOp.setModifiers(0); 1042 } 1043 } 1044 1045 1046 Operands.push_back(AMDGPUOperand::CreateReg( 1047 RegNo, S, E, getContext().getRegisterInfo(), 1048 isForcedVOP3())); 1049 1050 if (HasModifiers || Modifiers) { 1051 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[Operands.size() - 1]); 1052 RegOp.setModifiers(Modifiers); 1053 1054 } 1055 } else { 1056 Operands.push_back(AMDGPUOperand::CreateToken(Parser.getTok().getString(), 1057 S)); 1058 Parser.Lex(); 1059 } 1060 return MatchOperand_Success; 1061 } 1062 default: 1063 return MatchOperand_NoMatch; 1064 } 1065 } 1066 1067 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1068 StringRef Name, 1069 SMLoc NameLoc, OperandVector &Operands) { 1070 1071 // Clear any forced encodings from the previous instruction. 1072 setForcedEncodingSize(0); 1073 1074 if (Name.endswith("_e64")) 1075 setForcedEncodingSize(64); 1076 else if (Name.endswith("_e32")) 1077 setForcedEncodingSize(32); 1078 1079 // Add the instruction mnemonic 1080 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); 1081 1082 while (!getLexer().is(AsmToken::EndOfStatement)) { 1083 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); 1084 1085 // Eat the comma or space if there is one. 1086 if (getLexer().is(AsmToken::Comma)) 1087 Parser.Lex(); 1088 1089 switch (Res) { 1090 case MatchOperand_Success: break; 1091 case MatchOperand_ParseFail: return Error(getLexer().getLoc(), 1092 "failed parsing operand."); 1093 case MatchOperand_NoMatch: return Error(getLexer().getLoc(), 1094 "not a valid operand."); 1095 } 1096 } 1097 1098 // Once we reach end of statement, continue parsing so we can add default 1099 // values for optional arguments. 1100 AMDGPUAsmParser::OperandMatchResultTy Res; 1101 while ((Res = parseOperand(Operands, Name)) != MatchOperand_NoMatch) { 1102 if (Res != MatchOperand_Success) 1103 return Error(getLexer().getLoc(), "failed parsing operand."); 1104 } 1105 return false; 1106 } 1107 1108 //===----------------------------------------------------------------------===// 1109 // Utility functions 1110 //===----------------------------------------------------------------------===// 1111 1112 AMDGPUAsmParser::OperandMatchResultTy 1113 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int, 1114 int64_t Default) { 1115 1116 // We are at the end of the statement, and this is a default argument, so 1117 // use a default value. 1118 if (getLexer().is(AsmToken::EndOfStatement)) { 1119 Int = Default; 1120 return MatchOperand_Success; 1121 } 1122 1123 switch(getLexer().getKind()) { 1124 default: return MatchOperand_NoMatch; 1125 case AsmToken::Identifier: { 1126 StringRef OffsetName = Parser.getTok().getString(); 1127 if (!OffsetName.equals(Prefix)) 1128 return MatchOperand_NoMatch; 1129 1130 Parser.Lex(); 1131 if (getLexer().isNot(AsmToken::Colon)) 1132 return MatchOperand_ParseFail; 1133 1134 Parser.Lex(); 1135 if (getLexer().isNot(AsmToken::Integer)) 1136 return MatchOperand_ParseFail; 1137 1138 if (getParser().parseAbsoluteExpression(Int)) 1139 return MatchOperand_ParseFail; 1140 break; 1141 } 1142 } 1143 return MatchOperand_Success; 1144 } 1145 1146 AMDGPUAsmParser::OperandMatchResultTy 1147 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1148 enum AMDGPUOperand::ImmTy ImmTy) { 1149 1150 SMLoc S = Parser.getTok().getLoc(); 1151 int64_t Offset = 0; 1152 1153 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Offset); 1154 if (Res != MatchOperand_Success) 1155 return Res; 1156 1157 Operands.push_back(AMDGPUOperand::CreateImm(Offset, S, ImmTy)); 1158 return MatchOperand_Success; 1159 } 1160 1161 AMDGPUAsmParser::OperandMatchResultTy 1162 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 1163 enum AMDGPUOperand::ImmTy ImmTy) { 1164 int64_t Bit = 0; 1165 SMLoc S = Parser.getTok().getLoc(); 1166 1167 // We are at the end of the statement, and this is a default argument, so 1168 // use a default value. 1169 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1170 switch(getLexer().getKind()) { 1171 case AsmToken::Identifier: { 1172 StringRef Tok = Parser.getTok().getString(); 1173 if (Tok == Name) { 1174 Bit = 1; 1175 Parser.Lex(); 1176 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 1177 Bit = 0; 1178 Parser.Lex(); 1179 } else { 1180 return MatchOperand_NoMatch; 1181 } 1182 break; 1183 } 1184 default: 1185 return MatchOperand_NoMatch; 1186 } 1187 } 1188 1189 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy)); 1190 return MatchOperand_Success; 1191 } 1192 1193 static bool operandsHasOptionalOp(const OperandVector &Operands, 1194 const OptionalOperand &OOp) { 1195 for (unsigned i = 0; i < Operands.size(); i++) { 1196 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]); 1197 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) || 1198 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name)) 1199 return true; 1200 1201 } 1202 return false; 1203 } 1204 1205 AMDGPUAsmParser::OperandMatchResultTy 1206 AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps, 1207 OperandVector &Operands) { 1208 SMLoc S = Parser.getTok().getLoc(); 1209 for (const OptionalOperand &Op : OptionalOps) { 1210 if (operandsHasOptionalOp(Operands, Op)) 1211 continue; 1212 AMDGPUAsmParser::OperandMatchResultTy Res; 1213 int64_t Value; 1214 if (Op.IsBit) { 1215 Res = parseNamedBit(Op.Name, Operands, Op.Type); 1216 if (Res == MatchOperand_NoMatch) 1217 continue; 1218 return Res; 1219 } 1220 1221 Res = parseIntWithPrefix(Op.Name, Value, Op.Default); 1222 1223 if (Res == MatchOperand_NoMatch) 1224 continue; 1225 1226 if (Res != MatchOperand_Success) 1227 return Res; 1228 1229 if (Op.ConvertResult && !Op.ConvertResult(Value)) { 1230 return MatchOperand_ParseFail; 1231 } 1232 1233 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type)); 1234 return MatchOperand_Success; 1235 } 1236 return MatchOperand_NoMatch; 1237 } 1238 1239 //===----------------------------------------------------------------------===// 1240 // ds 1241 //===----------------------------------------------------------------------===// 1242 1243 static const OptionalOperand DSOptionalOps [] = { 1244 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1245 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1246 }; 1247 1248 static const OptionalOperand DSOptionalOpsOff01 [] = { 1249 {"offset0", AMDGPUOperand::ImmTyDSOffset0, false, 0, nullptr}, 1250 {"offset1", AMDGPUOperand::ImmTyDSOffset1, false, 0, nullptr}, 1251 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1252 }; 1253 1254 AMDGPUAsmParser::OperandMatchResultTy 1255 AMDGPUAsmParser::parseDSOptionalOps(OperandVector &Operands) { 1256 return parseOptionalOps(DSOptionalOps, Operands); 1257 } 1258 AMDGPUAsmParser::OperandMatchResultTy 1259 AMDGPUAsmParser::parseDSOff01OptionalOps(OperandVector &Operands) { 1260 return parseOptionalOps(DSOptionalOpsOff01, Operands); 1261 } 1262 1263 AMDGPUAsmParser::OperandMatchResultTy 1264 AMDGPUAsmParser::parseDSOffsetOptional(OperandVector &Operands) { 1265 SMLoc S = Parser.getTok().getLoc(); 1266 AMDGPUAsmParser::OperandMatchResultTy Res = 1267 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset); 1268 if (Res == MatchOperand_NoMatch) { 1269 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 1270 AMDGPUOperand::ImmTyOffset)); 1271 Res = MatchOperand_Success; 1272 } 1273 return Res; 1274 } 1275 1276 bool AMDGPUOperand::isDSOffset() const { 1277 return isImm() && isUInt<16>(getImm()); 1278 } 1279 1280 bool AMDGPUOperand::isDSOffset01() const { 1281 return isImm() && isUInt<8>(getImm()); 1282 } 1283 1284 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 1285 const OperandVector &Operands) { 1286 1287 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1288 1289 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1290 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1291 1292 // Add the register arguments 1293 if (Op.isReg()) { 1294 Op.addRegOperands(Inst, 1); 1295 continue; 1296 } 1297 1298 // Handle optional arguments 1299 OptionalIdx[Op.getImmTy()] = i; 1300 } 1301 1302 unsigned Offset0Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset0]; 1303 unsigned Offset1Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset1]; 1304 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1305 1306 ((AMDGPUOperand &)*Operands[Offset0Idx]).addImmOperands(Inst, 1); // offset0 1307 ((AMDGPUOperand &)*Operands[Offset1Idx]).addImmOperands(Inst, 1); // offset1 1308 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1309 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1310 } 1311 1312 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 1313 1314 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1315 bool GDSOnly = false; 1316 1317 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1318 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1319 1320 // Add the register arguments 1321 if (Op.isReg()) { 1322 Op.addRegOperands(Inst, 1); 1323 continue; 1324 } 1325 1326 if (Op.isToken() && Op.getToken() == "gds") { 1327 GDSOnly = true; 1328 continue; 1329 } 1330 1331 // Handle optional arguments 1332 OptionalIdx[Op.getImmTy()] = i; 1333 } 1334 1335 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1336 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); // offset 1337 1338 if (!GDSOnly) { 1339 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1340 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1341 } 1342 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1343 } 1344 1345 1346 //===----------------------------------------------------------------------===// 1347 // s_waitcnt 1348 //===----------------------------------------------------------------------===// 1349 1350 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 1351 StringRef CntName = Parser.getTok().getString(); 1352 int64_t CntVal; 1353 1354 Parser.Lex(); 1355 if (getLexer().isNot(AsmToken::LParen)) 1356 return true; 1357 1358 Parser.Lex(); 1359 if (getLexer().isNot(AsmToken::Integer)) 1360 return true; 1361 1362 if (getParser().parseAbsoluteExpression(CntVal)) 1363 return true; 1364 1365 if (getLexer().isNot(AsmToken::RParen)) 1366 return true; 1367 1368 Parser.Lex(); 1369 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 1370 Parser.Lex(); 1371 1372 int CntShift; 1373 int CntMask; 1374 1375 if (CntName == "vmcnt") { 1376 CntMask = 0xf; 1377 CntShift = 0; 1378 } else if (CntName == "expcnt") { 1379 CntMask = 0x7; 1380 CntShift = 4; 1381 } else if (CntName == "lgkmcnt") { 1382 CntMask = 0x7; 1383 CntShift = 8; 1384 } else { 1385 return true; 1386 } 1387 1388 IntVal &= ~(CntMask << CntShift); 1389 IntVal |= (CntVal << CntShift); 1390 return false; 1391 } 1392 1393 AMDGPUAsmParser::OperandMatchResultTy 1394 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 1395 // Disable all counters by default. 1396 // vmcnt [3:0] 1397 // expcnt [6:4] 1398 // lgkmcnt [10:8] 1399 int64_t CntVal = 0x77f; 1400 SMLoc S = Parser.getTok().getLoc(); 1401 1402 switch(getLexer().getKind()) { 1403 default: return MatchOperand_ParseFail; 1404 case AsmToken::Integer: 1405 // The operand can be an integer value. 1406 if (getParser().parseAbsoluteExpression(CntVal)) 1407 return MatchOperand_ParseFail; 1408 break; 1409 1410 case AsmToken::Identifier: 1411 do { 1412 if (parseCnt(CntVal)) 1413 return MatchOperand_ParseFail; 1414 } while(getLexer().isNot(AsmToken::EndOfStatement)); 1415 break; 1416 } 1417 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S)); 1418 return MatchOperand_Success; 1419 } 1420 1421 bool AMDGPUOperand::isSWaitCnt() const { 1422 return isImm(); 1423 } 1424 1425 //===----------------------------------------------------------------------===// 1426 // sopp branch targets 1427 //===----------------------------------------------------------------------===// 1428 1429 AMDGPUAsmParser::OperandMatchResultTy 1430 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 1431 SMLoc S = Parser.getTok().getLoc(); 1432 1433 switch (getLexer().getKind()) { 1434 default: return MatchOperand_ParseFail; 1435 case AsmToken::Integer: { 1436 int64_t Imm; 1437 if (getParser().parseAbsoluteExpression(Imm)) 1438 return MatchOperand_ParseFail; 1439 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S)); 1440 return MatchOperand_Success; 1441 } 1442 1443 case AsmToken::Identifier: 1444 Operands.push_back(AMDGPUOperand::CreateExpr( 1445 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 1446 Parser.getTok().getString()), getContext()), S)); 1447 Parser.Lex(); 1448 return MatchOperand_Success; 1449 } 1450 } 1451 1452 //===----------------------------------------------------------------------===// 1453 // flat 1454 //===----------------------------------------------------------------------===// 1455 1456 static const OptionalOperand FlatOptionalOps [] = { 1457 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1458 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1459 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1460 }; 1461 1462 static const OptionalOperand FlatAtomicOptionalOps [] = { 1463 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1464 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1465 }; 1466 1467 AMDGPUAsmParser::OperandMatchResultTy 1468 AMDGPUAsmParser::parseFlatOptionalOps(OperandVector &Operands) { 1469 return parseOptionalOps(FlatOptionalOps, Operands); 1470 } 1471 1472 AMDGPUAsmParser::OperandMatchResultTy 1473 AMDGPUAsmParser::parseFlatAtomicOptionalOps(OperandVector &Operands) { 1474 return parseOptionalOps(FlatAtomicOptionalOps, Operands); 1475 } 1476 1477 void AMDGPUAsmParser::cvtFlat(MCInst &Inst, 1478 const OperandVector &Operands) { 1479 std::map<AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1480 1481 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1482 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1483 1484 // Add the register arguments 1485 if (Op.isReg()) { 1486 Op.addRegOperands(Inst, 1); 1487 continue; 1488 } 1489 1490 // Handle 'glc' token which is sometimes hard-coded into the 1491 // asm string. There are no MCInst operands for these. 1492 if (Op.isToken()) 1493 continue; 1494 1495 // Handle optional arguments 1496 OptionalIdx[Op.getImmTy()] = i; 1497 1498 } 1499 1500 // flat atomic instructions don't have a glc argument. 1501 if (OptionalIdx.count(AMDGPUOperand::ImmTyGLC)) { 1502 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1503 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1504 } 1505 1506 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1507 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1508 1509 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1510 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1511 } 1512 1513 //===----------------------------------------------------------------------===// 1514 // mubuf 1515 //===----------------------------------------------------------------------===// 1516 1517 static const OptionalOperand MubufOptionalOps [] = { 1518 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1519 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1520 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1521 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1522 }; 1523 1524 AMDGPUAsmParser::OperandMatchResultTy 1525 AMDGPUAsmParser::parseMubufOptionalOps(OperandVector &Operands) { 1526 return parseOptionalOps(MubufOptionalOps, Operands); 1527 } 1528 1529 AMDGPUAsmParser::OperandMatchResultTy 1530 AMDGPUAsmParser::parseOffset(OperandVector &Operands) { 1531 return parseIntWithPrefix("offset", Operands); 1532 } 1533 1534 AMDGPUAsmParser::OperandMatchResultTy 1535 AMDGPUAsmParser::parseGLC(OperandVector &Operands) { 1536 return parseNamedBit("glc", Operands); 1537 } 1538 1539 AMDGPUAsmParser::OperandMatchResultTy 1540 AMDGPUAsmParser::parseSLC(OperandVector &Operands) { 1541 return parseNamedBit("slc", Operands); 1542 } 1543 1544 AMDGPUAsmParser::OperandMatchResultTy 1545 AMDGPUAsmParser::parseTFE(OperandVector &Operands) { 1546 return parseNamedBit("tfe", Operands); 1547 } 1548 1549 bool AMDGPUOperand::isMubufOffset() const { 1550 return isImm() && isUInt<12>(getImm()); 1551 } 1552 1553 void AMDGPUAsmParser::cvtMubuf(MCInst &Inst, 1554 const OperandVector &Operands) { 1555 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1556 1557 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1558 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1559 1560 // Add the register arguments 1561 if (Op.isReg()) { 1562 Op.addRegOperands(Inst, 1); 1563 continue; 1564 } 1565 1566 // Handle the case where soffset is an immediate 1567 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 1568 Op.addImmOperands(Inst, 1); 1569 continue; 1570 } 1571 1572 // Handle tokens like 'offen' which are sometimes hard-coded into the 1573 // asm string. There are no MCInst operands for these. 1574 if (Op.isToken()) { 1575 continue; 1576 } 1577 assert(Op.isImm()); 1578 1579 // Handle optional arguments 1580 OptionalIdx[Op.getImmTy()] = i; 1581 } 1582 1583 assert(OptionalIdx.size() == 4); 1584 1585 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1586 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1587 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1588 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1589 1590 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); 1591 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1592 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1593 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1594 } 1595 1596 //===----------------------------------------------------------------------===// 1597 // mimg 1598 //===----------------------------------------------------------------------===// 1599 1600 AMDGPUAsmParser::OperandMatchResultTy 1601 AMDGPUAsmParser::parseDMask(OperandVector &Operands) { 1602 return parseIntWithPrefix("dmask", Operands); 1603 } 1604 1605 AMDGPUAsmParser::OperandMatchResultTy 1606 AMDGPUAsmParser::parseUNorm(OperandVector &Operands) { 1607 return parseNamedBit("unorm", Operands); 1608 } 1609 1610 AMDGPUAsmParser::OperandMatchResultTy 1611 AMDGPUAsmParser::parseR128(OperandVector &Operands) { 1612 return parseNamedBit("r128", Operands); 1613 } 1614 1615 //===----------------------------------------------------------------------===// 1616 // smrd 1617 //===----------------------------------------------------------------------===// 1618 1619 bool AMDGPUOperand::isSMRDOffset() const { 1620 1621 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget 1622 // information here. 1623 return isImm() && isUInt<8>(getImm()); 1624 } 1625 1626 bool AMDGPUOperand::isSMRDLiteralOffset() const { 1627 // 32-bit literals are only supported on CI and we only want to use them 1628 // when the offset is > 8-bits. 1629 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 1630 } 1631 1632 //===----------------------------------------------------------------------===// 1633 // vop3 1634 //===----------------------------------------------------------------------===// 1635 1636 static bool ConvertOmodMul(int64_t &Mul) { 1637 if (Mul != 1 && Mul != 2 && Mul != 4) 1638 return false; 1639 1640 Mul >>= 1; 1641 return true; 1642 } 1643 1644 static bool ConvertOmodDiv(int64_t &Div) { 1645 if (Div == 1) { 1646 Div = 0; 1647 return true; 1648 } 1649 1650 if (Div == 2) { 1651 Div = 3; 1652 return true; 1653 } 1654 1655 return false; 1656 } 1657 1658 static const OptionalOperand VOP3OptionalOps [] = { 1659 {"clamp", AMDGPUOperand::ImmTyClamp, true, 0, nullptr}, 1660 {"mul", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodMul}, 1661 {"div", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodDiv}, 1662 }; 1663 1664 static bool isVOP3(OperandVector &Operands) { 1665 if (operandsHaveModifiers(Operands)) 1666 return true; 1667 1668 AMDGPUOperand &DstOp = ((AMDGPUOperand&)*Operands[1]); 1669 1670 if (DstOp.isReg() && DstOp.isRegClass(AMDGPU::SGPR_64RegClassID)) 1671 return true; 1672 1673 if (Operands.size() >= 5) 1674 return true; 1675 1676 if (Operands.size() > 3) { 1677 AMDGPUOperand &Src1Op = ((AMDGPUOperand&)*Operands[3]); 1678 if (Src1Op.getReg() && (Src1Op.isRegClass(AMDGPU::SReg_32RegClassID) || 1679 Src1Op.isRegClass(AMDGPU::SReg_64RegClassID))) 1680 return true; 1681 } 1682 return false; 1683 } 1684 1685 AMDGPUAsmParser::OperandMatchResultTy 1686 AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) { 1687 1688 // The value returned by this function may change after parsing 1689 // an operand so store the original value here. 1690 bool HasModifiers = operandsHaveModifiers(Operands); 1691 1692 bool IsVOP3 = isVOP3(Operands); 1693 if (HasModifiers || IsVOP3 || 1694 getLexer().isNot(AsmToken::EndOfStatement) || 1695 getForcedEncodingSize() == 64) { 1696 1697 AMDGPUAsmParser::OperandMatchResultTy Res = 1698 parseOptionalOps(VOP3OptionalOps, Operands); 1699 1700 if (!HasModifiers && Res == MatchOperand_Success) { 1701 // We have added a modifier operation, so we need to make sure all 1702 // previous register operands have modifiers 1703 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 1704 AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 1705 if (Op.isReg()) 1706 Op.setModifiers(0); 1707 } 1708 } 1709 return Res; 1710 } 1711 return MatchOperand_NoMatch; 1712 } 1713 1714 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 1715 1716 unsigned i = 1; 1717 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 1718 if (Desc.getNumDefs() > 0) { 1719 ((AMDGPUOperand &)*Operands[i++]).addRegOperands(Inst, 1); 1720 } 1721 1722 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1723 1724 if (operandsHaveModifiers(Operands)) { 1725 for (unsigned e = Operands.size(); i != e; ++i) { 1726 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1727 1728 if (Op.isRegWithInputMods()) { 1729 ((AMDGPUOperand &)*Operands[i]).addRegWithInputModsOperands(Inst, 2); 1730 continue; 1731 } 1732 OptionalIdx[Op.getImmTy()] = i; 1733 } 1734 1735 unsigned ClampIdx = OptionalIdx[AMDGPUOperand::ImmTyClamp]; 1736 unsigned OModIdx = OptionalIdx[AMDGPUOperand::ImmTyOMod]; 1737 1738 ((AMDGPUOperand &)*Operands[ClampIdx]).addImmOperands(Inst, 1); 1739 ((AMDGPUOperand &)*Operands[OModIdx]).addImmOperands(Inst, 1); 1740 } else { 1741 for (unsigned e = Operands.size(); i != e; ++i) 1742 ((AMDGPUOperand &)*Operands[i]).addRegOrImmOperands(Inst, 1); 1743 } 1744 } 1745 1746 /// Force static initialization. 1747 extern "C" void LLVMInitializeAMDGPUAsmParser() { 1748 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget); 1749 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget); 1750 } 1751 1752 #define GET_REGISTER_MATCHER 1753 #define GET_MATCHER_IMPLEMENTATION 1754 #include "AMDGPUGenAsmMatcher.inc" 1755 1756