xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/PredicateExpander.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===--------------------- PredicateExpander.cpp --------------------------===//
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 /// \file
9*0fca6ea1SDimitry Andric /// Functionalities used by the Tablegen backends to expand machine predicates.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "PredicateExpander.h"
14*0fca6ea1SDimitry Andric #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h"
16*0fca6ea1SDimitry Andric 
17*0fca6ea1SDimitry Andric namespace llvm {
18*0fca6ea1SDimitry Andric 
19*0fca6ea1SDimitry Andric void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20*0fca6ea1SDimitry Andric void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21*0fca6ea1SDimitry Andric 
22*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
23*0fca6ea1SDimitry Andric                                               int ImmVal,
24*0fca6ea1SDimitry Andric                                               StringRef FunctionMapper) {
25*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
26*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
27*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28*0fca6ea1SDimitry Andric      << ").getImm()";
29*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
30*0fca6ea1SDimitry Andric     OS << ")";
31*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
32*0fca6ea1SDimitry Andric }
33*0fca6ea1SDimitry Andric 
34*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35*0fca6ea1SDimitry Andric                                               StringRef ImmVal,
36*0fca6ea1SDimitry Andric                                               StringRef FunctionMapper) {
37*0fca6ea1SDimitry Andric   if (ImmVal.empty())
38*0fca6ea1SDimitry Andric     expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
41*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
42*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43*0fca6ea1SDimitry Andric      << ").getImm()";
44*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
45*0fca6ea1SDimitry Andric     OS << ")";
46*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
47*0fca6ea1SDimitry Andric }
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
50*0fca6ea1SDimitry Andric                                                     int OpIndex,
51*0fca6ea1SDimitry Andric                                                     StringRef FunctionMapper) {
52*0fca6ea1SDimitry Andric   if (shouldNegate())
53*0fca6ea1SDimitry Andric     OS << "!";
54*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
55*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
56*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57*0fca6ea1SDimitry Andric      << ").getImm()";
58*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
59*0fca6ea1SDimitry Andric     OS << ")";
60*0fca6ea1SDimitry Andric }
61*0fca6ea1SDimitry Andric 
62*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
63*0fca6ea1SDimitry Andric                                                 int ImmVal,
64*0fca6ea1SDimitry Andric                                                 StringRef FunctionMapper) {
65*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
66*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
67*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
68*0fca6ea1SDimitry Andric      << ").getImm()";
69*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
70*0fca6ea1SDimitry Andric     OS << ")";
71*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
72*0fca6ea1SDimitry Andric }
73*0fca6ea1SDimitry Andric 
74*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
75*0fca6ea1SDimitry Andric                                                 int ImmVal,
76*0fca6ea1SDimitry Andric                                                 StringRef FunctionMapper) {
77*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
78*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
79*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
80*0fca6ea1SDimitry Andric      << ").getImm()";
81*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
82*0fca6ea1SDimitry Andric     OS << ")";
83*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
84*0fca6ea1SDimitry Andric }
85*0fca6ea1SDimitry Andric 
86*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
87*0fca6ea1SDimitry Andric                                               const Record *Reg,
88*0fca6ea1SDimitry Andric                                               StringRef FunctionMapper) {
89*0fca6ea1SDimitry Andric   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
90*0fca6ea1SDimitry Andric 
91*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
92*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
93*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
94*0fca6ea1SDimitry Andric      << ").getReg()";
95*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
96*0fca6ea1SDimitry Andric     OS << ")";
97*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? " != " : " == ");
98*0fca6ea1SDimitry Andric   const StringRef Str = Reg->getValueAsString("Namespace");
99*0fca6ea1SDimitry Andric   if (!Str.empty())
100*0fca6ea1SDimitry Andric     OS << Str << "::";
101*0fca6ea1SDimitry Andric   OS << Reg->getName();
102*0fca6ea1SDimitry Andric }
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
105*0fca6ea1SDimitry Andric                                                     int OpIndex,
106*0fca6ea1SDimitry Andric                                                     StringRef FunctionMapper) {
107*0fca6ea1SDimitry Andric   if (shouldNegate())
108*0fca6ea1SDimitry Andric     OS << "!";
109*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
110*0fca6ea1SDimitry Andric     OS << FunctionMapper << "(";
111*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
112*0fca6ea1SDimitry Andric      << ").getReg()";
113*0fca6ea1SDimitry Andric   if (!FunctionMapper.empty())
114*0fca6ea1SDimitry Andric     OS << ")";
115*0fca6ea1SDimitry Andric }
116*0fca6ea1SDimitry Andric 
117*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
118*0fca6ea1SDimitry Andric                                                      int OpIndex) {
119*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
120*0fca6ea1SDimitry Andric      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
121*0fca6ea1SDimitry Andric }
122*0fca6ea1SDimitry Andric 
123*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
124*0fca6ea1SDimitry Andric                                                   int Second) {
125*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
126*0fca6ea1SDimitry Andric      << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
127*0fca6ea1SDimitry Andric      << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
128*0fca6ea1SDimitry Andric }
129*0fca6ea1SDimitry Andric 
130*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
131*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
132*0fca6ea1SDimitry Andric      << (shouldNegate() ? "!= " : "== ") << NumOps;
133*0fca6ea1SDimitry Andric }
134*0fca6ea1SDimitry Andric 
135*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
136*0fca6ea1SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
137*0fca6ea1SDimitry Andric      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
138*0fca6ea1SDimitry Andric      << "::" << Inst->getName();
139*0fca6ea1SDimitry Andric }
140*0fca6ea1SDimitry Andric 
141*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
142*0fca6ea1SDimitry Andric                                           const RecVec &Opcodes) {
143*0fca6ea1SDimitry Andric   assert(!Opcodes.empty() && "Expected at least one opcode to check!");
144*0fca6ea1SDimitry Andric   bool First = true;
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric   if (Opcodes.size() == 1) {
147*0fca6ea1SDimitry Andric     OS << "( ";
148*0fca6ea1SDimitry Andric     expandCheckOpcode(OS, Opcodes[0]);
149*0fca6ea1SDimitry Andric     OS << " )";
150*0fca6ea1SDimitry Andric     return;
151*0fca6ea1SDimitry Andric   }
152*0fca6ea1SDimitry Andric 
153*0fca6ea1SDimitry Andric   OS << '(';
154*0fca6ea1SDimitry Andric   increaseIndentLevel();
155*0fca6ea1SDimitry Andric   for (const Record *Rec : Opcodes) {
156*0fca6ea1SDimitry Andric     OS << '\n';
157*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
158*0fca6ea1SDimitry Andric     if (!First)
159*0fca6ea1SDimitry Andric       OS << (shouldNegate() ? "&& " : "|| ");
160*0fca6ea1SDimitry Andric 
161*0fca6ea1SDimitry Andric     expandCheckOpcode(OS, Rec);
162*0fca6ea1SDimitry Andric     First = false;
163*0fca6ea1SDimitry Andric   }
164*0fca6ea1SDimitry Andric 
165*0fca6ea1SDimitry Andric   OS << '\n';
166*0fca6ea1SDimitry Andric   decreaseIndentLevel();
167*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
168*0fca6ea1SDimitry Andric   OS << ')';
169*0fca6ea1SDimitry Andric }
170*0fca6ea1SDimitry Andric 
171*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
172*0fca6ea1SDimitry Andric                                           const RecVec &Opcodes) {
173*0fca6ea1SDimitry Andric   if (shouldExpandForMC())
174*0fca6ea1SDimitry Andric     expandFalse(OS);
175*0fca6ea1SDimitry Andric   else
176*0fca6ea1SDimitry Andric     expandCheckOpcode(OS, Opcodes);
177*0fca6ea1SDimitry Andric }
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
180*0fca6ea1SDimitry Andric                                                 const RecVec &Sequence,
181*0fca6ea1SDimitry Andric                                                 bool IsCheckAll) {
182*0fca6ea1SDimitry Andric   assert(!Sequence.empty() && "Found an invalid empty predicate set!");
183*0fca6ea1SDimitry Andric   if (Sequence.size() == 1)
184*0fca6ea1SDimitry Andric     return expandPredicate(OS, Sequence[0]);
185*0fca6ea1SDimitry Andric 
186*0fca6ea1SDimitry Andric   // Okay, there is more than one predicate in the set.
187*0fca6ea1SDimitry Andric   bool First = true;
188*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? "!(" : "(");
189*0fca6ea1SDimitry Andric   increaseIndentLevel();
190*0fca6ea1SDimitry Andric 
191*0fca6ea1SDimitry Andric   bool OldValue = shouldNegate();
192*0fca6ea1SDimitry Andric   setNegatePredicate(false);
193*0fca6ea1SDimitry Andric   for (const Record *Rec : Sequence) {
194*0fca6ea1SDimitry Andric     OS << '\n';
195*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
196*0fca6ea1SDimitry Andric     if (!First)
197*0fca6ea1SDimitry Andric       OS << (IsCheckAll ? "&& " : "|| ");
198*0fca6ea1SDimitry Andric     expandPredicate(OS, Rec);
199*0fca6ea1SDimitry Andric     First = false;
200*0fca6ea1SDimitry Andric   }
201*0fca6ea1SDimitry Andric   OS << '\n';
202*0fca6ea1SDimitry Andric   decreaseIndentLevel();
203*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
204*0fca6ea1SDimitry Andric   OS << ')';
205*0fca6ea1SDimitry Andric   setNegatePredicate(OldValue);
206*0fca6ea1SDimitry Andric }
207*0fca6ea1SDimitry Andric 
208*0fca6ea1SDimitry Andric void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
209*0fca6ea1SDimitry Andric                                               StringRef MethodName) {
210*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? "!" : "");
211*0fca6ea1SDimitry Andric   OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
212*0fca6ea1SDimitry Andric   OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
213*0fca6ea1SDimitry Andric }
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
216*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
217*0fca6ea1SDimitry Andric      << "getOperand(" << OpIndex << ").isReg() ";
218*0fca6ea1SDimitry Andric }
219*0fca6ea1SDimitry Andric 
220*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
221*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
222*0fca6ea1SDimitry Andric      << "getOperand(" << OpIndex << ").getReg().isVirtual()";
223*0fca6ea1SDimitry Andric }
224*0fca6ea1SDimitry Andric 
225*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
226*0fca6ea1SDimitry Andric   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
227*0fca6ea1SDimitry Andric      << "getOperand(" << OpIndex << ").isImm() ";
228*0fca6ea1SDimitry Andric }
229*0fca6ea1SDimitry Andric 
230*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckFunctionPredicateWithTII(
231*0fca6ea1SDimitry Andric     raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
232*0fca6ea1SDimitry Andric     StringRef TIIPtr) {
233*0fca6ea1SDimitry Andric   if (!shouldExpandForMC()) {
234*0fca6ea1SDimitry Andric     OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
235*0fca6ea1SDimitry Andric     OS << (isByRef() ? "(MI)" : "(*MI)");
236*0fca6ea1SDimitry Andric     return;
237*0fca6ea1SDimitry Andric   }
238*0fca6ea1SDimitry Andric 
239*0fca6ea1SDimitry Andric   OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
240*0fca6ea1SDimitry Andric }
241*0fca6ea1SDimitry Andric 
242*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
243*0fca6ea1SDimitry Andric                                                      StringRef MCInstFn,
244*0fca6ea1SDimitry Andric                                                      StringRef MachineInstrFn) {
245*0fca6ea1SDimitry Andric   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
246*0fca6ea1SDimitry Andric      << (isByRef() ? "(MI)" : "(*MI)");
247*0fca6ea1SDimitry Andric }
248*0fca6ea1SDimitry Andric 
249*0fca6ea1SDimitry Andric void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
250*0fca6ea1SDimitry Andric                                                StringRef Code) {
251*0fca6ea1SDimitry Andric   if (shouldExpandForMC())
252*0fca6ea1SDimitry Andric     return expandFalse(OS);
253*0fca6ea1SDimitry Andric 
254*0fca6ea1SDimitry Andric   OS << '(' << Code << ')';
255*0fca6ea1SDimitry Andric }
256*0fca6ea1SDimitry Andric 
257*0fca6ea1SDimitry Andric void PredicateExpander::expandReturnStatement(raw_ostream &OS,
258*0fca6ea1SDimitry Andric                                               const Record *Rec) {
259*0fca6ea1SDimitry Andric   std::string Buffer;
260*0fca6ea1SDimitry Andric   raw_string_ostream SS(Buffer);
261*0fca6ea1SDimitry Andric 
262*0fca6ea1SDimitry Andric   SS << "return ";
263*0fca6ea1SDimitry Andric   expandPredicate(SS, Rec);
264*0fca6ea1SDimitry Andric   SS << ";";
265*0fca6ea1SDimitry Andric   OS << Buffer;
266*0fca6ea1SDimitry Andric }
267*0fca6ea1SDimitry Andric 
268*0fca6ea1SDimitry Andric void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
269*0fca6ea1SDimitry Andric                                                const Record *Rec) {
270*0fca6ea1SDimitry Andric   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
271*0fca6ea1SDimitry Andric   for (const Record *Opcode : Opcodes) {
272*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
273*0fca6ea1SDimitry Andric     OS << "case " << Opcode->getValueAsString("Namespace")
274*0fca6ea1SDimitry Andric        << "::" << Opcode->getName() << ":\n";
275*0fca6ea1SDimitry Andric   }
276*0fca6ea1SDimitry Andric 
277*0fca6ea1SDimitry Andric   increaseIndentLevel();
278*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
279*0fca6ea1SDimitry Andric   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
280*0fca6ea1SDimitry Andric   decreaseIndentLevel();
281*0fca6ea1SDimitry Andric }
282*0fca6ea1SDimitry Andric 
283*0fca6ea1SDimitry Andric void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
284*0fca6ea1SDimitry Andric                                                     const RecVec &Cases,
285*0fca6ea1SDimitry Andric                                                     const Record *Default) {
286*0fca6ea1SDimitry Andric   std::string Buffer;
287*0fca6ea1SDimitry Andric   raw_string_ostream SS(Buffer);
288*0fca6ea1SDimitry Andric 
289*0fca6ea1SDimitry Andric   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
290*0fca6ea1SDimitry Andric   for (const Record *Rec : Cases) {
291*0fca6ea1SDimitry Andric     expandOpcodeSwitchCase(SS, Rec);
292*0fca6ea1SDimitry Andric     SS << '\n';
293*0fca6ea1SDimitry Andric   }
294*0fca6ea1SDimitry Andric 
295*0fca6ea1SDimitry Andric   // Expand the default case.
296*0fca6ea1SDimitry Andric   SS.indent(getIndentLevel() * 2);
297*0fca6ea1SDimitry Andric   SS << "default:\n";
298*0fca6ea1SDimitry Andric 
299*0fca6ea1SDimitry Andric   increaseIndentLevel();
300*0fca6ea1SDimitry Andric   SS.indent(getIndentLevel() * 2);
301*0fca6ea1SDimitry Andric   expandStatement(SS, Default);
302*0fca6ea1SDimitry Andric   decreaseIndentLevel();
303*0fca6ea1SDimitry Andric   SS << '\n';
304*0fca6ea1SDimitry Andric 
305*0fca6ea1SDimitry Andric   SS.indent(getIndentLevel() * 2);
306*0fca6ea1SDimitry Andric   SS << "} // end of switch-stmt";
307*0fca6ea1SDimitry Andric   OS << Buffer;
308*0fca6ea1SDimitry Andric }
309*0fca6ea1SDimitry Andric 
310*0fca6ea1SDimitry Andric void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
311*0fca6ea1SDimitry Andric   // Assume that padding has been added by the caller.
312*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
313*0fca6ea1SDimitry Andric     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
314*0fca6ea1SDimitry Andric                                 Rec->getValueAsDef("DefaultCase"));
315*0fca6ea1SDimitry Andric     return;
316*0fca6ea1SDimitry Andric   }
317*0fca6ea1SDimitry Andric 
318*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("MCReturnStatement")) {
319*0fca6ea1SDimitry Andric     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
320*0fca6ea1SDimitry Andric     return;
321*0fca6ea1SDimitry Andric   }
322*0fca6ea1SDimitry Andric 
323*0fca6ea1SDimitry Andric   llvm_unreachable("No known rules to expand this MCStatement");
324*0fca6ea1SDimitry Andric }
325*0fca6ea1SDimitry Andric 
326*0fca6ea1SDimitry Andric void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
327*0fca6ea1SDimitry Andric   // Assume that padding has been added by the caller.
328*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("MCTrue")) {
329*0fca6ea1SDimitry Andric     if (shouldNegate())
330*0fca6ea1SDimitry Andric       return expandFalse(OS);
331*0fca6ea1SDimitry Andric     return expandTrue(OS);
332*0fca6ea1SDimitry Andric   }
333*0fca6ea1SDimitry Andric 
334*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("MCFalse")) {
335*0fca6ea1SDimitry Andric     if (shouldNegate())
336*0fca6ea1SDimitry Andric       return expandTrue(OS);
337*0fca6ea1SDimitry Andric     return expandFalse(OS);
338*0fca6ea1SDimitry Andric   }
339*0fca6ea1SDimitry Andric 
340*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckNot")) {
341*0fca6ea1SDimitry Andric     flipNegatePredicate();
342*0fca6ea1SDimitry Andric     expandPredicate(OS, Rec->getValueAsDef("Pred"));
343*0fca6ea1SDimitry Andric     flipNegatePredicate();
344*0fca6ea1SDimitry Andric     return;
345*0fca6ea1SDimitry Andric   }
346*0fca6ea1SDimitry Andric 
347*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckIsRegOperand"))
348*0fca6ea1SDimitry Andric     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
349*0fca6ea1SDimitry Andric 
350*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckIsVRegOperand"))
351*0fca6ea1SDimitry Andric     return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));
352*0fca6ea1SDimitry Andric 
353*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckIsImmOperand"))
354*0fca6ea1SDimitry Andric     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
355*0fca6ea1SDimitry Andric 
356*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckRegOperand"))
357*0fca6ea1SDimitry Andric     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
358*0fca6ea1SDimitry Andric                                  Rec->getValueAsDef("Reg"),
359*0fca6ea1SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
360*0fca6ea1SDimitry Andric 
361*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckRegOperandSimple"))
362*0fca6ea1SDimitry Andric     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
363*0fca6ea1SDimitry Andric                                        Rec->getValueAsString("FunctionMapper"));
364*0fca6ea1SDimitry Andric 
365*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
366*0fca6ea1SDimitry Andric     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
367*0fca6ea1SDimitry Andric 
368*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperand"))
369*0fca6ea1SDimitry Andric     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
370*0fca6ea1SDimitry Andric                                  Rec->getValueAsInt("ImmVal"),
371*0fca6ea1SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
372*0fca6ea1SDimitry Andric 
373*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperand_s"))
374*0fca6ea1SDimitry Andric     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
375*0fca6ea1SDimitry Andric                                  Rec->getValueAsString("ImmVal"),
376*0fca6ea1SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
377*0fca6ea1SDimitry Andric 
378*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperandLT"))
379*0fca6ea1SDimitry Andric     return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),
380*0fca6ea1SDimitry Andric                                    Rec->getValueAsInt("ImmVal"),
381*0fca6ea1SDimitry Andric                                    Rec->getValueAsString("FunctionMapper"));
382*0fca6ea1SDimitry Andric 
383*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperandGT"))
384*0fca6ea1SDimitry Andric     return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),
385*0fca6ea1SDimitry Andric                                    Rec->getValueAsInt("ImmVal"),
386*0fca6ea1SDimitry Andric                                    Rec->getValueAsString("FunctionMapper"));
387*0fca6ea1SDimitry Andric 
388*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperandSimple"))
389*0fca6ea1SDimitry Andric     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
390*0fca6ea1SDimitry Andric                                        Rec->getValueAsString("FunctionMapper"));
391*0fca6ea1SDimitry Andric 
392*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckSameRegOperand"))
393*0fca6ea1SDimitry Andric     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
394*0fca6ea1SDimitry Andric                                      Rec->getValueAsInt("SecondIndex"));
395*0fca6ea1SDimitry Andric 
396*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckNumOperands"))
397*0fca6ea1SDimitry Andric     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
398*0fca6ea1SDimitry Andric 
399*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckPseudo"))
400*0fca6ea1SDimitry Andric     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
401*0fca6ea1SDimitry Andric 
402*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckOpcode"))
403*0fca6ea1SDimitry Andric     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
404*0fca6ea1SDimitry Andric 
405*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckAll"))
406*0fca6ea1SDimitry Andric     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
407*0fca6ea1SDimitry Andric                                    /* AllOf */ true);
408*0fca6ea1SDimitry Andric 
409*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckAny"))
410*0fca6ea1SDimitry Andric     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
411*0fca6ea1SDimitry Andric                                    /* AllOf */ false);
412*0fca6ea1SDimitry Andric 
413*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckFunctionPredicate")) {
414*0fca6ea1SDimitry Andric     return expandCheckFunctionPredicate(
415*0fca6ea1SDimitry Andric         OS, Rec->getValueAsString("MCInstFnName"),
416*0fca6ea1SDimitry Andric         Rec->getValueAsString("MachineInstrFnName"));
417*0fca6ea1SDimitry Andric   }
418*0fca6ea1SDimitry Andric 
419*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
420*0fca6ea1SDimitry Andric     return expandCheckFunctionPredicateWithTII(
421*0fca6ea1SDimitry Andric         OS, Rec->getValueAsString("MCInstFnName"),
422*0fca6ea1SDimitry Andric         Rec->getValueAsString("MachineInstrFnName"),
423*0fca6ea1SDimitry Andric         Rec->getValueAsString("TIIPtrName"));
424*0fca6ea1SDimitry Andric   }
425*0fca6ea1SDimitry Andric 
426*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("CheckNonPortable"))
427*0fca6ea1SDimitry Andric     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
428*0fca6ea1SDimitry Andric 
429*0fca6ea1SDimitry Andric   if (Rec->isSubClassOf("TIIPredicate"))
430*0fca6ea1SDimitry Andric     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
431*0fca6ea1SDimitry Andric 
432*0fca6ea1SDimitry Andric   llvm_unreachable("No known rules to expand this MCInstPredicate");
433*0fca6ea1SDimitry Andric }
434*0fca6ea1SDimitry Andric 
435*0fca6ea1SDimitry Andric void STIPredicateExpander::expandHeader(raw_ostream &OS,
436*0fca6ea1SDimitry Andric                                         const STIPredicateFunction &Fn) {
437*0fca6ea1SDimitry Andric   const Record *Rec = Fn.getDeclaration();
438*0fca6ea1SDimitry Andric   StringRef FunctionName = Rec->getValueAsString("Name");
439*0fca6ea1SDimitry Andric 
440*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
441*0fca6ea1SDimitry Andric   OS << "bool ";
442*0fca6ea1SDimitry Andric   if (shouldExpandDefinition())
443*0fca6ea1SDimitry Andric     OS << getClassPrefix() << "::";
444*0fca6ea1SDimitry Andric   OS << FunctionName << "(";
445*0fca6ea1SDimitry Andric   if (shouldExpandForMC())
446*0fca6ea1SDimitry Andric     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
447*0fca6ea1SDimitry Andric   else
448*0fca6ea1SDimitry Andric     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
449*0fca6ea1SDimitry Andric   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
450*0fca6ea1SDimitry Andric     OS << ", APInt &Mask";
451*0fca6ea1SDimitry Andric   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
452*0fca6ea1SDimitry Andric   if (shouldExpandDefinition()) {
453*0fca6ea1SDimitry Andric     OS << "{\n";
454*0fca6ea1SDimitry Andric     return;
455*0fca6ea1SDimitry Andric   }
456*0fca6ea1SDimitry Andric 
457*0fca6ea1SDimitry Andric   if (Rec->getValueAsBit("OverridesBaseClassMember"))
458*0fca6ea1SDimitry Andric     OS << "override";
459*0fca6ea1SDimitry Andric   OS << ";\n";
460*0fca6ea1SDimitry Andric }
461*0fca6ea1SDimitry Andric 
462*0fca6ea1SDimitry Andric void STIPredicateExpander::expandPrologue(raw_ostream &OS,
463*0fca6ea1SDimitry Andric                                           const STIPredicateFunction &Fn) {
464*0fca6ea1SDimitry Andric   RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
465*0fca6ea1SDimitry Andric   bool UpdatesOpcodeMask =
466*0fca6ea1SDimitry Andric       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
467*0fca6ea1SDimitry Andric 
468*0fca6ea1SDimitry Andric   increaseIndentLevel();
469*0fca6ea1SDimitry Andric   unsigned IndentLevel = getIndentLevel();
470*0fca6ea1SDimitry Andric   for (const Record *Delegate : Delegates) {
471*0fca6ea1SDimitry Andric     OS.indent(IndentLevel * 2);
472*0fca6ea1SDimitry Andric     OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
473*0fca6ea1SDimitry Andric     if (UpdatesOpcodeMask)
474*0fca6ea1SDimitry Andric       OS << ", Mask";
475*0fca6ea1SDimitry Andric     if (shouldExpandForMC())
476*0fca6ea1SDimitry Andric       OS << ", ProcessorID";
477*0fca6ea1SDimitry Andric     OS << "))\n";
478*0fca6ea1SDimitry Andric     OS.indent((1 + IndentLevel) * 2);
479*0fca6ea1SDimitry Andric     OS << "return true;\n\n";
480*0fca6ea1SDimitry Andric   }
481*0fca6ea1SDimitry Andric 
482*0fca6ea1SDimitry Andric   if (shouldExpandForMC())
483*0fca6ea1SDimitry Andric     return;
484*0fca6ea1SDimitry Andric 
485*0fca6ea1SDimitry Andric   OS.indent(IndentLevel * 2);
486*0fca6ea1SDimitry Andric   OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
487*0fca6ea1SDimitry Andric }
488*0fca6ea1SDimitry Andric 
489*0fca6ea1SDimitry Andric void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,
490*0fca6ea1SDimitry Andric                                              const OpcodeGroup &Group,
491*0fca6ea1SDimitry Andric                                              bool ShouldUpdateOpcodeMask) {
492*0fca6ea1SDimitry Andric   const OpcodeInfo &OI = Group.getOpcodeInfo();
493*0fca6ea1SDimitry Andric   for (const PredicateInfo &PI : OI.getPredicates()) {
494*0fca6ea1SDimitry Andric     const APInt &ProcModelMask = PI.ProcModelMask;
495*0fca6ea1SDimitry Andric     bool FirstProcID = true;
496*0fca6ea1SDimitry Andric     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
497*0fca6ea1SDimitry Andric       if (!ProcModelMask[I])
498*0fca6ea1SDimitry Andric         continue;
499*0fca6ea1SDimitry Andric 
500*0fca6ea1SDimitry Andric       if (FirstProcID) {
501*0fca6ea1SDimitry Andric         OS.indent(getIndentLevel() * 2);
502*0fca6ea1SDimitry Andric         OS << "if (ProcessorID == " << I;
503*0fca6ea1SDimitry Andric       } else {
504*0fca6ea1SDimitry Andric         OS << " || ProcessorID == " << I;
505*0fca6ea1SDimitry Andric       }
506*0fca6ea1SDimitry Andric       FirstProcID = false;
507*0fca6ea1SDimitry Andric     }
508*0fca6ea1SDimitry Andric 
509*0fca6ea1SDimitry Andric     OS << ") {\n";
510*0fca6ea1SDimitry Andric 
511*0fca6ea1SDimitry Andric     increaseIndentLevel();
512*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
513*0fca6ea1SDimitry Andric     if (ShouldUpdateOpcodeMask) {
514*0fca6ea1SDimitry Andric       if (PI.OperandMask.isZero())
515*0fca6ea1SDimitry Andric         OS << "Mask.clearAllBits();\n";
516*0fca6ea1SDimitry Andric       else
517*0fca6ea1SDimitry Andric         OS << "Mask = " << PI.OperandMask << ";\n";
518*0fca6ea1SDimitry Andric       OS.indent(getIndentLevel() * 2);
519*0fca6ea1SDimitry Andric     }
520*0fca6ea1SDimitry Andric     OS << "return ";
521*0fca6ea1SDimitry Andric     expandPredicate(OS, PI.Predicate);
522*0fca6ea1SDimitry Andric     OS << ";\n";
523*0fca6ea1SDimitry Andric     decreaseIndentLevel();
524*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
525*0fca6ea1SDimitry Andric     OS << "}\n";
526*0fca6ea1SDimitry Andric   }
527*0fca6ea1SDimitry Andric }
528*0fca6ea1SDimitry Andric 
529*0fca6ea1SDimitry Andric void STIPredicateExpander::expandBody(raw_ostream &OS,
530*0fca6ea1SDimitry Andric                                       const STIPredicateFunction &Fn) {
531*0fca6ea1SDimitry Andric   bool UpdatesOpcodeMask =
532*0fca6ea1SDimitry Andric       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
533*0fca6ea1SDimitry Andric 
534*0fca6ea1SDimitry Andric   unsigned IndentLevel = getIndentLevel();
535*0fca6ea1SDimitry Andric   OS.indent(IndentLevel * 2);
536*0fca6ea1SDimitry Andric   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
537*0fca6ea1SDimitry Andric   OS.indent(IndentLevel * 2);
538*0fca6ea1SDimitry Andric   OS << "default:\n";
539*0fca6ea1SDimitry Andric   OS.indent(IndentLevel * 2);
540*0fca6ea1SDimitry Andric   OS << "  break;";
541*0fca6ea1SDimitry Andric 
542*0fca6ea1SDimitry Andric   for (const OpcodeGroup &Group : Fn.getGroups()) {
543*0fca6ea1SDimitry Andric     for (const Record *Opcode : Group.getOpcodes()) {
544*0fca6ea1SDimitry Andric       OS << '\n';
545*0fca6ea1SDimitry Andric       OS.indent(IndentLevel * 2);
546*0fca6ea1SDimitry Andric       OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
547*0fca6ea1SDimitry Andric     }
548*0fca6ea1SDimitry Andric 
549*0fca6ea1SDimitry Andric     OS << '\n';
550*0fca6ea1SDimitry Andric     increaseIndentLevel();
551*0fca6ea1SDimitry Andric     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
552*0fca6ea1SDimitry Andric 
553*0fca6ea1SDimitry Andric     OS.indent(getIndentLevel() * 2);
554*0fca6ea1SDimitry Andric     OS << "break;\n";
555*0fca6ea1SDimitry Andric     decreaseIndentLevel();
556*0fca6ea1SDimitry Andric   }
557*0fca6ea1SDimitry Andric 
558*0fca6ea1SDimitry Andric   OS.indent(IndentLevel * 2);
559*0fca6ea1SDimitry Andric   OS << "}\n";
560*0fca6ea1SDimitry Andric }
561*0fca6ea1SDimitry Andric 
562*0fca6ea1SDimitry Andric void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
563*0fca6ea1SDimitry Andric                                           const STIPredicateFunction &Fn) {
564*0fca6ea1SDimitry Andric   OS << '\n';
565*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
566*0fca6ea1SDimitry Andric   OS << "return ";
567*0fca6ea1SDimitry Andric   expandPredicate(OS, Fn.getDefaultReturnPredicate());
568*0fca6ea1SDimitry Andric   OS << ";\n";
569*0fca6ea1SDimitry Andric 
570*0fca6ea1SDimitry Andric   decreaseIndentLevel();
571*0fca6ea1SDimitry Andric   OS.indent(getIndentLevel() * 2);
572*0fca6ea1SDimitry Andric   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
573*0fca6ea1SDimitry Andric   OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
574*0fca6ea1SDimitry Andric }
575*0fca6ea1SDimitry Andric 
576*0fca6ea1SDimitry Andric void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
577*0fca6ea1SDimitry Andric                                               const STIPredicateFunction &Fn) {
578*0fca6ea1SDimitry Andric   const Record *Rec = Fn.getDeclaration();
579*0fca6ea1SDimitry Andric   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
580*0fca6ea1SDimitry Andric     return;
581*0fca6ea1SDimitry Andric 
582*0fca6ea1SDimitry Andric   expandHeader(OS, Fn);
583*0fca6ea1SDimitry Andric   if (shouldExpandDefinition()) {
584*0fca6ea1SDimitry Andric     expandPrologue(OS, Fn);
585*0fca6ea1SDimitry Andric     expandBody(OS, Fn);
586*0fca6ea1SDimitry Andric     expandEpilogue(OS, Fn);
587*0fca6ea1SDimitry Andric   }
588*0fca6ea1SDimitry Andric }
589*0fca6ea1SDimitry Andric 
590*0fca6ea1SDimitry Andric } // namespace llvm
591