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() << '>'; 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 APInt IntVal32(32, IntVal); 991 if (IntVal32.getSExtValue() != IntVal) { 992 Error(S, "invalid immediate: only 32-bit values are legal"); 993 return MatchOperand_ParseFail; 994 } 995 996 IntVal = IntVal32.getSExtValue(); 997 if (Negate) 998 IntVal *= -1; 999 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S)); 1000 return MatchOperand_Success; 1001 } 1002 case AsmToken::Real: { 1003 // FIXME: We should emit an error if a double precisions floating-point 1004 // value is used. I'm not sure the best way to detect this. 1005 SMLoc S = Parser.getTok().getLoc(); 1006 int64_t IntVal; 1007 if (getParser().parseAbsoluteExpression(IntVal)) 1008 return MatchOperand_ParseFail; 1009 1010 APFloat F((float)BitsToDouble(IntVal)); 1011 if (Negate) 1012 F.changeSign(); 1013 Operands.push_back( 1014 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); 1015 return MatchOperand_Success; 1016 } 1017 case AsmToken::Identifier: { 1018 SMLoc S, E; 1019 unsigned RegNo; 1020 if (!ParseRegister(RegNo, S, E)) { 1021 1022 bool HasModifiers = operandsHaveModifiers(Operands); 1023 unsigned Modifiers = 0; 1024 1025 if (Negate) 1026 Modifiers |= 0x1; 1027 1028 if (Abs) { 1029 if (getLexer().getKind() != AsmToken::Pipe) 1030 return MatchOperand_ParseFail; 1031 Parser.Lex(); 1032 Modifiers |= 0x2; 1033 } 1034 1035 if (Modifiers && !HasModifiers) { 1036 // We are adding a modifier to src1 or src2 and previous sources 1037 // don't have modifiers, so we need to go back and empty modifers 1038 // for each previous source. 1039 for (unsigned PrevRegIdx = Operands.size() - 1; PrevRegIdx > 1; 1040 --PrevRegIdx) { 1041 1042 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[PrevRegIdx]); 1043 RegOp.setModifiers(0); 1044 } 1045 } 1046 1047 1048 Operands.push_back(AMDGPUOperand::CreateReg( 1049 RegNo, S, E, getContext().getRegisterInfo(), 1050 isForcedVOP3())); 1051 1052 if (HasModifiers || Modifiers) { 1053 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[Operands.size() - 1]); 1054 RegOp.setModifiers(Modifiers); 1055 1056 } 1057 } else { 1058 Operands.push_back(AMDGPUOperand::CreateToken(Parser.getTok().getString(), 1059 S)); 1060 Parser.Lex(); 1061 } 1062 return MatchOperand_Success; 1063 } 1064 default: 1065 return MatchOperand_NoMatch; 1066 } 1067 } 1068 1069 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1070 StringRef Name, 1071 SMLoc NameLoc, OperandVector &Operands) { 1072 1073 // Clear any forced encodings from the previous instruction. 1074 setForcedEncodingSize(0); 1075 1076 if (Name.endswith("_e64")) 1077 setForcedEncodingSize(64); 1078 else if (Name.endswith("_e32")) 1079 setForcedEncodingSize(32); 1080 1081 // Add the instruction mnemonic 1082 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); 1083 1084 while (!getLexer().is(AsmToken::EndOfStatement)) { 1085 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); 1086 1087 // Eat the comma or space if there is one. 1088 if (getLexer().is(AsmToken::Comma)) 1089 Parser.Lex(); 1090 1091 switch (Res) { 1092 case MatchOperand_Success: break; 1093 case MatchOperand_ParseFail: return Error(getLexer().getLoc(), 1094 "failed parsing operand."); 1095 case MatchOperand_NoMatch: return Error(getLexer().getLoc(), 1096 "not a valid operand."); 1097 } 1098 } 1099 1100 // Once we reach end of statement, continue parsing so we can add default 1101 // values for optional arguments. 1102 AMDGPUAsmParser::OperandMatchResultTy Res; 1103 while ((Res = parseOperand(Operands, Name)) != MatchOperand_NoMatch) { 1104 if (Res != MatchOperand_Success) 1105 return Error(getLexer().getLoc(), "failed parsing operand."); 1106 } 1107 return false; 1108 } 1109 1110 //===----------------------------------------------------------------------===// 1111 // Utility functions 1112 //===----------------------------------------------------------------------===// 1113 1114 AMDGPUAsmParser::OperandMatchResultTy 1115 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int, 1116 int64_t Default) { 1117 1118 // We are at the end of the statement, and this is a default argument, so 1119 // use a default value. 1120 if (getLexer().is(AsmToken::EndOfStatement)) { 1121 Int = Default; 1122 return MatchOperand_Success; 1123 } 1124 1125 switch(getLexer().getKind()) { 1126 default: return MatchOperand_NoMatch; 1127 case AsmToken::Identifier: { 1128 StringRef OffsetName = Parser.getTok().getString(); 1129 if (!OffsetName.equals(Prefix)) 1130 return MatchOperand_NoMatch; 1131 1132 Parser.Lex(); 1133 if (getLexer().isNot(AsmToken::Colon)) 1134 return MatchOperand_ParseFail; 1135 1136 Parser.Lex(); 1137 if (getLexer().isNot(AsmToken::Integer)) 1138 return MatchOperand_ParseFail; 1139 1140 if (getParser().parseAbsoluteExpression(Int)) 1141 return MatchOperand_ParseFail; 1142 break; 1143 } 1144 } 1145 return MatchOperand_Success; 1146 } 1147 1148 AMDGPUAsmParser::OperandMatchResultTy 1149 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1150 enum AMDGPUOperand::ImmTy ImmTy) { 1151 1152 SMLoc S = Parser.getTok().getLoc(); 1153 int64_t Offset = 0; 1154 1155 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Offset); 1156 if (Res != MatchOperand_Success) 1157 return Res; 1158 1159 Operands.push_back(AMDGPUOperand::CreateImm(Offset, S, ImmTy)); 1160 return MatchOperand_Success; 1161 } 1162 1163 AMDGPUAsmParser::OperandMatchResultTy 1164 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 1165 enum AMDGPUOperand::ImmTy ImmTy) { 1166 int64_t Bit = 0; 1167 SMLoc S = Parser.getTok().getLoc(); 1168 1169 // We are at the end of the statement, and this is a default argument, so 1170 // use a default value. 1171 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1172 switch(getLexer().getKind()) { 1173 case AsmToken::Identifier: { 1174 StringRef Tok = Parser.getTok().getString(); 1175 if (Tok == Name) { 1176 Bit = 1; 1177 Parser.Lex(); 1178 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 1179 Bit = 0; 1180 Parser.Lex(); 1181 } else { 1182 return MatchOperand_NoMatch; 1183 } 1184 break; 1185 } 1186 default: 1187 return MatchOperand_NoMatch; 1188 } 1189 } 1190 1191 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy)); 1192 return MatchOperand_Success; 1193 } 1194 1195 static bool operandsHasOptionalOp(const OperandVector &Operands, 1196 const OptionalOperand &OOp) { 1197 for (unsigned i = 0; i < Operands.size(); i++) { 1198 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]); 1199 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) || 1200 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name)) 1201 return true; 1202 1203 } 1204 return false; 1205 } 1206 1207 AMDGPUAsmParser::OperandMatchResultTy 1208 AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps, 1209 OperandVector &Operands) { 1210 SMLoc S = Parser.getTok().getLoc(); 1211 for (const OptionalOperand &Op : OptionalOps) { 1212 if (operandsHasOptionalOp(Operands, Op)) 1213 continue; 1214 AMDGPUAsmParser::OperandMatchResultTy Res; 1215 int64_t Value; 1216 if (Op.IsBit) { 1217 Res = parseNamedBit(Op.Name, Operands, Op.Type); 1218 if (Res == MatchOperand_NoMatch) 1219 continue; 1220 return Res; 1221 } 1222 1223 Res = parseIntWithPrefix(Op.Name, Value, Op.Default); 1224 1225 if (Res == MatchOperand_NoMatch) 1226 continue; 1227 1228 if (Res != MatchOperand_Success) 1229 return Res; 1230 1231 if (Op.ConvertResult && !Op.ConvertResult(Value)) { 1232 return MatchOperand_ParseFail; 1233 } 1234 1235 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type)); 1236 return MatchOperand_Success; 1237 } 1238 return MatchOperand_NoMatch; 1239 } 1240 1241 //===----------------------------------------------------------------------===// 1242 // ds 1243 //===----------------------------------------------------------------------===// 1244 1245 static const OptionalOperand DSOptionalOps [] = { 1246 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1247 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1248 }; 1249 1250 static const OptionalOperand DSOptionalOpsOff01 [] = { 1251 {"offset0", AMDGPUOperand::ImmTyDSOffset0, false, 0, nullptr}, 1252 {"offset1", AMDGPUOperand::ImmTyDSOffset1, false, 0, nullptr}, 1253 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1254 }; 1255 1256 AMDGPUAsmParser::OperandMatchResultTy 1257 AMDGPUAsmParser::parseDSOptionalOps(OperandVector &Operands) { 1258 return parseOptionalOps(DSOptionalOps, Operands); 1259 } 1260 AMDGPUAsmParser::OperandMatchResultTy 1261 AMDGPUAsmParser::parseDSOff01OptionalOps(OperandVector &Operands) { 1262 return parseOptionalOps(DSOptionalOpsOff01, Operands); 1263 } 1264 1265 AMDGPUAsmParser::OperandMatchResultTy 1266 AMDGPUAsmParser::parseDSOffsetOptional(OperandVector &Operands) { 1267 SMLoc S = Parser.getTok().getLoc(); 1268 AMDGPUAsmParser::OperandMatchResultTy Res = 1269 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset); 1270 if (Res == MatchOperand_NoMatch) { 1271 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 1272 AMDGPUOperand::ImmTyOffset)); 1273 Res = MatchOperand_Success; 1274 } 1275 return Res; 1276 } 1277 1278 bool AMDGPUOperand::isDSOffset() const { 1279 return isImm() && isUInt<16>(getImm()); 1280 } 1281 1282 bool AMDGPUOperand::isDSOffset01() const { 1283 return isImm() && isUInt<8>(getImm()); 1284 } 1285 1286 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 1287 const OperandVector &Operands) { 1288 1289 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1290 1291 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1292 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1293 1294 // Add the register arguments 1295 if (Op.isReg()) { 1296 Op.addRegOperands(Inst, 1); 1297 continue; 1298 } 1299 1300 // Handle optional arguments 1301 OptionalIdx[Op.getImmTy()] = i; 1302 } 1303 1304 unsigned Offset0Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset0]; 1305 unsigned Offset1Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset1]; 1306 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1307 1308 ((AMDGPUOperand &)*Operands[Offset0Idx]).addImmOperands(Inst, 1); // offset0 1309 ((AMDGPUOperand &)*Operands[Offset1Idx]).addImmOperands(Inst, 1); // offset1 1310 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1311 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1312 } 1313 1314 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 1315 1316 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1317 bool GDSOnly = false; 1318 1319 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1320 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1321 1322 // Add the register arguments 1323 if (Op.isReg()) { 1324 Op.addRegOperands(Inst, 1); 1325 continue; 1326 } 1327 1328 if (Op.isToken() && Op.getToken() == "gds") { 1329 GDSOnly = true; 1330 continue; 1331 } 1332 1333 // Handle optional arguments 1334 OptionalIdx[Op.getImmTy()] = i; 1335 } 1336 1337 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1338 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); // offset 1339 1340 if (!GDSOnly) { 1341 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1342 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1343 } 1344 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1345 } 1346 1347 1348 //===----------------------------------------------------------------------===// 1349 // s_waitcnt 1350 //===----------------------------------------------------------------------===// 1351 1352 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 1353 StringRef CntName = Parser.getTok().getString(); 1354 int64_t CntVal; 1355 1356 Parser.Lex(); 1357 if (getLexer().isNot(AsmToken::LParen)) 1358 return true; 1359 1360 Parser.Lex(); 1361 if (getLexer().isNot(AsmToken::Integer)) 1362 return true; 1363 1364 if (getParser().parseAbsoluteExpression(CntVal)) 1365 return true; 1366 1367 if (getLexer().isNot(AsmToken::RParen)) 1368 return true; 1369 1370 Parser.Lex(); 1371 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 1372 Parser.Lex(); 1373 1374 int CntShift; 1375 int CntMask; 1376 1377 if (CntName == "vmcnt") { 1378 CntMask = 0xf; 1379 CntShift = 0; 1380 } else if (CntName == "expcnt") { 1381 CntMask = 0x7; 1382 CntShift = 4; 1383 } else if (CntName == "lgkmcnt") { 1384 CntMask = 0x7; 1385 CntShift = 8; 1386 } else { 1387 return true; 1388 } 1389 1390 IntVal &= ~(CntMask << CntShift); 1391 IntVal |= (CntVal << CntShift); 1392 return false; 1393 } 1394 1395 AMDGPUAsmParser::OperandMatchResultTy 1396 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 1397 // Disable all counters by default. 1398 // vmcnt [3:0] 1399 // expcnt [6:4] 1400 // lgkmcnt [10:8] 1401 int64_t CntVal = 0x77f; 1402 SMLoc S = Parser.getTok().getLoc(); 1403 1404 switch(getLexer().getKind()) { 1405 default: return MatchOperand_ParseFail; 1406 case AsmToken::Integer: 1407 // The operand can be an integer value. 1408 if (getParser().parseAbsoluteExpression(CntVal)) 1409 return MatchOperand_ParseFail; 1410 break; 1411 1412 case AsmToken::Identifier: 1413 do { 1414 if (parseCnt(CntVal)) 1415 return MatchOperand_ParseFail; 1416 } while(getLexer().isNot(AsmToken::EndOfStatement)); 1417 break; 1418 } 1419 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S)); 1420 return MatchOperand_Success; 1421 } 1422 1423 bool AMDGPUOperand::isSWaitCnt() const { 1424 return isImm(); 1425 } 1426 1427 //===----------------------------------------------------------------------===// 1428 // sopp branch targets 1429 //===----------------------------------------------------------------------===// 1430 1431 AMDGPUAsmParser::OperandMatchResultTy 1432 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 1433 SMLoc S = Parser.getTok().getLoc(); 1434 1435 switch (getLexer().getKind()) { 1436 default: return MatchOperand_ParseFail; 1437 case AsmToken::Integer: { 1438 int64_t Imm; 1439 if (getParser().parseAbsoluteExpression(Imm)) 1440 return MatchOperand_ParseFail; 1441 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S)); 1442 return MatchOperand_Success; 1443 } 1444 1445 case AsmToken::Identifier: 1446 Operands.push_back(AMDGPUOperand::CreateExpr( 1447 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 1448 Parser.getTok().getString()), getContext()), S)); 1449 Parser.Lex(); 1450 return MatchOperand_Success; 1451 } 1452 } 1453 1454 //===----------------------------------------------------------------------===// 1455 // flat 1456 //===----------------------------------------------------------------------===// 1457 1458 static const OptionalOperand FlatOptionalOps [] = { 1459 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1460 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1461 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1462 }; 1463 1464 static const OptionalOperand FlatAtomicOptionalOps [] = { 1465 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1466 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1467 }; 1468 1469 AMDGPUAsmParser::OperandMatchResultTy 1470 AMDGPUAsmParser::parseFlatOptionalOps(OperandVector &Operands) { 1471 return parseOptionalOps(FlatOptionalOps, Operands); 1472 } 1473 1474 AMDGPUAsmParser::OperandMatchResultTy 1475 AMDGPUAsmParser::parseFlatAtomicOptionalOps(OperandVector &Operands) { 1476 return parseOptionalOps(FlatAtomicOptionalOps, Operands); 1477 } 1478 1479 void AMDGPUAsmParser::cvtFlat(MCInst &Inst, 1480 const OperandVector &Operands) { 1481 std::map<AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1482 1483 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1484 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1485 1486 // Add the register arguments 1487 if (Op.isReg()) { 1488 Op.addRegOperands(Inst, 1); 1489 continue; 1490 } 1491 1492 // Handle 'glc' token which is sometimes hard-coded into the 1493 // asm string. There are no MCInst operands for these. 1494 if (Op.isToken()) 1495 continue; 1496 1497 // Handle optional arguments 1498 OptionalIdx[Op.getImmTy()] = i; 1499 1500 } 1501 1502 // flat atomic instructions don't have a glc argument. 1503 if (OptionalIdx.count(AMDGPUOperand::ImmTyGLC)) { 1504 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1505 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1506 } 1507 1508 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1509 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1510 1511 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1512 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1513 } 1514 1515 //===----------------------------------------------------------------------===// 1516 // mubuf 1517 //===----------------------------------------------------------------------===// 1518 1519 static const OptionalOperand MubufOptionalOps [] = { 1520 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1521 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1522 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1523 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1524 }; 1525 1526 AMDGPUAsmParser::OperandMatchResultTy 1527 AMDGPUAsmParser::parseMubufOptionalOps(OperandVector &Operands) { 1528 return parseOptionalOps(MubufOptionalOps, Operands); 1529 } 1530 1531 AMDGPUAsmParser::OperandMatchResultTy 1532 AMDGPUAsmParser::parseOffset(OperandVector &Operands) { 1533 return parseIntWithPrefix("offset", Operands); 1534 } 1535 1536 AMDGPUAsmParser::OperandMatchResultTy 1537 AMDGPUAsmParser::parseGLC(OperandVector &Operands) { 1538 return parseNamedBit("glc", Operands); 1539 } 1540 1541 AMDGPUAsmParser::OperandMatchResultTy 1542 AMDGPUAsmParser::parseSLC(OperandVector &Operands) { 1543 return parseNamedBit("slc", Operands); 1544 } 1545 1546 AMDGPUAsmParser::OperandMatchResultTy 1547 AMDGPUAsmParser::parseTFE(OperandVector &Operands) { 1548 return parseNamedBit("tfe", Operands); 1549 } 1550 1551 bool AMDGPUOperand::isMubufOffset() const { 1552 return isImm() && isUInt<12>(getImm()); 1553 } 1554 1555 void AMDGPUAsmParser::cvtMubuf(MCInst &Inst, 1556 const OperandVector &Operands) { 1557 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1558 1559 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1560 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1561 1562 // Add the register arguments 1563 if (Op.isReg()) { 1564 Op.addRegOperands(Inst, 1); 1565 continue; 1566 } 1567 1568 // Handle the case where soffset is an immediate 1569 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 1570 Op.addImmOperands(Inst, 1); 1571 continue; 1572 } 1573 1574 // Handle tokens like 'offen' which are sometimes hard-coded into the 1575 // asm string. There are no MCInst operands for these. 1576 if (Op.isToken()) { 1577 continue; 1578 } 1579 assert(Op.isImm()); 1580 1581 // Handle optional arguments 1582 OptionalIdx[Op.getImmTy()] = i; 1583 } 1584 1585 assert(OptionalIdx.size() == 4); 1586 1587 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1588 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1589 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1590 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1591 1592 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); 1593 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1594 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1595 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1596 } 1597 1598 //===----------------------------------------------------------------------===// 1599 // mimg 1600 //===----------------------------------------------------------------------===// 1601 1602 AMDGPUAsmParser::OperandMatchResultTy 1603 AMDGPUAsmParser::parseDMask(OperandVector &Operands) { 1604 return parseIntWithPrefix("dmask", Operands); 1605 } 1606 1607 AMDGPUAsmParser::OperandMatchResultTy 1608 AMDGPUAsmParser::parseUNorm(OperandVector &Operands) { 1609 return parseNamedBit("unorm", Operands); 1610 } 1611 1612 AMDGPUAsmParser::OperandMatchResultTy 1613 AMDGPUAsmParser::parseR128(OperandVector &Operands) { 1614 return parseNamedBit("r128", Operands); 1615 } 1616 1617 //===----------------------------------------------------------------------===// 1618 // smrd 1619 //===----------------------------------------------------------------------===// 1620 1621 bool AMDGPUOperand::isSMRDOffset() const { 1622 1623 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget 1624 // information here. 1625 return isImm() && isUInt<8>(getImm()); 1626 } 1627 1628 bool AMDGPUOperand::isSMRDLiteralOffset() const { 1629 // 32-bit literals are only supported on CI and we only want to use them 1630 // when the offset is > 8-bits. 1631 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 1632 } 1633 1634 //===----------------------------------------------------------------------===// 1635 // vop3 1636 //===----------------------------------------------------------------------===// 1637 1638 static bool ConvertOmodMul(int64_t &Mul) { 1639 if (Mul != 1 && Mul != 2 && Mul != 4) 1640 return false; 1641 1642 Mul >>= 1; 1643 return true; 1644 } 1645 1646 static bool ConvertOmodDiv(int64_t &Div) { 1647 if (Div == 1) { 1648 Div = 0; 1649 return true; 1650 } 1651 1652 if (Div == 2) { 1653 Div = 3; 1654 return true; 1655 } 1656 1657 return false; 1658 } 1659 1660 static const OptionalOperand VOP3OptionalOps [] = { 1661 {"clamp", AMDGPUOperand::ImmTyClamp, true, 0, nullptr}, 1662 {"mul", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodMul}, 1663 {"div", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodDiv}, 1664 }; 1665 1666 static bool isVOP3(OperandVector &Operands) { 1667 if (operandsHaveModifiers(Operands)) 1668 return true; 1669 1670 AMDGPUOperand &DstOp = ((AMDGPUOperand&)*Operands[1]); 1671 1672 if (DstOp.isReg() && DstOp.isRegClass(AMDGPU::SGPR_64RegClassID)) 1673 return true; 1674 1675 if (Operands.size() >= 5) 1676 return true; 1677 1678 if (Operands.size() > 3) { 1679 AMDGPUOperand &Src1Op = ((AMDGPUOperand&)*Operands[3]); 1680 if (Src1Op.getReg() && (Src1Op.isRegClass(AMDGPU::SReg_32RegClassID) || 1681 Src1Op.isRegClass(AMDGPU::SReg_64RegClassID))) 1682 return true; 1683 } 1684 return false; 1685 } 1686 1687 AMDGPUAsmParser::OperandMatchResultTy 1688 AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) { 1689 1690 // The value returned by this function may change after parsing 1691 // an operand so store the original value here. 1692 bool HasModifiers = operandsHaveModifiers(Operands); 1693 1694 bool IsVOP3 = isVOP3(Operands); 1695 if (HasModifiers || IsVOP3 || 1696 getLexer().isNot(AsmToken::EndOfStatement) || 1697 getForcedEncodingSize() == 64) { 1698 1699 AMDGPUAsmParser::OperandMatchResultTy Res = 1700 parseOptionalOps(VOP3OptionalOps, Operands); 1701 1702 if (!HasModifiers && Res == MatchOperand_Success) { 1703 // We have added a modifier operation, so we need to make sure all 1704 // previous register operands have modifiers 1705 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 1706 AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 1707 if (Op.isReg()) 1708 Op.setModifiers(0); 1709 } 1710 } 1711 return Res; 1712 } 1713 return MatchOperand_NoMatch; 1714 } 1715 1716 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 1717 1718 unsigned i = 1; 1719 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 1720 if (Desc.getNumDefs() > 0) { 1721 ((AMDGPUOperand &)*Operands[i++]).addRegOperands(Inst, 1); 1722 } 1723 1724 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1725 1726 if (operandsHaveModifiers(Operands)) { 1727 for (unsigned e = Operands.size(); i != e; ++i) { 1728 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1729 1730 if (Op.isRegWithInputMods()) { 1731 ((AMDGPUOperand &)*Operands[i]).addRegWithInputModsOperands(Inst, 2); 1732 continue; 1733 } 1734 OptionalIdx[Op.getImmTy()] = i; 1735 } 1736 1737 unsigned ClampIdx = OptionalIdx[AMDGPUOperand::ImmTyClamp]; 1738 unsigned OModIdx = OptionalIdx[AMDGPUOperand::ImmTyOMod]; 1739 1740 ((AMDGPUOperand &)*Operands[ClampIdx]).addImmOperands(Inst, 1); 1741 ((AMDGPUOperand &)*Operands[OModIdx]).addImmOperands(Inst, 1); 1742 } else { 1743 for (unsigned e = Operands.size(); i != e; ++i) 1744 ((AMDGPUOperand &)*Operands[i]).addRegOrImmOperands(Inst, 1); 1745 } 1746 } 1747 1748 /// Force static initialization. 1749 extern "C" void LLVMInitializeAMDGPUAsmParser() { 1750 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget); 1751 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget); 1752 } 1753 1754 #define GET_REGISTER_MATCHER 1755 #define GET_MATCHER_IMPLEMENTATION 1756 #include "AMDGPUGenAsmMatcher.inc" 1757 1758