1 //===--------------------- PredicateExpander.cpp --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// Functionalities used by the Tablegen backends to expand machine predicates.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "PredicateExpander.h"
15 
16 namespace llvm {
17 
18 void PredicateExpander::expandTrue(formatted_raw_ostream &OS) { OS << "true"; }
19 void PredicateExpander::expandFalse(formatted_raw_ostream &OS) {
20   OS << "false";
21 }
22 
23 void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS,
24                                               int OpIndex, int ImmVal) {
25   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
26      << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal;
27 }
28 
29 void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS,
30                                               int OpIndex, StringRef ImmVal) {
31   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
32      << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal;
33 }
34 
35 void PredicateExpander::expandCheckRegOperand(formatted_raw_ostream &OS,
36                                               int OpIndex, const Record *Reg) {
37   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
38 
39   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
40      << ").getReg() " << (shouldNegate() ? "!= " : "== ");
41   const StringRef Str = Reg->getValueAsString("Namespace");
42   if (!Str.empty())
43     OS << Str << "::";
44   OS << Reg->getName();
45 }
46 
47 void PredicateExpander::expandCheckInvalidRegOperand(formatted_raw_ostream &OS,
48                                                      int OpIndex) {
49   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
50      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
51 }
52 
53 void PredicateExpander::expandCheckSameRegOperand(formatted_raw_ostream &OS,
54                                                   int First, int Second) {
55   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
56      << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
57      << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
58 }
59 
60 void PredicateExpander::expandCheckNumOperands(formatted_raw_ostream &OS,
61                                                int NumOps) {
62   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
63      << (shouldNegate() ? "!= " : "== ") << NumOps;
64 }
65 
66 void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS,
67                                           const Record *Inst) {
68   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
69      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
70      << "::" << Inst->getName();
71 }
72 
73 void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS,
74                                           const RecVec &Opcodes) {
75   assert(!Opcodes.empty() && "Expected at least one opcode to check!");
76   bool First = true;
77 
78   if (Opcodes.size() == 1) {
79     OS << "( ";
80     expandCheckOpcode(OS, Opcodes[0]);
81     OS << " )";
82     return;
83   }
84 
85   OS << '(';
86   increaseIndentLevel();
87   for (const Record *Rec : Opcodes) {
88     OS << '\n';
89     OS.PadToColumn(getIndentLevel() * 2);
90     if (!First)
91       OS << (shouldNegate() ? "&& " : "|| ");
92 
93     expandCheckOpcode(OS, Rec);
94     First = false;
95   }
96 
97   OS << '\n';
98   decreaseIndentLevel();
99   OS.PadToColumn(getIndentLevel() * 2);
100   OS << ')';
101 }
102 
103 void PredicateExpander::expandCheckPseudo(formatted_raw_ostream &OS,
104                                           const RecVec &Opcodes) {
105   if (shouldExpandForMC())
106     expandFalse(OS);
107   else
108     expandCheckOpcode(OS, Opcodes);
109 }
110 
111 void PredicateExpander::expandPredicateSequence(formatted_raw_ostream &OS,
112                                                 const RecVec &Sequence,
113                                                 bool IsCheckAll) {
114   assert(!Sequence.empty() && "Found an invalid empty predicate set!");
115   if (Sequence.size() == 1)
116     return expandPredicate(OS, Sequence[0]);
117 
118   // Okay, there is more than one predicate in the set.
119   bool First = true;
120   OS << (shouldNegate() ? "!(" : "(");
121   increaseIndentLevel();
122 
123   bool OldValue = shouldNegate();
124   setNegatePredicate(false);
125   for (const Record *Rec : Sequence) {
126     OS << '\n';
127     OS.PadToColumn(getIndentLevel() * 2);
128     if (!First)
129       OS << (IsCheckAll ? "&& " : "|| ");
130     expandPredicate(OS, Rec);
131     First = false;
132   }
133   OS << '\n';
134   decreaseIndentLevel();
135   OS.PadToColumn(getIndentLevel() * 2);
136   OS << ')';
137   setNegatePredicate(OldValue);
138 }
139 
140 void PredicateExpander::expandTIIFunctionCall(formatted_raw_ostream &OS,
141                                               StringRef TargetName,
142                                               StringRef MethodName) {
143   OS << (shouldNegate() ? "!" : "");
144   if (shouldExpandForMC())
145     OS << TargetName << "_MC::";
146   else
147     OS << TargetName << "Gen"
148        << "InstrInfo::";
149   OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
150 }
151 
152 void PredicateExpander::expandCheckIsRegOperand(formatted_raw_ostream &OS,
153                                                 int OpIndex) {
154   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
155      << "getOperand(" << OpIndex << ").isReg() ";
156 }
157 
158 void PredicateExpander::expandCheckIsImmOperand(formatted_raw_ostream &OS,
159                                                 int OpIndex) {
160   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
161      << "getOperand(" << OpIndex << ").isImm() ";
162 }
163 
164 void PredicateExpander::expandCheckFunctionPredicate(formatted_raw_ostream &OS,
165                                                      StringRef MCInstFn,
166                                                      StringRef MachineInstrFn) {
167   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
168      << (isByRef() ? "(MI)" : "(*MI)");
169 }
170 
171 void PredicateExpander::expandCheckNonPortable(formatted_raw_ostream &OS,
172                                                StringRef Code) {
173   if (shouldExpandForMC())
174     return expandFalse(OS);
175 
176   OS << '(' << Code << ')';
177 }
178 
179 void PredicateExpander::expandReturnStatement(formatted_raw_ostream &OS,
180                                               const Record *Rec) {
181   OS << "return ";
182   expandPredicate(OS, Rec);
183   OS << ";";
184 }
185 
186 void PredicateExpander::expandOpcodeSwitchCase(formatted_raw_ostream &OS,
187                                                const Record *Rec) {
188   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
189   for (const Record *Opcode : Opcodes) {
190     OS.PadToColumn(getIndentLevel() * 2);
191     OS << "case " << Opcode->getValueAsString("Namespace")
192        << "::" << Opcode->getName() << " :\n";
193   }
194 
195   increaseIndentLevel();
196   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
197   decreaseIndentLevel();
198 }
199 
200 void PredicateExpander::expandOpcodeSwitchStatement(formatted_raw_ostream &OS,
201                                                     const RecVec &Cases,
202                                                     const Record *Default) {
203   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
204 
205   for (const Record *Rec : Cases) {
206     expandOpcodeSwitchCase(OS, Rec);
207     OS << '\n';
208   }
209 
210   unsigned ColNum = getIndentLevel() * 2;
211   OS.PadToColumn(ColNum);
212 
213   // Expand the default case.
214   OS << "default :\n";
215   increaseIndentLevel();
216   expandStatement(OS, Default);
217   decreaseIndentLevel();
218   OS << '\n';
219 
220   OS.PadToColumn(ColNum);
221   OS << "} // end of switch-stmt";
222 }
223 
224 void PredicateExpander::expandStatement(formatted_raw_ostream &OS,
225                                         const Record *Rec) {
226   OS.flush();
227   unsigned ColNum = getIndentLevel() * 2;
228   if (OS.getColumn() < ColNum)
229     OS.PadToColumn(ColNum);
230 
231   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
232     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
233                                 Rec->getValueAsDef("DefaultCase"));
234     return;
235   }
236 
237   if (Rec->isSubClassOf("MCReturnStatement")) {
238     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
239     return;
240   }
241 
242   llvm_unreachable("No known rules to expand this MCStatement");
243 }
244 
245 void PredicateExpander::expandPredicate(formatted_raw_ostream &OS,
246                                         const Record *Rec) {
247   OS.flush();
248   unsigned ColNum = getIndentLevel() * 2;
249   if (OS.getColumn() < ColNum)
250     OS.PadToColumn(ColNum);
251 
252   if (Rec->isSubClassOf("MCTrue")) {
253     if (shouldNegate())
254       return expandFalse(OS);
255     return expandTrue(OS);
256   }
257 
258   if (Rec->isSubClassOf("MCFalse")) {
259     if (shouldNegate())
260       return expandTrue(OS);
261     return expandFalse(OS);
262   }
263 
264   if (Rec->isSubClassOf("CheckNot")) {
265     flipNegatePredicate();
266     expandPredicate(OS, Rec->getValueAsDef("Pred"));
267     flipNegatePredicate();
268     return;
269   }
270 
271   if (Rec->isSubClassOf("CheckIsRegOperand"))
272     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
273 
274   if (Rec->isSubClassOf("CheckIsImmOperand"))
275     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
276 
277   if (Rec->isSubClassOf("CheckRegOperand"))
278     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
279                                  Rec->getValueAsDef("Reg"));
280 
281   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
282     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
283 
284   if (Rec->isSubClassOf("CheckImmOperand"))
285     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
286                                  Rec->getValueAsInt("ImmVal"));
287 
288   if (Rec->isSubClassOf("CheckImmOperand_s"))
289     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
290                                  Rec->getValueAsString("ImmVal"));
291 
292   if (Rec->isSubClassOf("CheckSameRegOperand"))
293     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
294                                      Rec->getValueAsInt("SecondIndex"));
295 
296   if (Rec->isSubClassOf("CheckNumOperands"))
297     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
298 
299   if (Rec->isSubClassOf("CheckPseudo"))
300     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
301 
302   if (Rec->isSubClassOf("CheckOpcode"))
303     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
304 
305   if (Rec->isSubClassOf("CheckAll"))
306     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
307                                    /* AllOf */ true);
308 
309   if (Rec->isSubClassOf("CheckAny"))
310     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
311                                    /* AllOf */ false);
312 
313   if (Rec->isSubClassOf("CheckFunctionPredicate"))
314     return expandCheckFunctionPredicate(
315         OS, Rec->getValueAsString("MCInstFnName"),
316         Rec->getValueAsString("MachineInstrFnName"));
317 
318   if (Rec->isSubClassOf("CheckNonPortable"))
319     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
320 
321   if (Rec->isSubClassOf("TIIPredicate"))
322     return expandTIIFunctionCall(OS, Rec->getValueAsString("TargetName"),
323                                  Rec->getValueAsString("FunctionName"));
324 
325   llvm_unreachable("No known rules to expand this MCInstPredicate");
326 }
327 
328 } // namespace llvm
329