xref: /llvm-project/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp (revision 4048c64306e23b622443bbe7293057a9b07a13bb)
14f9aab2bSPierre van Houtryve //===- PatternParser.cpp ----------------------------------------*- C++ -*-===//
24f9aab2bSPierre van Houtryve //
34f9aab2bSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44f9aab2bSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information.
54f9aab2bSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64f9aab2bSPierre van Houtryve //
74f9aab2bSPierre van Houtryve //===----------------------------------------------------------------------===//
84f9aab2bSPierre van Houtryve 
94f9aab2bSPierre van Houtryve #include "Common/GlobalISel/PatternParser.h"
104f9aab2bSPierre van Houtryve #include "Basic/CodeGenIntrinsics.h"
114f9aab2bSPierre van Houtryve #include "Common/CodeGenTarget.h"
124f9aab2bSPierre van Houtryve #include "Common/GlobalISel/CombinerUtils.h"
134f9aab2bSPierre van Houtryve #include "Common/GlobalISel/Patterns.h"
144f9aab2bSPierre van Houtryve #include "llvm/ADT/StringRef.h"
154f9aab2bSPierre van Houtryve #include "llvm/Support/PrettyStackTrace.h"
164f9aab2bSPierre van Houtryve #include "llvm/Support/SaveAndRestore.h"
174f9aab2bSPierre van Houtryve #include "llvm/TableGen/Error.h"
184f9aab2bSPierre van Houtryve #include "llvm/TableGen/Record.h"
194f9aab2bSPierre van Houtryve 
204f9aab2bSPierre van Houtryve namespace llvm {
214f9aab2bSPierre van Houtryve namespace gi {
224f9aab2bSPierre van Houtryve static constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum";
234f9aab2bSPierre van Houtryve 
244f9aab2bSPierre van Houtryve namespace {
254f9aab2bSPierre van Houtryve class PrettyStackTraceParse : public PrettyStackTraceEntry {
264f9aab2bSPierre van Houtryve   const Record &Def;
274f9aab2bSPierre van Houtryve 
284f9aab2bSPierre van Houtryve public:
294f9aab2bSPierre van Houtryve   PrettyStackTraceParse(const Record &Def) : Def(Def) {}
304f9aab2bSPierre van Houtryve 
314f9aab2bSPierre van Houtryve   void print(raw_ostream &OS) const override {
324f9aab2bSPierre van Houtryve     if (Def.isSubClassOf("GICombineRule"))
334f9aab2bSPierre van Houtryve       OS << "Parsing GICombineRule '" << Def.getName() << '\'';
344f9aab2bSPierre van Houtryve     else if (Def.isSubClassOf(PatFrag::ClassName))
354f9aab2bSPierre van Houtryve       OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << '\'';
364f9aab2bSPierre van Houtryve     else
374f9aab2bSPierre van Houtryve       OS << "Parsing '" << Def.getName() << '\'';
384f9aab2bSPierre van Houtryve     OS << '\n';
394f9aab2bSPierre van Houtryve   }
404f9aab2bSPierre van Houtryve };
414f9aab2bSPierre van Houtryve } // namespace
424f9aab2bSPierre van Houtryve 
434f9aab2bSPierre van Houtryve bool PatternParser::parsePatternList(
444f9aab2bSPierre van Houtryve     const DagInit &List,
454f9aab2bSPierre van Houtryve     function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
464f9aab2bSPierre van Houtryve     StringRef Operator, StringRef AnonPatNamePrefix) {
474f9aab2bSPierre van Houtryve   if (List.getOperatorAsDef(DiagLoc)->getName() != Operator) {
484f9aab2bSPierre van Houtryve     PrintError(DiagLoc, "Expected " + Operator + " operator");
494f9aab2bSPierre van Houtryve     return false;
504f9aab2bSPierre van Houtryve   }
514f9aab2bSPierre van Houtryve 
524f9aab2bSPierre van Houtryve   if (List.getNumArgs() == 0) {
534f9aab2bSPierre van Houtryve     PrintError(DiagLoc, Operator + " pattern list is empty");
544f9aab2bSPierre van Houtryve     return false;
554f9aab2bSPierre van Houtryve   }
564f9aab2bSPierre van Houtryve 
574f9aab2bSPierre van Houtryve   // The match section consists of a list of matchers and predicates. Parse each
584f9aab2bSPierre van Houtryve   // one and add the equivalent GIMatchDag nodes, predicates, and edges.
594f9aab2bSPierre van Houtryve   for (unsigned I = 0; I < List.getNumArgs(); ++I) {
60*62e2c7fbSRahul Joshi     const Init *Arg = List.getArg(I);
614f9aab2bSPierre van Houtryve     std::string Name = List.getArgName(I)
624f9aab2bSPierre van Houtryve                            ? List.getArgName(I)->getValue().str()
634f9aab2bSPierre van Houtryve                            : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str();
644f9aab2bSPierre van Houtryve 
654f9aab2bSPierre van Houtryve     if (auto Pat = parseInstructionPattern(*Arg, Name)) {
664f9aab2bSPierre van Houtryve       if (!ParseAction(std::move(Pat)))
674f9aab2bSPierre van Houtryve         return false;
684f9aab2bSPierre van Houtryve       continue;
694f9aab2bSPierre van Houtryve     }
704f9aab2bSPierre van Houtryve 
714f9aab2bSPierre van Houtryve     if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) {
724f9aab2bSPierre van Houtryve       if (!ParseAction(std::move(Pat)))
734f9aab2bSPierre van Houtryve         return false;
744f9aab2bSPierre van Houtryve       continue;
754f9aab2bSPierre van Houtryve     }
764f9aab2bSPierre van Houtryve 
774f9aab2bSPierre van Houtryve     // Parse arbitrary C++ code
784f9aab2bSPierre van Houtryve     if (const auto *StringI = dyn_cast<StringInit>(Arg)) {
794f9aab2bSPierre van Houtryve       auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name));
804f9aab2bSPierre van Houtryve       if (!ParseAction(std::move(CXXPat)))
814f9aab2bSPierre van Houtryve         return false;
824f9aab2bSPierre van Houtryve       continue;
834f9aab2bSPierre van Houtryve     }
844f9aab2bSPierre van Houtryve 
854f9aab2bSPierre van Houtryve     PrintError(DiagLoc,
864f9aab2bSPierre van Houtryve                "Failed to parse pattern: '" + Arg->getAsString() + '\'');
874f9aab2bSPierre van Houtryve     return false;
884f9aab2bSPierre van Houtryve   }
894f9aab2bSPierre van Houtryve 
904f9aab2bSPierre van Houtryve   return true;
914f9aab2bSPierre van Houtryve }
924f9aab2bSPierre van Houtryve 
934f9aab2bSPierre van Houtryve static const CodeGenInstruction &
944f9aab2bSPierre van Houtryve getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) {
954f9aab2bSPierre van Houtryve   StringRef Opc;
964f9aab2bSPierre van Houtryve   if (I->isConvergent) {
974f9aab2bSPierre van Houtryve     Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"
984f9aab2bSPierre van Houtryve                             : "G_INTRINSIC_CONVERGENT";
994f9aab2bSPierre van Houtryve   } else {
1004f9aab2bSPierre van Houtryve     Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC";
1014f9aab2bSPierre van Houtryve   }
1024f9aab2bSPierre van Houtryve 
1034f9aab2bSPierre van Houtryve   RecordKeeper &RK = I->TheDef->getRecords();
1044f9aab2bSPierre van Houtryve   return CGT.getInstruction(RK.getDef(Opc));
1054f9aab2bSPierre van Houtryve }
1064f9aab2bSPierre van Houtryve 
1074f9aab2bSPierre van Houtryve std::unique_ptr<Pattern>
1084f9aab2bSPierre van Houtryve PatternParser::parseInstructionPattern(const Init &Arg, StringRef Name) {
1094f9aab2bSPierre van Houtryve   const DagInit *DagPat = dyn_cast<DagInit>(&Arg);
1104f9aab2bSPierre van Houtryve   if (!DagPat)
1114f9aab2bSPierre van Houtryve     return nullptr;
1124f9aab2bSPierre van Houtryve 
1134f9aab2bSPierre van Houtryve   std::unique_ptr<InstructionPattern> Pat;
1144f9aab2bSPierre van Houtryve   if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) {
1154f9aab2bSPierre van Houtryve     auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(DiagLoc));
1164f9aab2bSPierre van Houtryve     Pat =
1174f9aab2bSPierre van Houtryve         std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
1184f9aab2bSPierre van Houtryve   } else if (const DagInit *IP =
1194f9aab2bSPierre van Houtryve                  getDagWithOperatorOfSubClass(Arg, "Intrinsic")) {
1203138eb50SRahul Joshi     const Record *TheDef = IP->getOperatorAsDef(DiagLoc);
121c1e3b990SRahul Joshi     const CodeGenIntrinsic *Intrin = &CGT.getIntrinsic(TheDef);
1224f9aab2bSPierre van Houtryve     const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin);
1234f9aab2bSPierre van Houtryve     Pat =
1244f9aab2bSPierre van Houtryve         std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
1254f9aab2bSPierre van Houtryve     cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin);
1264f9aab2bSPierre van Houtryve   } else if (const DagInit *PFP =
1274f9aab2bSPierre van Houtryve                  getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) {
1284f9aab2bSPierre van Houtryve     const Record *Def = PFP->getOperatorAsDef(DiagLoc);
1294f9aab2bSPierre van Houtryve     const PatFrag *PF = parsePatFrag(Def);
1304f9aab2bSPierre van Houtryve     if (!PF)
1314f9aab2bSPierre van Houtryve       return nullptr; // Already diagnosed by parsePatFrag
1324f9aab2bSPierre van Houtryve     Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name));
1334f9aab2bSPierre van Houtryve   } else if (const DagInit *BP =
1344f9aab2bSPierre van Houtryve                  getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) {
1354f9aab2bSPierre van Houtryve     Pat = std::make_unique<BuiltinPattern>(*BP->getOperatorAsDef(DiagLoc),
1364f9aab2bSPierre van Houtryve                                            insertStrRef(Name));
1374f9aab2bSPierre van Houtryve   } else
1384f9aab2bSPierre van Houtryve     return nullptr;
1394f9aab2bSPierre van Houtryve 
1404f9aab2bSPierre van Houtryve   for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) {
141*62e2c7fbSRahul Joshi     const Init *Arg = DagPat->getArg(K);
1424f9aab2bSPierre van Houtryve     if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) {
1434f9aab2bSPierre van Houtryve       if (!parseInstructionPatternMIFlags(*Pat, DagArg))
1444f9aab2bSPierre van Houtryve         return nullptr;
1454f9aab2bSPierre van Houtryve       continue;
1464f9aab2bSPierre van Houtryve     }
1474f9aab2bSPierre van Houtryve 
1484f9aab2bSPierre van Houtryve     if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K)))
1494f9aab2bSPierre van Houtryve       return nullptr;
1504f9aab2bSPierre van Houtryve   }
1514f9aab2bSPierre van Houtryve 
1524f9aab2bSPierre van Houtryve   if (!Pat->checkSemantics(DiagLoc))
1534f9aab2bSPierre van Houtryve     return nullptr;
1544f9aab2bSPierre van Houtryve 
1554f9aab2bSPierre van Houtryve   return std::move(Pat);
1564f9aab2bSPierre van Houtryve }
1574f9aab2bSPierre van Houtryve 
1584f9aab2bSPierre van Houtryve std::unique_ptr<Pattern>
1594f9aab2bSPierre van Houtryve PatternParser::parseWipMatchOpcodeMatcher(const Init &Arg, StringRef Name) {
1604f9aab2bSPierre van Houtryve   const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode");
1614f9aab2bSPierre van Houtryve   if (!Matcher)
1624f9aab2bSPierre van Houtryve     return nullptr;
1634f9aab2bSPierre van Houtryve 
1644f9aab2bSPierre van Houtryve   if (Matcher->getNumArgs() == 0) {
1654f9aab2bSPierre van Houtryve     PrintError(DiagLoc, "Empty wip_match_opcode");
1664f9aab2bSPierre van Houtryve     return nullptr;
1674f9aab2bSPierre van Houtryve   }
1684f9aab2bSPierre van Houtryve 
1694f9aab2bSPierre van Houtryve   // Each argument is an opcode that can match.
1704f9aab2bSPierre van Houtryve   auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name));
1714f9aab2bSPierre van Houtryve   for (const auto &Arg : Matcher->getArgs()) {
1723138eb50SRahul Joshi     const Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction");
1734f9aab2bSPierre van Houtryve     if (OpcodeDef) {
1744f9aab2bSPierre van Houtryve       Result->addOpcode(&CGT.getInstruction(OpcodeDef));
1754f9aab2bSPierre van Houtryve       continue;
1764f9aab2bSPierre van Houtryve     }
1774f9aab2bSPierre van Houtryve 
1784f9aab2bSPierre van Houtryve     PrintError(DiagLoc, "Arguments to wip_match_opcode must be instructions");
1794f9aab2bSPierre van Houtryve     return nullptr;
1804f9aab2bSPierre van Houtryve   }
1814f9aab2bSPierre van Houtryve 
1824f9aab2bSPierre van Houtryve   return std::move(Result);
1834f9aab2bSPierre van Houtryve }
1844f9aab2bSPierre van Houtryve 
1854f9aab2bSPierre van Houtryve bool PatternParser::parseInstructionPatternOperand(InstructionPattern &IP,
1864f9aab2bSPierre van Houtryve                                                    const Init *OpInit,
1874f9aab2bSPierre van Houtryve                                                    const StringInit *OpName) {
1884f9aab2bSPierre van Houtryve   const auto ParseErr = [&]() {
1894f9aab2bSPierre van Houtryve     PrintError(DiagLoc,
1904f9aab2bSPierre van Houtryve                "cannot parse operand '" + OpInit->getAsUnquotedString() + "' ");
1914f9aab2bSPierre van Houtryve     if (OpName)
1924f9aab2bSPierre van Houtryve       PrintNote(DiagLoc,
1934f9aab2bSPierre van Houtryve                 "operand name is '" + OpName->getAsUnquotedString() + '\'');
1944f9aab2bSPierre van Houtryve     return false;
1954f9aab2bSPierre van Houtryve   };
1964f9aab2bSPierre van Houtryve 
1974f9aab2bSPierre van Houtryve   // untyped immediate, e.g. 0
1984f9aab2bSPierre van Houtryve   if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) {
1994f9aab2bSPierre van Houtryve     std::string Name = OpName ? OpName->getAsUnquotedString() : "";
2004f9aab2bSPierre van Houtryve     IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType());
2014f9aab2bSPierre van Houtryve     return true;
2024f9aab2bSPierre van Houtryve   }
2034f9aab2bSPierre van Houtryve 
2044f9aab2bSPierre van Houtryve   // typed immediate, e.g. (i32 0)
2054f9aab2bSPierre van Houtryve   if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) {
2064f9aab2bSPierre van Houtryve     if (DagOp->getNumArgs() != 1)
2074f9aab2bSPierre van Houtryve       return ParseErr();
2084f9aab2bSPierre van Houtryve 
2094f9aab2bSPierre van Houtryve     const Record *TyDef = DagOp->getOperatorAsDef(DiagLoc);
2104f9aab2bSPierre van Houtryve     auto ImmTy = PatternType::get(DiagLoc, TyDef,
2114f9aab2bSPierre van Houtryve                                   "cannot parse immediate '" +
2124f9aab2bSPierre van Houtryve                                       DagOp->getAsUnquotedString() + '\'');
2134f9aab2bSPierre van Houtryve     if (!ImmTy)
2144f9aab2bSPierre van Houtryve       return false;
2154f9aab2bSPierre van Houtryve 
2164f9aab2bSPierre van Houtryve     if (!IP.hasAllDefs()) {
2174f9aab2bSPierre van Houtryve       PrintError(DiagLoc, "out operand of '" + IP.getInstName() +
2184f9aab2bSPierre van Houtryve                               "' cannot be an immediate");
2194f9aab2bSPierre van Houtryve       return false;
2204f9aab2bSPierre van Houtryve     }
2214f9aab2bSPierre van Houtryve 
2224f9aab2bSPierre van Houtryve     const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0));
2234f9aab2bSPierre van Houtryve     if (!Val)
2244f9aab2bSPierre van Houtryve       return ParseErr();
2254f9aab2bSPierre van Houtryve 
2264f9aab2bSPierre van Houtryve     std::string Name = OpName ? OpName->getAsUnquotedString() : "";
2274f9aab2bSPierre van Houtryve     IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy);
2284f9aab2bSPierre van Houtryve     return true;
2294f9aab2bSPierre van Houtryve   }
2304f9aab2bSPierre van Houtryve 
2314f9aab2bSPierre van Houtryve   // Typed operand e.g. $x/$z in (G_FNEG $x, $z)
2324f9aab2bSPierre van Houtryve   if (auto *DefI = dyn_cast<DefInit>(OpInit)) {
2334f9aab2bSPierre van Houtryve     if (!OpName) {
2344f9aab2bSPierre van Houtryve       PrintError(DiagLoc, "expected an operand name after '" +
2354f9aab2bSPierre van Houtryve                               OpInit->getAsString() + '\'');
2364f9aab2bSPierre van Houtryve       return false;
2374f9aab2bSPierre van Houtryve     }
2384f9aab2bSPierre van Houtryve     const Record *Def = DefI->getDef();
2394f9aab2bSPierre van Houtryve     auto Ty = PatternType::get(DiagLoc, Def, "cannot parse operand type");
2404f9aab2bSPierre van Houtryve     if (!Ty)
2414f9aab2bSPierre van Houtryve       return false;
2424f9aab2bSPierre van Houtryve     IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty);
2434f9aab2bSPierre van Houtryve     return true;
2444f9aab2bSPierre van Houtryve   }
2454f9aab2bSPierre van Houtryve 
2464f9aab2bSPierre van Houtryve   // Untyped operand e.g. $x/$z in (G_FNEG $x, $z)
2474f9aab2bSPierre van Houtryve   if (isa<UnsetInit>(OpInit)) {
2484f9aab2bSPierre van Houtryve     assert(OpName && "Unset w/ no OpName?");
2494f9aab2bSPierre van Houtryve     IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType());
2504f9aab2bSPierre van Houtryve     return true;
2514f9aab2bSPierre van Houtryve   }
2524f9aab2bSPierre van Houtryve 
2534f9aab2bSPierre van Houtryve   return ParseErr();
2544f9aab2bSPierre van Houtryve }
2554f9aab2bSPierre van Houtryve 
2564f9aab2bSPierre van Houtryve bool PatternParser::parseInstructionPatternMIFlags(InstructionPattern &IP,
2574f9aab2bSPierre van Houtryve                                                    const DagInit *Op) {
2584f9aab2bSPierre van Houtryve   auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP);
2594f9aab2bSPierre van Houtryve   if (!CGIP) {
2604f9aab2bSPierre van Houtryve     PrintError(DiagLoc,
2614f9aab2bSPierre van Houtryve                "matching/writing MIFlags is only allowed on CodeGenInstruction "
2624f9aab2bSPierre van Houtryve                "patterns");
2634f9aab2bSPierre van Houtryve     return false;
2644f9aab2bSPierre van Houtryve   }
2654f9aab2bSPierre van Houtryve 
2664f9aab2bSPierre van Houtryve   const auto CheckFlagEnum = [&](const Record *R) {
2674f9aab2bSPierre van Houtryve     if (!R->isSubClassOf(MIFlagsEnumClassName)) {
2684f9aab2bSPierre van Houtryve       PrintError(DiagLoc, "'" + R->getName() + "' is not a subclass of '" +
2694f9aab2bSPierre van Houtryve                               MIFlagsEnumClassName + "'");
2704f9aab2bSPierre van Houtryve       return false;
2714f9aab2bSPierre van Houtryve     }
2724f9aab2bSPierre van Houtryve 
2734f9aab2bSPierre van Houtryve     return true;
2744f9aab2bSPierre van Houtryve   };
2754f9aab2bSPierre van Houtryve 
2764f9aab2bSPierre van Houtryve   if (CGIP->getMIFlagsInfo()) {
2774f9aab2bSPierre van Houtryve     PrintError(DiagLoc, "MIFlags can only be present once on an instruction");
2784f9aab2bSPierre van Houtryve     return false;
2794f9aab2bSPierre van Houtryve   }
2804f9aab2bSPierre van Houtryve 
2814f9aab2bSPierre van Houtryve   auto &FI = CGIP->getOrCreateMIFlagsInfo();
2824f9aab2bSPierre van Houtryve   for (unsigned K = 0; K < Op->getNumArgs(); ++K) {
2834f9aab2bSPierre van Houtryve     const Init *Arg = Op->getArg(K);
2844f9aab2bSPierre van Houtryve 
2854f9aab2bSPierre van Houtryve     // Match/set a flag: (MIFlags FmNoNans)
2864f9aab2bSPierre van Houtryve     if (const auto *Def = dyn_cast<DefInit>(Arg)) {
2874f9aab2bSPierre van Houtryve       const Record *R = Def->getDef();
2884f9aab2bSPierre van Houtryve       if (!CheckFlagEnum(R))
2894f9aab2bSPierre van Houtryve         return false;
2904f9aab2bSPierre van Houtryve 
2914f9aab2bSPierre van Houtryve       FI.addSetFlag(R);
2924f9aab2bSPierre van Houtryve       continue;
2934f9aab2bSPierre van Houtryve     }
2944f9aab2bSPierre van Houtryve 
2954f9aab2bSPierre van Houtryve     // Do not match a flag/unset a flag: (MIFlags (not FmNoNans))
2964f9aab2bSPierre van Houtryve     if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) {
2974f9aab2bSPierre van Houtryve       for (const Init *NotArg : NotDag->getArgs()) {
2984f9aab2bSPierre van Houtryve         const DefInit *DefArg = dyn_cast<DefInit>(NotArg);
2994f9aab2bSPierre van Houtryve         if (!DefArg) {
3004f9aab2bSPierre van Houtryve           PrintError(DiagLoc, "cannot parse '" + NotArg->getAsUnquotedString() +
3014f9aab2bSPierre van Houtryve                                   "': expected a '" + MIFlagsEnumClassName +
3024f9aab2bSPierre van Houtryve                                   "'");
3034f9aab2bSPierre van Houtryve           return false;
3044f9aab2bSPierre van Houtryve         }
3054f9aab2bSPierre van Houtryve 
3064f9aab2bSPierre van Houtryve         const Record *R = DefArg->getDef();
3074f9aab2bSPierre van Houtryve         if (!CheckFlagEnum(R))
3084f9aab2bSPierre van Houtryve           return false;
3094f9aab2bSPierre van Houtryve 
3104f9aab2bSPierre van Houtryve         FI.addUnsetFlag(R);
3114f9aab2bSPierre van Houtryve       }
3124f9aab2bSPierre van Houtryve 
3134f9aab2bSPierre van Houtryve       continue;
3144f9aab2bSPierre van Houtryve     }
3154f9aab2bSPierre van Houtryve 
3164f9aab2bSPierre van Houtryve     // Copy flags from a matched instruction: (MIFlags $mi)
3174f9aab2bSPierre van Houtryve     if (isa<UnsetInit>(Arg)) {
3184f9aab2bSPierre van Houtryve       FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString()));
3194f9aab2bSPierre van Houtryve       continue;
3204f9aab2bSPierre van Houtryve     }
3214f9aab2bSPierre van Houtryve   }
3224f9aab2bSPierre van Houtryve 
3234f9aab2bSPierre van Houtryve   return true;
3244f9aab2bSPierre van Houtryve }
3254f9aab2bSPierre van Houtryve 
3264f9aab2bSPierre van Houtryve std::unique_ptr<PatFrag> PatternParser::parsePatFragImpl(const Record *Def) {
3274f9aab2bSPierre van Houtryve   auto StackTrace = PrettyStackTraceParse(*Def);
3284f9aab2bSPierre van Houtryve   if (!Def->isSubClassOf(PatFrag::ClassName))
3294f9aab2bSPierre van Houtryve     return nullptr;
3304f9aab2bSPierre van Houtryve 
3314f9aab2bSPierre van Houtryve   const DagInit *Ins = Def->getValueAsDag("InOperands");
3324f9aab2bSPierre van Houtryve   if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") {
3334f9aab2bSPierre van Houtryve     PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName +
3344f9aab2bSPierre van Houtryve                         " in operands list");
3354f9aab2bSPierre van Houtryve     return nullptr;
3364f9aab2bSPierre van Houtryve   }
3374f9aab2bSPierre van Houtryve 
3384f9aab2bSPierre van Houtryve   const DagInit *Outs = Def->getValueAsDag("OutOperands");
3394f9aab2bSPierre van Houtryve   if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") {
3404f9aab2bSPierre van Houtryve     PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName +
3414f9aab2bSPierre van Houtryve                         " out operands list");
3424f9aab2bSPierre van Houtryve     return nullptr;
3434f9aab2bSPierre van Houtryve   }
3444f9aab2bSPierre van Houtryve 
3454f9aab2bSPierre van Houtryve   auto Result = std::make_unique<PatFrag>(*Def);
3464f9aab2bSPierre van Houtryve   if (!parsePatFragParamList(*Outs, [&](StringRef Name, unsigned Kind) {
3474f9aab2bSPierre van Houtryve         Result->addOutParam(insertStrRef(Name), (PatFrag::ParamKind)Kind);
3484f9aab2bSPierre van Houtryve         return true;
3494f9aab2bSPierre van Houtryve       }))
3504f9aab2bSPierre van Houtryve     return nullptr;
3514f9aab2bSPierre van Houtryve 
3524f9aab2bSPierre van Houtryve   if (!parsePatFragParamList(*Ins, [&](StringRef Name, unsigned Kind) {
3534f9aab2bSPierre van Houtryve         Result->addInParam(insertStrRef(Name), (PatFrag::ParamKind)Kind);
3544f9aab2bSPierre van Houtryve         return true;
3554f9aab2bSPierre van Houtryve       }))
3564f9aab2bSPierre van Houtryve     return nullptr;
3574f9aab2bSPierre van Houtryve 
3584f9aab2bSPierre van Houtryve   const ListInit *Alts = Def->getValueAsListInit("Alternatives");
3594f9aab2bSPierre van Houtryve   unsigned AltIdx = 0;
3604f9aab2bSPierre van Houtryve   for (const Init *Alt : *Alts) {
3614f9aab2bSPierre van Houtryve     const auto *PatDag = dyn_cast<DagInit>(Alt);
3624f9aab2bSPierre van Houtryve     if (!PatDag) {
3634f9aab2bSPierre van Houtryve       PrintError(Def, "expected dag init for PatFrag pattern alternative");
3644f9aab2bSPierre van Houtryve       return nullptr;
3654f9aab2bSPierre van Houtryve     }
3664f9aab2bSPierre van Houtryve 
3674f9aab2bSPierre van Houtryve     PatFrag::Alternative &A = Result->addAlternative();
3684f9aab2bSPierre van Houtryve     const auto AddPat = [&](std::unique_ptr<Pattern> Pat) {
3694f9aab2bSPierre van Houtryve       A.Pats.push_back(std::move(Pat));
3704f9aab2bSPierre van Houtryve       return true;
3714f9aab2bSPierre van Houtryve     };
3724f9aab2bSPierre van Houtryve 
3734f9aab2bSPierre van Houtryve     SaveAndRestore<ArrayRef<SMLoc>> DiagLocSAR(DiagLoc, Def->getLoc());
3744f9aab2bSPierre van Houtryve     if (!parsePatternList(
3754f9aab2bSPierre van Houtryve             *PatDag, AddPat, "pattern",
3764f9aab2bSPierre van Houtryve             /*AnonPatPrefix*/
3774f9aab2bSPierre van Houtryve             (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str()))
3784f9aab2bSPierre van Houtryve       return nullptr;
3794f9aab2bSPierre van Houtryve   }
3804f9aab2bSPierre van Houtryve 
3814f9aab2bSPierre van Houtryve   if (!Result->buildOperandsTables() || !Result->checkSemantics())
3824f9aab2bSPierre van Houtryve     return nullptr;
3834f9aab2bSPierre van Houtryve 
3844f9aab2bSPierre van Houtryve   return Result;
3854f9aab2bSPierre van Houtryve }
3864f9aab2bSPierre van Houtryve 
3874f9aab2bSPierre van Houtryve bool PatternParser::parsePatFragParamList(
3884f9aab2bSPierre van Houtryve     const DagInit &OpsList,
3894f9aab2bSPierre van Houtryve     function_ref<bool(StringRef, unsigned)> ParseAction) {
3904f9aab2bSPierre van Houtryve   for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) {
3914f9aab2bSPierre van Houtryve     const StringInit *Name = OpsList.getArgName(K);
3924f9aab2bSPierre van Houtryve     const Init *Ty = OpsList.getArg(K);
3934f9aab2bSPierre van Houtryve 
3944f9aab2bSPierre van Houtryve     if (!Name) {
3954f9aab2bSPierre van Houtryve       PrintError(DiagLoc, "all operands must be named'");
3964f9aab2bSPierre van Houtryve       return false;
3974f9aab2bSPierre van Houtryve     }
3984f9aab2bSPierre van Houtryve     const std::string NameStr = Name->getAsUnquotedString();
3994f9aab2bSPierre van Houtryve 
4004f9aab2bSPierre van Houtryve     PatFrag::ParamKind OpKind;
4014f9aab2bSPierre van Houtryve     if (isSpecificDef(*Ty, "gi_imm"))
4024f9aab2bSPierre van Houtryve       OpKind = PatFrag::PK_Imm;
4034f9aab2bSPierre van Houtryve     else if (isSpecificDef(*Ty, "root"))
4044f9aab2bSPierre van Houtryve       OpKind = PatFrag::PK_Root;
4054f9aab2bSPierre van Houtryve     else if (isa<UnsetInit>(Ty) ||
4064f9aab2bSPierre van Houtryve              isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo.
4074f9aab2bSPierre van Houtryve       OpKind = PatFrag::PK_MachineOperand;
4084f9aab2bSPierre van Houtryve     else {
4094f9aab2bSPierre van Houtryve       PrintError(
4104f9aab2bSPierre van Houtryve           DiagLoc,
4114f9aab2bSPierre van Houtryve           '\'' + NameStr +
4124f9aab2bSPierre van Houtryve               "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'");
4134f9aab2bSPierre van Houtryve       return false;
4144f9aab2bSPierre van Houtryve     }
4154f9aab2bSPierre van Houtryve 
4164f9aab2bSPierre van Houtryve     if (!ParseAction(NameStr, (unsigned)OpKind))
4174f9aab2bSPierre van Houtryve       return false;
4184f9aab2bSPierre van Houtryve   }
4194f9aab2bSPierre van Houtryve 
4204f9aab2bSPierre van Houtryve   return true;
4214f9aab2bSPierre van Houtryve }
4224f9aab2bSPierre van Houtryve 
4234f9aab2bSPierre van Houtryve const PatFrag *PatternParser::parsePatFrag(const Record *Def) {
4244f9aab2bSPierre van Houtryve   // Cache already parsed PatFrags to avoid doing extra work.
4254f9aab2bSPierre van Houtryve   static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags;
4264f9aab2bSPierre van Houtryve 
4274f9aab2bSPierre van Houtryve   auto It = ParsedPatFrags.find(Def);
4284f9aab2bSPierre van Houtryve   if (It != ParsedPatFrags.end()) {
4294f9aab2bSPierre van Houtryve     SeenPatFrags.insert(It->second.get());
4304f9aab2bSPierre van Houtryve     return It->second.get();
4314f9aab2bSPierre van Houtryve   }
4324f9aab2bSPierre van Houtryve 
4334f9aab2bSPierre van Houtryve   std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def);
4344f9aab2bSPierre van Houtryve   if (!NewPatFrag) {
4354f9aab2bSPierre van Houtryve     PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" +
4364f9aab2bSPierre van Houtryve                         Def->getName() + "'");
4374f9aab2bSPierre van Houtryve     // Put a nullptr in the map so we don't attempt parsing this again.
4384f9aab2bSPierre van Houtryve     ParsedPatFrags[Def] = nullptr;
4394f9aab2bSPierre van Houtryve     return nullptr;
4404f9aab2bSPierre van Houtryve   }
4414f9aab2bSPierre van Houtryve 
4424f9aab2bSPierre van Houtryve   const auto *Res = NewPatFrag.get();
4434f9aab2bSPierre van Houtryve   ParsedPatFrags[Def] = std::move(NewPatFrag);
4444f9aab2bSPierre van Houtryve   SeenPatFrags.insert(Res);
4454f9aab2bSPierre van Houtryve   return Res;
4464f9aab2bSPierre van Houtryve }
4474f9aab2bSPierre van Houtryve 
4484f9aab2bSPierre van Houtryve } // namespace gi
4494f9aab2bSPierre van Houtryve } // namespace llvm
450