1345c1449SAlex Lorenz //===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
2345c1449SAlex Lorenz //
3345c1449SAlex Lorenz //                     The LLVM Compiler Infrastructure
4345c1449SAlex Lorenz //
5345c1449SAlex Lorenz // This file is distributed under the University of Illinois Open Source
6345c1449SAlex Lorenz // License. See LICENSE.TXT for details.
7345c1449SAlex Lorenz //
8345c1449SAlex Lorenz //===----------------------------------------------------------------------===//
9345c1449SAlex Lorenz //
10345c1449SAlex Lorenz // This file implements the class that prints out the LLVM IR and machine
11345c1449SAlex Lorenz // functions using the MIR serialization format.
12345c1449SAlex Lorenz //
13345c1449SAlex Lorenz //===----------------------------------------------------------------------===//
14345c1449SAlex Lorenz 
15345c1449SAlex Lorenz #include "MIRPrinter.h"
16345c1449SAlex Lorenz #include "llvm/ADT/STLExtras.h"
17ab980499SAlex Lorenz #include "llvm/CodeGen/MachineConstantPool.h"
18345c1449SAlex Lorenz #include "llvm/CodeGen/MachineFunction.h"
1960541c1dSAlex Lorenz #include "llvm/CodeGen/MachineFrameInfo.h"
20f4baeb51SAlex Lorenz #include "llvm/CodeGen/MachineModuleInfo.h"
2154565cf0SAlex Lorenz #include "llvm/CodeGen/MachineRegisterInfo.h"
22345c1449SAlex Lorenz #include "llvm/CodeGen/MIRYamlMapping.h"
234f093bf1SAlex Lorenz #include "llvm/IR/BasicBlock.h"
2437643a04SAlex Lorenz #include "llvm/IR/Instructions.h"
256ede3744SAlex Lorenz #include "llvm/IR/IRPrintingPasses.h"
26345c1449SAlex Lorenz #include "llvm/IR/Module.h"
27900b5cb2SAlex Lorenz #include "llvm/IR/ModuleSlotTracker.h"
28345c1449SAlex Lorenz #include "llvm/Support/MemoryBuffer.h"
29345c1449SAlex Lorenz #include "llvm/Support/raw_ostream.h"
30345c1449SAlex Lorenz #include "llvm/Support/YAMLTraits.h"
318e0a1b48SAlex Lorenz #include "llvm/Target/TargetInstrInfo.h"
328e0a1b48SAlex Lorenz #include "llvm/Target/TargetSubtargetInfo.h"
33345c1449SAlex Lorenz 
34345c1449SAlex Lorenz using namespace llvm;
35345c1449SAlex Lorenz 
36345c1449SAlex Lorenz namespace {
37345c1449SAlex Lorenz 
387feaf7c6SAlex Lorenz /// This structure describes how to print out stack object references.
397feaf7c6SAlex Lorenz struct FrameIndexOperand {
407feaf7c6SAlex Lorenz   std::string Name;
417feaf7c6SAlex Lorenz   unsigned ID;
427feaf7c6SAlex Lorenz   bool IsFixed;
437feaf7c6SAlex Lorenz 
447feaf7c6SAlex Lorenz   FrameIndexOperand(StringRef Name, unsigned ID, bool IsFixed)
457feaf7c6SAlex Lorenz       : Name(Name.str()), ID(ID), IsFixed(IsFixed) {}
467feaf7c6SAlex Lorenz 
477feaf7c6SAlex Lorenz   /// Return an ordinary stack object reference.
487feaf7c6SAlex Lorenz   static FrameIndexOperand create(StringRef Name, unsigned ID) {
497feaf7c6SAlex Lorenz     return FrameIndexOperand(Name, ID, /*IsFixed=*/false);
507feaf7c6SAlex Lorenz   }
517feaf7c6SAlex Lorenz 
527feaf7c6SAlex Lorenz   /// Return a fixed stack object reference.
537feaf7c6SAlex Lorenz   static FrameIndexOperand createFixed(unsigned ID) {
547feaf7c6SAlex Lorenz     return FrameIndexOperand("", ID, /*IsFixed=*/true);
557feaf7c6SAlex Lorenz   }
567feaf7c6SAlex Lorenz };
577feaf7c6SAlex Lorenz 
58345c1449SAlex Lorenz /// This class prints out the machine functions using the MIR serialization
59345c1449SAlex Lorenz /// format.
60345c1449SAlex Lorenz class MIRPrinter {
61345c1449SAlex Lorenz   raw_ostream &OS;
628f6f4285SAlex Lorenz   DenseMap<const uint32_t *, unsigned> RegisterMaskIds;
637feaf7c6SAlex Lorenz   /// Maps from stack object indices to operand indices which will be used when
647feaf7c6SAlex Lorenz   /// printing frame index machine operands.
657feaf7c6SAlex Lorenz   DenseMap<int, FrameIndexOperand> StackObjectOperandMapping;
66345c1449SAlex Lorenz 
67345c1449SAlex Lorenz public:
68345c1449SAlex Lorenz   MIRPrinter(raw_ostream &OS) : OS(OS) {}
69345c1449SAlex Lorenz 
70345c1449SAlex Lorenz   void print(const MachineFunction &MF);
714f093bf1SAlex Lorenz 
7228148ba8SAlex Lorenz   void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
7328148ba8SAlex Lorenz                const TargetRegisterInfo *TRI);
7460541c1dSAlex Lorenz   void convert(yaml::MachineFrameInfo &YamlMFI, const MachineFrameInfo &MFI);
75ab980499SAlex Lorenz   void convert(yaml::MachineFunction &MF,
76ab980499SAlex Lorenz                const MachineConstantPool &ConstantPool);
776799e9b3SAlex Lorenz   void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
786799e9b3SAlex Lorenz                const MachineJumpTableInfo &JTI);
79900b5cb2SAlex Lorenz   void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB,
805d6108e4SAlex Lorenz                const MachineBasicBlock &MBB);
81f6bc8667SAlex Lorenz   void convertStackObjects(yaml::MachineFunction &MF,
82f6bc8667SAlex Lorenz                            const MachineFrameInfo &MFI);
838f6f4285SAlex Lorenz 
848f6f4285SAlex Lorenz private:
858f6f4285SAlex Lorenz   void initRegisterMaskIds(const MachineFunction &MF);
86345c1449SAlex Lorenz };
87345c1449SAlex Lorenz 
888e0a1b48SAlex Lorenz /// This class prints out the machine instructions using the MIR serialization
898e0a1b48SAlex Lorenz /// format.
908e0a1b48SAlex Lorenz class MIPrinter {
918e0a1b48SAlex Lorenz   raw_ostream &OS;
92900b5cb2SAlex Lorenz   ModuleSlotTracker &MST;
938f6f4285SAlex Lorenz   const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
947feaf7c6SAlex Lorenz   const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
958e0a1b48SAlex Lorenz 
968e0a1b48SAlex Lorenz public:
97900b5cb2SAlex Lorenz   MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
987feaf7c6SAlex Lorenz             const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
997feaf7c6SAlex Lorenz             const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping)
1007feaf7c6SAlex Lorenz       : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds),
1017feaf7c6SAlex Lorenz         StackObjectOperandMapping(StackObjectOperandMapping) {}
1028e0a1b48SAlex Lorenz 
1038e0a1b48SAlex Lorenz   void print(const MachineInstr &MI);
1045d26fa83SAlex Lorenz   void printMBBReference(const MachineBasicBlock &MBB);
1057feaf7c6SAlex Lorenz   void printStackObjectReference(int FrameIndex);
106f3db51deSAlex Lorenz   void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
107f4baeb51SAlex Lorenz 
108f4baeb51SAlex Lorenz   void print(const MCCFIInstruction &CFI);
1098e0a1b48SAlex Lorenz };
1108e0a1b48SAlex Lorenz 
111345c1449SAlex Lorenz } // end anonymous namespace
112345c1449SAlex Lorenz 
113345c1449SAlex Lorenz namespace llvm {
114345c1449SAlex Lorenz namespace yaml {
115345c1449SAlex Lorenz 
116345c1449SAlex Lorenz /// This struct serializes the LLVM IR module.
117345c1449SAlex Lorenz template <> struct BlockScalarTraits<Module> {
118345c1449SAlex Lorenz   static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
119345c1449SAlex Lorenz     Mod.print(OS, nullptr);
120345c1449SAlex Lorenz   }
121345c1449SAlex Lorenz   static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
122345c1449SAlex Lorenz     llvm_unreachable("LLVM Module is supposed to be parsed separately");
123345c1449SAlex Lorenz     return "";
124345c1449SAlex Lorenz   }
125345c1449SAlex Lorenz };
126345c1449SAlex Lorenz 
127345c1449SAlex Lorenz } // end namespace yaml
128345c1449SAlex Lorenz } // end namespace llvm
129345c1449SAlex Lorenz 
13015a00a85SAlex Lorenz static void printReg(unsigned Reg, raw_ostream &OS,
13115a00a85SAlex Lorenz                      const TargetRegisterInfo *TRI) {
13215a00a85SAlex Lorenz   // TODO: Print Stack Slots.
13315a00a85SAlex Lorenz   if (!Reg)
13415a00a85SAlex Lorenz     OS << '_';
13515a00a85SAlex Lorenz   else if (TargetRegisterInfo::isVirtualRegister(Reg))
13615a00a85SAlex Lorenz     OS << '%' << TargetRegisterInfo::virtReg2Index(Reg);
13715a00a85SAlex Lorenz   else if (Reg < TRI->getNumRegs())
13815a00a85SAlex Lorenz     OS << '%' << StringRef(TRI->getName(Reg)).lower();
13915a00a85SAlex Lorenz   else
14015a00a85SAlex Lorenz     llvm_unreachable("Can't print this kind of register yet");
14115a00a85SAlex Lorenz }
14215a00a85SAlex Lorenz 
143345c1449SAlex Lorenz void MIRPrinter::print(const MachineFunction &MF) {
1448f6f4285SAlex Lorenz   initRegisterMaskIds(MF);
1458f6f4285SAlex Lorenz 
146345c1449SAlex Lorenz   yaml::MachineFunction YamlMF;
147345c1449SAlex Lorenz   YamlMF.Name = MF.getName();
1485b5f9753SAlex Lorenz   YamlMF.Alignment = MF.getAlignment();
1495b5f9753SAlex Lorenz   YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
1505b5f9753SAlex Lorenz   YamlMF.HasInlineAsm = MF.hasInlineAsm();
15128148ba8SAlex Lorenz   convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
15260541c1dSAlex Lorenz   convert(YamlMF.FrameInfo, *MF.getFrameInfo());
153f6bc8667SAlex Lorenz   convertStackObjects(YamlMF, *MF.getFrameInfo());
154ab980499SAlex Lorenz   if (const auto *ConstantPool = MF.getConstantPool())
155ab980499SAlex Lorenz     convert(YamlMF, *ConstantPool);
15633f0aef3SAlex Lorenz 
157900b5cb2SAlex Lorenz   ModuleSlotTracker MST(MF.getFunction()->getParent());
1586799e9b3SAlex Lorenz   if (const auto *JumpTableInfo = MF.getJumpTableInfo())
1596799e9b3SAlex Lorenz     convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
1606799e9b3SAlex Lorenz   int I = 0;
1614f093bf1SAlex Lorenz   for (const auto &MBB : MF) {
16233f0aef3SAlex Lorenz     // TODO: Allow printing of non sequentially numbered MBBs.
16333f0aef3SAlex Lorenz     // This is currently needed as the basic block references get their index
16433f0aef3SAlex Lorenz     // from MBB.getNumber(), thus it should be sequential so that the parser can
16533f0aef3SAlex Lorenz     // map back to the correct MBBs when parsing the output.
16633f0aef3SAlex Lorenz     assert(MBB.getNumber() == I++ &&
16733f0aef3SAlex Lorenz            "Can't print MBBs that aren't sequentially numbered");
168ec6b26b9SAlex Lorenz     (void)I;
1694f093bf1SAlex Lorenz     yaml::MachineBasicBlock YamlMBB;
170900b5cb2SAlex Lorenz     convert(MST, YamlMBB, MBB);
1714f093bf1SAlex Lorenz     YamlMF.BasicBlocks.push_back(YamlMBB);
1724f093bf1SAlex Lorenz   }
173345c1449SAlex Lorenz   yaml::Output Out(OS);
174345c1449SAlex Lorenz   Out << YamlMF;
175345c1449SAlex Lorenz }
176345c1449SAlex Lorenz 
17754565cf0SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
17828148ba8SAlex Lorenz                          const MachineRegisterInfo &RegInfo,
17928148ba8SAlex Lorenz                          const TargetRegisterInfo *TRI) {
18054565cf0SAlex Lorenz   MF.IsSSA = RegInfo.isSSA();
18154565cf0SAlex Lorenz   MF.TracksRegLiveness = RegInfo.tracksLiveness();
18254565cf0SAlex Lorenz   MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
18328148ba8SAlex Lorenz 
18428148ba8SAlex Lorenz   // Print the virtual register definitions.
18528148ba8SAlex Lorenz   for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
18628148ba8SAlex Lorenz     unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
18728148ba8SAlex Lorenz     yaml::VirtualRegisterDefinition VReg;
18828148ba8SAlex Lorenz     VReg.ID = I;
18928148ba8SAlex Lorenz     VReg.Class =
19028148ba8SAlex Lorenz         StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
19128148ba8SAlex Lorenz     MF.VirtualRegisters.push_back(VReg);
19228148ba8SAlex Lorenz   }
19354565cf0SAlex Lorenz }
19454565cf0SAlex Lorenz 
19560541c1dSAlex Lorenz void MIRPrinter::convert(yaml::MachineFrameInfo &YamlMFI,
19660541c1dSAlex Lorenz                          const MachineFrameInfo &MFI) {
19760541c1dSAlex Lorenz   YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
19860541c1dSAlex Lorenz   YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
19960541c1dSAlex Lorenz   YamlMFI.HasStackMap = MFI.hasStackMap();
20060541c1dSAlex Lorenz   YamlMFI.HasPatchPoint = MFI.hasPatchPoint();
20160541c1dSAlex Lorenz   YamlMFI.StackSize = MFI.getStackSize();
20260541c1dSAlex Lorenz   YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment();
20360541c1dSAlex Lorenz   YamlMFI.MaxAlignment = MFI.getMaxAlignment();
20460541c1dSAlex Lorenz   YamlMFI.AdjustsStack = MFI.adjustsStack();
20560541c1dSAlex Lorenz   YamlMFI.HasCalls = MFI.hasCalls();
20660541c1dSAlex Lorenz   YamlMFI.MaxCallFrameSize = MFI.getMaxCallFrameSize();
20760541c1dSAlex Lorenz   YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment();
20860541c1dSAlex Lorenz   YamlMFI.HasVAStart = MFI.hasVAStart();
20960541c1dSAlex Lorenz   YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc();
21060541c1dSAlex Lorenz }
21160541c1dSAlex Lorenz 
212f6bc8667SAlex Lorenz void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
213f6bc8667SAlex Lorenz                                      const MachineFrameInfo &MFI) {
214de491f05SAlex Lorenz   // Process fixed stack objects.
215f6bc8667SAlex Lorenz   unsigned ID = 0;
216de491f05SAlex Lorenz   for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
217de491f05SAlex Lorenz     if (MFI.isDeadObjectIndex(I))
218de491f05SAlex Lorenz       continue;
219de491f05SAlex Lorenz 
220de491f05SAlex Lorenz     yaml::FixedMachineStackObject YamlObject;
2217feaf7c6SAlex Lorenz     YamlObject.ID = ID;
222de491f05SAlex Lorenz     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
223de491f05SAlex Lorenz                           ? yaml::FixedMachineStackObject::SpillSlot
224de491f05SAlex Lorenz                           : yaml::FixedMachineStackObject::DefaultType;
225de491f05SAlex Lorenz     YamlObject.Offset = MFI.getObjectOffset(I);
226de491f05SAlex Lorenz     YamlObject.Size = MFI.getObjectSize(I);
227de491f05SAlex Lorenz     YamlObject.Alignment = MFI.getObjectAlignment(I);
228de491f05SAlex Lorenz     YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
229de491f05SAlex Lorenz     YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
230de491f05SAlex Lorenz     MF.FixedStackObjects.push_back(YamlObject);
2317feaf7c6SAlex Lorenz     StackObjectOperandMapping.insert(
2327feaf7c6SAlex Lorenz         std::make_pair(I, FrameIndexOperand::createFixed(ID++)));
233de491f05SAlex Lorenz   }
234de491f05SAlex Lorenz 
235de491f05SAlex Lorenz   // Process ordinary stack objects.
236de491f05SAlex Lorenz   ID = 0;
237f6bc8667SAlex Lorenz   for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I) {
238f6bc8667SAlex Lorenz     if (MFI.isDeadObjectIndex(I))
239f6bc8667SAlex Lorenz       continue;
240f6bc8667SAlex Lorenz 
241f6bc8667SAlex Lorenz     yaml::MachineStackObject YamlObject;
2427feaf7c6SAlex Lorenz     YamlObject.ID = ID;
24337643a04SAlex Lorenz     if (const auto *Alloca = MFI.getObjectAllocation(I))
24437643a04SAlex Lorenz       YamlObject.Name.Value =
24537643a04SAlex Lorenz           Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>";
246f6bc8667SAlex Lorenz     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
247f6bc8667SAlex Lorenz                           ? yaml::MachineStackObject::SpillSlot
248418f3ec1SAlex Lorenz                           : MFI.isVariableSizedObjectIndex(I)
249418f3ec1SAlex Lorenz                                 ? yaml::MachineStackObject::VariableSized
250f6bc8667SAlex Lorenz                                 : yaml::MachineStackObject::DefaultType;
251f6bc8667SAlex Lorenz     YamlObject.Offset = MFI.getObjectOffset(I);
252f6bc8667SAlex Lorenz     YamlObject.Size = MFI.getObjectSize(I);
253f6bc8667SAlex Lorenz     YamlObject.Alignment = MFI.getObjectAlignment(I);
254f6bc8667SAlex Lorenz 
255f6bc8667SAlex Lorenz     MF.StackObjects.push_back(YamlObject);
2567feaf7c6SAlex Lorenz     StackObjectOperandMapping.insert(std::make_pair(
2577feaf7c6SAlex Lorenz         I, FrameIndexOperand::create(YamlObject.Name.Value, ID++)));
258f6bc8667SAlex Lorenz   }
259f6bc8667SAlex Lorenz }
260f6bc8667SAlex Lorenz 
261ab980499SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
262ab980499SAlex Lorenz                          const MachineConstantPool &ConstantPool) {
263ab980499SAlex Lorenz   unsigned ID = 0;
264ab980499SAlex Lorenz   for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) {
265ab980499SAlex Lorenz     // TODO: Serialize target specific constant pool entries.
266ab980499SAlex Lorenz     if (Constant.isMachineConstantPoolEntry())
267ab980499SAlex Lorenz       llvm_unreachable("Can't print target specific constant pool entries yet");
268ab980499SAlex Lorenz 
269ab980499SAlex Lorenz     yaml::MachineConstantPoolValue YamlConstant;
270ab980499SAlex Lorenz     std::string Str;
271ab980499SAlex Lorenz     raw_string_ostream StrOS(Str);
272ab980499SAlex Lorenz     Constant.Val.ConstVal->printAsOperand(StrOS);
273ab980499SAlex Lorenz     YamlConstant.ID = ID++;
274ab980499SAlex Lorenz     YamlConstant.Value = StrOS.str();
275ab980499SAlex Lorenz     YamlConstant.Alignment = Constant.getAlignment();
276ab980499SAlex Lorenz     MF.Constants.push_back(YamlConstant);
277ab980499SAlex Lorenz   }
278ab980499SAlex Lorenz }
279ab980499SAlex Lorenz 
280900b5cb2SAlex Lorenz void MIRPrinter::convert(ModuleSlotTracker &MST,
2816799e9b3SAlex Lorenz                          yaml::MachineJumpTable &YamlJTI,
2826799e9b3SAlex Lorenz                          const MachineJumpTableInfo &JTI) {
2836799e9b3SAlex Lorenz   YamlJTI.Kind = JTI.getEntryKind();
2846799e9b3SAlex Lorenz   unsigned ID = 0;
2856799e9b3SAlex Lorenz   for (const auto &Table : JTI.getJumpTables()) {
2866799e9b3SAlex Lorenz     std::string Str;
2876799e9b3SAlex Lorenz     yaml::MachineJumpTable::Entry Entry;
2886799e9b3SAlex Lorenz     Entry.ID = ID++;
2896799e9b3SAlex Lorenz     for (const auto *MBB : Table.MBBs) {
2906799e9b3SAlex Lorenz       raw_string_ostream StrOS(Str);
2917feaf7c6SAlex Lorenz       MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
2927feaf7c6SAlex Lorenz           .printMBBReference(*MBB);
2936799e9b3SAlex Lorenz       Entry.Blocks.push_back(StrOS.str());
2946799e9b3SAlex Lorenz       Str.clear();
2956799e9b3SAlex Lorenz     }
2966799e9b3SAlex Lorenz     YamlJTI.Entries.push_back(Entry);
2976799e9b3SAlex Lorenz   }
2986799e9b3SAlex Lorenz }
2996799e9b3SAlex Lorenz 
3006799e9b3SAlex Lorenz void MIRPrinter::convert(ModuleSlotTracker &MST,
301900b5cb2SAlex Lorenz                          yaml::MachineBasicBlock &YamlMBB,
3024f093bf1SAlex Lorenz                          const MachineBasicBlock &MBB) {
30333f0aef3SAlex Lorenz   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
30433f0aef3SAlex Lorenz   YamlMBB.ID = (unsigned)MBB.getNumber();
3054f093bf1SAlex Lorenz   // TODO: Serialize unnamed BB references.
3064f093bf1SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock())
307b1f9ce8fSAlex Lorenz     YamlMBB.Name.Value = BB->hasName() ? BB->getName() : "<unnamed bb>";
3084f093bf1SAlex Lorenz   else
309b1f9ce8fSAlex Lorenz     YamlMBB.Name.Value = "";
3104f093bf1SAlex Lorenz   YamlMBB.Alignment = MBB.getAlignment();
3114f093bf1SAlex Lorenz   YamlMBB.AddressTaken = MBB.hasAddressTaken();
3124f093bf1SAlex Lorenz   YamlMBB.IsLandingPad = MBB.isLandingPad();
313eb5112bfSAlex Lorenz   for (const auto *SuccMBB : MBB.successors()) {
314f09df00dSAlex Lorenz     std::string Str;
315f09df00dSAlex Lorenz     raw_string_ostream StrOS(Str);
3167feaf7c6SAlex Lorenz     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
3177feaf7c6SAlex Lorenz         .printMBBReference(*SuccMBB);
318f09df00dSAlex Lorenz     YamlMBB.Successors.push_back(StrOS.str());
319f09df00dSAlex Lorenz   }
3209fab370dSAlex Lorenz   // Print the live in registers.
3219fab370dSAlex Lorenz   const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
3229fab370dSAlex Lorenz   assert(TRI && "Expected target register info");
3239fab370dSAlex Lorenz   for (auto I = MBB.livein_begin(), E = MBB.livein_end(); I != E; ++I) {
3249fab370dSAlex Lorenz     std::string Str;
3259fab370dSAlex Lorenz     raw_string_ostream StrOS(Str);
3269fab370dSAlex Lorenz     printReg(*I, StrOS, TRI);
3279fab370dSAlex Lorenz     YamlMBB.LiveIns.push_back(StrOS.str());
3289fab370dSAlex Lorenz   }
3298e0a1b48SAlex Lorenz   // Print the machine instructions.
3308e0a1b48SAlex Lorenz   YamlMBB.Instructions.reserve(MBB.size());
3318e0a1b48SAlex Lorenz   std::string Str;
3328e0a1b48SAlex Lorenz   for (const auto &MI : MBB) {
3338e0a1b48SAlex Lorenz     raw_string_ostream StrOS(Str);
3347feaf7c6SAlex Lorenz     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping).print(MI);
3358e0a1b48SAlex Lorenz     YamlMBB.Instructions.push_back(StrOS.str());
3368e0a1b48SAlex Lorenz     Str.clear();
3378e0a1b48SAlex Lorenz   }
3388e0a1b48SAlex Lorenz }
3398e0a1b48SAlex Lorenz 
3408f6f4285SAlex Lorenz void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
3418f6f4285SAlex Lorenz   const auto *TRI = MF.getSubtarget().getRegisterInfo();
3428f6f4285SAlex Lorenz   unsigned I = 0;
3438f6f4285SAlex Lorenz   for (const uint32_t *Mask : TRI->getRegMasks())
3448f6f4285SAlex Lorenz     RegisterMaskIds.insert(std::make_pair(Mask, I++));
3458f6f4285SAlex Lorenz }
3468f6f4285SAlex Lorenz 
3478e0a1b48SAlex Lorenz void MIPrinter::print(const MachineInstr &MI) {
3488e0a1b48SAlex Lorenz   const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
349f3db51deSAlex Lorenz   const auto *TRI = SubTarget.getRegisterInfo();
350f3db51deSAlex Lorenz   assert(TRI && "Expected target register info");
3518e0a1b48SAlex Lorenz   const auto *TII = SubTarget.getInstrInfo();
3528e0a1b48SAlex Lorenz   assert(TII && "Expected target instruction info");
353f4baeb51SAlex Lorenz   if (MI.isCFIInstruction())
354f4baeb51SAlex Lorenz     assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
3558e0a1b48SAlex Lorenz 
356f3db51deSAlex Lorenz   unsigned I = 0, E = MI.getNumOperands();
357f3db51deSAlex Lorenz   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
358f3db51deSAlex Lorenz          !MI.getOperand(I).isImplicit();
359f3db51deSAlex Lorenz        ++I) {
360f3db51deSAlex Lorenz     if (I)
361f3db51deSAlex Lorenz       OS << ", ";
362f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
363f3db51deSAlex Lorenz   }
364f3db51deSAlex Lorenz 
365f3db51deSAlex Lorenz   if (I)
366f3db51deSAlex Lorenz     OS << " = ";
367e5a44660SAlex Lorenz   if (MI.getFlag(MachineInstr::FrameSetup))
368e5a44660SAlex Lorenz     OS << "frame-setup ";
3698e0a1b48SAlex Lorenz   OS << TII->getName(MI.getOpcode());
370e5a44660SAlex Lorenz   // TODO: Print the bundling instruction flags, machine mem operands.
371f3db51deSAlex Lorenz   if (I < E)
372f3db51deSAlex Lorenz     OS << ' ';
373f3db51deSAlex Lorenz 
374f3db51deSAlex Lorenz   bool NeedComma = false;
375f3db51deSAlex Lorenz   for (; I < E; ++I) {
376f3db51deSAlex Lorenz     if (NeedComma)
377f3db51deSAlex Lorenz       OS << ", ";
378f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
379f3db51deSAlex Lorenz     NeedComma = true;
380f3db51deSAlex Lorenz   }
381*46d760d1SAlex Lorenz 
382*46d760d1SAlex Lorenz   if (MI.getDebugLoc()) {
383*46d760d1SAlex Lorenz     if (NeedComma)
384*46d760d1SAlex Lorenz       OS << ',';
385*46d760d1SAlex Lorenz     OS << " debug-location ";
386*46d760d1SAlex Lorenz     MI.getDebugLoc()->printAsOperand(OS, MST);
387*46d760d1SAlex Lorenz   }
388f3db51deSAlex Lorenz }
389f3db51deSAlex Lorenz 
3905d26fa83SAlex Lorenz void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
3915d26fa83SAlex Lorenz   OS << "%bb." << MBB.getNumber();
3925d26fa83SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock()) {
3935d26fa83SAlex Lorenz     if (BB->hasName())
3945d26fa83SAlex Lorenz       OS << '.' << BB->getName();
3955d26fa83SAlex Lorenz   }
3965d26fa83SAlex Lorenz }
3975d26fa83SAlex Lorenz 
3987feaf7c6SAlex Lorenz void MIPrinter::printStackObjectReference(int FrameIndex) {
3997feaf7c6SAlex Lorenz   auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
4007feaf7c6SAlex Lorenz   assert(ObjectInfo != StackObjectOperandMapping.end() &&
4017feaf7c6SAlex Lorenz          "Invalid frame index");
4027feaf7c6SAlex Lorenz   const FrameIndexOperand &Operand = ObjectInfo->second;
4037feaf7c6SAlex Lorenz   if (Operand.IsFixed) {
4047feaf7c6SAlex Lorenz     OS << "%fixed-stack." << Operand.ID;
4057feaf7c6SAlex Lorenz     return;
4067feaf7c6SAlex Lorenz   }
4077feaf7c6SAlex Lorenz   OS << "%stack." << Operand.ID;
4087feaf7c6SAlex Lorenz   if (!Operand.Name.empty())
4097feaf7c6SAlex Lorenz     OS << '.' << Operand.Name;
4107feaf7c6SAlex Lorenz }
4117feaf7c6SAlex Lorenz 
412f3db51deSAlex Lorenz void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
413f3db51deSAlex Lorenz   switch (Op.getType()) {
414f3db51deSAlex Lorenz   case MachineOperand::MO_Register:
415cb268d46SAlex Lorenz     // TODO: Print the other register flags.
416cb268d46SAlex Lorenz     if (Op.isImplicit())
417cb268d46SAlex Lorenz       OS << (Op.isDef() ? "implicit-def " : "implicit ");
418cbbfd0b1SAlex Lorenz     if (Op.isDead())
419cbbfd0b1SAlex Lorenz       OS << "dead ";
420495ad879SAlex Lorenz     if (Op.isKill())
421495ad879SAlex Lorenz       OS << "killed ";
4224d026b89SAlex Lorenz     if (Op.isUndef())
4234d026b89SAlex Lorenz       OS << "undef ";
424f3db51deSAlex Lorenz     printReg(Op.getReg(), OS, TRI);
4252eacca86SAlex Lorenz     // Print the sub register.
4262eacca86SAlex Lorenz     if (Op.getSubReg() != 0)
4272eacca86SAlex Lorenz       OS << ':' << TRI->getSubRegIndexName(Op.getSubReg());
428f3db51deSAlex Lorenz     break;
429240fc1e0SAlex Lorenz   case MachineOperand::MO_Immediate:
430240fc1e0SAlex Lorenz     OS << Op.getImm();
431240fc1e0SAlex Lorenz     break;
43233f0aef3SAlex Lorenz   case MachineOperand::MO_MachineBasicBlock:
4335d26fa83SAlex Lorenz     printMBBReference(*Op.getMBB());
43433f0aef3SAlex Lorenz     break;
4357feaf7c6SAlex Lorenz   case MachineOperand::MO_FrameIndex:
4367feaf7c6SAlex Lorenz     printStackObjectReference(Op.getIndex());
4377feaf7c6SAlex Lorenz     break;
438ab980499SAlex Lorenz   case MachineOperand::MO_ConstantPoolIndex:
439ab980499SAlex Lorenz     OS << "%const." << Op.getIndex();
440ab980499SAlex Lorenz     // TODO: Print offset and target flags.
441ab980499SAlex Lorenz     break;
44231d70683SAlex Lorenz   case MachineOperand::MO_JumpTableIndex:
44331d70683SAlex Lorenz     OS << "%jump-table." << Op.getIndex();
44431d70683SAlex Lorenz     // TODO: Print target flags.
44531d70683SAlex Lorenz     break;
4466ede3744SAlex Lorenz   case MachineOperand::MO_ExternalSymbol:
4476ede3744SAlex Lorenz     OS << '$';
4486ede3744SAlex Lorenz     printLLVMNameWithoutPrefix(OS, Op.getSymbolName());
4496ede3744SAlex Lorenz     // TODO: Print the target flags.
4506ede3744SAlex Lorenz     break;
4515d6108e4SAlex Lorenz   case MachineOperand::MO_GlobalAddress:
452900b5cb2SAlex Lorenz     Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
4535d6108e4SAlex Lorenz     // TODO: Print offset and target flags.
4545d6108e4SAlex Lorenz     break;
4558f6f4285SAlex Lorenz   case MachineOperand::MO_RegisterMask: {
4568f6f4285SAlex Lorenz     auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
4578f6f4285SAlex Lorenz     if (RegMaskInfo != RegisterMaskIds.end())
4588f6f4285SAlex Lorenz       OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
4598f6f4285SAlex Lorenz     else
4608f6f4285SAlex Lorenz       llvm_unreachable("Can't print this machine register mask yet.");
4618f6f4285SAlex Lorenz     break;
4628f6f4285SAlex Lorenz   }
46335e44469SAlex Lorenz   case MachineOperand::MO_Metadata:
46435e44469SAlex Lorenz     Op.getMetadata()->printAsOperand(OS, MST);
46535e44469SAlex Lorenz     break;
466f4baeb51SAlex Lorenz   case MachineOperand::MO_CFIIndex: {
467f4baeb51SAlex Lorenz     const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI();
468f4baeb51SAlex Lorenz     print(MMI.getFrameInstructions()[Op.getCFIIndex()]);
469f4baeb51SAlex Lorenz     break;
470f4baeb51SAlex Lorenz   }
471f3db51deSAlex Lorenz   default:
472f3db51deSAlex Lorenz     // TODO: Print the other machine operands.
473f3db51deSAlex Lorenz     llvm_unreachable("Can't print this machine operand at the moment");
474f3db51deSAlex Lorenz   }
4754f093bf1SAlex Lorenz }
4764f093bf1SAlex Lorenz 
477f4baeb51SAlex Lorenz void MIPrinter::print(const MCCFIInstruction &CFI) {
478f4baeb51SAlex Lorenz   switch (CFI.getOperation()) {
479f4baeb51SAlex Lorenz   case MCCFIInstruction::OpDefCfaOffset:
480f4baeb51SAlex Lorenz     OS << ".cfi_def_cfa_offset ";
481f4baeb51SAlex Lorenz     if (CFI.getLabel())
482f4baeb51SAlex Lorenz       OS << "<mcsymbol> ";
483f4baeb51SAlex Lorenz     OS << CFI.getOffset();
484f4baeb51SAlex Lorenz     break;
485f4baeb51SAlex Lorenz   default:
486f4baeb51SAlex Lorenz     // TODO: Print the other CFI Operations.
487f4baeb51SAlex Lorenz     OS << "<unserializable cfi operation>";
488f4baeb51SAlex Lorenz     break;
489f4baeb51SAlex Lorenz   }
490f4baeb51SAlex Lorenz }
491f4baeb51SAlex Lorenz 
492345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const Module &M) {
493345c1449SAlex Lorenz   yaml::Output Out(OS);
494345c1449SAlex Lorenz   Out << const_cast<Module &>(M);
495345c1449SAlex Lorenz }
496345c1449SAlex Lorenz 
497345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
498345c1449SAlex Lorenz   MIRPrinter Printer(OS);
499345c1449SAlex Lorenz   Printer.print(MF);
500345c1449SAlex Lorenz }
501