xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
PrettyStackTraceParse(const Record & Def)29*0fca6ea1SDimitry Andric   PrettyStackTraceParse(const Record &Def) : Def(Def) {}
30*0fca6ea1SDimitry Andric 
print(raw_ostream & OS) const31*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 
parsePatternList(const DagInit & List,function_ref<bool (std::unique_ptr<Pattern>)> ParseAction,StringRef Operator,StringRef AnonPatNamePrefix)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 &
getInstrForIntrinsic(const CodeGenTarget & CGT,const CodeGenIntrinsic * I)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 
getCodeGenIntrinsic(Record * R)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>
parseInstructionPattern(const Init & Arg,StringRef Name)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>
parseWipMatchOpcodeMatcher(const Init & Arg,StringRef Name)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 
parseInstructionPatternOperand(InstructionPattern & IP,const Init * OpInit,const StringInit * OpName)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 
parseInstructionPatternMIFlags(InstructionPattern & IP,const DagInit * Op)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 
parsePatFragImpl(const Record * Def)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 
parsePatFragParamList(const DagInit & OpsList,function_ref<bool (StringRef,unsigned)> ParseAction)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 
parsePatFrag(const Record * Def)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