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