xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MIRPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
13a0822f0SDimitry Andric //===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
23a0822f0SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63a0822f0SDimitry Andric //
73a0822f0SDimitry Andric //===----------------------------------------------------------------------===//
83a0822f0SDimitry Andric //
93a0822f0SDimitry Andric // This file implements the class that prints out the LLVM IR and machine
103a0822f0SDimitry Andric // functions using the MIR serialization format.
113a0822f0SDimitry Andric //
123a0822f0SDimitry Andric //===----------------------------------------------------------------------===//
133a0822f0SDimitry Andric 
14044eb2f6SDimitry Andric #include "llvm/CodeGen/MIRPrinter.h"
157ab83427SDimitry Andric #include "llvm/ADT/DenseMap.h"
16044eb2f6SDimitry Andric #include "llvm/ADT/STLExtras.h"
17b915e9e0SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
187ab83427SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
197ab83427SDimitry Andric #include "llvm/ADT/SmallVector.h"
207ab83427SDimitry Andric #include "llvm/ADT/StringRef.h"
21044eb2f6SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
227ab83427SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
23dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
24ee8648bdSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
2501095a5dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
267ab83427SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
277ab83427SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
28dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
29344a3780SDimitry Andric #include "llvm/CodeGen/MachineModuleSlotTracker.h"
307ab83427SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
311a82d4c0SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
32344a3780SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
33044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
34044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
35044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
36ac9a064cSDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
37145449b1SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
387ab83427SDimitry Andric #include "llvm/IR/DebugLoc.h"
397ab83427SDimitry Andric #include "llvm/IR/Function.h"
40044eb2f6SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
4101095a5dSDimitry Andric #include "llvm/IR/Instructions.h"
423a0822f0SDimitry Andric #include "llvm/IR/Module.h"
43ee8648bdSDimitry Andric #include "llvm/IR/ModuleSlotTracker.h"
447ab83427SDimitry Andric #include "llvm/IR/Value.h"
457ab83427SDimitry Andric #include "llvm/MC/LaneBitmask.h"
467ab83427SDimitry Andric #include "llvm/Support/BranchProbability.h"
477ab83427SDimitry Andric #include "llvm/Support/Casting.h"
487ab83427SDimitry Andric #include "llvm/Support/CommandLine.h"
497ab83427SDimitry Andric #include "llvm/Support/ErrorHandling.h"
50b915e9e0SDimitry Andric #include "llvm/Support/Format.h"
517ab83427SDimitry Andric #include "llvm/Support/YAMLTraits.h"
52044eb2f6SDimitry Andric #include "llvm/Support/raw_ostream.h"
537ab83427SDimitry Andric #include "llvm/Target/TargetMachine.h"
547ab83427SDimitry Andric #include <algorithm>
557ab83427SDimitry Andric #include <cassert>
567ab83427SDimitry Andric #include <cinttypes>
577ab83427SDimitry Andric #include <cstdint>
587ab83427SDimitry Andric #include <iterator>
597ab83427SDimitry Andric #include <string>
607ab83427SDimitry Andric #include <utility>
617ab83427SDimitry Andric #include <vector>
623a0822f0SDimitry Andric 
633a0822f0SDimitry Andric using namespace llvm;
643a0822f0SDimitry Andric 
65044eb2f6SDimitry Andric static cl::opt<bool> SimplifyMIR(
66044eb2f6SDimitry Andric     "simplify-mir", cl::Hidden,
67c46e6a59SDimitry Andric     cl::desc("Leave out unnecessary information when printing MIR"));
68c46e6a59SDimitry Andric 
69cfca06d7SDimitry Andric static cl::opt<bool> PrintLocations("mir-debug-loc", cl::Hidden, cl::init(true),
70cfca06d7SDimitry Andric                                     cl::desc("Print MIR debug-locations"));
71cfca06d7SDimitry Andric 
72ac9a064cSDimitry Andric extern cl::opt<bool> WriteNewDbgInfoFormat;
73ac9a064cSDimitry Andric 
743a0822f0SDimitry Andric namespace {
753a0822f0SDimitry Andric 
76dd58ef01SDimitry Andric /// This structure describes how to print out stack object references.
77dd58ef01SDimitry Andric struct FrameIndexOperand {
78dd58ef01SDimitry Andric   std::string Name;
79dd58ef01SDimitry Andric   unsigned ID;
80dd58ef01SDimitry Andric   bool IsFixed;
81dd58ef01SDimitry Andric 
FrameIndexOperand__anon5e715b950111::FrameIndexOperand82dd58ef01SDimitry Andric   FrameIndexOperand(StringRef Name, unsigned ID, bool IsFixed)
83dd58ef01SDimitry Andric       : Name(Name.str()), ID(ID), IsFixed(IsFixed) {}
84dd58ef01SDimitry Andric 
85dd58ef01SDimitry Andric   /// Return an ordinary stack object reference.
create__anon5e715b950111::FrameIndexOperand86dd58ef01SDimitry Andric   static FrameIndexOperand create(StringRef Name, unsigned ID) {
87dd58ef01SDimitry Andric     return FrameIndexOperand(Name, ID, /*IsFixed=*/false);
88dd58ef01SDimitry Andric   }
89dd58ef01SDimitry Andric 
90dd58ef01SDimitry Andric   /// Return a fixed stack object reference.
createFixed__anon5e715b950111::FrameIndexOperand91dd58ef01SDimitry Andric   static FrameIndexOperand createFixed(unsigned ID) {
92dd58ef01SDimitry Andric     return FrameIndexOperand("", ID, /*IsFixed=*/true);
93dd58ef01SDimitry Andric   }
94dd58ef01SDimitry Andric };
95dd58ef01SDimitry Andric 
96dd58ef01SDimitry Andric } // end anonymous namespace
97dd58ef01SDimitry Andric 
98dd58ef01SDimitry Andric namespace llvm {
99dd58ef01SDimitry Andric 
1003a0822f0SDimitry Andric /// This class prints out the machine functions using the MIR serialization
1013a0822f0SDimitry Andric /// format.
1023a0822f0SDimitry Andric class MIRPrinter {
1033a0822f0SDimitry Andric   raw_ostream &OS;
1041a82d4c0SDimitry Andric   DenseMap<const uint32_t *, unsigned> RegisterMaskIds;
105dd58ef01SDimitry Andric   /// Maps from stack object indices to operand indices which will be used when
106dd58ef01SDimitry Andric   /// printing frame index machine operands.
107dd58ef01SDimitry Andric   DenseMap<int, FrameIndexOperand> StackObjectOperandMapping;
1083a0822f0SDimitry Andric 
1093a0822f0SDimitry Andric public:
MIRPrinter(raw_ostream & OS)1103a0822f0SDimitry Andric   MIRPrinter(raw_ostream &OS) : OS(OS) {}
1113a0822f0SDimitry Andric 
1123a0822f0SDimitry Andric   void print(const MachineFunction &MF);
1133a0822f0SDimitry Andric 
114ee8648bdSDimitry Andric   void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
115ee8648bdSDimitry Andric                const TargetRegisterInfo *TRI);
116dd58ef01SDimitry Andric   void convert(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
117ee8648bdSDimitry Andric                const MachineFrameInfo &MFI);
118dd58ef01SDimitry Andric   void convert(yaml::MachineFunction &MF,
119dd58ef01SDimitry Andric                const MachineConstantPool &ConstantPool);
120dd58ef01SDimitry Andric   void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
121dd58ef01SDimitry Andric                const MachineJumpTableInfo &JTI);
122b915e9e0SDimitry Andric   void convertStackObjects(yaml::MachineFunction &YMF,
123b915e9e0SDimitry Andric                            const MachineFunction &MF, ModuleSlotTracker &MST);
1247fa27ce4SDimitry Andric   void convertEntryValueObjects(yaml::MachineFunction &YMF,
1257fa27ce4SDimitry Andric                                 const MachineFunction &MF,
1267fa27ce4SDimitry Andric                                 ModuleSlotTracker &MST);
127e6d15924SDimitry Andric   void convertCallSiteObjects(yaml::MachineFunction &YMF,
128e6d15924SDimitry Andric                               const MachineFunction &MF,
129e6d15924SDimitry Andric                               ModuleSlotTracker &MST);
130344a3780SDimitry Andric   void convertMachineMetadataNodes(yaml::MachineFunction &YMF,
131344a3780SDimitry Andric                                    const MachineFunction &MF,
132344a3780SDimitry Andric                                    MachineModuleSlotTracker &MST);
1331a82d4c0SDimitry Andric 
1341a82d4c0SDimitry Andric private:
1351a82d4c0SDimitry Andric   void initRegisterMaskIds(const MachineFunction &MF);
1361a82d4c0SDimitry Andric };
1371a82d4c0SDimitry Andric 
1381a82d4c0SDimitry Andric /// This class prints out the machine instructions using the MIR serialization
1391a82d4c0SDimitry Andric /// format.
1401a82d4c0SDimitry Andric class MIPrinter {
1411a82d4c0SDimitry Andric   raw_ostream &OS;
142ee8648bdSDimitry Andric   ModuleSlotTracker &MST;
1431a82d4c0SDimitry Andric   const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
144dd58ef01SDimitry Andric   const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
145ca089b24SDimitry Andric   /// Synchronization scope names registered with LLVMContext.
146ca089b24SDimitry Andric   SmallVector<StringRef, 8> SSNs;
1471a82d4c0SDimitry Andric 
148c46e6a59SDimitry Andric   bool canPredictBranchProbabilities(const MachineBasicBlock &MBB) const;
149c46e6a59SDimitry Andric   bool canPredictSuccessors(const MachineBasicBlock &MBB) const;
150c46e6a59SDimitry Andric 
1511a82d4c0SDimitry Andric public:
MIPrinter(raw_ostream & OS,ModuleSlotTracker & MST,const DenseMap<const uint32_t *,unsigned> & RegisterMaskIds,const DenseMap<int,FrameIndexOperand> & StackObjectOperandMapping)152ee8648bdSDimitry Andric   MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
153dd58ef01SDimitry Andric             const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
154dd58ef01SDimitry Andric             const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping)
155dd58ef01SDimitry Andric       : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds),
156dd58ef01SDimitry Andric         StackObjectOperandMapping(StackObjectOperandMapping) {}
157dd58ef01SDimitry Andric 
158dd58ef01SDimitry Andric   void print(const MachineBasicBlock &MBB);
1591a82d4c0SDimitry Andric 
1601a82d4c0SDimitry Andric   void print(const MachineInstr &MI);
161dd58ef01SDimitry Andric   void printStackObjectReference(int FrameIndex);
162044eb2f6SDimitry Andric   void print(const MachineInstr &MI, unsigned OpIdx,
163cfca06d7SDimitry Andric              const TargetRegisterInfo *TRI, const TargetInstrInfo *TII,
164cfca06d7SDimitry Andric              bool ShouldPrintRegisterTies, LLT TypeToPrint,
165cfca06d7SDimitry Andric              bool PrintDef = true);
1663a0822f0SDimitry Andric };
1673a0822f0SDimitry Andric 
168dd58ef01SDimitry Andric } // end namespace llvm
1693a0822f0SDimitry Andric 
1703a0822f0SDimitry Andric namespace llvm {
1713a0822f0SDimitry Andric namespace yaml {
1723a0822f0SDimitry Andric 
1733a0822f0SDimitry Andric /// This struct serializes the LLVM IR module.
1743a0822f0SDimitry Andric template <> struct BlockScalarTraits<Module> {
outputllvm::yaml::BlockScalarTraits1753a0822f0SDimitry Andric   static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
1763a0822f0SDimitry Andric     Mod.print(OS, nullptr);
1773a0822f0SDimitry Andric   }
1787ab83427SDimitry Andric 
inputllvm::yaml::BlockScalarTraits1793a0822f0SDimitry Andric   static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
1803a0822f0SDimitry Andric     llvm_unreachable("LLVM Module is supposed to be parsed separately");
1813a0822f0SDimitry Andric     return "";
1823a0822f0SDimitry Andric   }
1833a0822f0SDimitry Andric };
1843a0822f0SDimitry Andric 
1853a0822f0SDimitry Andric } // end namespace yaml
1863a0822f0SDimitry Andric } // end namespace llvm
1873a0822f0SDimitry Andric 
printRegMIR(unsigned Reg,yaml::StringValue & Dest,const TargetRegisterInfo * TRI)188044eb2f6SDimitry Andric static void printRegMIR(unsigned Reg, yaml::StringValue &Dest,
189dd58ef01SDimitry Andric                         const TargetRegisterInfo *TRI) {
190dd58ef01SDimitry Andric   raw_string_ostream OS(Dest.Value);
191044eb2f6SDimitry Andric   OS << printReg(Reg, TRI);
192dd58ef01SDimitry Andric }
193dd58ef01SDimitry Andric 
print(const MachineFunction & MF)1943a0822f0SDimitry Andric void MIRPrinter::print(const MachineFunction &MF) {
1951a82d4c0SDimitry Andric   initRegisterMaskIds(MF);
1961a82d4c0SDimitry Andric 
1973a0822f0SDimitry Andric   yaml::MachineFunction YamlMF;
1983a0822f0SDimitry Andric   YamlMF.Name = MF.getName();
199cfca06d7SDimitry Andric   YamlMF.Alignment = MF.getAlignment();
2003a0822f0SDimitry Andric   YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
201d8e91e46SDimitry Andric   YamlMF.HasWinCFI = MF.hasWinCFI();
202b915e9e0SDimitry Andric 
203145449b1SDimitry Andric   YamlMF.CallsEHReturn = MF.callsEHReturn();
204145449b1SDimitry Andric   YamlMF.CallsUnwindInit = MF.callsUnwindInit();
205145449b1SDimitry Andric   YamlMF.HasEHCatchret = MF.hasEHCatchret();
206145449b1SDimitry Andric   YamlMF.HasEHScopes = MF.hasEHScopes();
207145449b1SDimitry Andric   YamlMF.HasEHFunclets = MF.hasEHFunclets();
2087fa27ce4SDimitry Andric   YamlMF.IsOutlined = MF.isOutlined();
209e3b55780SDimitry Andric   YamlMF.UseDebugInstrRef = MF.useDebugInstrRef();
210145449b1SDimitry Andric 
211b915e9e0SDimitry Andric   YamlMF.Legalized = MF.getProperties().hasProperty(
212b915e9e0SDimitry Andric       MachineFunctionProperties::Property::Legalized);
213b915e9e0SDimitry Andric   YamlMF.RegBankSelected = MF.getProperties().hasProperty(
214b915e9e0SDimitry Andric       MachineFunctionProperties::Property::RegBankSelected);
215b915e9e0SDimitry Andric   YamlMF.Selected = MF.getProperties().hasProperty(
216b915e9e0SDimitry Andric       MachineFunctionProperties::Property::Selected);
217eb11fae6SDimitry Andric   YamlMF.FailedISel = MF.getProperties().hasProperty(
218eb11fae6SDimitry Andric       MachineFunctionProperties::Property::FailedISel);
219c0981da4SDimitry Andric   YamlMF.FailsVerification = MF.getProperties().hasProperty(
220c0981da4SDimitry Andric       MachineFunctionProperties::Property::FailsVerification);
22177fc4c14SDimitry Andric   YamlMF.TracksDebugUserValues = MF.getProperties().hasProperty(
22277fc4c14SDimitry Andric       MachineFunctionProperties::Property::TracksDebugUserValues);
22301095a5dSDimitry Andric 
224ee8648bdSDimitry Andric   convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
225344a3780SDimitry Andric   MachineModuleSlotTracker MST(&MF);
226044eb2f6SDimitry Andric   MST.incorporateFunction(MF.getFunction());
227b915e9e0SDimitry Andric   convert(MST, YamlMF.FrameInfo, MF.getFrameInfo());
228b915e9e0SDimitry Andric   convertStackObjects(YamlMF, MF, MST);
2297fa27ce4SDimitry Andric   convertEntryValueObjects(YamlMF, MF, MST);
230e6d15924SDimitry Andric   convertCallSiteObjects(YamlMF, MF, MST);
231344a3780SDimitry Andric   for (const auto &Sub : MF.DebugValueSubstitutions) {
232344a3780SDimitry Andric     const auto &SubSrc = Sub.Src;
233344a3780SDimitry Andric     const auto &SubDest = Sub.Dest;
234344a3780SDimitry Andric     YamlMF.DebugValueSubstitutions.push_back({SubSrc.first, SubSrc.second,
235344a3780SDimitry Andric                                               SubDest.first,
236344a3780SDimitry Andric                                               SubDest.second,
237344a3780SDimitry Andric                                               Sub.Subreg});
238344a3780SDimitry Andric   }
239dd58ef01SDimitry Andric   if (const auto *ConstantPool = MF.getConstantPool())
240dd58ef01SDimitry Andric     convert(YamlMF, *ConstantPool);
241dd58ef01SDimitry Andric   if (const auto *JumpTableInfo = MF.getJumpTableInfo())
242dd58ef01SDimitry Andric     convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
243e6d15924SDimitry Andric 
244e6d15924SDimitry Andric   const TargetMachine &TM = MF.getTarget();
245e6d15924SDimitry Andric   YamlMF.MachineFuncInfo =
246e6d15924SDimitry Andric       std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF));
247e6d15924SDimitry Andric 
248dd58ef01SDimitry Andric   raw_string_ostream StrOS(YamlMF.Body.Value.Value);
249dd58ef01SDimitry Andric   bool IsNewlineNeeded = false;
2503a0822f0SDimitry Andric   for (const auto &MBB : MF) {
251dd58ef01SDimitry Andric     if (IsNewlineNeeded)
252dd58ef01SDimitry Andric       StrOS << "\n";
253dd58ef01SDimitry Andric     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
254dd58ef01SDimitry Andric         .print(MBB);
255dd58ef01SDimitry Andric     IsNewlineNeeded = true;
2563a0822f0SDimitry Andric   }
257dd58ef01SDimitry Andric   StrOS.flush();
258344a3780SDimitry Andric   // Convert machine metadata collected during the print of the machine
259344a3780SDimitry Andric   // function.
260344a3780SDimitry Andric   convertMachineMetadataNodes(YamlMF, MF, MST);
261344a3780SDimitry Andric 
2623a0822f0SDimitry Andric   yaml::Output Out(OS);
2637ab83427SDimitry Andric   if (!SimplifyMIR)
2647ab83427SDimitry Andric       Out.setWriteDefaultValues(true);
2653a0822f0SDimitry Andric   Out << YamlMF;
2663a0822f0SDimitry Andric }
2673a0822f0SDimitry Andric 
printCustomRegMask(const uint32_t * RegMask,raw_ostream & OS,const TargetRegisterInfo * TRI)26871d5a254SDimitry Andric static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS,
26971d5a254SDimitry Andric                                const TargetRegisterInfo *TRI) {
27071d5a254SDimitry Andric   assert(RegMask && "Can't print an empty register mask");
27171d5a254SDimitry Andric   OS << StringRef("CustomRegMask(");
27271d5a254SDimitry Andric 
27371d5a254SDimitry Andric   bool IsRegInRegMaskFound = false;
27471d5a254SDimitry Andric   for (int I = 0, E = TRI->getNumRegs(); I < E; I++) {
27571d5a254SDimitry Andric     // Check whether the register is asserted in regmask.
27671d5a254SDimitry Andric     if (RegMask[I / 32] & (1u << (I % 32))) {
27771d5a254SDimitry Andric       if (IsRegInRegMaskFound)
27871d5a254SDimitry Andric         OS << ',';
279044eb2f6SDimitry Andric       OS << printReg(I, TRI);
28071d5a254SDimitry Andric       IsRegInRegMaskFound = true;
28171d5a254SDimitry Andric     }
28271d5a254SDimitry Andric   }
28371d5a254SDimitry Andric 
28471d5a254SDimitry Andric   OS << ')';
28571d5a254SDimitry Andric }
28671d5a254SDimitry Andric 
printRegClassOrBank(unsigned Reg,yaml::StringValue & Dest,const MachineRegisterInfo & RegInfo,const TargetRegisterInfo * TRI)287044eb2f6SDimitry Andric static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest,
288044eb2f6SDimitry Andric                                 const MachineRegisterInfo &RegInfo,
289044eb2f6SDimitry Andric                                 const TargetRegisterInfo *TRI) {
290044eb2f6SDimitry Andric   raw_string_ostream OS(Dest.Value);
291044eb2f6SDimitry Andric   OS << printRegClassOrBank(Reg, RegInfo, TRI);
292044eb2f6SDimitry Andric }
293044eb2f6SDimitry Andric 
294eb11fae6SDimitry Andric template <typename T>
295eb11fae6SDimitry Andric static void
printStackObjectDbgInfo(const MachineFunction::VariableDbgInfo & DebugVar,T & Object,ModuleSlotTracker & MST)296eb11fae6SDimitry Andric printStackObjectDbgInfo(const MachineFunction::VariableDbgInfo &DebugVar,
297eb11fae6SDimitry Andric                         T &Object, ModuleSlotTracker &MST) {
298eb11fae6SDimitry Andric   std::array<std::string *, 3> Outputs{{&Object.DebugVar.Value,
299eb11fae6SDimitry Andric                                         &Object.DebugExpr.Value,
300eb11fae6SDimitry Andric                                         &Object.DebugLoc.Value}};
301eb11fae6SDimitry Andric   std::array<const Metadata *, 3> Metas{{DebugVar.Var,
302eb11fae6SDimitry Andric                                         DebugVar.Expr,
303eb11fae6SDimitry Andric                                         DebugVar.Loc}};
304eb11fae6SDimitry Andric   for (unsigned i = 0; i < 3; ++i) {
305eb11fae6SDimitry Andric     raw_string_ostream StrOS(*Outputs[i]);
306eb11fae6SDimitry Andric     Metas[i]->printAsOperand(StrOS, MST);
307eb11fae6SDimitry Andric   }
308eb11fae6SDimitry Andric }
309044eb2f6SDimitry Andric 
convert(yaml::MachineFunction & MF,const MachineRegisterInfo & RegInfo,const TargetRegisterInfo * TRI)3101a82d4c0SDimitry Andric void MIRPrinter::convert(yaml::MachineFunction &MF,
311ee8648bdSDimitry Andric                          const MachineRegisterInfo &RegInfo,
312ee8648bdSDimitry Andric                          const TargetRegisterInfo *TRI) {
3131a82d4c0SDimitry Andric   MF.TracksRegLiveness = RegInfo.tracksLiveness();
314ee8648bdSDimitry Andric 
315ee8648bdSDimitry Andric   // Print the virtual register definitions.
316ee8648bdSDimitry Andric   for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
317e3b55780SDimitry Andric     Register Reg = Register::index2VirtReg(I);
318ee8648bdSDimitry Andric     yaml::VirtualRegisterDefinition VReg;
319ee8648bdSDimitry Andric     VReg.ID = I;
320eb11fae6SDimitry Andric     if (RegInfo.getVRegName(Reg) != "")
321eb11fae6SDimitry Andric       continue;
322044eb2f6SDimitry Andric     ::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI);
323e3b55780SDimitry Andric     Register PreferredReg = RegInfo.getSimpleHint(Reg);
324dd58ef01SDimitry Andric     if (PreferredReg)
325044eb2f6SDimitry Andric       printRegMIR(PreferredReg, VReg.PreferredRegister, TRI);
326ee8648bdSDimitry Andric     MF.VirtualRegisters.push_back(VReg);
327ee8648bdSDimitry Andric   }
328dd58ef01SDimitry Andric 
329dd58ef01SDimitry Andric   // Print the live ins.
330044eb2f6SDimitry Andric   for (std::pair<unsigned, unsigned> LI : RegInfo.liveins()) {
331dd58ef01SDimitry Andric     yaml::MachineFunctionLiveIn LiveIn;
332044eb2f6SDimitry Andric     printRegMIR(LI.first, LiveIn.Register, TRI);
333044eb2f6SDimitry Andric     if (LI.second)
334044eb2f6SDimitry Andric       printRegMIR(LI.second, LiveIn.VirtualRegister, TRI);
335dd58ef01SDimitry Andric     MF.LiveIns.push_back(LiveIn);
336dd58ef01SDimitry Andric   }
33771d5a254SDimitry Andric 
33871d5a254SDimitry Andric   // Prints the callee saved registers.
33971d5a254SDimitry Andric   if (RegInfo.isUpdatedCSRsInitialized()) {
34071d5a254SDimitry Andric     const MCPhysReg *CalleeSavedRegs = RegInfo.getCalleeSavedRegs();
341dd58ef01SDimitry Andric     std::vector<yaml::FlowStringValue> CalleeSavedRegisters;
34271d5a254SDimitry Andric     for (const MCPhysReg *I = CalleeSavedRegs; *I; ++I) {
343dd58ef01SDimitry Andric       yaml::FlowStringValue Reg;
344044eb2f6SDimitry Andric       printRegMIR(*I, Reg, TRI);
345dd58ef01SDimitry Andric       CalleeSavedRegisters.push_back(Reg);
346dd58ef01SDimitry Andric     }
347dd58ef01SDimitry Andric     MF.CalleeSavedRegisters = CalleeSavedRegisters;
3481a82d4c0SDimitry Andric   }
34971d5a254SDimitry Andric }
3501a82d4c0SDimitry Andric 
convert(ModuleSlotTracker & MST,yaml::MachineFrameInfo & YamlMFI,const MachineFrameInfo & MFI)351dd58ef01SDimitry Andric void MIRPrinter::convert(ModuleSlotTracker &MST,
352dd58ef01SDimitry Andric                          yaml::MachineFrameInfo &YamlMFI,
353ee8648bdSDimitry Andric                          const MachineFrameInfo &MFI) {
354ee8648bdSDimitry Andric   YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
355ee8648bdSDimitry Andric   YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
356ee8648bdSDimitry Andric   YamlMFI.HasStackMap = MFI.hasStackMap();
357ee8648bdSDimitry Andric   YamlMFI.HasPatchPoint = MFI.hasPatchPoint();
358ee8648bdSDimitry Andric   YamlMFI.StackSize = MFI.getStackSize();
359ee8648bdSDimitry Andric   YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment();
360cfca06d7SDimitry Andric   YamlMFI.MaxAlignment = MFI.getMaxAlign().value();
361ee8648bdSDimitry Andric   YamlMFI.AdjustsStack = MFI.adjustsStack();
362ee8648bdSDimitry Andric   YamlMFI.HasCalls = MFI.hasCalls();
363a303c417SDimitry Andric   YamlMFI.MaxCallFrameSize = MFI.isMaxCallFrameSizeComputed()
364a303c417SDimitry Andric     ? MFI.getMaxCallFrameSize() : ~0u;
365d8e91e46SDimitry Andric   YamlMFI.CVBytesOfCalleeSavedRegisters =
366d8e91e46SDimitry Andric       MFI.getCVBytesOfCalleeSavedRegisters();
367ee8648bdSDimitry Andric   YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment();
368ee8648bdSDimitry Andric   YamlMFI.HasVAStart = MFI.hasVAStart();
369ee8648bdSDimitry Andric   YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc();
370344a3780SDimitry Andric   YamlMFI.HasTailCall = MFI.hasTailCall();
371ac9a064cSDimitry Andric   YamlMFI.IsCalleeSavedInfoValid = MFI.isCalleeSavedInfoValid();
372eb11fae6SDimitry Andric   YamlMFI.LocalFrameSize = MFI.getLocalFrameSize();
373dd58ef01SDimitry Andric   if (MFI.getSavePoint()) {
374dd58ef01SDimitry Andric     raw_string_ostream StrOS(YamlMFI.SavePoint.Value);
375044eb2f6SDimitry Andric     StrOS << printMBBReference(*MFI.getSavePoint());
376dd58ef01SDimitry Andric   }
377dd58ef01SDimitry Andric   if (MFI.getRestorePoint()) {
378dd58ef01SDimitry Andric     raw_string_ostream StrOS(YamlMFI.RestorePoint.Value);
379044eb2f6SDimitry Andric     StrOS << printMBBReference(*MFI.getRestorePoint());
380dd58ef01SDimitry Andric   }
381ee8648bdSDimitry Andric }
382ee8648bdSDimitry Andric 
convertEntryValueObjects(yaml::MachineFunction & YMF,const MachineFunction & MF,ModuleSlotTracker & MST)3837fa27ce4SDimitry Andric void MIRPrinter::convertEntryValueObjects(yaml::MachineFunction &YMF,
3847fa27ce4SDimitry Andric                                           const MachineFunction &MF,
3857fa27ce4SDimitry Andric                                           ModuleSlotTracker &MST) {
3867fa27ce4SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
3877fa27ce4SDimitry Andric   for (const MachineFunction::VariableDbgInfo &DebugVar :
3887fa27ce4SDimitry Andric        MF.getEntryValueVariableDbgInfo()) {
3897fa27ce4SDimitry Andric     yaml::EntryValueObject &Obj = YMF.EntryValueObjects.emplace_back();
3907fa27ce4SDimitry Andric     printStackObjectDbgInfo(DebugVar, Obj, MST);
3917fa27ce4SDimitry Andric     MCRegister EntryValReg = DebugVar.getEntryValueRegister();
3927fa27ce4SDimitry Andric     printRegMIR(EntryValReg, Obj.EntryValueRegister, TRI);
3937fa27ce4SDimitry Andric   }
3947fa27ce4SDimitry Andric }
3957fa27ce4SDimitry Andric 
convertStackObjects(yaml::MachineFunction & YMF,const MachineFunction & MF,ModuleSlotTracker & MST)396b915e9e0SDimitry Andric void MIRPrinter::convertStackObjects(yaml::MachineFunction &YMF,
397b915e9e0SDimitry Andric                                      const MachineFunction &MF,
398b915e9e0SDimitry Andric                                      ModuleSlotTracker &MST) {
399b915e9e0SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
400b915e9e0SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
401b60736ecSDimitry Andric 
402ee8648bdSDimitry Andric   // Process fixed stack objects.
403b60736ecSDimitry Andric   assert(YMF.FixedStackObjects.empty());
404b60736ecSDimitry Andric   SmallVector<int, 32> FixedStackObjectsIdx;
405b60736ecSDimitry Andric   const int BeginIdx = MFI.getObjectIndexBegin();
406b60736ecSDimitry Andric   if (BeginIdx < 0)
407b60736ecSDimitry Andric     FixedStackObjectsIdx.reserve(-BeginIdx);
408b60736ecSDimitry Andric 
409ee8648bdSDimitry Andric   unsigned ID = 0;
410b60736ecSDimitry Andric   for (int I = BeginIdx; I < 0; ++I, ++ID) {
411b60736ecSDimitry Andric     FixedStackObjectsIdx.push_back(-1); // Fill index for possible dead.
412ee8648bdSDimitry Andric     if (MFI.isDeadObjectIndex(I))
413ee8648bdSDimitry Andric       continue;
414ee8648bdSDimitry Andric 
415ee8648bdSDimitry Andric     yaml::FixedMachineStackObject YamlObject;
416dd58ef01SDimitry Andric     YamlObject.ID = ID;
417ee8648bdSDimitry Andric     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
418ee8648bdSDimitry Andric                           ? yaml::FixedMachineStackObject::SpillSlot
419ee8648bdSDimitry Andric                           : yaml::FixedMachineStackObject::DefaultType;
420ee8648bdSDimitry Andric     YamlObject.Offset = MFI.getObjectOffset(I);
421ee8648bdSDimitry Andric     YamlObject.Size = MFI.getObjectSize(I);
422cfca06d7SDimitry Andric     YamlObject.Alignment = MFI.getObjectAlign(I);
423e6d15924SDimitry Andric     YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
424ee8648bdSDimitry Andric     YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
425ee8648bdSDimitry Andric     YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
426b60736ecSDimitry Andric     // Save the ID' position in FixedStackObjects storage vector.
427b60736ecSDimitry Andric     FixedStackObjectsIdx[ID] = YMF.FixedStackObjects.size();
428b915e9e0SDimitry Andric     YMF.FixedStackObjects.push_back(YamlObject);
429dd58ef01SDimitry Andric     StackObjectOperandMapping.insert(
430e6d15924SDimitry Andric         std::make_pair(I, FrameIndexOperand::createFixed(ID)));
431ee8648bdSDimitry Andric   }
432ee8648bdSDimitry Andric 
433ee8648bdSDimitry Andric   // Process ordinary stack objects.
434b60736ecSDimitry Andric   assert(YMF.StackObjects.empty());
435b60736ecSDimitry Andric   SmallVector<unsigned, 32> StackObjectsIdx;
436b60736ecSDimitry Andric   const int EndIdx = MFI.getObjectIndexEnd();
437b60736ecSDimitry Andric   if (EndIdx > 0)
438b60736ecSDimitry Andric     StackObjectsIdx.reserve(EndIdx);
439ee8648bdSDimitry Andric   ID = 0;
440b60736ecSDimitry Andric   for (int I = 0; I < EndIdx; ++I, ++ID) {
441b60736ecSDimitry Andric     StackObjectsIdx.push_back(-1); // Fill index for possible dead.
442ee8648bdSDimitry Andric     if (MFI.isDeadObjectIndex(I))
443ee8648bdSDimitry Andric       continue;
444ee8648bdSDimitry Andric 
445ee8648bdSDimitry Andric     yaml::MachineStackObject YamlObject;
446dd58ef01SDimitry Andric     YamlObject.ID = ID;
447dd58ef01SDimitry Andric     if (const auto *Alloca = MFI.getObjectAllocation(I))
448cfca06d7SDimitry Andric       YamlObject.Name.Value = std::string(
449b60736ecSDimitry Andric           Alloca->hasName() ? Alloca->getName() : "");
450ee8648bdSDimitry Andric     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
451ee8648bdSDimitry Andric                           ? yaml::MachineStackObject::SpillSlot
452ee8648bdSDimitry Andric                           : MFI.isVariableSizedObjectIndex(I)
453ee8648bdSDimitry Andric                                 ? yaml::MachineStackObject::VariableSized
454ee8648bdSDimitry Andric                                 : yaml::MachineStackObject::DefaultType;
455ee8648bdSDimitry Andric     YamlObject.Offset = MFI.getObjectOffset(I);
456ee8648bdSDimitry Andric     YamlObject.Size = MFI.getObjectSize(I);
457cfca06d7SDimitry Andric     YamlObject.Alignment = MFI.getObjectAlign(I);
458e6d15924SDimitry Andric     YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
459ee8648bdSDimitry Andric 
460b60736ecSDimitry Andric     // Save the ID' position in StackObjects storage vector.
461b60736ecSDimitry Andric     StackObjectsIdx[ID] = YMF.StackObjects.size();
462b915e9e0SDimitry Andric     YMF.StackObjects.push_back(YamlObject);
463dd58ef01SDimitry Andric     StackObjectOperandMapping.insert(std::make_pair(
464e6d15924SDimitry Andric         I, FrameIndexOperand::create(YamlObject.Name.Value, ID)));
465dd58ef01SDimitry Andric   }
466dd58ef01SDimitry Andric 
467dd58ef01SDimitry Andric   for (const auto &CSInfo : MFI.getCalleeSavedInfo()) {
468b60736ecSDimitry Andric     const int FrameIdx = CSInfo.getFrameIdx();
469b60736ecSDimitry Andric     if (!CSInfo.isSpilledToReg() && MFI.isDeadObjectIndex(FrameIdx))
470e6d15924SDimitry Andric       continue;
471e6d15924SDimitry Andric 
472dd58ef01SDimitry Andric     yaml::StringValue Reg;
473044eb2f6SDimitry Andric     printRegMIR(CSInfo.getReg(), Reg, TRI);
474d8e91e46SDimitry Andric     if (!CSInfo.isSpilledToReg()) {
475b60736ecSDimitry Andric       assert(FrameIdx >= MFI.getObjectIndexBegin() &&
476b60736ecSDimitry Andric              FrameIdx < MFI.getObjectIndexEnd() &&
477dd58ef01SDimitry Andric              "Invalid stack object index");
478b60736ecSDimitry Andric       if (FrameIdx < 0) { // Negative index means fixed objects.
479b60736ecSDimitry Andric         auto &Object =
480b60736ecSDimitry Andric             YMF.FixedStackObjects
481b60736ecSDimitry Andric                 [FixedStackObjectsIdx[FrameIdx + MFI.getNumFixedObjects()]];
482b60736ecSDimitry Andric         Object.CalleeSavedRegister = Reg;
483b60736ecSDimitry Andric         Object.CalleeSavedRestored = CSInfo.isRestored();
484044eb2f6SDimitry Andric       } else {
485b60736ecSDimitry Andric         auto &Object = YMF.StackObjects[StackObjectsIdx[FrameIdx]];
486b60736ecSDimitry Andric         Object.CalleeSavedRegister = Reg;
487b60736ecSDimitry Andric         Object.CalleeSavedRestored = CSInfo.isRestored();
488044eb2f6SDimitry Andric       }
489dd58ef01SDimitry Andric     }
490d8e91e46SDimitry Andric   }
491dd58ef01SDimitry Andric   for (unsigned I = 0, E = MFI.getLocalFrameObjectCount(); I < E; ++I) {
492dd58ef01SDimitry Andric     auto LocalObject = MFI.getLocalFrameObjectMap(I);
493b60736ecSDimitry Andric     assert(LocalObject.first >= 0 && "Expected a locally mapped stack object");
494b60736ecSDimitry Andric     YMF.StackObjects[StackObjectsIdx[LocalObject.first]].LocalOffset =
495b60736ecSDimitry Andric         LocalObject.second;
496dd58ef01SDimitry Andric   }
497dd58ef01SDimitry Andric 
498dd58ef01SDimitry Andric   // Print the stack object references in the frame information class after
499dd58ef01SDimitry Andric   // converting the stack objects.
500dd58ef01SDimitry Andric   if (MFI.hasStackProtectorIndex()) {
501b915e9e0SDimitry Andric     raw_string_ostream StrOS(YMF.FrameInfo.StackProtector.Value);
502dd58ef01SDimitry Andric     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
503dd58ef01SDimitry Andric         .printStackObjectReference(MFI.getStackProtectorIndex());
504dd58ef01SDimitry Andric   }
505dd58ef01SDimitry Andric 
506145449b1SDimitry Andric   if (MFI.hasFunctionContextIndex()) {
507145449b1SDimitry Andric     raw_string_ostream StrOS(YMF.FrameInfo.FunctionContext.Value);
508145449b1SDimitry Andric     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
509145449b1SDimitry Andric         .printStackObjectReference(MFI.getFunctionContextIndex());
510145449b1SDimitry Andric   }
511145449b1SDimitry Andric 
512dd58ef01SDimitry Andric   // Print the debug variable information.
513b915e9e0SDimitry Andric   for (const MachineFunction::VariableDbgInfo &DebugVar :
5147fa27ce4SDimitry Andric        MF.getInStackSlotVariableDbgInfo()) {
5157fa27ce4SDimitry Andric     int Idx = DebugVar.getStackSlot();
5167fa27ce4SDimitry Andric     assert(Idx >= MFI.getObjectIndexBegin() && Idx < MFI.getObjectIndexEnd() &&
517dd58ef01SDimitry Andric            "Invalid stack object index");
5187fa27ce4SDimitry Andric     if (Idx < 0) { // Negative index means fixed objects.
519b60736ecSDimitry Andric       auto &Object =
5207fa27ce4SDimitry Andric           YMF.FixedStackObjects[FixedStackObjectsIdx[Idx +
521b60736ecSDimitry Andric                                                      MFI.getNumFixedObjects()]];
522eb11fae6SDimitry Andric       printStackObjectDbgInfo(DebugVar, Object, MST);
523eb11fae6SDimitry Andric     } else {
5247fa27ce4SDimitry Andric       auto &Object = YMF.StackObjects[StackObjectsIdx[Idx]];
525eb11fae6SDimitry Andric       printStackObjectDbgInfo(DebugVar, Object, MST);
526dd58ef01SDimitry Andric     }
527dd58ef01SDimitry Andric   }
528dd58ef01SDimitry Andric }
529dd58ef01SDimitry Andric 
convertCallSiteObjects(yaml::MachineFunction & YMF,const MachineFunction & MF,ModuleSlotTracker & MST)530e6d15924SDimitry Andric void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
531e6d15924SDimitry Andric                                         const MachineFunction &MF,
532e6d15924SDimitry Andric                                         ModuleSlotTracker &MST) {
533e6d15924SDimitry Andric   const auto *TRI = MF.getSubtarget().getRegisterInfo();
534e6d15924SDimitry Andric   for (auto CSInfo : MF.getCallSitesInfo()) {
535e6d15924SDimitry Andric     yaml::CallSiteInfo YmlCS;
536e6d15924SDimitry Andric     yaml::CallSiteInfo::MachineInstrLoc CallLocation;
537e6d15924SDimitry Andric 
538e6d15924SDimitry Andric     // Prepare instruction position.
5391d5ae102SDimitry Andric     MachineBasicBlock::const_instr_iterator CallI = CSInfo.first->getIterator();
540e6d15924SDimitry Andric     CallLocation.BlockNum = CallI->getParent()->getNumber();
541e6d15924SDimitry Andric     // Get call instruction offset from the beginning of block.
5421d5ae102SDimitry Andric     CallLocation.Offset =
5431d5ae102SDimitry Andric         std::distance(CallI->getParent()->instr_begin(), CallI);
544e6d15924SDimitry Andric     YmlCS.CallLocation = CallLocation;
545e6d15924SDimitry Andric     // Construct call arguments and theirs forwarding register info.
546ac9a064cSDimitry Andric     for (auto ArgReg : CSInfo.second.ArgRegPairs) {
547e6d15924SDimitry Andric       yaml::CallSiteInfo::ArgRegPair YmlArgReg;
548e6d15924SDimitry Andric       YmlArgReg.ArgNo = ArgReg.ArgNo;
549e6d15924SDimitry Andric       printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
550e6d15924SDimitry Andric       YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
551e6d15924SDimitry Andric     }
552e6d15924SDimitry Andric     YMF.CallSitesInfo.push_back(YmlCS);
553e6d15924SDimitry Andric   }
554e6d15924SDimitry Andric 
555e6d15924SDimitry Andric   // Sort call info by position of call instructions.
556e6d15924SDimitry Andric   llvm::sort(YMF.CallSitesInfo.begin(), YMF.CallSitesInfo.end(),
557e6d15924SDimitry Andric              [](yaml::CallSiteInfo A, yaml::CallSiteInfo B) {
558e6d15924SDimitry Andric                if (A.CallLocation.BlockNum == B.CallLocation.BlockNum)
559e6d15924SDimitry Andric                  return A.CallLocation.Offset < B.CallLocation.Offset;
560e6d15924SDimitry Andric                return A.CallLocation.BlockNum < B.CallLocation.BlockNum;
561e6d15924SDimitry Andric              });
562e6d15924SDimitry Andric }
563e6d15924SDimitry Andric 
convertMachineMetadataNodes(yaml::MachineFunction & YMF,const MachineFunction & MF,MachineModuleSlotTracker & MST)564344a3780SDimitry Andric void MIRPrinter::convertMachineMetadataNodes(yaml::MachineFunction &YMF,
565344a3780SDimitry Andric                                              const MachineFunction &MF,
566344a3780SDimitry Andric                                              MachineModuleSlotTracker &MST) {
567344a3780SDimitry Andric   MachineModuleSlotTracker::MachineMDNodeListType MDList;
568344a3780SDimitry Andric   MST.collectMachineMDNodes(MDList);
569344a3780SDimitry Andric   for (auto &MD : MDList) {
570344a3780SDimitry Andric     std::string NS;
571344a3780SDimitry Andric     raw_string_ostream StrOS(NS);
572344a3780SDimitry Andric     MD.second->print(StrOS, MST, MF.getFunction().getParent());
573ac9a064cSDimitry Andric     YMF.MachineMetadataNodes.push_back(NS);
574344a3780SDimitry Andric   }
575344a3780SDimitry Andric }
576344a3780SDimitry Andric 
convert(yaml::MachineFunction & MF,const MachineConstantPool & ConstantPool)577dd58ef01SDimitry Andric void MIRPrinter::convert(yaml::MachineFunction &MF,
578dd58ef01SDimitry Andric                          const MachineConstantPool &ConstantPool) {
579dd58ef01SDimitry Andric   unsigned ID = 0;
580dd58ef01SDimitry Andric   for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) {
581dd58ef01SDimitry Andric     std::string Str;
582dd58ef01SDimitry Andric     raw_string_ostream StrOS(Str);
583044eb2f6SDimitry Andric     if (Constant.isMachineConstantPoolEntry()) {
584044eb2f6SDimitry Andric       Constant.Val.MachineCPVal->print(StrOS);
585044eb2f6SDimitry Andric     } else {
586dd58ef01SDimitry Andric       Constant.Val.ConstVal->printAsOperand(StrOS);
587044eb2f6SDimitry Andric     }
588044eb2f6SDimitry Andric 
589044eb2f6SDimitry Andric     yaml::MachineConstantPoolValue YamlConstant;
590dd58ef01SDimitry Andric     YamlConstant.ID = ID++;
591ac9a064cSDimitry Andric     YamlConstant.Value = Str;
592cfca06d7SDimitry Andric     YamlConstant.Alignment = Constant.getAlign();
593044eb2f6SDimitry Andric     YamlConstant.IsTargetSpecific = Constant.isMachineConstantPoolEntry();
594044eb2f6SDimitry Andric 
595dd58ef01SDimitry Andric     MF.Constants.push_back(YamlConstant);
596ee8648bdSDimitry Andric   }
597ee8648bdSDimitry Andric }
598ee8648bdSDimitry Andric 
convert(ModuleSlotTracker & MST,yaml::MachineJumpTable & YamlJTI,const MachineJumpTableInfo & JTI)599ee8648bdSDimitry Andric void MIRPrinter::convert(ModuleSlotTracker &MST,
600dd58ef01SDimitry Andric                          yaml::MachineJumpTable &YamlJTI,
601dd58ef01SDimitry Andric                          const MachineJumpTableInfo &JTI) {
602dd58ef01SDimitry Andric   YamlJTI.Kind = JTI.getEntryKind();
603dd58ef01SDimitry Andric   unsigned ID = 0;
604dd58ef01SDimitry Andric   for (const auto &Table : JTI.getJumpTables()) {
6051a82d4c0SDimitry Andric     std::string Str;
606dd58ef01SDimitry Andric     yaml::MachineJumpTable::Entry Entry;
607dd58ef01SDimitry Andric     Entry.ID = ID++;
608dd58ef01SDimitry Andric     for (const auto *MBB : Table.MBBs) {
6091a82d4c0SDimitry Andric       raw_string_ostream StrOS(Str);
610044eb2f6SDimitry Andric       StrOS << printMBBReference(*MBB);
611ac9a064cSDimitry Andric       Entry.Blocks.push_back(Str);
6121a82d4c0SDimitry Andric       Str.clear();
6131a82d4c0SDimitry Andric     }
614dd58ef01SDimitry Andric     YamlJTI.Entries.push_back(Entry);
615dd58ef01SDimitry Andric   }
6161a82d4c0SDimitry Andric }
6171a82d4c0SDimitry Andric 
initRegisterMaskIds(const MachineFunction & MF)6181a82d4c0SDimitry Andric void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
6191a82d4c0SDimitry Andric   const auto *TRI = MF.getSubtarget().getRegisterInfo();
6201a82d4c0SDimitry Andric   unsigned I = 0;
6211a82d4c0SDimitry Andric   for (const uint32_t *Mask : TRI->getRegMasks())
6221a82d4c0SDimitry Andric     RegisterMaskIds.insert(std::make_pair(Mask, I++));
6231a82d4c0SDimitry Andric }
6241a82d4c0SDimitry Andric 
guessSuccessors(const MachineBasicBlock & MBB,SmallVectorImpl<MachineBasicBlock * > & Result,bool & IsFallthrough)625c46e6a59SDimitry Andric void llvm::guessSuccessors(const MachineBasicBlock &MBB,
626c46e6a59SDimitry Andric                            SmallVectorImpl<MachineBasicBlock*> &Result,
627c46e6a59SDimitry Andric                            bool &IsFallthrough) {
628c46e6a59SDimitry Andric   SmallPtrSet<MachineBasicBlock*,8> Seen;
629c46e6a59SDimitry Andric 
630c46e6a59SDimitry Andric   for (const MachineInstr &MI : MBB) {
631c46e6a59SDimitry Andric     if (MI.isPHI())
632c46e6a59SDimitry Andric       continue;
633c46e6a59SDimitry Andric     for (const MachineOperand &MO : MI.operands()) {
634c46e6a59SDimitry Andric       if (!MO.isMBB())
635c46e6a59SDimitry Andric         continue;
636c46e6a59SDimitry Andric       MachineBasicBlock *Succ = MO.getMBB();
637c46e6a59SDimitry Andric       auto RP = Seen.insert(Succ);
638c46e6a59SDimitry Andric       if (RP.second)
639c46e6a59SDimitry Andric         Result.push_back(Succ);
640c46e6a59SDimitry Andric     }
641c46e6a59SDimitry Andric   }
642c46e6a59SDimitry Andric   MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr();
643c46e6a59SDimitry Andric   IsFallthrough = I == MBB.end() || !I->isBarrier();
644c46e6a59SDimitry Andric }
645c46e6a59SDimitry Andric 
646c46e6a59SDimitry Andric bool
canPredictBranchProbabilities(const MachineBasicBlock & MBB) const647c46e6a59SDimitry Andric MIPrinter::canPredictBranchProbabilities(const MachineBasicBlock &MBB) const {
648c46e6a59SDimitry Andric   if (MBB.succ_size() <= 1)
649c46e6a59SDimitry Andric     return true;
650c46e6a59SDimitry Andric   if (!MBB.hasSuccessorProbabilities())
651c46e6a59SDimitry Andric     return true;
652c46e6a59SDimitry Andric 
653c46e6a59SDimitry Andric   SmallVector<BranchProbability,8> Normalized(MBB.Probs.begin(),
654c46e6a59SDimitry Andric                                               MBB.Probs.end());
655c46e6a59SDimitry Andric   BranchProbability::normalizeProbabilities(Normalized.begin(),
656c46e6a59SDimitry Andric                                             Normalized.end());
657c46e6a59SDimitry Andric   SmallVector<BranchProbability,8> Equal(Normalized.size());
658c46e6a59SDimitry Andric   BranchProbability::normalizeProbabilities(Equal.begin(), Equal.end());
659c46e6a59SDimitry Andric 
660c46e6a59SDimitry Andric   return std::equal(Normalized.begin(), Normalized.end(), Equal.begin());
661c46e6a59SDimitry Andric }
662c46e6a59SDimitry Andric 
canPredictSuccessors(const MachineBasicBlock & MBB) const663c46e6a59SDimitry Andric bool MIPrinter::canPredictSuccessors(const MachineBasicBlock &MBB) const {
664c46e6a59SDimitry Andric   SmallVector<MachineBasicBlock*,8> GuessedSuccs;
665c46e6a59SDimitry Andric   bool GuessedFallthrough;
666c46e6a59SDimitry Andric   guessSuccessors(MBB, GuessedSuccs, GuessedFallthrough);
667c46e6a59SDimitry Andric   if (GuessedFallthrough) {
668c46e6a59SDimitry Andric     const MachineFunction &MF = *MBB.getParent();
669c46e6a59SDimitry Andric     MachineFunction::const_iterator NextI = std::next(MBB.getIterator());
670c46e6a59SDimitry Andric     if (NextI != MF.end()) {
671c46e6a59SDimitry Andric       MachineBasicBlock *Next = const_cast<MachineBasicBlock*>(&*NextI);
672c46e6a59SDimitry Andric       if (!is_contained(GuessedSuccs, Next))
673c46e6a59SDimitry Andric         GuessedSuccs.push_back(Next);
674c46e6a59SDimitry Andric     }
675c46e6a59SDimitry Andric   }
676c46e6a59SDimitry Andric   if (GuessedSuccs.size() != MBB.succ_size())
677c46e6a59SDimitry Andric     return false;
678c46e6a59SDimitry Andric   return std::equal(MBB.succ_begin(), MBB.succ_end(), GuessedSuccs.begin());
679c46e6a59SDimitry Andric }
680c46e6a59SDimitry Andric 
print(const MachineBasicBlock & MBB)681dd58ef01SDimitry Andric void MIPrinter::print(const MachineBasicBlock &MBB) {
682dd58ef01SDimitry Andric   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
683b60736ecSDimitry Andric   MBB.printName(OS,
684b60736ecSDimitry Andric                 MachineBasicBlock::PrintNameIr |
685b60736ecSDimitry Andric                     MachineBasicBlock::PrintNameAttributes,
686b60736ecSDimitry Andric                 &MST);
687dd58ef01SDimitry Andric   OS << ":\n";
688dd58ef01SDimitry Andric 
689dd58ef01SDimitry Andric   bool HasLineAttributes = false;
690dd58ef01SDimitry Andric   // Print the successors
691c46e6a59SDimitry Andric   bool canPredictProbs = canPredictBranchProbabilities(MBB);
692044eb2f6SDimitry Andric   // Even if the list of successors is empty, if we cannot guess it,
693044eb2f6SDimitry Andric   // we need to print it to tell the parser that the list is empty.
694044eb2f6SDimitry Andric   // This is needed, because MI model unreachable as empty blocks
695044eb2f6SDimitry Andric   // with an empty successor list. If the parser would see that
696044eb2f6SDimitry Andric   // without the successor list, it would guess the code would
697044eb2f6SDimitry Andric   // fallthrough.
698044eb2f6SDimitry Andric   if ((!MBB.succ_empty() && !SimplifyMIR) || !canPredictProbs ||
699044eb2f6SDimitry Andric       !canPredictSuccessors(MBB)) {
700dd58ef01SDimitry Andric     OS.indent(2) << "successors:";
701ac9a064cSDimitry Andric     if (!MBB.succ_empty())
702ac9a064cSDimitry Andric       OS << " ";
703dd58ef01SDimitry Andric     for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) {
704dd58ef01SDimitry Andric       if (I != MBB.succ_begin())
705dd58ef01SDimitry Andric         OS << ", ";
706044eb2f6SDimitry Andric       OS << printMBBReference(**I);
707c46e6a59SDimitry Andric       if (!SimplifyMIR || !canPredictProbs)
708b915e9e0SDimitry Andric         OS << '('
709b915e9e0SDimitry Andric            << format("0x%08" PRIx32, MBB.getSuccProbability(I).getNumerator())
710b915e9e0SDimitry Andric            << ')';
711dd58ef01SDimitry Andric     }
712dd58ef01SDimitry Andric     OS << "\n";
713dd58ef01SDimitry Andric     HasLineAttributes = true;
714dd58ef01SDimitry Andric   }
715dd58ef01SDimitry Andric 
716dd58ef01SDimitry Andric   // Print the live in registers.
7177e7b6700SDimitry Andric   const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
718145449b1SDimitry Andric   if (!MBB.livein_empty()) {
7197e7b6700SDimitry Andric     const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
720dd58ef01SDimitry Andric     OS.indent(2) << "liveins: ";
721dd58ef01SDimitry Andric     bool First = true;
722145449b1SDimitry Andric     for (const auto &LI : MBB.liveins_dbg()) {
723dd58ef01SDimitry Andric       if (!First)
724dd58ef01SDimitry Andric         OS << ", ";
725dd58ef01SDimitry Andric       First = false;
726044eb2f6SDimitry Andric       OS << printReg(LI.PhysReg, &TRI);
727b915e9e0SDimitry Andric       if (!LI.LaneMask.all())
728b915e9e0SDimitry Andric         OS << ":0x" << PrintLaneMask(LI.LaneMask);
729dd58ef01SDimitry Andric     }
730dd58ef01SDimitry Andric     OS << "\n";
731dd58ef01SDimitry Andric     HasLineAttributes = true;
732dd58ef01SDimitry Andric   }
733dd58ef01SDimitry Andric 
734ac9a064cSDimitry Andric   if (HasLineAttributes && !MBB.empty())
735dd58ef01SDimitry Andric     OS << "\n";
736dd58ef01SDimitry Andric   bool IsInBundle = false;
737ac9a064cSDimitry Andric   for (const MachineInstr &MI : MBB.instrs()) {
738dd58ef01SDimitry Andric     if (IsInBundle && !MI.isInsideBundle()) {
739dd58ef01SDimitry Andric       OS.indent(2) << "}\n";
740dd58ef01SDimitry Andric       IsInBundle = false;
741dd58ef01SDimitry Andric     }
742dd58ef01SDimitry Andric     OS.indent(IsInBundle ? 4 : 2);
743dd58ef01SDimitry Andric     print(MI);
744dd58ef01SDimitry Andric     if (!IsInBundle && MI.getFlag(MachineInstr::BundledSucc)) {
745dd58ef01SDimitry Andric       OS << " {";
746dd58ef01SDimitry Andric       IsInBundle = true;
747dd58ef01SDimitry Andric     }
748dd58ef01SDimitry Andric     OS << "\n";
749dd58ef01SDimitry Andric   }
750dd58ef01SDimitry Andric   if (IsInBundle)
751dd58ef01SDimitry Andric     OS.indent(2) << "}\n";
752dd58ef01SDimitry Andric }
753dd58ef01SDimitry Andric 
print(const MachineInstr & MI)7541a82d4c0SDimitry Andric void MIPrinter::print(const MachineInstr &MI) {
755044eb2f6SDimitry Andric   const auto *MF = MI.getMF();
75601095a5dSDimitry Andric   const auto &MRI = MF->getRegInfo();
75701095a5dSDimitry Andric   const auto &SubTarget = MF->getSubtarget();
7581a82d4c0SDimitry Andric   const auto *TRI = SubTarget.getRegisterInfo();
7591a82d4c0SDimitry Andric   assert(TRI && "Expected target register info");
7601a82d4c0SDimitry Andric   const auto *TII = SubTarget.getInstrInfo();
7611a82d4c0SDimitry Andric   assert(TII && "Expected target instruction info");
762dd58ef01SDimitry Andric   if (MI.isCFIInstruction())
763dd58ef01SDimitry Andric     assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
7641a82d4c0SDimitry Andric 
765b915e9e0SDimitry Andric   SmallBitVector PrintedTypes(8);
766044eb2f6SDimitry Andric   bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies();
7671a82d4c0SDimitry Andric   unsigned I = 0, E = MI.getNumOperands();
7681a82d4c0SDimitry Andric   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
7691a82d4c0SDimitry Andric          !MI.getOperand(I).isImplicit();
7701a82d4c0SDimitry Andric        ++I) {
7711a82d4c0SDimitry Andric     if (I)
7721a82d4c0SDimitry Andric       OS << ", ";
773cfca06d7SDimitry Andric     print(MI, I, TRI, TII, ShouldPrintRegisterTies,
774044eb2f6SDimitry Andric           MI.getTypeToPrint(I, PrintedTypes, MRI),
775044eb2f6SDimitry Andric           /*PrintDef=*/false);
7761a82d4c0SDimitry Andric   }
7771a82d4c0SDimitry Andric 
7781a82d4c0SDimitry Andric   if (I)
7791a82d4c0SDimitry Andric     OS << " = ";
780dd58ef01SDimitry Andric   if (MI.getFlag(MachineInstr::FrameSetup))
781dd58ef01SDimitry Andric     OS << "frame-setup ";
782eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FrameDestroy))
783eb11fae6SDimitry Andric     OS << "frame-destroy ";
784eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmNoNans))
785eb11fae6SDimitry Andric     OS << "nnan ";
786eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmNoInfs))
787eb11fae6SDimitry Andric     OS << "ninf ";
788eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmNsz))
789eb11fae6SDimitry Andric     OS << "nsz ";
790eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmArcp))
791eb11fae6SDimitry Andric     OS << "arcp ";
792eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmContract))
793eb11fae6SDimitry Andric     OS << "contract ";
794eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmAfn))
795eb11fae6SDimitry Andric     OS << "afn ";
796eb11fae6SDimitry Andric   if (MI.getFlag(MachineInstr::FmReassoc))
797eb11fae6SDimitry Andric     OS << "reassoc ";
798d8e91e46SDimitry Andric   if (MI.getFlag(MachineInstr::NoUWrap))
799d8e91e46SDimitry Andric     OS << "nuw ";
800d8e91e46SDimitry Andric   if (MI.getFlag(MachineInstr::NoSWrap))
801d8e91e46SDimitry Andric     OS << "nsw ";
802d8e91e46SDimitry Andric   if (MI.getFlag(MachineInstr::IsExact))
803d8e91e46SDimitry Andric     OS << "exact ";
804706b4fc4SDimitry Andric   if (MI.getFlag(MachineInstr::NoFPExcept))
805706b4fc4SDimitry Andric     OS << "nofpexcept ";
806cfca06d7SDimitry Andric   if (MI.getFlag(MachineInstr::NoMerge))
807cfca06d7SDimitry Andric     OS << "nomerge ";
8087fa27ce4SDimitry Andric   if (MI.getFlag(MachineInstr::Unpredictable))
8097fa27ce4SDimitry Andric     OS << "unpredictable ";
810b1c73532SDimitry Andric   if (MI.getFlag(MachineInstr::NoConvergent))
811b1c73532SDimitry Andric     OS << "noconvergent ";
812ac9a064cSDimitry Andric   if (MI.getFlag(MachineInstr::NonNeg))
813ac9a064cSDimitry Andric     OS << "nneg ";
814ac9a064cSDimitry Andric   if (MI.getFlag(MachineInstr::Disjoint))
815ac9a064cSDimitry Andric     OS << "disjoint ";
816ac9a064cSDimitry Andric   if (MI.getFlag(MachineInstr::NoUSWrap))
817ac9a064cSDimitry Andric     OS << "nusw ";
818eb11fae6SDimitry Andric 
8191a82d4c0SDimitry Andric   OS << TII->getName(MI.getOpcode());
8201a82d4c0SDimitry Andric   if (I < E)
8211a82d4c0SDimitry Andric     OS << ' ';
8221a82d4c0SDimitry Andric 
8231a82d4c0SDimitry Andric   bool NeedComma = false;
8241a82d4c0SDimitry Andric   for (; I < E; ++I) {
8251a82d4c0SDimitry Andric     if (NeedComma)
8261a82d4c0SDimitry Andric       OS << ", ";
827cfca06d7SDimitry Andric     print(MI, I, TRI, TII, ShouldPrintRegisterTies,
828044eb2f6SDimitry Andric           MI.getTypeToPrint(I, PrintedTypes, MRI));
8291a82d4c0SDimitry Andric     NeedComma = true;
8301a82d4c0SDimitry Andric   }
831dd58ef01SDimitry Andric 
832d8e91e46SDimitry Andric   // Print any optional symbols attached to this instruction as-if they were
833d8e91e46SDimitry Andric   // operands.
834d8e91e46SDimitry Andric   if (MCSymbol *PreInstrSymbol = MI.getPreInstrSymbol()) {
835d8e91e46SDimitry Andric     if (NeedComma)
836d8e91e46SDimitry Andric       OS << ',';
837d8e91e46SDimitry Andric     OS << " pre-instr-symbol ";
838d8e91e46SDimitry Andric     MachineOperand::printSymbol(OS, *PreInstrSymbol);
839d8e91e46SDimitry Andric     NeedComma = true;
840d8e91e46SDimitry Andric   }
841d8e91e46SDimitry Andric   if (MCSymbol *PostInstrSymbol = MI.getPostInstrSymbol()) {
842d8e91e46SDimitry Andric     if (NeedComma)
843d8e91e46SDimitry Andric       OS << ',';
844d8e91e46SDimitry Andric     OS << " post-instr-symbol ";
845d8e91e46SDimitry Andric     MachineOperand::printSymbol(OS, *PostInstrSymbol);
846d8e91e46SDimitry Andric     NeedComma = true;
847d8e91e46SDimitry Andric   }
848706b4fc4SDimitry Andric   if (MDNode *HeapAllocMarker = MI.getHeapAllocMarker()) {
849706b4fc4SDimitry Andric     if (NeedComma)
850706b4fc4SDimitry Andric       OS << ',';
851706b4fc4SDimitry Andric     OS << " heap-alloc-marker ";
852706b4fc4SDimitry Andric     HeapAllocMarker->printAsOperand(OS, MST);
853706b4fc4SDimitry Andric     NeedComma = true;
854706b4fc4SDimitry Andric   }
855e3b55780SDimitry Andric   if (MDNode *PCSections = MI.getPCSections()) {
856e3b55780SDimitry Andric     if (NeedComma)
857e3b55780SDimitry Andric       OS << ',';
858e3b55780SDimitry Andric     OS << " pcsections ";
859e3b55780SDimitry Andric     PCSections->printAsOperand(OS, MST);
860e3b55780SDimitry Andric     NeedComma = true;
861e3b55780SDimitry Andric   }
862ac9a064cSDimitry Andric   if (MDNode *MMRA = MI.getMMRAMetadata()) {
863ac9a064cSDimitry Andric     if (NeedComma)
864ac9a064cSDimitry Andric       OS << ',';
865ac9a064cSDimitry Andric     OS << " mmra ";
866ac9a064cSDimitry Andric     MMRA->printAsOperand(OS, MST);
867ac9a064cSDimitry Andric     NeedComma = true;
868ac9a064cSDimitry Andric   }
869e3b55780SDimitry Andric   if (uint32_t CFIType = MI.getCFIType()) {
870e3b55780SDimitry Andric     if (NeedComma)
871e3b55780SDimitry Andric       OS << ',';
872e3b55780SDimitry Andric     OS << " cfi-type " << CFIType;
873e3b55780SDimitry Andric     NeedComma = true;
874e3b55780SDimitry Andric   }
875d8e91e46SDimitry Andric 
876b60736ecSDimitry Andric   if (auto Num = MI.peekDebugInstrNum()) {
877b60736ecSDimitry Andric     if (NeedComma)
878b60736ecSDimitry Andric       OS << ',';
879b60736ecSDimitry Andric     OS << " debug-instr-number " << Num;
880b60736ecSDimitry Andric     NeedComma = true;
881b60736ecSDimitry Andric   }
882b60736ecSDimitry Andric 
883cfca06d7SDimitry Andric   if (PrintLocations) {
884eb11fae6SDimitry Andric     if (const DebugLoc &DL = MI.getDebugLoc()) {
885dd58ef01SDimitry Andric       if (NeedComma)
886dd58ef01SDimitry Andric         OS << ',';
887dd58ef01SDimitry Andric       OS << " debug-location ";
888eb11fae6SDimitry Andric       DL->printAsOperand(OS, MST);
889dd58ef01SDimitry Andric     }
890cfca06d7SDimitry Andric   }
891dd58ef01SDimitry Andric 
892dd58ef01SDimitry Andric   if (!MI.memoperands_empty()) {
893dd58ef01SDimitry Andric     OS << " :: ";
894044eb2f6SDimitry Andric     const LLVMContext &Context = MF->getFunction().getContext();
895eb11fae6SDimitry Andric     const MachineFrameInfo &MFI = MF->getFrameInfo();
896dd58ef01SDimitry Andric     bool NeedComma = false;
897dd58ef01SDimitry Andric     for (const auto *Op : MI.memoperands()) {
898dd58ef01SDimitry Andric       if (NeedComma)
899dd58ef01SDimitry Andric         OS << ", ";
900eb11fae6SDimitry Andric       Op->print(OS, MST, SSNs, Context, &MFI, TII);
901dd58ef01SDimitry Andric       NeedComma = true;
902dd58ef01SDimitry Andric     }
903dd58ef01SDimitry Andric   }
9041a82d4c0SDimitry Andric }
9051a82d4c0SDimitry Andric 
printStackObjectReference(int FrameIndex)906dd58ef01SDimitry Andric void MIPrinter::printStackObjectReference(int FrameIndex) {
907dd58ef01SDimitry Andric   auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
908dd58ef01SDimitry Andric   assert(ObjectInfo != StackObjectOperandMapping.end() &&
909dd58ef01SDimitry Andric          "Invalid frame index");
910dd58ef01SDimitry Andric   const FrameIndexOperand &Operand = ObjectInfo->second;
911044eb2f6SDimitry Andric   MachineOperand::printStackObjectReference(OS, Operand.ID, Operand.IsFixed,
912044eb2f6SDimitry Andric                                             Operand.Name);
913dd58ef01SDimitry Andric }
914dd58ef01SDimitry Andric 
formatOperandComment(std::string Comment)915cfca06d7SDimitry Andric static std::string formatOperandComment(std::string Comment) {
916cfca06d7SDimitry Andric   if (Comment.empty())
917cfca06d7SDimitry Andric     return Comment;
918cfca06d7SDimitry Andric   return std::string(" /* " + Comment + " */");
919cfca06d7SDimitry Andric }
920cfca06d7SDimitry Andric 
print(const MachineInstr & MI,unsigned OpIdx,const TargetRegisterInfo * TRI,const TargetInstrInfo * TII,bool ShouldPrintRegisterTies,LLT TypeToPrint,bool PrintDef)921044eb2f6SDimitry Andric void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx,
922044eb2f6SDimitry Andric                       const TargetRegisterInfo *TRI,
923cfca06d7SDimitry Andric                       const TargetInstrInfo *TII,
924044eb2f6SDimitry Andric                       bool ShouldPrintRegisterTies, LLT TypeToPrint,
925044eb2f6SDimitry Andric                       bool PrintDef) {
926044eb2f6SDimitry Andric   const MachineOperand &Op = MI.getOperand(OpIdx);
927cfca06d7SDimitry Andric   std::string MOComment = TII->createMIROperandComment(MI, Op, OpIdx, TRI);
928cfca06d7SDimitry Andric 
9291a82d4c0SDimitry Andric   switch (Op.getType()) {
9301a82d4c0SDimitry Andric   case MachineOperand::MO_Immediate:
931044eb2f6SDimitry Andric     if (MI.isOperandSubregIdx(OpIdx)) {
932044eb2f6SDimitry Andric       MachineOperand::printTargetFlags(OS, Op);
933eb11fae6SDimitry Andric       MachineOperand::printSubRegIdx(OS, Op.getImm(), TRI);
9341a82d4c0SDimitry Andric       break;
935044eb2f6SDimitry Andric     }
936e3b55780SDimitry Andric     [[fallthrough]];
937044eb2f6SDimitry Andric   case MachineOperand::MO_Register:
938dd58ef01SDimitry Andric   case MachineOperand::MO_CImmediate:
939c7dac04cSDimitry Andric   case MachineOperand::MO_FPImmediate:
940044eb2f6SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
941044eb2f6SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
942044eb2f6SDimitry Andric   case MachineOperand::MO_TargetIndex:
943044eb2f6SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
944044eb2f6SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
945044eb2f6SDimitry Andric   case MachineOperand::MO_GlobalAddress:
946044eb2f6SDimitry Andric   case MachineOperand::MO_RegisterLiveOut:
947044eb2f6SDimitry Andric   case MachineOperand::MO_Metadata:
948c7dac04cSDimitry Andric   case MachineOperand::MO_MCSymbol:
949c7dac04cSDimitry Andric   case MachineOperand::MO_CFIIndex:
950c7dac04cSDimitry Andric   case MachineOperand::MO_IntrinsicID:
951c7dac04cSDimitry Andric   case MachineOperand::MO_Predicate:
9521d5ae102SDimitry Andric   case MachineOperand::MO_BlockAddress:
953e3b55780SDimitry Andric   case MachineOperand::MO_DbgInstrRef:
9541d5ae102SDimitry Andric   case MachineOperand::MO_ShuffleMask: {
955044eb2f6SDimitry Andric     unsigned TiedOperandIdx = 0;
956044eb2f6SDimitry Andric     if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef())
957044eb2f6SDimitry Andric       TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx);
958044eb2f6SDimitry Andric     const TargetIntrinsicInfo *TII = MI.getMF()->getTarget().getIntrinsicInfo();
959706b4fc4SDimitry Andric     Op.print(OS, MST, TypeToPrint, OpIdx, PrintDef, /*IsStandalone=*/false,
960eb11fae6SDimitry Andric              ShouldPrintRegisterTies, TiedOperandIdx, TRI, TII);
961cfca06d7SDimitry Andric       OS << formatOperandComment(MOComment);
962dd58ef01SDimitry Andric     break;
963044eb2f6SDimitry Andric   }
964dd58ef01SDimitry Andric   case MachineOperand::MO_FrameIndex:
965dd58ef01SDimitry Andric     printStackObjectReference(Op.getIndex());
966dd58ef01SDimitry Andric     break;
9671a82d4c0SDimitry Andric   case MachineOperand::MO_RegisterMask: {
9681a82d4c0SDimitry Andric     auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
9691a82d4c0SDimitry Andric     if (RegMaskInfo != RegisterMaskIds.end())
9701a82d4c0SDimitry Andric       OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
9711a82d4c0SDimitry Andric     else
97271d5a254SDimitry Andric       printCustomRegMask(Op.getRegMask(), OS, TRI);
9731a82d4c0SDimitry Andric     break;
9741a82d4c0SDimitry Andric   }
975dd58ef01SDimitry Andric   }
976dd58ef01SDimitry Andric }
977dd58ef01SDimitry Andric 
printIRValue(raw_ostream & OS,const Value & V,ModuleSlotTracker & MST)978706b4fc4SDimitry Andric void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V,
979706b4fc4SDimitry Andric                                 ModuleSlotTracker &MST) {
980706b4fc4SDimitry Andric   if (isa<GlobalValue>(V)) {
981706b4fc4SDimitry Andric     V.printAsOperand(OS, /*PrintType=*/false, MST);
982706b4fc4SDimitry Andric     return;
983706b4fc4SDimitry Andric   }
984706b4fc4SDimitry Andric   if (isa<Constant>(V)) {
985706b4fc4SDimitry Andric     // Machine memory operands can load/store to/from constant value pointers.
986706b4fc4SDimitry Andric     OS << '`';
987706b4fc4SDimitry Andric     V.printAsOperand(OS, /*PrintType=*/true, MST);
988706b4fc4SDimitry Andric     OS << '`';
989706b4fc4SDimitry Andric     return;
990706b4fc4SDimitry Andric   }
991706b4fc4SDimitry Andric   OS << "%ir.";
992706b4fc4SDimitry Andric   if (V.hasName()) {
993706b4fc4SDimitry Andric     printLLVMNameWithoutPrefix(OS, V.getName());
994706b4fc4SDimitry Andric     return;
995706b4fc4SDimitry Andric   }
996706b4fc4SDimitry Andric   int Slot = MST.getCurrentFunction() ? MST.getLocalSlot(&V) : -1;
997706b4fc4SDimitry Andric   MachineOperand::printIRSlotNumber(OS, Slot);
998706b4fc4SDimitry Andric }
999706b4fc4SDimitry Andric 
printMIR(raw_ostream & OS,const Module & M)10003a0822f0SDimitry Andric void llvm::printMIR(raw_ostream &OS, const Module &M) {
1001ac9a064cSDimitry Andric   ScopedDbgInfoFormatSetter FormatSetter(const_cast<Module &>(M),
1002ac9a064cSDimitry Andric                                          WriteNewDbgInfoFormat);
1003b1c73532SDimitry Andric 
10043a0822f0SDimitry Andric   yaml::Output Out(OS);
10053a0822f0SDimitry Andric   Out << const_cast<Module &>(M);
10063a0822f0SDimitry Andric }
10073a0822f0SDimitry Andric 
printMIR(raw_ostream & OS,const MachineFunction & MF)10083a0822f0SDimitry Andric void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
1009ac9a064cSDimitry Andric   // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info
1010b1c73532SDimitry Andric   // in dbg.value format.
1011ac9a064cSDimitry Andric   ScopedDbgInfoFormatSetter FormatSetter(
1012ac9a064cSDimitry Andric       const_cast<Function &>(MF.getFunction()), WriteNewDbgInfoFormat);
1013b1c73532SDimitry Andric 
10143a0822f0SDimitry Andric   MIRPrinter Printer(OS);
10153a0822f0SDimitry Andric   Printer.print(MF);
10163a0822f0SDimitry Andric }
1017