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