1 //===- Patterns.cpp --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Patterns.h" 10 #include "Basic/CodeGenIntrinsics.h" 11 #include "CXXPredicates.h" 12 #include "CodeExpander.h" 13 #include "CodeExpansions.h" 14 #include "Common/CodeGenInstruction.h" 15 #include "llvm/ADT/StringSet.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/raw_ostream.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/Record.h" 20 21 namespace llvm { 22 namespace gi { 23 24 //===- PatternType --------------------------------------------------------===// 25 26 std::optional<PatternType> PatternType::get(ArrayRef<SMLoc> DiagLoc, 27 const Record *R, Twine DiagCtx) { 28 assert(R); 29 if (R->isSubClassOf("ValueType")) { 30 PatternType PT(PT_ValueType); 31 PT.Data.Def = R; 32 return PT; 33 } 34 35 if (R->isSubClassOf(TypeOfClassName)) { 36 auto RawOpName = R->getValueAsString("OpName"); 37 if (!RawOpName.starts_with("$")) { 38 PrintError(DiagLoc, DiagCtx + ": invalid operand name format '" + 39 RawOpName + "' in " + TypeOfClassName + 40 ": expected '$' followed by an operand name"); 41 return std::nullopt; 42 } 43 44 PatternType PT(PT_TypeOf); 45 PT.Data.Str = RawOpName.drop_front(1); 46 return PT; 47 } 48 49 PrintError(DiagLoc, DiagCtx + ": unknown type '" + R->getName() + "'"); 50 return std::nullopt; 51 } 52 53 PatternType PatternType::getTypeOf(StringRef OpName) { 54 PatternType PT(PT_TypeOf); 55 PT.Data.Str = OpName; 56 return PT; 57 } 58 59 StringRef PatternType::getTypeOfOpName() const { 60 assert(isTypeOf()); 61 return Data.Str; 62 } 63 64 const Record *PatternType::getLLTRecord() const { 65 assert(isLLT()); 66 return Data.Def; 67 } 68 69 bool PatternType::operator==(const PatternType &Other) const { 70 if (Kind != Other.Kind) 71 return false; 72 73 switch (Kind) { 74 case PT_None: 75 return true; 76 case PT_ValueType: 77 return Data.Def == Other.Data.Def; 78 case PT_TypeOf: 79 return Data.Str == Other.Data.Str; 80 } 81 82 llvm_unreachable("Unknown Type Kind"); 83 } 84 85 std::string PatternType::str() const { 86 switch (Kind) { 87 case PT_None: 88 return ""; 89 case PT_ValueType: 90 return Data.Def->getName().str(); 91 case PT_TypeOf: 92 return (TypeOfClassName + "<$" + getTypeOfOpName() + ">").str(); 93 } 94 95 llvm_unreachable("Unknown type!"); 96 } 97 98 //===- Pattern ------------------------------------------------------------===// 99 100 void Pattern::dump() const { return print(dbgs()); } 101 102 const char *Pattern::getKindName() const { 103 switch (Kind) { 104 case K_AnyOpcode: 105 return "AnyOpcodePattern"; 106 case K_CXX: 107 return "CXXPattern"; 108 case K_CodeGenInstruction: 109 return "CodeGenInstructionPattern"; 110 case K_PatFrag: 111 return "PatFragPattern"; 112 case K_Builtin: 113 return "BuiltinPattern"; 114 } 115 116 llvm_unreachable("unknown pattern kind!"); 117 } 118 119 void Pattern::printImpl(raw_ostream &OS, bool PrintName, 120 function_ref<void()> ContentPrinter) const { 121 OS << "(" << getKindName() << " "; 122 if (PrintName) 123 OS << "name:" << getName() << " "; 124 ContentPrinter(); 125 OS << ")"; 126 } 127 128 //===- AnyOpcodePattern ---------------------------------------------------===// 129 130 void AnyOpcodePattern::print(raw_ostream &OS, bool PrintName) const { 131 printImpl(OS, PrintName, [&OS, this]() { 132 OS << "[" 133 << join(map_range(Insts, 134 [](const auto *I) { return I->TheDef->getName(); }), 135 ", ") 136 << "]"; 137 }); 138 } 139 140 //===- CXXPattern ---------------------------------------------------------===// 141 142 CXXPattern::CXXPattern(const StringInit &Code, StringRef Name) 143 : CXXPattern(Code.getAsUnquotedString(), Name) {} 144 145 const CXXPredicateCode & 146 CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef<SMLoc> Locs, 147 function_ref<void(raw_ostream &)> AddComment) const { 148 assert(!IsApply && "'apply' CXX patterns should be handled differently!"); 149 150 std::string Result; 151 raw_string_ostream OS(Result); 152 153 if (AddComment) 154 AddComment(OS); 155 156 CodeExpander Expander(RawCode, CE, Locs, /*ShowExpansions*/ false); 157 Expander.emit(OS); 158 return CXXPredicateCode::getMatchCode(std::move(Result)); 159 } 160 161 void CXXPattern::print(raw_ostream &OS, bool PrintName) const { 162 printImpl(OS, PrintName, [&OS, this] { 163 OS << (IsApply ? "apply" : "match") << " code:\""; 164 printEscapedString(getRawCode(), OS); 165 OS << "\""; 166 }); 167 } 168 169 //===- InstructionOperand -------------------------------------------------===// 170 171 std::string InstructionOperand::describe() const { 172 if (!hasImmValue()) 173 return "MachineOperand $" + getOperandName().str() + ""; 174 std::string Str = "imm " + std::to_string(getImmValue()); 175 if (isNamedImmediate()) 176 Str += ":$" + getOperandName().str() + ""; 177 return Str; 178 } 179 180 void InstructionOperand::print(raw_ostream &OS) const { 181 if (isDef()) 182 OS << "<def>"; 183 184 bool NeedsColon = true; 185 if (Type) { 186 if (hasImmValue()) 187 OS << "(" << Type.str() << " " << getImmValue() << ")"; 188 else 189 OS << Type.str(); 190 } else if (hasImmValue()) 191 OS << getImmValue(); 192 else 193 NeedsColon = false; 194 195 if (isNamedOperand()) 196 OS << (NeedsColon ? ":" : "") << "$" << getOperandName(); 197 } 198 199 void InstructionOperand::dump() const { return print(dbgs()); } 200 201 //===- InstructionPattern -------------------------------------------------===// 202 203 bool InstructionPattern::diagnoseAllSpecialTypes(ArrayRef<SMLoc> Loc, 204 Twine Msg) const { 205 bool HasDiag = false; 206 for (const auto &[Idx, Op] : enumerate(operands())) { 207 if (Op.getType().isSpecial()) { 208 PrintError(Loc, Msg); 209 PrintNote(Loc, "operand " + Twine(Idx) + " of '" + getName() + 210 "' has type '" + Op.getType().str() + "'"); 211 HasDiag = true; 212 } 213 } 214 return HasDiag; 215 } 216 217 void InstructionPattern::reportUnreachable(ArrayRef<SMLoc> Locs) const { 218 PrintError(Locs, "pattern '" + getName() + "' ('" + getInstName() + 219 "') is unreachable from the pattern root!"); 220 } 221 222 bool InstructionPattern::checkSemantics(ArrayRef<SMLoc> Loc) { 223 unsigned NumExpectedOperands = getNumInstOperands(); 224 225 if (isVariadic()) { 226 if (Operands.size() < NumExpectedOperands) { 227 PrintError(Loc, +"'" + getInstName() + "' expected at least " + 228 Twine(NumExpectedOperands) + " operands, got " + 229 Twine(Operands.size())); 230 return false; 231 } 232 } else if (NumExpectedOperands != Operands.size()) { 233 PrintError(Loc, +"'" + getInstName() + "' expected " + 234 Twine(NumExpectedOperands) + " operands, got " + 235 Twine(Operands.size())); 236 return false; 237 } 238 239 unsigned OpIdx = 0; 240 unsigned NumDefs = getNumInstDefs(); 241 for (auto &Op : Operands) 242 Op.setIsDef(OpIdx++ < NumDefs); 243 244 return true; 245 } 246 247 void InstructionPattern::print(raw_ostream &OS, bool PrintName) const { 248 printImpl(OS, PrintName, [&OS, this] { 249 OS << getInstName() << " operands:["; 250 StringRef Sep; 251 for (const auto &Op : Operands) { 252 OS << Sep; 253 Op.print(OS); 254 Sep = ", "; 255 } 256 OS << "]"; 257 258 printExtras(OS); 259 }); 260 } 261 262 //===- OperandTable -------------------------------------------------------===// 263 264 bool OperandTable::addPattern(InstructionPattern *P, 265 function_ref<void(StringRef)> DiagnoseRedef) { 266 for (const auto &Op : P->named_operands()) { 267 StringRef OpName = Op.getOperandName(); 268 269 // We always create an entry in the OperandTable, even for uses. 270 // Uses of operands that don't have a def (= live-ins) will remain with a 271 // nullptr as the Def. 272 // 273 // This allows us tell whether an operand exists in a pattern or not. If 274 // there is no entry for it, it doesn't exist, if there is an entry, it's 275 // used/def'd at least once. 276 auto &Def = Table[OpName]; 277 278 if (!Op.isDef()) 279 continue; 280 281 if (Def) { 282 DiagnoseRedef(OpName); 283 return false; 284 } 285 286 Def = P; 287 } 288 289 return true; 290 } 291 292 void OperandTable::print(raw_ostream &OS, StringRef Name, 293 StringRef Indent) const { 294 OS << Indent << "(OperandTable "; 295 if (!Name.empty()) 296 OS << Name << " "; 297 if (Table.empty()) { 298 OS << "<empty>)\n"; 299 return; 300 } 301 302 SmallVector<StringRef, 0> Keys(Table.keys()); 303 sort(Keys); 304 305 OS << '\n'; 306 for (const auto &Key : Keys) { 307 const auto *Def = Table.at(Key); 308 OS << Indent << " " << Key << " -> " 309 << (Def ? Def->getName() : "<live-in>") << '\n'; 310 } 311 OS << Indent << ")\n"; 312 } 313 314 void OperandTable::dump() const { print(dbgs()); } 315 316 //===- MIFlagsInfo --------------------------------------------------------===// 317 318 void MIFlagsInfo::addSetFlag(const Record *R) { 319 SetF.insert(R->getValueAsString("EnumName")); 320 } 321 322 void MIFlagsInfo::addUnsetFlag(const Record *R) { 323 UnsetF.insert(R->getValueAsString("EnumName")); 324 } 325 326 void MIFlagsInfo::addCopyFlag(StringRef InstName) { CopyF.insert(InstName); } 327 328 //===- CodeGenInstructionPattern ------------------------------------------===// 329 330 bool CodeGenInstructionPattern::is(StringRef OpcodeName) const { 331 return I.TheDef->getName() == OpcodeName; 332 } 333 334 bool CodeGenInstructionPattern::isVariadic() const { 335 return !isIntrinsic() && I.Operands.isVariadic; 336 } 337 338 bool CodeGenInstructionPattern::hasVariadicDefs() const { 339 // Note: we cannot use variadicOpsAreDefs, it's not set for 340 // GenericInstructions. 341 if (!isVariadic()) 342 return false; 343 344 if (I.variadicOpsAreDefs) 345 return true; 346 347 DagInit *OutOps = I.TheDef->getValueAsDag("OutOperandList"); 348 if (OutOps->arg_empty()) 349 return false; 350 351 auto *LastArgTy = dyn_cast<DefInit>(OutOps->getArg(OutOps->arg_size() - 1)); 352 return LastArgTy && LastArgTy->getDef()->getName() == "variable_ops"; 353 } 354 355 unsigned CodeGenInstructionPattern::getNumInstDefs() const { 356 if (isIntrinsic()) 357 return IntrinInfo->IS.RetTys.size(); 358 359 if (!isVariadic() || !hasVariadicDefs()) 360 return I.Operands.NumDefs; 361 unsigned NumOuts = I.Operands.size() - I.Operands.NumDefs; 362 assert(Operands.size() > NumOuts); 363 return std::max<unsigned>(I.Operands.NumDefs, Operands.size() - NumOuts); 364 } 365 366 unsigned CodeGenInstructionPattern::getNumInstOperands() const { 367 if (isIntrinsic()) 368 return IntrinInfo->IS.RetTys.size() + IntrinInfo->IS.ParamTys.size(); 369 370 unsigned NumCGIOps = I.Operands.size(); 371 return isVariadic() ? std::max<unsigned>(NumCGIOps, Operands.size()) 372 : NumCGIOps; 373 } 374 375 MIFlagsInfo &CodeGenInstructionPattern::getOrCreateMIFlagsInfo() { 376 if (!FI) 377 FI = std::make_unique<MIFlagsInfo>(); 378 return *FI; 379 } 380 381 StringRef CodeGenInstructionPattern::getInstName() const { 382 return I.TheDef->getName(); 383 } 384 385 void CodeGenInstructionPattern::printExtras(raw_ostream &OS) const { 386 if (isIntrinsic()) 387 OS << " intrinsic(@" << IntrinInfo->Name << ")"; 388 389 if (!FI) 390 return; 391 392 OS << " (MIFlags"; 393 if (!FI->set_flags().empty()) 394 OS << " (set " << join(FI->set_flags(), ", ") << ")"; 395 if (!FI->unset_flags().empty()) 396 OS << " (unset " << join(FI->unset_flags(), ", ") << ")"; 397 if (!FI->copy_flags().empty()) 398 OS << " (copy " << join(FI->copy_flags(), ", ") << ")"; 399 OS << ')'; 400 } 401 402 //===- OperandTypeChecker -------------------------------------------------===// 403 404 bool OperandTypeChecker::check( 405 InstructionPattern &P, 406 std::function<bool(const PatternType &)> VerifyTypeOfOperand) { 407 Pats.push_back(&P); 408 409 for (auto &Op : P.operands()) { 410 const auto Ty = Op.getType(); 411 if (!Ty) 412 continue; 413 414 if (Ty.isTypeOf() && !VerifyTypeOfOperand(Ty)) 415 return false; 416 417 if (!Op.isNamedOperand()) 418 continue; 419 420 StringRef OpName = Op.getOperandName(); 421 auto &Info = Types[OpName]; 422 if (!Info.Type) { 423 Info.Type = Ty; 424 Info.PrintTypeSrcNote = [this, OpName, Ty, &P]() { 425 PrintSeenWithTypeIn(P, OpName, Ty); 426 }; 427 continue; 428 } 429 430 if (Info.Type != Ty) { 431 PrintError(DiagLoc, "conflicting types for operand '" + 432 Op.getOperandName() + "': '" + Info.Type.str() + 433 "' vs '" + Ty.str() + "'"); 434 PrintSeenWithTypeIn(P, OpName, Ty); 435 Info.PrintTypeSrcNote(); 436 return false; 437 } 438 } 439 440 return true; 441 } 442 443 void OperandTypeChecker::propagateTypes() { 444 for (auto *Pat : Pats) { 445 for (auto &Op : Pat->named_operands()) { 446 if (auto &Info = Types[Op.getOperandName()]; Info.Type) 447 Op.setType(Info.Type); 448 } 449 } 450 } 451 452 void OperandTypeChecker::PrintSeenWithTypeIn(InstructionPattern &P, 453 StringRef OpName, 454 PatternType Ty) const { 455 PrintNote(DiagLoc, "'" + OpName + "' seen with type '" + Ty.str() + "' in '" + 456 P.getName() + "'"); 457 } 458 459 StringRef PatFrag::getParamKindStr(ParamKind OK) { 460 switch (OK) { 461 case PK_Root: 462 return "root"; 463 case PK_MachineOperand: 464 return "machine_operand"; 465 case PK_Imm: 466 return "imm"; 467 } 468 469 llvm_unreachable("Unknown operand kind!"); 470 } 471 472 //===- PatFrag -----------------------------------------------------------===// 473 474 PatFrag::PatFrag(const Record &Def) : Def(Def) { 475 assert(Def.isSubClassOf(ClassName)); 476 } 477 478 StringRef PatFrag::getName() const { return Def.getName(); } 479 480 ArrayRef<SMLoc> PatFrag::getLoc() const { return Def.getLoc(); } 481 482 void PatFrag::addInParam(StringRef Name, ParamKind Kind) { 483 Params.emplace_back(Param{Name, Kind}); 484 } 485 486 iterator_range<PatFrag::ParamIt> PatFrag::in_params() const { 487 return {Params.begin() + NumOutParams, Params.end()}; 488 } 489 490 void PatFrag::addOutParam(StringRef Name, ParamKind Kind) { 491 assert(NumOutParams == Params.size() && 492 "Adding out-param after an in-param!"); 493 Params.emplace_back(Param{Name, Kind}); 494 ++NumOutParams; 495 } 496 497 iterator_range<PatFrag::ParamIt> PatFrag::out_params() const { 498 return {Params.begin(), Params.begin() + NumOutParams}; 499 } 500 501 unsigned PatFrag::num_roots() const { 502 return count_if(out_params(), 503 [&](const auto &P) { return P.Kind == PK_Root; }); 504 } 505 506 unsigned PatFrag::getParamIdx(StringRef Name) const { 507 for (const auto &[Idx, Op] : enumerate(Params)) { 508 if (Op.Name == Name) 509 return Idx; 510 } 511 512 return -1; 513 } 514 515 bool PatFrag::checkSemantics() { 516 for (const auto &Alt : Alts) { 517 for (const auto &Pat : Alt.Pats) { 518 switch (Pat->getKind()) { 519 case Pattern::K_AnyOpcode: 520 PrintError("wip_match_opcode cannot be used in " + ClassName); 521 return false; 522 case Pattern::K_Builtin: 523 PrintError("Builtin instructions cannot be used in " + ClassName); 524 return false; 525 case Pattern::K_CXX: 526 continue; 527 case Pattern::K_CodeGenInstruction: 528 if (cast<CodeGenInstructionPattern>(Pat.get())->diagnoseAllSpecialTypes( 529 Def.getLoc(), PatternType::SpecialTyClassName + 530 " is not supported in " + ClassName)) 531 return false; 532 continue; 533 case Pattern::K_PatFrag: 534 // TODO: It's just that the emitter doesn't handle it but technically 535 // there is no reason why we can't. We just have to be careful with 536 // operand mappings, it could get complex. 537 PrintError("nested " + ClassName + " are not supported"); 538 return false; 539 } 540 } 541 } 542 543 StringSet<> SeenOps; 544 for (const auto &Op : in_params()) { 545 if (SeenOps.count(Op.Name)) { 546 PrintError("duplicate parameter '" + Op.Name + "'"); 547 return false; 548 } 549 550 // Check this operand is NOT defined in any alternative's patterns. 551 for (const auto &Alt : Alts) { 552 if (Alt.OpTable.lookup(Op.Name).Def) { 553 PrintError("input parameter '" + Op.Name + "' cannot be redefined!"); 554 return false; 555 } 556 } 557 558 if (Op.Kind == PK_Root) { 559 PrintError("input parameterr '" + Op.Name + "' cannot be a root!"); 560 return false; 561 } 562 563 SeenOps.insert(Op.Name); 564 } 565 566 for (const auto &Op : out_params()) { 567 if (Op.Kind != PK_Root && Op.Kind != PK_MachineOperand) { 568 PrintError("output parameter '" + Op.Name + 569 "' must be 'root' or 'gi_mo'"); 570 return false; 571 } 572 573 if (SeenOps.count(Op.Name)) { 574 PrintError("duplicate parameter '" + Op.Name + "'"); 575 return false; 576 } 577 578 // Check this operand is defined in all alternative's patterns. 579 for (const auto &Alt : Alts) { 580 const auto *OpDef = Alt.OpTable.getDef(Op.Name); 581 if (!OpDef) { 582 PrintError("output parameter '" + Op.Name + 583 "' must be defined by all alternative patterns in '" + 584 Def.getName() + "'"); 585 return false; 586 } 587 588 if (Op.Kind == PK_Root && OpDef->getNumInstDefs() != 1) { 589 // The instruction that defines the root must have a single def. 590 // Otherwise we'd need to support multiple roots and it gets messy. 591 // 592 // e.g. this is not supported: 593 // (pattern (G_UNMERGE_VALUES $x, $root, $vec)) 594 PrintError("all instructions that define root '" + Op.Name + "' in '" + 595 Def.getName() + "' can only have a single output operand"); 596 return false; 597 } 598 } 599 600 SeenOps.insert(Op.Name); 601 } 602 603 if (num_out_params() != 0 && num_roots() == 0) { 604 PrintError(ClassName + " must have one root in its 'out' operands"); 605 return false; 606 } 607 608 if (num_roots() > 1) { 609 PrintError(ClassName + " can only have one root"); 610 return false; 611 } 612 613 // TODO: find unused params 614 615 const auto CheckTypeOf = [&](const PatternType &) -> bool { 616 llvm_unreachable("GITypeOf should have been rejected earlier!"); 617 }; 618 619 // Now, typecheck all alternatives. 620 for (auto &Alt : Alts) { 621 OperandTypeChecker OTC(Def.getLoc()); 622 for (auto &Pat : Alt.Pats) { 623 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) { 624 if (!OTC.check(*IP, CheckTypeOf)) 625 return false; 626 } 627 } 628 OTC.propagateTypes(); 629 } 630 631 return true; 632 } 633 634 bool PatFrag::handleUnboundInParam(StringRef ParamName, StringRef ArgName, 635 ArrayRef<SMLoc> DiagLoc) const { 636 // The parameter must be a live-in of all alternatives for this to work. 637 // Otherwise, we risk having unbound parameters being used (= crashes). 638 // 639 // Examples: 640 // 641 // in (ins $y), (patterns (G_FNEG $dst, $y), "return matchFnegOp(${y})") 642 // even if $y is unbound, we'll lazily bind it when emitting the G_FNEG. 643 // 644 // in (ins $y), (patterns "return matchFnegOp(${y})") 645 // if $y is unbound when this fragment is emitted, C++ code expansion will 646 // fail. 647 for (const auto &Alt : Alts) { 648 auto &OT = Alt.OpTable; 649 if (!OT.lookup(ParamName).Found) { 650 llvm::PrintError(DiagLoc, "operand '" + ArgName + "' (for parameter '" + 651 ParamName + "' of '" + getName() + 652 "') cannot be unbound"); 653 PrintNote( 654 DiagLoc, 655 "one or more alternatives of '" + getName() + "' do not bind '" + 656 ParamName + 657 "' to an instruction operand; either use a bound operand or " 658 "ensure '" + 659 Def.getName() + "' binds '" + ParamName + 660 "' in all alternatives"); 661 return false; 662 } 663 } 664 665 return true; 666 } 667 668 bool PatFrag::buildOperandsTables() { 669 // enumerate(...) doesn't seem to allow lvalues so we need to count the old 670 // way. 671 unsigned Idx = 0; 672 673 const auto DiagnoseRedef = [this, &Idx](StringRef OpName) { 674 PrintError("Operand '" + OpName + 675 "' is defined multiple times in patterns of alternative #" + 676 std::to_string(Idx)); 677 }; 678 679 for (auto &Alt : Alts) { 680 for (auto &Pat : Alt.Pats) { 681 auto *IP = dyn_cast<InstructionPattern>(Pat.get()); 682 if (!IP) 683 continue; 684 685 if (!Alt.OpTable.addPattern(IP, DiagnoseRedef)) 686 return false; 687 } 688 689 ++Idx; 690 } 691 692 return true; 693 } 694 695 void PatFrag::print(raw_ostream &OS, StringRef Indent) const { 696 OS << Indent << "(PatFrag name:" << getName() << '\n'; 697 if (!in_params().empty()) { 698 OS << Indent << " (ins "; 699 printParamsList(OS, in_params()); 700 OS << ")\n"; 701 } 702 703 if (!out_params().empty()) { 704 OS << Indent << " (outs "; 705 printParamsList(OS, out_params()); 706 OS << ")\n"; 707 } 708 709 // TODO: Dump OperandTable as well. 710 OS << Indent << " (alternatives [\n"; 711 for (const auto &Alt : Alts) { 712 OS << Indent << " [\n"; 713 for (const auto &Pat : Alt.Pats) { 714 OS << Indent << " "; 715 Pat->print(OS, /*PrintName=*/true); 716 OS << ",\n"; 717 } 718 OS << Indent << " ],\n"; 719 } 720 OS << Indent << " ])\n"; 721 722 OS << Indent << ')'; 723 } 724 725 void PatFrag::dump() const { print(dbgs()); } 726 727 void PatFrag::printParamsList(raw_ostream &OS, iterator_range<ParamIt> Params) { 728 OS << '[' 729 << join(map_range(Params, 730 [](auto &O) { 731 return (O.Name + ":" + getParamKindStr(O.Kind)).str(); 732 }), 733 ", ") 734 << ']'; 735 } 736 737 void PatFrag::PrintError(Twine Msg) const { llvm::PrintError(&Def, Msg); } 738 739 ArrayRef<InstructionOperand> PatFragPattern::getApplyDefsNeeded() const { 740 assert(PF.num_roots() == 1); 741 // Only roots need to be redef. 742 for (auto [Idx, Param] : enumerate(PF.out_params())) { 743 if (Param.Kind == PatFrag::PK_Root) 744 return getOperand(Idx); 745 } 746 llvm_unreachable("root not found!"); 747 } 748 749 //===- PatFragPattern -----------------------------------------------------===// 750 751 bool PatFragPattern::checkSemantics(ArrayRef<SMLoc> DiagLoc) { 752 if (!InstructionPattern::checkSemantics(DiagLoc)) 753 return false; 754 755 for (const auto &[Idx, Op] : enumerate(Operands)) { 756 switch (PF.getParam(Idx).Kind) { 757 case PatFrag::PK_Imm: 758 if (!Op.hasImmValue()) { 759 PrintError(DiagLoc, "expected operand " + std::to_string(Idx) + 760 " of '" + getInstName() + 761 "' to be an immediate; got " + Op.describe()); 762 return false; 763 } 764 if (Op.isNamedImmediate()) { 765 PrintError(DiagLoc, "operand " + std::to_string(Idx) + " of '" + 766 getInstName() + 767 "' cannot be a named immediate"); 768 return false; 769 } 770 break; 771 case PatFrag::PK_Root: 772 case PatFrag::PK_MachineOperand: 773 if (!Op.isNamedOperand() || Op.isNamedImmediate()) { 774 PrintError(DiagLoc, "expected operand " + std::to_string(Idx) + 775 " of '" + getInstName() + 776 "' to be a MachineOperand; got " + 777 Op.describe()); 778 return false; 779 } 780 break; 781 } 782 } 783 784 return true; 785 } 786 787 bool PatFragPattern::mapInputCodeExpansions(const CodeExpansions &ParentCEs, 788 CodeExpansions &PatFragCEs, 789 ArrayRef<SMLoc> DiagLoc) const { 790 for (const auto &[Idx, Op] : enumerate(operands())) { 791 StringRef ParamName = PF.getParam(Idx).Name; 792 793 // Operands to a PFP can only be named, or be an immediate, but not a named 794 // immediate. 795 assert(!Op.isNamedImmediate()); 796 797 if (Op.isNamedOperand()) { 798 StringRef ArgName = Op.getOperandName(); 799 // Map it only if it's been defined. 800 auto It = ParentCEs.find(ArgName); 801 if (It == ParentCEs.end()) { 802 if (!PF.handleUnboundInParam(ParamName, ArgName, DiagLoc)) 803 return false; 804 } else 805 PatFragCEs.declare(ParamName, It->second); 806 continue; 807 } 808 809 if (Op.hasImmValue()) { 810 PatFragCEs.declare(ParamName, std::to_string(Op.getImmValue())); 811 continue; 812 } 813 814 llvm_unreachable("Unknown Operand Type!"); 815 } 816 817 return true; 818 } 819 820 //===- BuiltinPattern -----------------------------------------------------===// 821 822 BuiltinPattern::BuiltinInfo BuiltinPattern::getBuiltinInfo(const Record &Def) { 823 assert(Def.isSubClassOf(ClassName)); 824 825 StringRef Name = Def.getName(); 826 for (const auto &KBI : KnownBuiltins) { 827 if (KBI.DefName == Name) 828 return KBI; 829 } 830 831 PrintFatalError(Def.getLoc(), 832 "Unimplemented " + ClassName + " def '" + Name + "'"); 833 } 834 835 bool BuiltinPattern::checkSemantics(ArrayRef<SMLoc> Loc) { 836 if (!InstructionPattern::checkSemantics(Loc)) 837 return false; 838 839 // For now all builtins just take names, no immediates. 840 for (const auto &[Idx, Op] : enumerate(operands())) { 841 if (!Op.isNamedOperand() || Op.isNamedImmediate()) { 842 PrintError(Loc, "expected operand " + std::to_string(Idx) + " of '" + 843 getInstName() + "' to be a name"); 844 return false; 845 } 846 } 847 848 return true; 849 } 850 851 } // namespace gi 852 } // namespace llvm 853