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