LLVM  9.0.0svn
MIRPrinter.cpp
Go to the documentation of this file.
1 //===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
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 //
9 // This file implements the class that prints out the LLVM IR and machine
10 // functions using the MIR serialization format.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/None.h"
17 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Twine.h"
39 #include "llvm/IR/BasicBlock.h"
40 #include "llvm/IR/Constants.h"
41 #include "llvm/IR/DebugInfo.h"
42 #include "llvm/IR/DebugLoc.h"
43 #include "llvm/IR/Function.h"
44 #include "llvm/IR/GlobalValue.h"
46 #include "llvm/IR/InstrTypes.h"
47 #include "llvm/IR/Instructions.h"
48 #include "llvm/IR/Intrinsics.h"
49 #include "llvm/IR/Module.h"
51 #include "llvm/IR/Value.h"
52 #include "llvm/MC/LaneBitmask.h"
53 #include "llvm/MC/MCContext.h"
54 #include "llvm/MC/MCDwarf.h"
55 #include "llvm/MC/MCSymbol.h"
58 #include "llvm/Support/Casting.h"
61 #include "llvm/Support/Format.h"
67 #include <algorithm>
68 #include <cassert>
69 #include <cinttypes>
70 #include <cstdint>
71 #include <iterator>
72 #include <string>
73 #include <utility>
74 #include <vector>
75 
76 using namespace llvm;
77 
79  "simplify-mir", cl::Hidden,
80  cl::desc("Leave out unnecessary information when printing MIR"));
81 
82 namespace {
83 
84 /// This structure describes how to print out stack object references.
85 struct FrameIndexOperand {
86  std::string Name;
87  unsigned ID;
88  bool IsFixed;
89 
90  FrameIndexOperand(StringRef Name, unsigned ID, bool IsFixed)
91  : Name(Name.str()), ID(ID), IsFixed(IsFixed) {}
92 
93  /// Return an ordinary stack object reference.
94  static FrameIndexOperand create(StringRef Name, unsigned ID) {
95  return FrameIndexOperand(Name, ID, /*IsFixed=*/false);
96  }
97 
98  /// Return a fixed stack object reference.
99  static FrameIndexOperand createFixed(unsigned ID) {
100  return FrameIndexOperand("", ID, /*IsFixed=*/true);
101  }
102 };
103 
104 } // end anonymous namespace
105 
106 namespace llvm {
107 
108 /// This class prints out the machine functions using the MIR serialization
109 /// format.
110 class MIRPrinter {
111  raw_ostream &OS;
112  DenseMap<const uint32_t *, unsigned> RegisterMaskIds;
113  /// Maps from stack object indices to operand indices which will be used when
114  /// printing frame index machine operands.
115  DenseMap<int, FrameIndexOperand> StackObjectOperandMapping;
116 
117 public:
118  MIRPrinter(raw_ostream &OS) : OS(OS) {}
119 
120  void print(const MachineFunction &MF);
121 
122  void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
123  const TargetRegisterInfo *TRI);
124  void convert(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
125  const MachineFrameInfo &MFI);
126  void convert(yaml::MachineFunction &MF,
128  void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
129  const MachineJumpTableInfo &JTI);
130  void convertStackObjects(yaml::MachineFunction &YMF,
131  const MachineFunction &MF, ModuleSlotTracker &MST);
132 
133 private:
134  void initRegisterMaskIds(const MachineFunction &MF);
135 };
136 
137 /// This class prints out the machine instructions using the MIR serialization
138 /// format.
139 class MIPrinter {
140  raw_ostream &OS;
141  ModuleSlotTracker &MST;
142  const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
143  const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
144  /// Synchronization scope names registered with LLVMContext.
146 
147  bool canPredictBranchProbabilities(const MachineBasicBlock &MBB) const;
148  bool canPredictSuccessors(const MachineBasicBlock &MBB) const;
149 
150 public:
152  const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
153  const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping)
154  : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds),
155  StackObjectOperandMapping(StackObjectOperandMapping) {}
156 
157  void print(const MachineBasicBlock &MBB);
158 
159  void print(const MachineInstr &MI);
160  void printStackObjectReference(int FrameIndex);
161  void print(const MachineInstr &MI, unsigned OpIdx,
162  const TargetRegisterInfo *TRI, bool ShouldPrintRegisterTies,
163  LLT TypeToPrint, bool PrintDef = true);
164 };
165 
166 } // end namespace llvm
167 
168 namespace llvm {
169 namespace yaml {
170 
171 /// This struct serializes the LLVM IR module.
172 template <> struct BlockScalarTraits<Module> {
173  static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
174  Mod.print(OS, nullptr);
175  }
176 
177  static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
178  llvm_unreachable("LLVM Module is supposed to be parsed separately");
179  return "";
180  }
181 };
182 
183 } // end namespace yaml
184 } // end namespace llvm
185 
186 static void printRegMIR(unsigned Reg, yaml::StringValue &Dest,
187  const TargetRegisterInfo *TRI) {
188  raw_string_ostream OS(Dest.Value);
189  OS << printReg(Reg, TRI);
190 }
191 
193  initRegisterMaskIds(MF);
194 
195  yaml::MachineFunction YamlMF;
196  YamlMF.Name = MF.getName();
197  YamlMF.Alignment = MF.getAlignment();
199  YamlMF.HasWinCFI = MF.hasWinCFI();
200 
201  YamlMF.Legalized = MF.getProperties().hasProperty(
205  YamlMF.Selected = MF.getProperties().hasProperty(
207  YamlMF.FailedISel = MF.getProperties().hasProperty(
209 
210  convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
213  convert(MST, YamlMF.FrameInfo, MF.getFrameInfo());
214  convertStackObjects(YamlMF, MF, MST);
215  if (const auto *ConstantPool = MF.getConstantPool())
216  convert(YamlMF, *ConstantPool);
217  if (const auto *JumpTableInfo = MF.getJumpTableInfo())
218  convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
219 
220  const TargetMachine &TM = MF.getTarget();
221  YamlMF.MachineFuncInfo =
222  std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF));
223 
224  raw_string_ostream StrOS(YamlMF.Body.Value.Value);
225  bool IsNewlineNeeded = false;
226  for (const auto &MBB : MF) {
227  if (IsNewlineNeeded)
228  StrOS << "\n";
229  MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
230  .print(MBB);
231  IsNewlineNeeded = true;
232  }
233  StrOS.flush();
234  yaml::Output Out(OS);
235  if (!SimplifyMIR)
236  Out.setWriteDefaultValues(true);
237  Out << YamlMF;
238 }
239 
240 static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS,
241  const TargetRegisterInfo *TRI) {
242  assert(RegMask && "Can't print an empty register mask");
243  OS << StringRef("CustomRegMask(");
244 
245  bool IsRegInRegMaskFound = false;
246  for (int I = 0, E = TRI->getNumRegs(); I < E; I++) {
247  // Check whether the register is asserted in regmask.
248  if (RegMask[I / 32] & (1u << (I % 32))) {
249  if (IsRegInRegMaskFound)
250  OS << ',';
251  OS << printReg(I, TRI);
252  IsRegInRegMaskFound = true;
253  }
254  }
255 
256  OS << ')';
257 }
258 
259 static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest,
260  const MachineRegisterInfo &RegInfo,
261  const TargetRegisterInfo *TRI) {
262  raw_string_ostream OS(Dest.Value);
263  OS << printRegClassOrBank(Reg, RegInfo, TRI);
264 }
265 
266 template <typename T>
267 static void
269  T &Object, ModuleSlotTracker &MST) {
270  std::array<std::string *, 3> Outputs{{&Object.DebugVar.Value,
271  &Object.DebugExpr.Value,
272  &Object.DebugLoc.Value}};
273  std::array<const Metadata *, 3> Metas{{DebugVar.Var,
274  DebugVar.Expr,
275  DebugVar.Loc}};
276  for (unsigned i = 0; i < 3; ++i) {
277  raw_string_ostream StrOS(*Outputs[i]);
278  Metas[i]->printAsOperand(StrOS, MST);
279  }
280 }
281 
283  const MachineRegisterInfo &RegInfo,
284  const TargetRegisterInfo *TRI) {
285  MF.TracksRegLiveness = RegInfo.tracksLiveness();
286 
287  // Print the virtual register definitions.
288  for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
291  VReg.ID = I;
292  if (RegInfo.getVRegName(Reg) != "")
293  continue;
294  ::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI);
295  unsigned PreferredReg = RegInfo.getSimpleHint(Reg);
296  if (PreferredReg)
297  printRegMIR(PreferredReg, VReg.PreferredRegister, TRI);
298  MF.VirtualRegisters.push_back(VReg);
299  }
300 
301  // Print the live ins.
302  for (std::pair<unsigned, unsigned> LI : RegInfo.liveins()) {
304  printRegMIR(LI.first, LiveIn.Register, TRI);
305  if (LI.second)
306  printRegMIR(LI.second, LiveIn.VirtualRegister, TRI);
307  MF.LiveIns.push_back(LiveIn);
308  }
309 
310  // Prints the callee saved registers.
311  if (RegInfo.isUpdatedCSRsInitialized()) {
312  const MCPhysReg *CalleeSavedRegs = RegInfo.getCalleeSavedRegs();
313  std::vector<yaml::FlowStringValue> CalleeSavedRegisters;
314  for (const MCPhysReg *I = CalleeSavedRegs; *I; ++I) {
316  printRegMIR(*I, Reg, TRI);
317  CalleeSavedRegisters.push_back(Reg);
318  }
319  MF.CalleeSavedRegisters = CalleeSavedRegisters;
320  }
321 }
322 
324  yaml::MachineFrameInfo &YamlMFI,
325  const MachineFrameInfo &MFI) {
328  YamlMFI.HasStackMap = MFI.hasStackMap();
329  YamlMFI.HasPatchPoint = MFI.hasPatchPoint();
330  YamlMFI.StackSize = MFI.getStackSize();
331  YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment();
332  YamlMFI.MaxAlignment = MFI.getMaxAlignment();
333  YamlMFI.AdjustsStack = MFI.adjustsStack();
334  YamlMFI.HasCalls = MFI.hasCalls();
336  ? MFI.getMaxCallFrameSize() : ~0u;
340  YamlMFI.HasVAStart = MFI.hasVAStart();
342  YamlMFI.LocalFrameSize = MFI.getLocalFrameSize();
343  if (MFI.getSavePoint()) {
344  raw_string_ostream StrOS(YamlMFI.SavePoint.Value);
345  StrOS << printMBBReference(*MFI.getSavePoint());
346  }
347  if (MFI.getRestorePoint()) {
348  raw_string_ostream StrOS(YamlMFI.RestorePoint.Value);
349  StrOS << printMBBReference(*MFI.getRestorePoint());
350  }
351 }
352 
354  const MachineFunction &MF,
355  ModuleSlotTracker &MST) {
356  const MachineFrameInfo &MFI = MF.getFrameInfo();
358  // Process fixed stack objects.
359  unsigned ID = 0;
360  for (int I = MFI.getObjectIndexBegin(); I < 0; ++I, ++ID) {
361  if (MFI.isDeadObjectIndex(I))
362  continue;
363 
365  YamlObject.ID = ID;
366  YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
369  YamlObject.Offset = MFI.getObjectOffset(I);
370  YamlObject.Size = MFI.getObjectSize(I);
371  YamlObject.Alignment = MFI.getObjectAlignment(I);
372  YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
373  YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
374  YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
375  YMF.FixedStackObjects.push_back(YamlObject);
376  StackObjectOperandMapping.insert(
377  std::make_pair(I, FrameIndexOperand::createFixed(ID)));
378  }
379 
380  // Process ordinary stack objects.
381  ID = 0;
382  for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I, ++ID) {
383  if (MFI.isDeadObjectIndex(I))
384  continue;
385 
386  yaml::MachineStackObject YamlObject;
387  YamlObject.ID = ID;
388  if (const auto *Alloca = MFI.getObjectAllocation(I))
389  YamlObject.Name.Value =
390  Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>";
391  YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
396  YamlObject.Offset = MFI.getObjectOffset(I);
397  YamlObject.Size = MFI.getObjectSize(I);
398  YamlObject.Alignment = MFI.getObjectAlignment(I);
399  YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
400 
401  YMF.StackObjects.push_back(YamlObject);
402  StackObjectOperandMapping.insert(std::make_pair(
403  I, FrameIndexOperand::create(YamlObject.Name.Value, ID)));
404  }
405 
406  for (const auto &CSInfo : MFI.getCalleeSavedInfo()) {
407  if (!CSInfo.isSpilledToReg() && MFI.isDeadObjectIndex(CSInfo.getFrameIdx()))
408  continue;
409 
411  printRegMIR(CSInfo.getReg(), Reg, TRI);
412  if (!CSInfo.isSpilledToReg()) {
413  auto StackObjectInfo = StackObjectOperandMapping.find(CSInfo.getFrameIdx());
414  assert(StackObjectInfo != StackObjectOperandMapping.end() &&
415  "Invalid stack object index");
416  const FrameIndexOperand &StackObject = StackObjectInfo->second;
417  if (StackObject.IsFixed) {
418  YMF.FixedStackObjects[StackObject.ID].CalleeSavedRegister = Reg;
419  YMF.FixedStackObjects[StackObject.ID].CalleeSavedRestored =
420  CSInfo.isRestored();
421  } else {
422  YMF.StackObjects[StackObject.ID].CalleeSavedRegister = Reg;
423  YMF.StackObjects[StackObject.ID].CalleeSavedRestored =
424  CSInfo.isRestored();
425  }
426  }
427  }
428  for (unsigned I = 0, E = MFI.getLocalFrameObjectCount(); I < E; ++I) {
429  auto LocalObject = MFI.getLocalFrameObjectMap(I);
430  auto StackObjectInfo = StackObjectOperandMapping.find(LocalObject.first);
431  assert(StackObjectInfo != StackObjectOperandMapping.end() &&
432  "Invalid stack object index");
433  const FrameIndexOperand &StackObject = StackObjectInfo->second;
434  assert(!StackObject.IsFixed && "Expected a locally mapped stack object");
435  YMF.StackObjects[StackObject.ID].LocalOffset = LocalObject.second;
436  }
437 
438  // Print the stack object references in the frame information class after
439  // converting the stack objects.
440  if (MFI.hasStackProtectorIndex()) {
442  MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
444  }
445 
446  // Print the debug variable information.
447  for (const MachineFunction::VariableDbgInfo &DebugVar :
448  MF.getVariableDbgInfo()) {
449  auto StackObjectInfo = StackObjectOperandMapping.find(DebugVar.Slot);
450  assert(StackObjectInfo != StackObjectOperandMapping.end() &&
451  "Invalid stack object index");
452  const FrameIndexOperand &StackObject = StackObjectInfo->second;
453  if (StackObject.IsFixed) {
454  auto &Object = YMF.FixedStackObjects[StackObject.ID];
455  printStackObjectDbgInfo(DebugVar, Object, MST);
456  } else {
457  auto &Object = YMF.StackObjects[StackObject.ID];
458  printStackObjectDbgInfo(DebugVar, Object, MST);
459  }
460  }
461 }
462 
465  unsigned ID = 0;
466  for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) {
467  std::string Str;
468  raw_string_ostream StrOS(Str);
469  if (Constant.isMachineConstantPoolEntry()) {
470  Constant.Val.MachineCPVal->print(StrOS);
471  } else {
472  Constant.Val.ConstVal->printAsOperand(StrOS);
473  }
474 
475  yaml::MachineConstantPoolValue YamlConstant;
476  YamlConstant.ID = ID++;
477  YamlConstant.Value = StrOS.str();
478  YamlConstant.Alignment = Constant.getAlignment();
479  YamlConstant.IsTargetSpecific = Constant.isMachineConstantPoolEntry();
480 
481  MF.Constants.push_back(YamlConstant);
482  }
483 }
484 
486  yaml::MachineJumpTable &YamlJTI,
487  const MachineJumpTableInfo &JTI) {
488  YamlJTI.Kind = JTI.getEntryKind();
489  unsigned ID = 0;
490  for (const auto &Table : JTI.getJumpTables()) {
491  std::string Str;
493  Entry.ID = ID++;
494  for (const auto *MBB : Table.MBBs) {
495  raw_string_ostream StrOS(Str);
496  StrOS << printMBBReference(*MBB);
497  Entry.Blocks.push_back(StrOS.str());
498  Str.clear();
499  }
500  YamlJTI.Entries.push_back(Entry);
501  }
502 }
503 
504 void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
505  const auto *TRI = MF.getSubtarget().getRegisterInfo();
506  unsigned I = 0;
507  for (const uint32_t *Mask : TRI->getRegMasks())
508  RegisterMaskIds.insert(std::make_pair(Mask, I++));
509 }
510 
513  bool &IsFallthrough) {
515 
516  for (const MachineInstr &MI : MBB) {
517  if (MI.isPHI())
518  continue;
519  for (const MachineOperand &MO : MI.operands()) {
520  if (!MO.isMBB())
521  continue;
522  MachineBasicBlock *Succ = MO.getMBB();
523  auto RP = Seen.insert(Succ);
524  if (RP.second)
525  Result.push_back(Succ);
526  }
527  }
528  MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr();
529  IsFallthrough = I == MBB.end() || !I->isBarrier();
530 }
531 
532 bool
533 MIPrinter::canPredictBranchProbabilities(const MachineBasicBlock &MBB) const {
534  if (MBB.succ_size() <= 1)
535  return true;
536  if (!MBB.hasSuccessorProbabilities())
537  return true;
538 
539  SmallVector<BranchProbability,8> Normalized(MBB.Probs.begin(),
540  MBB.Probs.end());
542  Normalized.end());
543  SmallVector<BranchProbability,8> Equal(Normalized.size());
545 
546  return std::equal(Normalized.begin(), Normalized.end(), Equal.begin());
547 }
548 
549 bool MIPrinter::canPredictSuccessors(const MachineBasicBlock &MBB) const {
551  bool GuessedFallthrough;
552  guessSuccessors(MBB, GuessedSuccs, GuessedFallthrough);
553  if (GuessedFallthrough) {
554  const MachineFunction &MF = *MBB.getParent();
555  MachineFunction::const_iterator NextI = std::next(MBB.getIterator());
556  if (NextI != MF.end()) {
557  MachineBasicBlock *Next = const_cast<MachineBasicBlock*>(&*NextI);
558  if (!is_contained(GuessedSuccs, Next))
559  GuessedSuccs.push_back(Next);
560  }
561  }
562  if (GuessedSuccs.size() != MBB.succ_size())
563  return false;
564  return std::equal(MBB.succ_begin(), MBB.succ_end(), GuessedSuccs.begin());
565 }
566 
568  assert(MBB.getNumber() >= 0 && "Invalid MBB number");
569  OS << "bb." << MBB.getNumber();
570  bool HasAttributes = false;
571  if (const auto *BB = MBB.getBasicBlock()) {
572  if (BB->hasName()) {
573  OS << "." << BB->getName();
574  } else {
575  HasAttributes = true;
576  OS << " (";
577  int Slot = MST.getLocalSlot(BB);
578  if (Slot == -1)
579  OS << "<ir-block badref>";
580  else
581  OS << (Twine("%ir-block.") + Twine(Slot)).str();
582  }
583  }
584  if (MBB.hasAddressTaken()) {
585  OS << (HasAttributes ? ", " : " (");
586  OS << "address-taken";
587  HasAttributes = true;
588  }
589  if (MBB.isEHPad()) {
590  OS << (HasAttributes ? ", " : " (");
591  OS << "landing-pad";
592  HasAttributes = true;
593  }
594  if (MBB.getAlignment()) {
595  OS << (HasAttributes ? ", " : " (");
596  OS << "align " << MBB.getAlignment();
597  HasAttributes = true;
598  }
599  if (HasAttributes)
600  OS << ")";
601  OS << ":\n";
602 
603  bool HasLineAttributes = false;
604  // Print the successors
605  bool canPredictProbs = canPredictBranchProbabilities(MBB);
606  // Even if the list of successors is empty, if we cannot guess it,
607  // we need to print it to tell the parser that the list is empty.
608  // This is needed, because MI model unreachable as empty blocks
609  // with an empty successor list. If the parser would see that
610  // without the successor list, it would guess the code would
611  // fallthrough.
612  if ((!MBB.succ_empty() && !SimplifyMIR) || !canPredictProbs ||
613  !canPredictSuccessors(MBB)) {
614  OS.indent(2) << "successors: ";
615  for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) {
616  if (I != MBB.succ_begin())
617  OS << ", ";
618  OS << printMBBReference(**I);
619  if (!SimplifyMIR || !canPredictProbs)
620  OS << '('
621  << format("0x%08" PRIx32, MBB.getSuccProbability(I).getNumerator())
622  << ')';
623  }
624  OS << "\n";
625  HasLineAttributes = true;
626  }
627 
628  // Print the live in registers.
629  const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
630  if (MRI.tracksLiveness() && !MBB.livein_empty()) {
632  OS.indent(2) << "liveins: ";
633  bool First = true;
634  for (const auto &LI : MBB.liveins()) {
635  if (!First)
636  OS << ", ";
637  First = false;
638  OS << printReg(LI.PhysReg, &TRI);
639  if (!LI.LaneMask.all())
640  OS << ":0x" << PrintLaneMask(LI.LaneMask);
641  }
642  OS << "\n";
643  HasLineAttributes = true;
644  }
645 
646  if (HasLineAttributes)
647  OS << "\n";
648  bool IsInBundle = false;
649  for (auto I = MBB.instr_begin(), E = MBB.instr_end(); I != E; ++I) {
650  const MachineInstr &MI = *I;
651  if (IsInBundle && !MI.isInsideBundle()) {
652  OS.indent(2) << "}\n";
653  IsInBundle = false;
654  }
655  OS.indent(IsInBundle ? 4 : 2);
656  print(MI);
657  if (!IsInBundle && MI.getFlag(MachineInstr::BundledSucc)) {
658  OS << " {";
659  IsInBundle = true;
660  }
661  OS << "\n";
662  }
663  if (IsInBundle)
664  OS.indent(2) << "}\n";
665 }
666 
668  const auto *MF = MI.getMF();
669  const auto &MRI = MF->getRegInfo();
670  const auto &SubTarget = MF->getSubtarget();
671  const auto *TRI = SubTarget.getRegisterInfo();
672  assert(TRI && "Expected target register info");
673  const auto *TII = SubTarget.getInstrInfo();
674  assert(TII && "Expected target instruction info");
675  if (MI.isCFIInstruction())
676  assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
677 
678  SmallBitVector PrintedTypes(8);
679  bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies();
680  unsigned I = 0, E = MI.getNumOperands();
681  for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
682  !MI.getOperand(I).isImplicit();
683  ++I) {
684  if (I)
685  OS << ", ";
686  print(MI, I, TRI, ShouldPrintRegisterTies,
687  MI.getTypeToPrint(I, PrintedTypes, MRI),
688  /*PrintDef=*/false);
689  }
690 
691  if (I)
692  OS << " = ";
694  OS << "frame-setup ";
696  OS << "frame-destroy ";
698  OS << "nnan ";
700  OS << "ninf ";
702  OS << "nsz ";
704  OS << "arcp ";
706  OS << "contract ";
708  OS << "afn ";
710  OS << "reassoc ";
712  OS << "nuw ";
714  OS << "nsw ";
716  OS << "exact ";
718  OS << "fpexcept ";
719 
720  OS << TII->getName(MI.getOpcode());
721  if (I < E)
722  OS << ' ';
723 
724  bool NeedComma = false;
725  for (; I < E; ++I) {
726  if (NeedComma)
727  OS << ", ";
728  print(MI, I, TRI, ShouldPrintRegisterTies,
729  MI.getTypeToPrint(I, PrintedTypes, MRI));
730  NeedComma = true;
731  }
732 
733  // Print any optional symbols attached to this instruction as-if they were
734  // operands.
735  if (MCSymbol *PreInstrSymbol = MI.getPreInstrSymbol()) {
736  if (NeedComma)
737  OS << ',';
738  OS << " pre-instr-symbol ";
739  MachineOperand::printSymbol(OS, *PreInstrSymbol);
740  NeedComma = true;
741  }
742  if (MCSymbol *PostInstrSymbol = MI.getPostInstrSymbol()) {
743  if (NeedComma)
744  OS << ',';
745  OS << " post-instr-symbol ";
746  MachineOperand::printSymbol(OS, *PostInstrSymbol);
747  NeedComma = true;
748  }
749 
750  if (const DebugLoc &DL = MI.getDebugLoc()) {
751  if (NeedComma)
752  OS << ',';
753  OS << " debug-location ";
754  DL->printAsOperand(OS, MST);
755  }
756 
757  if (!MI.memoperands_empty()) {
758  OS << " :: ";
759  const LLVMContext &Context = MF->getFunction().getContext();
760  const MachineFrameInfo &MFI = MF->getFrameInfo();
761  bool NeedComma = false;
762  for (const auto *Op : MI.memoperands()) {
763  if (NeedComma)
764  OS << ", ";
765  Op->print(OS, MST, SSNs, Context, &MFI, TII);
766  NeedComma = true;
767  }
768  }
769 }
770 
772  auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
773  assert(ObjectInfo != StackObjectOperandMapping.end() &&
774  "Invalid frame index");
775  const FrameIndexOperand &Operand = ObjectInfo->second;
776  MachineOperand::printStackObjectReference(OS, Operand.ID, Operand.IsFixed,
777  Operand.Name);
778 }
779 
780 void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx,
781  const TargetRegisterInfo *TRI,
782  bool ShouldPrintRegisterTies, LLT TypeToPrint,
783  bool PrintDef) {
784  const MachineOperand &Op = MI.getOperand(OpIdx);
785  switch (Op.getType()) {
787  if (MI.isOperandSubregIdx(OpIdx)) {
790  break;
791  }
809  unsigned TiedOperandIdx = 0;
810  if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef())
811  TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx);
813  Op.print(OS, MST, TypeToPrint, PrintDef, /*IsStandalone=*/false,
814  ShouldPrintRegisterTies, TiedOperandIdx, TRI, TII);
815  break;
816  }
818  printStackObjectReference(Op.getIndex());
819  break;
821  auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
822  if (RegMaskInfo != RegisterMaskIds.end())
823  OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
824  else
825  printCustomRegMask(Op.getRegMask(), OS, TRI);
826  break;
827  }
828  }
829 }
830 
831 void llvm::printMIR(raw_ostream &OS, const Module &M) {
832  yaml::Output Out(OS);
833  Out << const_cast<Module &>(M);
834 }
835 
837  MIRPrinter Printer(OS);
838  Printer.print(MF);
839 }
LLT getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes, const MachineRegisterInfo &MRI) const
Debugging supportDetermine the generic type to be printed (if needed) on uses and defs...
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
bool hasSuccessorProbabilities() const
Return true if any of the successors have probabilities attached to them.
A common definition of LaneBitmask for use in TableGen and CodeGen.
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
instr_iterator instr_begin()
static void printStackObjectDbgInfo(const MachineFunction::VariableDbgInfo &DebugVar, T &Object, ModuleSlotTracker &MST)
Definition: MIRPrinter.cpp:268
LLVMContext & Context
static StringRef input(StringRef Str, void *Ctxt, Module &Mod)
Definition: MIRPrinter.cpp:177
instr_iterator instr_end()
Atomic ordering constants.
This is a &#39;bitvector&#39; (really, a variable-sized bit array), optimized for the case when the array is ...
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
static unsigned index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
bool hasStackProtectorIndex() const
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
This class prints out the machine functions using the MIR serialization format.
Definition: MIRPrinter.cpp:110
bool isCFIInstruction() const
const MachineFunctionProperties & getProperties() const
Get the function properties.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
Optional< std::vector< FlowStringValue > > CalleeSavedRegisters
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:384
static void printTargetFlags(raw_ostream &OS, const MachineOperand &Op)
Print operand target flags.
bool hasOpaqueSPAdjustment() const
Returns true if the function contains opaque dynamic stack adjustments.
int64_t getLocalFrameSize() const
Get the size of the local object blob.
Address of indexed Jump Table for switch.
unsigned Reg
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:123
MachineBasicBlock reference.
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
Definition: LaneBitmask.h:93
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
Manage lifetime of a slot tracker for printing IR.
std::unique_ptr< MachineFunctionInfo > MachineFuncInfo
Constant pool.
Mask of live-out registers.
print alias Alias Set Printer
TargetStackID::Value StackID
VariableDbgInfoMapTy & getVariableDbgInfo()
bool isVariableSizedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a variable sized object.
Mask of preserved registers.
void guessSuccessors(const MachineBasicBlock &MBB, SmallVectorImpl< MachineBasicBlock *> &Result, bool &IsFallthrough)
Determine a possible list of successors of a basic block based on the basic block machine operand bei...
Definition: MIRPrinter.cpp:511
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
std::pair< int, int64_t > getLocalFrameObjectMap(int i) const
Get the local offset mapping for a for an object.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
const HexagonInstrInfo * TII
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Serializable representation of the fixed stack object from the MachineFrameInfo class.
MCCFIInstruction index.
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:413
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MachineBasicBlock * getRestorePoint() const
void print(const MachineBasicBlock &MBB)
Definition: MIRPrinter.cpp:567
Target-dependent index+offset operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
Name of external global symbol.
unsigned getAlignment() const
getAlignment - Return the alignment (log2, not bytes) of the function.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:410
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
static cl::opt< bool > SimplifyMIR("simplify-mir", cl::Hidden, cl::desc("Leave out unnecessary information when printing MIR"))
std::vector< VirtualRegisterDefinition > VirtualRegisters
Immediate >64bit operand.
static void normalizeProbabilities(ProbabilityIter Begin, ProbabilityIter End)
int getObjectIndexBegin() const
Return the minimum frame object index.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
This class is a data container for one entry in a MachineConstantPool.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they&#39;re not in a MachineFuncti...
Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo, const TargetRegisterInfo *TRI)
Create Printable object to print register classes or register banks on a raw_ostream.
bool isInsideBundle() const
Return true if MI is in a bundle (but not the first MI in a bundle).
Definition: MachineInstr.h:351
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
MCSymbol * getPreInstrSymbol() const
Helper to extract a pre-instruction symbol if one has been added.
Definition: MachineInstr.h:556
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
unsigned getObjectAlignment(int ObjectIdx) const
Return the alignment of the specified stack object.
Address of a global value.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
MIRPrinter(raw_ostream &OS)
Definition: MIRPrinter.cpp:118
const TargetRegisterInfo * getTargetRegisterInfo() const
std::vector< FlowStringValue > Blocks
unsigned const MachineRegisterInfo * MRI
Serializable representation of stack object from the MachineFrameInfo class.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:517
static void printRegMIR(unsigned Reg, yaml::StringValue &Dest, const TargetRegisterInfo *TRI)
Definition: MIRPrinter.cpp:186
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
MachineJumpTable JumpTableInfo
bool isOperandSubregIdx(unsigned OpIdx) const
Return true if operand OpIdx is a subregister index.
Definition: MachineInstr.h:430
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:370
unsigned getAlignment() const
Return alignment of the basic block.
int getStackProtectorIndex() const
Return the index for the stack protector object.
static void printStackObjectReference(raw_ostream &OS, unsigned FrameIndex, bool IsFixed, StringRef Name)
Print a stack object reference.
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Address of a basic block.
virtual ArrayRef< const char * > getRegMaskNames() const =0
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
Definition: AsmWriter.cpp:4232
void convertStackObjects(yaml::MachineFunction &YMF, const MachineFunction &MF, ModuleSlotTracker &MST)
Definition: MIRPrinter.cpp:353
unsigned MaxCallFrameSize
~0u means: not computed yet.
This class prints out the machine instructions using the MIR serialization format.
Definition: MIRPrinter.cpp:139
std::vector< MachineStackObject > StackObjects
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
self_iterator getIterator()
Definition: ilist_node.h:81
bool hasComplexRegisterTies() const
Return true when an instruction has tied register that can&#39;t be determined by the instruction&#39;s descr...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS, const TargetRegisterInfo *TRI)
Definition: MIRPrinter.cpp:240
Serializable representation of MachineFrameInfo.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:205
void printMIR(raw_ostream &OS, const Module &M)
Print LLVM IR using the MIR serialization format to the given output stream.
Definition: MIRPrinter.cpp:831
void incorporateFunction(const Function &F)
Incorporate the given function.
Definition: AsmWriter.cpp:843
bool hasAddressTaken() const
Test whether this block is potentially the target of an indirect branch.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
size_t size() const
Definition: SmallVector.h:52
static void printSymbol(raw_ostream &OS, MCSymbol &Sym)
Print a MCSymbol as an operand.
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
Definition: AsmWriter.cpp:4309
std::string & str()
Flushes the stream contents to the target string and returns the string&#39;s reference.
Definition: raw_ostream.h:498
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MCSymbol * getPostInstrSymbol() const
Helper to extract a post-instruction symbol if one has been added.
Definition: MachineInstr.h:568
TargetIntrinsicInfo - Interface to description of machine instruction set.
const std::vector< MachineConstantPoolEntry > & getConstants() const
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the module to an output stream with an optional AssemblyAnnotationWriter.
Definition: AsmWriter.cpp:4149
unsigned findTiedOperandIdx(unsigned OpIdx) const
Given the index of a tied register operand, find the operand it is tied to.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Definition: SmallPtrSet.h:417
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call...
Generic predicate for ISel.
void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr, const TargetIntrinsicInfo *IntrinsicInfo=nullptr) const
Print the MachineOperand to os.
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Module.h This file contains the declarations for the Module class.
bool hasMustTailInVarArgFunc() const
Returns true if the function is variadic and contains a musttail call.
int64_t getImm() const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
The access may modify the value stored in memory.
MCSymbol reference (for debug/eh info)
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
virtual yaml::MachineFunctionInfo * convertFuncInfoToYAML(const MachineFunction &MF) const
Allocate and initialize an instance of the YAML representation of the MachineFunctionInfo.
ArrayRef< std::pair< unsigned, unsigned > > liveins() const
A wrapper around std::string which contains a source range that&#39;s being set during parsing...
unsigned succ_size() const
static void printSubRegIdx(raw_ostream &OS, uint64_t Index, const TargetRegisterInfo *TRI)
Print a subreg index operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:63
const AllocaInst * getObjectAllocation(int ObjectIdx) const
Return the underlying Alloca of the specified stack object if it exists.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
std::vector< MachineFunctionLiveIn > LiveIns
static void output(const Module &Mod, void *Ctxt, raw_ostream &OS)
Definition: MIRPrinter.cpp:173
bool isUpdatedCSRsInitialized() const
Returns true if the updated CSR list was initialized and false otherwise.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isEHPad() const
Returns true if the block is a landing pad.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool isAliasedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an object that might be pointed to by an LLVM IR v...
std::vector< Entry > Entries
virtual const TargetIntrinsicInfo * getIntrinsicInfo() const
If intrinsic information is available, return it. If not, return null.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
#define I(x, y, z)
Definition: MD5.cpp:58
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
std::vector< MachineConstantPoolValue > Constants
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
int getOffsetAdjustment() const
Return the correction for frame offsets.
Abstract Stack Frame Index.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
iterator_range< livein_iterator > liveins() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo, const TargetRegisterInfo *TRI)
Definition: MIRPrinter.cpp:282
This file defines passes to print out IR in various granularities.
uint8_t getStackID(int ObjectIdx) const
MachineBasicBlock * getSavePoint() const
bool memoperands_empty() const
Return true if we don&#39;t have any memory operands which described the memory access done by this instr...
Definition: MachineInstr.h:547
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool hasProperty(Property P) const
std::vector< FixedMachineStackObject > FixedStackObjects
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:482
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
JTEntryKind getEntryKind() const
Floating-point immediate operand.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:250
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:80
void printStackObjectReference(int FrameIndex)
Definition: MIRPrinter.cpp:771
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
bool isMaxCallFrameSizeComputed() const
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
IRTranslator LLVM IR MI
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Address of indexed Constant in Constant Pool.
MachineJumpTableInfo::JTEntryKind Kind
unsigned getSimpleHint(unsigned VReg) const
getSimpleHint - same as getRegAllocationHint except it will only return a target independent hint...
MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST, const DenseMap< const uint32_t *, unsigned > &RegisterMaskIds, const DenseMap< int, FrameIndexOperand > &StackObjectOperandMapping)
Definition: MIRPrinter.cpp:151
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415
int64_t getLocalFrameObjectCount() const
Return the number of objects allocated into the local object block.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
void print(const MachineFunction &MF)
Definition: MIRPrinter.cpp:192
uint32_t getNumerator() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
Definition: MachineInstr.h:296
StringRef getVRegName(unsigned Reg) const
bool isSpillSlotObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a spill slot.
bool isImplicit() const
bool hasCalls() const
Return true if the current function has any function calls.
Metadata reference (for debug info)
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1251