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