[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / utils / TableGen / Common / GlobalISel / Patterns.cpp
blob0b84a9bbe6343f04233eab7920174ef885ecee8f
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 //===----------------------------------------------------------------------===//
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"
21 namespace llvm {
22 namespace gi {
24 //===- PatternType --------------------------------------------------------===//
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;
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;
44 PatternType PT(PT_TypeOf);
45 PT.Data.Str = RawOpName.drop_front(1);
46 return PT;
49 if (R->isSubClassOf(VariadicClassName)) {
50 const int64_t Min = R->getValueAsInt("MinArgs");
51 const int64_t Max = R->getValueAsInt("MaxArgs");
53 if (Min == 0) {
54 PrintError(
55 DiagLoc,
56 DiagCtx +
57 ": minimum number of arguments must be greater than zero in " +
58 VariadicClassName);
59 return std::nullopt;
62 if (Max <= Min && Max != 0) {
63 PrintError(DiagLoc, DiagCtx + ": maximum number of arguments (" +
64 Twine(Max) +
65 ") must be zero, or greater "
66 "than the minimum number of arguments (" +
67 Twine(Min) + ") in " + VariadicClassName);
68 return std::nullopt;
71 PatternType PT(PT_VariadicPack);
72 PT.Data.VPTI = {unsigned(Min), unsigned(Max)};
73 return PT;
76 PrintError(DiagLoc, DiagCtx + ": unknown type '" + R->getName() + "'");
77 return std::nullopt;
80 PatternType PatternType::getTypeOf(StringRef OpName) {
81 PatternType PT(PT_TypeOf);
82 PT.Data.Str = OpName;
83 return PT;
86 StringRef PatternType::getTypeOfOpName() const {
87 assert(isTypeOf());
88 return Data.Str;
91 const Record *PatternType::getLLTRecord() const {
92 assert(isLLT());
93 return Data.Def;
96 VariadicPackTypeInfo PatternType::getVariadicPackTypeInfo() const {
97 assert(isVariadicPack());
98 return Data.VPTI;
101 bool PatternType::operator==(const PatternType &Other) const {
102 if (Kind != Other.Kind)
103 return false;
105 switch (Kind) {
106 case PT_None:
107 return true;
108 case PT_ValueType:
109 return Data.Def == Other.Data.Def;
110 case PT_TypeOf:
111 return Data.Str == Other.Data.Str;
112 case PT_VariadicPack:
113 return Data.VPTI == Other.Data.VPTI;
116 llvm_unreachable("Unknown Type Kind");
119 std::string PatternType::str() const {
120 switch (Kind) {
121 case PT_None:
122 return "";
123 case PT_ValueType:
124 return Data.Def->getName().str();
125 case PT_TypeOf:
126 return (TypeOfClassName + "<$" + getTypeOfOpName() + ">").str();
127 case PT_VariadicPack:
128 return (VariadicClassName + "<" + Twine(Data.VPTI.Min) + "," +
129 Twine(Data.VPTI.Max) + ">")
130 .str();
133 llvm_unreachable("Unknown type!");
136 //===- Pattern ------------------------------------------------------------===//
138 void Pattern::dump() const { return print(dbgs()); }
140 const char *Pattern::getKindName() const {
141 switch (Kind) {
142 case K_AnyOpcode:
143 return "AnyOpcodePattern";
144 case K_CXX:
145 return "CXXPattern";
146 case K_CodeGenInstruction:
147 return "CodeGenInstructionPattern";
148 case K_PatFrag:
149 return "PatFragPattern";
150 case K_Builtin:
151 return "BuiltinPattern";
154 llvm_unreachable("unknown pattern kind!");
157 void Pattern::printImpl(raw_ostream &OS, bool PrintName,
158 function_ref<void()> ContentPrinter) const {
159 OS << "(" << getKindName() << " ";
160 if (PrintName)
161 OS << "name:" << getName() << " ";
162 ContentPrinter();
163 OS << ")";
166 //===- AnyOpcodePattern ---------------------------------------------------===//
168 void AnyOpcodePattern::print(raw_ostream &OS, bool PrintName) const {
169 printImpl(OS, PrintName, [&OS, this]() {
170 OS << "["
171 << join(map_range(Insts,
172 [](const auto *I) { return I->TheDef->getName(); }),
173 ", ")
174 << "]";
178 //===- CXXPattern ---------------------------------------------------------===//
180 CXXPattern::CXXPattern(const StringInit &Code, StringRef Name)
181 : CXXPattern(Code.getAsUnquotedString(), Name) {}
183 const CXXPredicateCode &
184 CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef<SMLoc> Locs,
185 function_ref<void(raw_ostream &)> AddComment) const {
186 assert(!IsApply && "'apply' CXX patterns should be handled differently!");
188 std::string Result;
189 raw_string_ostream OS(Result);
191 if (AddComment)
192 AddComment(OS);
194 CodeExpander Expander(RawCode, CE, Locs, /*ShowExpansions*/ false);
195 Expander.emit(OS);
196 return CXXPredicateCode::getMatchCode(std::move(Result));
199 void CXXPattern::print(raw_ostream &OS, bool PrintName) const {
200 printImpl(OS, PrintName, [&OS, this] {
201 OS << (IsApply ? "apply" : "match") << " code:\"";
202 printEscapedString(getRawCode(), OS);
203 OS << "\"";
207 //===- InstructionOperand -------------------------------------------------===//
209 std::string InstructionOperand::describe() const {
210 if (!hasImmValue())
211 return "MachineOperand $" + getOperandName().str() + "";
212 std::string Str = "imm " + std::to_string(getImmValue());
213 if (isNamedImmediate())
214 Str += ":$" + getOperandName().str() + "";
215 return Str;
218 void InstructionOperand::print(raw_ostream &OS) const {
219 if (isDef())
220 OS << "<def>";
222 bool NeedsColon = true;
223 if (Type) {
224 if (hasImmValue())
225 OS << "(" << Type.str() << " " << getImmValue() << ")";
226 else
227 OS << Type.str();
228 } else if (hasImmValue())
229 OS << getImmValue();
230 else
231 NeedsColon = false;
233 if (isNamedOperand())
234 OS << (NeedsColon ? ":" : "") << "$" << getOperandName();
237 void InstructionOperand::dump() const { return print(dbgs()); }
239 //===- InstructionPattern -------------------------------------------------===//
241 bool InstructionPattern::diagnoseAllSpecialTypes(ArrayRef<SMLoc> Loc,
242 Twine Msg) const {
243 bool HasDiag = false;
244 for (const auto &[Idx, Op] : enumerate(operands())) {
245 if (Op.getType().isSpecial()) {
246 PrintError(Loc, Msg);
247 PrintNote(Loc, "operand " + Twine(Idx) + " of '" + getName() +
248 "' has type '" + Op.getType().str() + "'");
249 HasDiag = true;
252 return HasDiag;
255 void InstructionPattern::reportUnreachable(ArrayRef<SMLoc> Locs) const {
256 PrintError(Locs, "pattern '" + getName() + "' ('" + getInstName() +
257 "') is unreachable from the pattern root!");
260 bool InstructionPattern::checkSemantics(ArrayRef<SMLoc> Loc) {
261 unsigned NumExpectedOperands = getNumInstOperands();
263 if (isVariadic()) {
264 if (Operands.size() < NumExpectedOperands) {
265 PrintError(Loc, +"'" + getInstName() + "' expected at least " +
266 Twine(NumExpectedOperands) + " operands, got " +
267 Twine(Operands.size()));
268 return false;
270 } else if (NumExpectedOperands != Operands.size()) {
271 PrintError(Loc, +"'" + getInstName() + "' expected " +
272 Twine(NumExpectedOperands) + " operands, got " +
273 Twine(Operands.size()));
274 return false;
277 unsigned OpIdx = 0;
278 unsigned NumDefs = getNumInstDefs();
279 for (auto &Op : Operands)
280 Op.setIsDef(OpIdx++ < NumDefs);
282 return true;
285 void InstructionPattern::print(raw_ostream &OS, bool PrintName) const {
286 printImpl(OS, PrintName, [&OS, this] {
287 OS << getInstName() << " operands:[";
288 StringRef Sep;
289 for (const auto &Op : Operands) {
290 OS << Sep;
291 Op.print(OS);
292 Sep = ", ";
294 OS << "]";
296 printExtras(OS);
300 //===- OperandTable -------------------------------------------------------===//
302 bool OperandTable::addPattern(InstructionPattern *P,
303 function_ref<void(StringRef)> DiagnoseRedef) {
304 for (const auto &Op : P->named_operands()) {
305 StringRef OpName = Op.getOperandName();
307 // We always create an entry in the OperandTable, even for uses.
308 // Uses of operands that don't have a def (= live-ins) will remain with a
309 // nullptr as the Def.
311 // This allows us tell whether an operand exists in a pattern or not. If
312 // there is no entry for it, it doesn't exist, if there is an entry, it's
313 // used/def'd at least once.
314 auto &Def = Table[OpName];
316 if (!Op.isDef())
317 continue;
319 if (Def) {
320 DiagnoseRedef(OpName);
321 return false;
324 Def = P;
327 return true;
330 void OperandTable::print(raw_ostream &OS, StringRef Name,
331 StringRef Indent) const {
332 OS << Indent << "(OperandTable ";
333 if (!Name.empty())
334 OS << Name << " ";
335 if (Table.empty()) {
336 OS << "<empty>)\n";
337 return;
340 SmallVector<StringRef, 0> Keys(Table.keys());
341 sort(Keys);
343 OS << '\n';
344 for (const auto &Key : Keys) {
345 const auto *Def = Table.at(Key);
346 OS << Indent << " " << Key << " -> "
347 << (Def ? Def->getName() : "<live-in>") << '\n';
349 OS << Indent << ")\n";
352 void OperandTable::dump() const { print(dbgs()); }
354 //===- MIFlagsInfo --------------------------------------------------------===//
356 void MIFlagsInfo::addSetFlag(const Record *R) {
357 SetF.insert(R->getValueAsString("EnumName"));
360 void MIFlagsInfo::addUnsetFlag(const Record *R) {
361 UnsetF.insert(R->getValueAsString("EnumName"));
364 void MIFlagsInfo::addCopyFlag(StringRef InstName) { CopyF.insert(InstName); }
366 //===- CodeGenInstructionPattern ------------------------------------------===//
368 bool CodeGenInstructionPattern::is(StringRef OpcodeName) const {
369 return I.TheDef->getName() == OpcodeName;
372 bool CodeGenInstructionPattern::isVariadic() const {
373 return !isIntrinsic() && I.Operands.isVariadic;
376 bool CodeGenInstructionPattern::hasVariadicDefs() const {
377 // Note: we cannot use variadicOpsAreDefs, it's not set for
378 // GenericInstructions.
379 if (!isVariadic())
380 return false;
382 if (I.variadicOpsAreDefs)
383 return true;
385 const DagInit *OutOps = I.TheDef->getValueAsDag("OutOperandList");
386 if (OutOps->arg_empty())
387 return false;
389 auto *LastArgTy = dyn_cast<DefInit>(OutOps->getArg(OutOps->arg_size() - 1));
390 return LastArgTy && LastArgTy->getDef()->getName() == "variable_ops";
393 unsigned CodeGenInstructionPattern::getNumInstDefs() const {
394 if (isIntrinsic())
395 return IntrinInfo->IS.RetTys.size();
397 if (!isVariadic() || !hasVariadicDefs())
398 return I.Operands.NumDefs;
399 unsigned NumOuts = I.Operands.size() - I.Operands.NumDefs;
400 assert(Operands.size() > NumOuts);
401 return std::max<unsigned>(I.Operands.NumDefs, Operands.size() - NumOuts);
404 unsigned CodeGenInstructionPattern::getNumInstOperands() const {
405 if (isIntrinsic())
406 return IntrinInfo->IS.RetTys.size() + IntrinInfo->IS.ParamTys.size();
408 unsigned NumCGIOps = I.Operands.size();
409 return isVariadic() ? std::max<unsigned>(NumCGIOps, Operands.size())
410 : NumCGIOps;
413 MIFlagsInfo &CodeGenInstructionPattern::getOrCreateMIFlagsInfo() {
414 if (!FI)
415 FI = std::make_unique<MIFlagsInfo>();
416 return *FI;
419 StringRef CodeGenInstructionPattern::getInstName() const {
420 return I.TheDef->getName();
423 void CodeGenInstructionPattern::printExtras(raw_ostream &OS) const {
424 if (isIntrinsic())
425 OS << " intrinsic(@" << IntrinInfo->Name << ")";
427 if (!FI)
428 return;
430 OS << " (MIFlags";
431 if (!FI->set_flags().empty())
432 OS << " (set " << join(FI->set_flags(), ", ") << ")";
433 if (!FI->unset_flags().empty())
434 OS << " (unset " << join(FI->unset_flags(), ", ") << ")";
435 if (!FI->copy_flags().empty())
436 OS << " (copy " << join(FI->copy_flags(), ", ") << ")";
437 OS << ')';
440 //===- OperandTypeChecker -------------------------------------------------===//
442 bool OperandTypeChecker::check(
443 InstructionPattern &P,
444 std::function<bool(const PatternType &)> VerifyTypeOfOperand) {
445 Pats.push_back(&P);
447 for (auto &Op : P.operands()) {
448 const auto Ty = Op.getType();
449 if (!Ty)
450 continue;
452 if (Ty.isTypeOf() && !VerifyTypeOfOperand(Ty))
453 return false;
455 if (!Op.isNamedOperand())
456 continue;
458 StringRef OpName = Op.getOperandName();
459 auto &Info = Types[OpName];
460 if (!Info.Type) {
461 Info.Type = Ty;
462 Info.PrintTypeSrcNote = [this, OpName, Ty, &P]() {
463 PrintSeenWithTypeIn(P, OpName, Ty);
465 continue;
468 if (Info.Type != Ty) {
469 PrintError(DiagLoc, "conflicting types for operand '" +
470 Op.getOperandName() + "': '" + Info.Type.str() +
471 "' vs '" + Ty.str() + "'");
472 PrintSeenWithTypeIn(P, OpName, Ty);
473 Info.PrintTypeSrcNote();
474 return false;
478 return true;
481 void OperandTypeChecker::propagateTypes() {
482 for (auto *Pat : Pats) {
483 for (auto &Op : Pat->named_operands()) {
484 if (auto &Info = Types[Op.getOperandName()]; Info.Type)
485 Op.setType(Info.Type);
490 void OperandTypeChecker::PrintSeenWithTypeIn(InstructionPattern &P,
491 StringRef OpName,
492 PatternType Ty) const {
493 PrintNote(DiagLoc, "'" + OpName + "' seen with type '" + Ty.str() + "' in '" +
494 P.getName() + "'");
497 StringRef PatFrag::getParamKindStr(ParamKind OK) {
498 switch (OK) {
499 case PK_Root:
500 return "root";
501 case PK_MachineOperand:
502 return "machine_operand";
503 case PK_Imm:
504 return "imm";
507 llvm_unreachable("Unknown operand kind!");
510 //===- PatFrag -----------------------------------------------------------===//
512 PatFrag::PatFrag(const Record &Def) : Def(Def) {
513 assert(Def.isSubClassOf(ClassName));
516 StringRef PatFrag::getName() const { return Def.getName(); }
518 ArrayRef<SMLoc> PatFrag::getLoc() const { return Def.getLoc(); }
520 void PatFrag::addInParam(StringRef Name, ParamKind Kind) {
521 Params.emplace_back(Param{Name, Kind});
524 iterator_range<PatFrag::ParamIt> PatFrag::in_params() const {
525 return {Params.begin() + NumOutParams, Params.end()};
528 void PatFrag::addOutParam(StringRef Name, ParamKind Kind) {
529 assert(NumOutParams == Params.size() &&
530 "Adding out-param after an in-param!");
531 Params.emplace_back(Param{Name, Kind});
532 ++NumOutParams;
535 iterator_range<PatFrag::ParamIt> PatFrag::out_params() const {
536 return {Params.begin(), Params.begin() + NumOutParams};
539 unsigned PatFrag::num_roots() const {
540 return count_if(out_params(),
541 [&](const auto &P) { return P.Kind == PK_Root; });
544 unsigned PatFrag::getParamIdx(StringRef Name) const {
545 for (const auto &[Idx, Op] : enumerate(Params)) {
546 if (Op.Name == Name)
547 return Idx;
550 return -1;
553 bool PatFrag::checkSemantics() {
554 for (const auto &Alt : Alts) {
555 for (const auto &Pat : Alt.Pats) {
556 switch (Pat->getKind()) {
557 case Pattern::K_AnyOpcode:
558 PrintError("wip_match_opcode cannot be used in " + ClassName);
559 return false;
560 case Pattern::K_Builtin:
561 PrintError("Builtin instructions cannot be used in " + ClassName);
562 return false;
563 case Pattern::K_CXX:
564 continue;
565 case Pattern::K_CodeGenInstruction:
566 // TODO: Allow VarArgs?
567 if (cast<CodeGenInstructionPattern>(Pat.get())->diagnoseAllSpecialTypes(
568 Def.getLoc(), PatternType::SpecialTyClassName +
569 " is not supported in " + ClassName))
570 return false;
571 continue;
572 case Pattern::K_PatFrag:
573 // TODO: It's just that the emitter doesn't handle it but technically
574 // there is no reason why we can't. We just have to be careful with
575 // operand mappings, it could get complex.
576 PrintError("nested " + ClassName + " are not supported");
577 return false;
582 StringSet<> SeenOps;
583 for (const auto &Op : in_params()) {
584 if (SeenOps.count(Op.Name)) {
585 PrintError("duplicate parameter '" + Op.Name + "'");
586 return false;
589 // Check this operand is NOT defined in any alternative's patterns.
590 for (const auto &Alt : Alts) {
591 if (Alt.OpTable.lookup(Op.Name).Def) {
592 PrintError("input parameter '" + Op.Name + "' cannot be redefined!");
593 return false;
597 if (Op.Kind == PK_Root) {
598 PrintError("input parameterr '" + Op.Name + "' cannot be a root!");
599 return false;
602 SeenOps.insert(Op.Name);
605 for (const auto &Op : out_params()) {
606 if (Op.Kind != PK_Root && Op.Kind != PK_MachineOperand) {
607 PrintError("output parameter '" + Op.Name +
608 "' must be 'root' or 'gi_mo'");
609 return false;
612 if (SeenOps.count(Op.Name)) {
613 PrintError("duplicate parameter '" + Op.Name + "'");
614 return false;
617 // Check this operand is defined in all alternative's patterns.
618 for (const auto &Alt : Alts) {
619 const auto *OpDef = Alt.OpTable.getDef(Op.Name);
620 if (!OpDef) {
621 PrintError("output parameter '" + Op.Name +
622 "' must be defined by all alternative patterns in '" +
623 Def.getName() + "'");
624 return false;
627 if (Op.Kind == PK_Root && OpDef->getNumInstDefs() != 1) {
628 // The instruction that defines the root must have a single def.
629 // Otherwise we'd need to support multiple roots and it gets messy.
631 // e.g. this is not supported:
632 // (pattern (G_UNMERGE_VALUES $x, $root, $vec))
633 PrintError("all instructions that define root '" + Op.Name + "' in '" +
634 Def.getName() + "' can only have a single output operand");
635 return false;
639 SeenOps.insert(Op.Name);
642 if (num_out_params() != 0 && num_roots() == 0) {
643 PrintError(ClassName + " must have one root in its 'out' operands");
644 return false;
647 if (num_roots() > 1) {
648 PrintError(ClassName + " can only have one root");
649 return false;
652 // TODO: find unused params
654 const auto CheckTypeOf = [&](const PatternType &) -> bool {
655 llvm_unreachable("GITypeOf should have been rejected earlier!");
658 // Now, typecheck all alternatives.
659 for (auto &Alt : Alts) {
660 OperandTypeChecker OTC(Def.getLoc());
661 for (auto &Pat : Alt.Pats) {
662 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
663 if (!OTC.check(*IP, CheckTypeOf))
664 return false;
667 OTC.propagateTypes();
670 return true;
673 bool PatFrag::handleUnboundInParam(StringRef ParamName, StringRef ArgName,
674 ArrayRef<SMLoc> DiagLoc) const {
675 // The parameter must be a live-in of all alternatives for this to work.
676 // Otherwise, we risk having unbound parameters being used (= crashes).
678 // Examples:
680 // in (ins $y), (patterns (G_FNEG $dst, $y), "return matchFnegOp(${y})")
681 // even if $y is unbound, we'll lazily bind it when emitting the G_FNEG.
683 // in (ins $y), (patterns "return matchFnegOp(${y})")
684 // if $y is unbound when this fragment is emitted, C++ code expansion will
685 // fail.
686 for (const auto &Alt : Alts) {
687 auto &OT = Alt.OpTable;
688 if (!OT.lookup(ParamName).Found) {
689 llvm::PrintError(DiagLoc, "operand '" + ArgName + "' (for parameter '" +
690 ParamName + "' of '" + getName() +
691 "') cannot be unbound");
692 PrintNote(
693 DiagLoc,
694 "one or more alternatives of '" + getName() + "' do not bind '" +
695 ParamName +
696 "' to an instruction operand; either use a bound operand or "
697 "ensure '" +
698 Def.getName() + "' binds '" + ParamName +
699 "' in all alternatives");
700 return false;
704 return true;
707 bool PatFrag::buildOperandsTables() {
708 // enumerate(...) doesn't seem to allow lvalues so we need to count the old
709 // way.
710 unsigned Idx = 0;
712 const auto DiagnoseRedef = [this, &Idx](StringRef OpName) {
713 PrintError("Operand '" + OpName +
714 "' is defined multiple times in patterns of alternative #" +
715 std::to_string(Idx));
718 for (auto &Alt : Alts) {
719 for (auto &Pat : Alt.Pats) {
720 auto *IP = dyn_cast<InstructionPattern>(Pat.get());
721 if (!IP)
722 continue;
724 if (!Alt.OpTable.addPattern(IP, DiagnoseRedef))
725 return false;
728 ++Idx;
731 return true;
734 void PatFrag::print(raw_ostream &OS, StringRef Indent) const {
735 OS << Indent << "(PatFrag name:" << getName() << '\n';
736 if (!in_params().empty()) {
737 OS << Indent << " (ins ";
738 printParamsList(OS, in_params());
739 OS << ")\n";
742 if (!out_params().empty()) {
743 OS << Indent << " (outs ";
744 printParamsList(OS, out_params());
745 OS << ")\n";
748 // TODO: Dump OperandTable as well.
749 OS << Indent << " (alternatives [\n";
750 for (const auto &Alt : Alts) {
751 OS << Indent << " [\n";
752 for (const auto &Pat : Alt.Pats) {
753 OS << Indent << " ";
754 Pat->print(OS, /*PrintName=*/true);
755 OS << ",\n";
757 OS << Indent << " ],\n";
759 OS << Indent << " ])\n";
761 OS << Indent << ')';
764 void PatFrag::dump() const { print(dbgs()); }
766 void PatFrag::printParamsList(raw_ostream &OS, iterator_range<ParamIt> Params) {
767 OS << '['
768 << join(map_range(Params,
769 [](auto &O) {
770 return (O.Name + ":" + getParamKindStr(O.Kind)).str();
772 ", ")
773 << ']';
776 void PatFrag::PrintError(Twine Msg) const { llvm::PrintError(&Def, Msg); }
778 ArrayRef<InstructionOperand> PatFragPattern::getApplyDefsNeeded() const {
779 assert(PF.num_roots() == 1);
780 // Only roots need to be redef.
781 for (auto [Idx, Param] : enumerate(PF.out_params())) {
782 if (Param.Kind == PatFrag::PK_Root)
783 return getOperand(Idx);
785 llvm_unreachable("root not found!");
788 //===- PatFragPattern -----------------------------------------------------===//
790 bool PatFragPattern::checkSemantics(ArrayRef<SMLoc> DiagLoc) {
791 if (!InstructionPattern::checkSemantics(DiagLoc))
792 return false;
794 for (const auto &[Idx, Op] : enumerate(Operands)) {
795 switch (PF.getParam(Idx).Kind) {
796 case PatFrag::PK_Imm:
797 if (!Op.hasImmValue()) {
798 PrintError(DiagLoc, "expected operand " + std::to_string(Idx) +
799 " of '" + getInstName() +
800 "' to be an immediate; got " + Op.describe());
801 return false;
803 if (Op.isNamedImmediate()) {
804 PrintError(DiagLoc, "operand " + std::to_string(Idx) + " of '" +
805 getInstName() +
806 "' cannot be a named immediate");
807 return false;
809 break;
810 case PatFrag::PK_Root:
811 case PatFrag::PK_MachineOperand:
812 if (!Op.isNamedOperand() || Op.isNamedImmediate()) {
813 PrintError(DiagLoc, "expected operand " + std::to_string(Idx) +
814 " of '" + getInstName() +
815 "' to be a MachineOperand; got " +
816 Op.describe());
817 return false;
819 break;
823 return true;
826 bool PatFragPattern::mapInputCodeExpansions(const CodeExpansions &ParentCEs,
827 CodeExpansions &PatFragCEs,
828 ArrayRef<SMLoc> DiagLoc) const {
829 for (const auto &[Idx, Op] : enumerate(operands())) {
830 StringRef ParamName = PF.getParam(Idx).Name;
832 // Operands to a PFP can only be named, or be an immediate, but not a named
833 // immediate.
834 assert(!Op.isNamedImmediate());
836 if (Op.isNamedOperand()) {
837 StringRef ArgName = Op.getOperandName();
838 // Map it only if it's been defined.
839 auto It = ParentCEs.find(ArgName);
840 if (It == ParentCEs.end()) {
841 if (!PF.handleUnboundInParam(ParamName, ArgName, DiagLoc))
842 return false;
843 } else
844 PatFragCEs.declare(ParamName, It->second);
845 continue;
848 if (Op.hasImmValue()) {
849 PatFragCEs.declare(ParamName, std::to_string(Op.getImmValue()));
850 continue;
853 llvm_unreachable("Unknown Operand Type!");
856 return true;
859 //===- BuiltinPattern -----------------------------------------------------===//
861 BuiltinPattern::BuiltinInfo BuiltinPattern::getBuiltinInfo(const Record &Def) {
862 assert(Def.isSubClassOf(ClassName));
864 StringRef Name = Def.getName();
865 for (const auto &KBI : KnownBuiltins) {
866 if (KBI.DefName == Name)
867 return KBI;
870 PrintFatalError(Def.getLoc(),
871 "Unimplemented " + ClassName + " def '" + Name + "'");
874 bool BuiltinPattern::checkSemantics(ArrayRef<SMLoc> Loc) {
875 if (!InstructionPattern::checkSemantics(Loc))
876 return false;
878 // For now all builtins just take names, no immediates.
879 for (const auto &[Idx, Op] : enumerate(operands())) {
880 if (!Op.isNamedOperand() || Op.isNamedImmediate()) {
881 PrintError(Loc, "expected operand " + std::to_string(Idx) + " of '" +
882 getInstName() + "' to be a name");
883 return false;
887 return true;
890 } // namespace gi
891 } // namespace llvm