1*0fca6ea1SDimitry Andric //===- PatternParser.cpp ----------------------------------------*- C++ -*-===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "Common/GlobalISel/PatternParser.h" 10*0fca6ea1SDimitry Andric #include "Basic/CodeGenIntrinsics.h" 11*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 12*0fca6ea1SDimitry Andric #include "Common/GlobalISel/CombinerUtils.h" 13*0fca6ea1SDimitry Andric #include "Common/GlobalISel/Patterns.h" 14*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h" 15*0fca6ea1SDimitry Andric #include "llvm/Support/PrettyStackTrace.h" 16*0fca6ea1SDimitry Andric #include "llvm/Support/SaveAndRestore.h" 17*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 18*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 19*0fca6ea1SDimitry Andric 20*0fca6ea1SDimitry Andric namespace llvm { 21*0fca6ea1SDimitry Andric namespace gi { 22*0fca6ea1SDimitry Andric static constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum"; 23*0fca6ea1SDimitry Andric 24*0fca6ea1SDimitry Andric namespace { 25*0fca6ea1SDimitry Andric class PrettyStackTraceParse : public PrettyStackTraceEntry { 26*0fca6ea1SDimitry Andric const Record &Def; 27*0fca6ea1SDimitry Andric 28*0fca6ea1SDimitry Andric public: 29*0fca6ea1SDimitry Andric PrettyStackTraceParse(const Record &Def) : Def(Def) {} 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric void print(raw_ostream &OS) const override { 32*0fca6ea1SDimitry Andric if (Def.isSubClassOf("GICombineRule")) 33*0fca6ea1SDimitry Andric OS << "Parsing GICombineRule '" << Def.getName() << '\''; 34*0fca6ea1SDimitry Andric else if (Def.isSubClassOf(PatFrag::ClassName)) 35*0fca6ea1SDimitry Andric OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << '\''; 36*0fca6ea1SDimitry Andric else 37*0fca6ea1SDimitry Andric OS << "Parsing '" << Def.getName() << '\''; 38*0fca6ea1SDimitry Andric OS << '\n'; 39*0fca6ea1SDimitry Andric } 40*0fca6ea1SDimitry Andric }; 41*0fca6ea1SDimitry Andric } // namespace 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric bool PatternParser::parsePatternList( 44*0fca6ea1SDimitry Andric const DagInit &List, 45*0fca6ea1SDimitry Andric function_ref<bool(std::unique_ptr<Pattern>)> ParseAction, 46*0fca6ea1SDimitry Andric StringRef Operator, StringRef AnonPatNamePrefix) { 47*0fca6ea1SDimitry Andric if (List.getOperatorAsDef(DiagLoc)->getName() != Operator) { 48*0fca6ea1SDimitry Andric PrintError(DiagLoc, "Expected " + Operator + " operator"); 49*0fca6ea1SDimitry Andric return false; 50*0fca6ea1SDimitry Andric } 51*0fca6ea1SDimitry Andric 52*0fca6ea1SDimitry Andric if (List.getNumArgs() == 0) { 53*0fca6ea1SDimitry Andric PrintError(DiagLoc, Operator + " pattern list is empty"); 54*0fca6ea1SDimitry Andric return false; 55*0fca6ea1SDimitry Andric } 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric // The match section consists of a list of matchers and predicates. Parse each 58*0fca6ea1SDimitry Andric // one and add the equivalent GIMatchDag nodes, predicates, and edges. 59*0fca6ea1SDimitry Andric for (unsigned I = 0; I < List.getNumArgs(); ++I) { 60*0fca6ea1SDimitry Andric Init *Arg = List.getArg(I); 61*0fca6ea1SDimitry Andric std::string Name = List.getArgName(I) 62*0fca6ea1SDimitry Andric ? List.getArgName(I)->getValue().str() 63*0fca6ea1SDimitry Andric : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str(); 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric if (auto Pat = parseInstructionPattern(*Arg, Name)) { 66*0fca6ea1SDimitry Andric if (!ParseAction(std::move(Pat))) 67*0fca6ea1SDimitry Andric return false; 68*0fca6ea1SDimitry Andric continue; 69*0fca6ea1SDimitry Andric } 70*0fca6ea1SDimitry Andric 71*0fca6ea1SDimitry Andric if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) { 72*0fca6ea1SDimitry Andric if (!ParseAction(std::move(Pat))) 73*0fca6ea1SDimitry Andric return false; 74*0fca6ea1SDimitry Andric continue; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric // Parse arbitrary C++ code 78*0fca6ea1SDimitry Andric if (const auto *StringI = dyn_cast<StringInit>(Arg)) { 79*0fca6ea1SDimitry Andric auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name)); 80*0fca6ea1SDimitry Andric if (!ParseAction(std::move(CXXPat))) 81*0fca6ea1SDimitry Andric return false; 82*0fca6ea1SDimitry Andric continue; 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric PrintError(DiagLoc, 86*0fca6ea1SDimitry Andric "Failed to parse pattern: '" + Arg->getAsString() + '\''); 87*0fca6ea1SDimitry Andric return false; 88*0fca6ea1SDimitry Andric } 89*0fca6ea1SDimitry Andric 90*0fca6ea1SDimitry Andric return true; 91*0fca6ea1SDimitry Andric } 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric static const CodeGenInstruction & 94*0fca6ea1SDimitry Andric getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) { 95*0fca6ea1SDimitry Andric StringRef Opc; 96*0fca6ea1SDimitry Andric if (I->isConvergent) { 97*0fca6ea1SDimitry Andric Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS" 98*0fca6ea1SDimitry Andric : "G_INTRINSIC_CONVERGENT"; 99*0fca6ea1SDimitry Andric } else { 100*0fca6ea1SDimitry Andric Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC"; 101*0fca6ea1SDimitry Andric } 102*0fca6ea1SDimitry Andric 103*0fca6ea1SDimitry Andric RecordKeeper &RK = I->TheDef->getRecords(); 104*0fca6ea1SDimitry Andric return CGT.getInstruction(RK.getDef(Opc)); 105*0fca6ea1SDimitry Andric } 106*0fca6ea1SDimitry Andric 107*0fca6ea1SDimitry Andric static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) { 108*0fca6ea1SDimitry Andric // Intrinsics need to have a static lifetime because the match table keeps 109*0fca6ea1SDimitry Andric // references to CodeGenIntrinsic objects. 110*0fca6ea1SDimitry Andric static DenseMap<const Record *, std::unique_ptr<CodeGenIntrinsic>> 111*0fca6ea1SDimitry Andric AllIntrinsics; 112*0fca6ea1SDimitry Andric 113*0fca6ea1SDimitry Andric auto &Ptr = AllIntrinsics[R]; 114*0fca6ea1SDimitry Andric if (!Ptr) 115*0fca6ea1SDimitry Andric Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>()); 116*0fca6ea1SDimitry Andric return Ptr.get(); 117*0fca6ea1SDimitry Andric } 118*0fca6ea1SDimitry Andric 119*0fca6ea1SDimitry Andric std::unique_ptr<Pattern> 120*0fca6ea1SDimitry Andric PatternParser::parseInstructionPattern(const Init &Arg, StringRef Name) { 121*0fca6ea1SDimitry Andric const DagInit *DagPat = dyn_cast<DagInit>(&Arg); 122*0fca6ea1SDimitry Andric if (!DagPat) 123*0fca6ea1SDimitry Andric return nullptr; 124*0fca6ea1SDimitry Andric 125*0fca6ea1SDimitry Andric std::unique_ptr<InstructionPattern> Pat; 126*0fca6ea1SDimitry Andric if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) { 127*0fca6ea1SDimitry Andric auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(DiagLoc)); 128*0fca6ea1SDimitry Andric Pat = 129*0fca6ea1SDimitry Andric std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); 130*0fca6ea1SDimitry Andric } else if (const DagInit *IP = 131*0fca6ea1SDimitry Andric getDagWithOperatorOfSubClass(Arg, "Intrinsic")) { 132*0fca6ea1SDimitry Andric Record *TheDef = IP->getOperatorAsDef(DiagLoc); 133*0fca6ea1SDimitry Andric const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef); 134*0fca6ea1SDimitry Andric const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin); 135*0fca6ea1SDimitry Andric Pat = 136*0fca6ea1SDimitry Andric std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); 137*0fca6ea1SDimitry Andric cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin); 138*0fca6ea1SDimitry Andric } else if (const DagInit *PFP = 139*0fca6ea1SDimitry Andric getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) { 140*0fca6ea1SDimitry Andric const Record *Def = PFP->getOperatorAsDef(DiagLoc); 141*0fca6ea1SDimitry Andric const PatFrag *PF = parsePatFrag(Def); 142*0fca6ea1SDimitry Andric if (!PF) 143*0fca6ea1SDimitry Andric return nullptr; // Already diagnosed by parsePatFrag 144*0fca6ea1SDimitry Andric Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name)); 145*0fca6ea1SDimitry Andric } else if (const DagInit *BP = 146*0fca6ea1SDimitry Andric getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) { 147*0fca6ea1SDimitry Andric Pat = std::make_unique<BuiltinPattern>(*BP->getOperatorAsDef(DiagLoc), 148*0fca6ea1SDimitry Andric insertStrRef(Name)); 149*0fca6ea1SDimitry Andric } else 150*0fca6ea1SDimitry Andric return nullptr; 151*0fca6ea1SDimitry Andric 152*0fca6ea1SDimitry Andric for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) { 153*0fca6ea1SDimitry Andric Init *Arg = DagPat->getArg(K); 154*0fca6ea1SDimitry Andric if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) { 155*0fca6ea1SDimitry Andric if (!parseInstructionPatternMIFlags(*Pat, DagArg)) 156*0fca6ea1SDimitry Andric return nullptr; 157*0fca6ea1SDimitry Andric continue; 158*0fca6ea1SDimitry Andric } 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K))) 161*0fca6ea1SDimitry Andric return nullptr; 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric if (!Pat->checkSemantics(DiagLoc)) 165*0fca6ea1SDimitry Andric return nullptr; 166*0fca6ea1SDimitry Andric 167*0fca6ea1SDimitry Andric return std::move(Pat); 168*0fca6ea1SDimitry Andric } 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric std::unique_ptr<Pattern> 171*0fca6ea1SDimitry Andric PatternParser::parseWipMatchOpcodeMatcher(const Init &Arg, StringRef Name) { 172*0fca6ea1SDimitry Andric const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode"); 173*0fca6ea1SDimitry Andric if (!Matcher) 174*0fca6ea1SDimitry Andric return nullptr; 175*0fca6ea1SDimitry Andric 176*0fca6ea1SDimitry Andric if (Matcher->getNumArgs() == 0) { 177*0fca6ea1SDimitry Andric PrintError(DiagLoc, "Empty wip_match_opcode"); 178*0fca6ea1SDimitry Andric return nullptr; 179*0fca6ea1SDimitry Andric } 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric // Each argument is an opcode that can match. 182*0fca6ea1SDimitry Andric auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name)); 183*0fca6ea1SDimitry Andric for (const auto &Arg : Matcher->getArgs()) { 184*0fca6ea1SDimitry Andric Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); 185*0fca6ea1SDimitry Andric if (OpcodeDef) { 186*0fca6ea1SDimitry Andric Result->addOpcode(&CGT.getInstruction(OpcodeDef)); 187*0fca6ea1SDimitry Andric continue; 188*0fca6ea1SDimitry Andric } 189*0fca6ea1SDimitry Andric 190*0fca6ea1SDimitry Andric PrintError(DiagLoc, "Arguments to wip_match_opcode must be instructions"); 191*0fca6ea1SDimitry Andric return nullptr; 192*0fca6ea1SDimitry Andric } 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric return std::move(Result); 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric bool PatternParser::parseInstructionPatternOperand(InstructionPattern &IP, 198*0fca6ea1SDimitry Andric const Init *OpInit, 199*0fca6ea1SDimitry Andric const StringInit *OpName) { 200*0fca6ea1SDimitry Andric const auto ParseErr = [&]() { 201*0fca6ea1SDimitry Andric PrintError(DiagLoc, 202*0fca6ea1SDimitry Andric "cannot parse operand '" + OpInit->getAsUnquotedString() + "' "); 203*0fca6ea1SDimitry Andric if (OpName) 204*0fca6ea1SDimitry Andric PrintNote(DiagLoc, 205*0fca6ea1SDimitry Andric "operand name is '" + OpName->getAsUnquotedString() + '\''); 206*0fca6ea1SDimitry Andric return false; 207*0fca6ea1SDimitry Andric }; 208*0fca6ea1SDimitry Andric 209*0fca6ea1SDimitry Andric // untyped immediate, e.g. 0 210*0fca6ea1SDimitry Andric if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) { 211*0fca6ea1SDimitry Andric std::string Name = OpName ? OpName->getAsUnquotedString() : ""; 212*0fca6ea1SDimitry Andric IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType()); 213*0fca6ea1SDimitry Andric return true; 214*0fca6ea1SDimitry Andric } 215*0fca6ea1SDimitry Andric 216*0fca6ea1SDimitry Andric // typed immediate, e.g. (i32 0) 217*0fca6ea1SDimitry Andric if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) { 218*0fca6ea1SDimitry Andric if (DagOp->getNumArgs() != 1) 219*0fca6ea1SDimitry Andric return ParseErr(); 220*0fca6ea1SDimitry Andric 221*0fca6ea1SDimitry Andric const Record *TyDef = DagOp->getOperatorAsDef(DiagLoc); 222*0fca6ea1SDimitry Andric auto ImmTy = PatternType::get(DiagLoc, TyDef, 223*0fca6ea1SDimitry Andric "cannot parse immediate '" + 224*0fca6ea1SDimitry Andric DagOp->getAsUnquotedString() + '\''); 225*0fca6ea1SDimitry Andric if (!ImmTy) 226*0fca6ea1SDimitry Andric return false; 227*0fca6ea1SDimitry Andric 228*0fca6ea1SDimitry Andric if (!IP.hasAllDefs()) { 229*0fca6ea1SDimitry Andric PrintError(DiagLoc, "out operand of '" + IP.getInstName() + 230*0fca6ea1SDimitry Andric "' cannot be an immediate"); 231*0fca6ea1SDimitry Andric return false; 232*0fca6ea1SDimitry Andric } 233*0fca6ea1SDimitry Andric 234*0fca6ea1SDimitry Andric const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0)); 235*0fca6ea1SDimitry Andric if (!Val) 236*0fca6ea1SDimitry Andric return ParseErr(); 237*0fca6ea1SDimitry Andric 238*0fca6ea1SDimitry Andric std::string Name = OpName ? OpName->getAsUnquotedString() : ""; 239*0fca6ea1SDimitry Andric IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy); 240*0fca6ea1SDimitry Andric return true; 241*0fca6ea1SDimitry Andric } 242*0fca6ea1SDimitry Andric 243*0fca6ea1SDimitry Andric // Typed operand e.g. $x/$z in (G_FNEG $x, $z) 244*0fca6ea1SDimitry Andric if (auto *DefI = dyn_cast<DefInit>(OpInit)) { 245*0fca6ea1SDimitry Andric if (!OpName) { 246*0fca6ea1SDimitry Andric PrintError(DiagLoc, "expected an operand name after '" + 247*0fca6ea1SDimitry Andric OpInit->getAsString() + '\''); 248*0fca6ea1SDimitry Andric return false; 249*0fca6ea1SDimitry Andric } 250*0fca6ea1SDimitry Andric const Record *Def = DefI->getDef(); 251*0fca6ea1SDimitry Andric auto Ty = PatternType::get(DiagLoc, Def, "cannot parse operand type"); 252*0fca6ea1SDimitry Andric if (!Ty) 253*0fca6ea1SDimitry Andric return false; 254*0fca6ea1SDimitry Andric IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty); 255*0fca6ea1SDimitry Andric return true; 256*0fca6ea1SDimitry Andric } 257*0fca6ea1SDimitry Andric 258*0fca6ea1SDimitry Andric // Untyped operand e.g. $x/$z in (G_FNEG $x, $z) 259*0fca6ea1SDimitry Andric if (isa<UnsetInit>(OpInit)) { 260*0fca6ea1SDimitry Andric assert(OpName && "Unset w/ no OpName?"); 261*0fca6ea1SDimitry Andric IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType()); 262*0fca6ea1SDimitry Andric return true; 263*0fca6ea1SDimitry Andric } 264*0fca6ea1SDimitry Andric 265*0fca6ea1SDimitry Andric return ParseErr(); 266*0fca6ea1SDimitry Andric } 267*0fca6ea1SDimitry Andric 268*0fca6ea1SDimitry Andric bool PatternParser::parseInstructionPatternMIFlags(InstructionPattern &IP, 269*0fca6ea1SDimitry Andric const DagInit *Op) { 270*0fca6ea1SDimitry Andric auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP); 271*0fca6ea1SDimitry Andric if (!CGIP) { 272*0fca6ea1SDimitry Andric PrintError(DiagLoc, 273*0fca6ea1SDimitry Andric "matching/writing MIFlags is only allowed on CodeGenInstruction " 274*0fca6ea1SDimitry Andric "patterns"); 275*0fca6ea1SDimitry Andric return false; 276*0fca6ea1SDimitry Andric } 277*0fca6ea1SDimitry Andric 278*0fca6ea1SDimitry Andric const auto CheckFlagEnum = [&](const Record *R) { 279*0fca6ea1SDimitry Andric if (!R->isSubClassOf(MIFlagsEnumClassName)) { 280*0fca6ea1SDimitry Andric PrintError(DiagLoc, "'" + R->getName() + "' is not a subclass of '" + 281*0fca6ea1SDimitry Andric MIFlagsEnumClassName + "'"); 282*0fca6ea1SDimitry Andric return false; 283*0fca6ea1SDimitry Andric } 284*0fca6ea1SDimitry Andric 285*0fca6ea1SDimitry Andric return true; 286*0fca6ea1SDimitry Andric }; 287*0fca6ea1SDimitry Andric 288*0fca6ea1SDimitry Andric if (CGIP->getMIFlagsInfo()) { 289*0fca6ea1SDimitry Andric PrintError(DiagLoc, "MIFlags can only be present once on an instruction"); 290*0fca6ea1SDimitry Andric return false; 291*0fca6ea1SDimitry Andric } 292*0fca6ea1SDimitry Andric 293*0fca6ea1SDimitry Andric auto &FI = CGIP->getOrCreateMIFlagsInfo(); 294*0fca6ea1SDimitry Andric for (unsigned K = 0; K < Op->getNumArgs(); ++K) { 295*0fca6ea1SDimitry Andric const Init *Arg = Op->getArg(K); 296*0fca6ea1SDimitry Andric 297*0fca6ea1SDimitry Andric // Match/set a flag: (MIFlags FmNoNans) 298*0fca6ea1SDimitry Andric if (const auto *Def = dyn_cast<DefInit>(Arg)) { 299*0fca6ea1SDimitry Andric const Record *R = Def->getDef(); 300*0fca6ea1SDimitry Andric if (!CheckFlagEnum(R)) 301*0fca6ea1SDimitry Andric return false; 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric FI.addSetFlag(R); 304*0fca6ea1SDimitry Andric continue; 305*0fca6ea1SDimitry Andric } 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric // Do not match a flag/unset a flag: (MIFlags (not FmNoNans)) 308*0fca6ea1SDimitry Andric if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) { 309*0fca6ea1SDimitry Andric for (const Init *NotArg : NotDag->getArgs()) { 310*0fca6ea1SDimitry Andric const DefInit *DefArg = dyn_cast<DefInit>(NotArg); 311*0fca6ea1SDimitry Andric if (!DefArg) { 312*0fca6ea1SDimitry Andric PrintError(DiagLoc, "cannot parse '" + NotArg->getAsUnquotedString() + 313*0fca6ea1SDimitry Andric "': expected a '" + MIFlagsEnumClassName + 314*0fca6ea1SDimitry Andric "'"); 315*0fca6ea1SDimitry Andric return false; 316*0fca6ea1SDimitry Andric } 317*0fca6ea1SDimitry Andric 318*0fca6ea1SDimitry Andric const Record *R = DefArg->getDef(); 319*0fca6ea1SDimitry Andric if (!CheckFlagEnum(R)) 320*0fca6ea1SDimitry Andric return false; 321*0fca6ea1SDimitry Andric 322*0fca6ea1SDimitry Andric FI.addUnsetFlag(R); 323*0fca6ea1SDimitry Andric continue; 324*0fca6ea1SDimitry Andric } 325*0fca6ea1SDimitry Andric 326*0fca6ea1SDimitry Andric continue; 327*0fca6ea1SDimitry Andric } 328*0fca6ea1SDimitry Andric 329*0fca6ea1SDimitry Andric // Copy flags from a matched instruction: (MIFlags $mi) 330*0fca6ea1SDimitry Andric if (isa<UnsetInit>(Arg)) { 331*0fca6ea1SDimitry Andric FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString())); 332*0fca6ea1SDimitry Andric continue; 333*0fca6ea1SDimitry Andric } 334*0fca6ea1SDimitry Andric } 335*0fca6ea1SDimitry Andric 336*0fca6ea1SDimitry Andric return true; 337*0fca6ea1SDimitry Andric } 338*0fca6ea1SDimitry Andric 339*0fca6ea1SDimitry Andric std::unique_ptr<PatFrag> PatternParser::parsePatFragImpl(const Record *Def) { 340*0fca6ea1SDimitry Andric auto StackTrace = PrettyStackTraceParse(*Def); 341*0fca6ea1SDimitry Andric if (!Def->isSubClassOf(PatFrag::ClassName)) 342*0fca6ea1SDimitry Andric return nullptr; 343*0fca6ea1SDimitry Andric 344*0fca6ea1SDimitry Andric const DagInit *Ins = Def->getValueAsDag("InOperands"); 345*0fca6ea1SDimitry Andric if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") { 346*0fca6ea1SDimitry Andric PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName + 347*0fca6ea1SDimitry Andric " in operands list"); 348*0fca6ea1SDimitry Andric return nullptr; 349*0fca6ea1SDimitry Andric } 350*0fca6ea1SDimitry Andric 351*0fca6ea1SDimitry Andric const DagInit *Outs = Def->getValueAsDag("OutOperands"); 352*0fca6ea1SDimitry Andric if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") { 353*0fca6ea1SDimitry Andric PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName + 354*0fca6ea1SDimitry Andric " out operands list"); 355*0fca6ea1SDimitry Andric return nullptr; 356*0fca6ea1SDimitry Andric } 357*0fca6ea1SDimitry Andric 358*0fca6ea1SDimitry Andric auto Result = std::make_unique<PatFrag>(*Def); 359*0fca6ea1SDimitry Andric if (!parsePatFragParamList(*Outs, [&](StringRef Name, unsigned Kind) { 360*0fca6ea1SDimitry Andric Result->addOutParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); 361*0fca6ea1SDimitry Andric return true; 362*0fca6ea1SDimitry Andric })) 363*0fca6ea1SDimitry Andric return nullptr; 364*0fca6ea1SDimitry Andric 365*0fca6ea1SDimitry Andric if (!parsePatFragParamList(*Ins, [&](StringRef Name, unsigned Kind) { 366*0fca6ea1SDimitry Andric Result->addInParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); 367*0fca6ea1SDimitry Andric return true; 368*0fca6ea1SDimitry Andric })) 369*0fca6ea1SDimitry Andric return nullptr; 370*0fca6ea1SDimitry Andric 371*0fca6ea1SDimitry Andric const ListInit *Alts = Def->getValueAsListInit("Alternatives"); 372*0fca6ea1SDimitry Andric unsigned AltIdx = 0; 373*0fca6ea1SDimitry Andric for (const Init *Alt : *Alts) { 374*0fca6ea1SDimitry Andric const auto *PatDag = dyn_cast<DagInit>(Alt); 375*0fca6ea1SDimitry Andric if (!PatDag) { 376*0fca6ea1SDimitry Andric PrintError(Def, "expected dag init for PatFrag pattern alternative"); 377*0fca6ea1SDimitry Andric return nullptr; 378*0fca6ea1SDimitry Andric } 379*0fca6ea1SDimitry Andric 380*0fca6ea1SDimitry Andric PatFrag::Alternative &A = Result->addAlternative(); 381*0fca6ea1SDimitry Andric const auto AddPat = [&](std::unique_ptr<Pattern> Pat) { 382*0fca6ea1SDimitry Andric A.Pats.push_back(std::move(Pat)); 383*0fca6ea1SDimitry Andric return true; 384*0fca6ea1SDimitry Andric }; 385*0fca6ea1SDimitry Andric 386*0fca6ea1SDimitry Andric SaveAndRestore<ArrayRef<SMLoc>> DiagLocSAR(DiagLoc, Def->getLoc()); 387*0fca6ea1SDimitry Andric if (!parsePatternList( 388*0fca6ea1SDimitry Andric *PatDag, AddPat, "pattern", 389*0fca6ea1SDimitry Andric /*AnonPatPrefix*/ 390*0fca6ea1SDimitry Andric (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str())) 391*0fca6ea1SDimitry Andric return nullptr; 392*0fca6ea1SDimitry Andric } 393*0fca6ea1SDimitry Andric 394*0fca6ea1SDimitry Andric if (!Result->buildOperandsTables() || !Result->checkSemantics()) 395*0fca6ea1SDimitry Andric return nullptr; 396*0fca6ea1SDimitry Andric 397*0fca6ea1SDimitry Andric return Result; 398*0fca6ea1SDimitry Andric } 399*0fca6ea1SDimitry Andric 400*0fca6ea1SDimitry Andric bool PatternParser::parsePatFragParamList( 401*0fca6ea1SDimitry Andric const DagInit &OpsList, 402*0fca6ea1SDimitry Andric function_ref<bool(StringRef, unsigned)> ParseAction) { 403*0fca6ea1SDimitry Andric for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) { 404*0fca6ea1SDimitry Andric const StringInit *Name = OpsList.getArgName(K); 405*0fca6ea1SDimitry Andric const Init *Ty = OpsList.getArg(K); 406*0fca6ea1SDimitry Andric 407*0fca6ea1SDimitry Andric if (!Name) { 408*0fca6ea1SDimitry Andric PrintError(DiagLoc, "all operands must be named'"); 409*0fca6ea1SDimitry Andric return false; 410*0fca6ea1SDimitry Andric } 411*0fca6ea1SDimitry Andric const std::string NameStr = Name->getAsUnquotedString(); 412*0fca6ea1SDimitry Andric 413*0fca6ea1SDimitry Andric PatFrag::ParamKind OpKind; 414*0fca6ea1SDimitry Andric if (isSpecificDef(*Ty, "gi_imm")) 415*0fca6ea1SDimitry Andric OpKind = PatFrag::PK_Imm; 416*0fca6ea1SDimitry Andric else if (isSpecificDef(*Ty, "root")) 417*0fca6ea1SDimitry Andric OpKind = PatFrag::PK_Root; 418*0fca6ea1SDimitry Andric else if (isa<UnsetInit>(Ty) || 419*0fca6ea1SDimitry Andric isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo. 420*0fca6ea1SDimitry Andric OpKind = PatFrag::PK_MachineOperand; 421*0fca6ea1SDimitry Andric else { 422*0fca6ea1SDimitry Andric PrintError( 423*0fca6ea1SDimitry Andric DiagLoc, 424*0fca6ea1SDimitry Andric '\'' + NameStr + 425*0fca6ea1SDimitry Andric "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'"); 426*0fca6ea1SDimitry Andric return false; 427*0fca6ea1SDimitry Andric } 428*0fca6ea1SDimitry Andric 429*0fca6ea1SDimitry Andric if (!ParseAction(NameStr, (unsigned)OpKind)) 430*0fca6ea1SDimitry Andric return false; 431*0fca6ea1SDimitry Andric } 432*0fca6ea1SDimitry Andric 433*0fca6ea1SDimitry Andric return true; 434*0fca6ea1SDimitry Andric } 435*0fca6ea1SDimitry Andric 436*0fca6ea1SDimitry Andric const PatFrag *PatternParser::parsePatFrag(const Record *Def) { 437*0fca6ea1SDimitry Andric // Cache already parsed PatFrags to avoid doing extra work. 438*0fca6ea1SDimitry Andric static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags; 439*0fca6ea1SDimitry Andric 440*0fca6ea1SDimitry Andric auto It = ParsedPatFrags.find(Def); 441*0fca6ea1SDimitry Andric if (It != ParsedPatFrags.end()) { 442*0fca6ea1SDimitry Andric SeenPatFrags.insert(It->second.get()); 443*0fca6ea1SDimitry Andric return It->second.get(); 444*0fca6ea1SDimitry Andric } 445*0fca6ea1SDimitry Andric 446*0fca6ea1SDimitry Andric std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def); 447*0fca6ea1SDimitry Andric if (!NewPatFrag) { 448*0fca6ea1SDimitry Andric PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" + 449*0fca6ea1SDimitry Andric Def->getName() + "'"); 450*0fca6ea1SDimitry Andric // Put a nullptr in the map so we don't attempt parsing this again. 451*0fca6ea1SDimitry Andric ParsedPatFrags[Def] = nullptr; 452*0fca6ea1SDimitry Andric return nullptr; 453*0fca6ea1SDimitry Andric } 454*0fca6ea1SDimitry Andric 455*0fca6ea1SDimitry Andric const auto *Res = NewPatFrag.get(); 456*0fca6ea1SDimitry Andric ParsedPatFrags[Def] = std::move(NewPatFrag); 457*0fca6ea1SDimitry Andric SeenPatFrags.insert(Res); 458*0fca6ea1SDimitry Andric return Res; 459*0fca6ea1SDimitry Andric } 460*0fca6ea1SDimitry Andric 461*0fca6ea1SDimitry Andric } // namespace gi 462*0fca6ea1SDimitry Andric } // namespace llvm 463