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,
821bb48de1SAlex Lorenz                            const MachineFrameInfo &MFI,
831bb48de1SAlex Lorenz                            const TargetRegisterInfo *TRI);
848f6f4285SAlex Lorenz 
858f6f4285SAlex Lorenz private:
868f6f4285SAlex Lorenz   void initRegisterMaskIds(const MachineFunction &MF);
87345c1449SAlex Lorenz };
88345c1449SAlex Lorenz 
898e0a1b48SAlex Lorenz /// This class prints out the machine instructions using the MIR serialization
908e0a1b48SAlex Lorenz /// format.
918e0a1b48SAlex Lorenz class MIPrinter {
928e0a1b48SAlex Lorenz   raw_ostream &OS;
93900b5cb2SAlex Lorenz   ModuleSlotTracker &MST;
948f6f4285SAlex Lorenz   const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
957feaf7c6SAlex Lorenz   const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
968e0a1b48SAlex Lorenz 
978e0a1b48SAlex Lorenz public:
98900b5cb2SAlex Lorenz   MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
997feaf7c6SAlex Lorenz             const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
1007feaf7c6SAlex Lorenz             const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping)
1017feaf7c6SAlex Lorenz       : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds),
1027feaf7c6SAlex Lorenz         StackObjectOperandMapping(StackObjectOperandMapping) {}
1038e0a1b48SAlex Lorenz 
1048e0a1b48SAlex Lorenz   void print(const MachineInstr &MI);
1055d26fa83SAlex Lorenz   void printMBBReference(const MachineBasicBlock &MBB);
1067feaf7c6SAlex Lorenz   void printStackObjectReference(int FrameIndex);
107f3db51deSAlex Lorenz   void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
108f4baeb51SAlex Lorenz 
1098cfc6867SAlex Lorenz   void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI);
1108e0a1b48SAlex Lorenz };
1118e0a1b48SAlex Lorenz 
112345c1449SAlex Lorenz } // end anonymous namespace
113345c1449SAlex Lorenz 
114345c1449SAlex Lorenz namespace llvm {
115345c1449SAlex Lorenz namespace yaml {
116345c1449SAlex Lorenz 
117345c1449SAlex Lorenz /// This struct serializes the LLVM IR module.
118345c1449SAlex Lorenz template <> struct BlockScalarTraits<Module> {
119345c1449SAlex Lorenz   static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
120345c1449SAlex Lorenz     Mod.print(OS, nullptr);
121345c1449SAlex Lorenz   }
122345c1449SAlex Lorenz   static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
123345c1449SAlex Lorenz     llvm_unreachable("LLVM Module is supposed to be parsed separately");
124345c1449SAlex Lorenz     return "";
125345c1449SAlex Lorenz   }
126345c1449SAlex Lorenz };
127345c1449SAlex Lorenz 
128345c1449SAlex Lorenz } // end namespace yaml
129345c1449SAlex Lorenz } // end namespace llvm
130345c1449SAlex Lorenz 
13115a00a85SAlex Lorenz static void printReg(unsigned Reg, raw_ostream &OS,
13215a00a85SAlex Lorenz                      const TargetRegisterInfo *TRI) {
13315a00a85SAlex Lorenz   // TODO: Print Stack Slots.
13415a00a85SAlex Lorenz   if (!Reg)
13515a00a85SAlex Lorenz     OS << '_';
13615a00a85SAlex Lorenz   else if (TargetRegisterInfo::isVirtualRegister(Reg))
13715a00a85SAlex Lorenz     OS << '%' << TargetRegisterInfo::virtReg2Index(Reg);
13815a00a85SAlex Lorenz   else if (Reg < TRI->getNumRegs())
13915a00a85SAlex Lorenz     OS << '%' << StringRef(TRI->getName(Reg)).lower();
14015a00a85SAlex Lorenz   else
14115a00a85SAlex Lorenz     llvm_unreachable("Can't print this kind of register yet");
14215a00a85SAlex Lorenz }
14315a00a85SAlex Lorenz 
144ab4cbcfdSAlex Lorenz static void printReg(unsigned Reg, yaml::StringValue &Dest,
145ab4cbcfdSAlex Lorenz                      const TargetRegisterInfo *TRI) {
146ab4cbcfdSAlex Lorenz   raw_string_ostream OS(Dest.Value);
147ab4cbcfdSAlex Lorenz   printReg(Reg, OS, TRI);
148ab4cbcfdSAlex Lorenz }
149ab4cbcfdSAlex Lorenz 
150345c1449SAlex Lorenz void MIRPrinter::print(const MachineFunction &MF) {
1518f6f4285SAlex Lorenz   initRegisterMaskIds(MF);
1528f6f4285SAlex Lorenz 
153345c1449SAlex Lorenz   yaml::MachineFunction YamlMF;
154345c1449SAlex Lorenz   YamlMF.Name = MF.getName();
1555b5f9753SAlex Lorenz   YamlMF.Alignment = MF.getAlignment();
1565b5f9753SAlex Lorenz   YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
1575b5f9753SAlex Lorenz   YamlMF.HasInlineAsm = MF.hasInlineAsm();
15828148ba8SAlex Lorenz   convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
15960541c1dSAlex Lorenz   convert(YamlMF.FrameInfo, *MF.getFrameInfo());
1601bb48de1SAlex Lorenz   convertStackObjects(YamlMF, *MF.getFrameInfo(),
1611bb48de1SAlex Lorenz                       MF.getSubtarget().getRegisterInfo());
162ab980499SAlex Lorenz   if (const auto *ConstantPool = MF.getConstantPool())
163ab980499SAlex Lorenz     convert(YamlMF, *ConstantPool);
16433f0aef3SAlex Lorenz 
165900b5cb2SAlex Lorenz   ModuleSlotTracker MST(MF.getFunction()->getParent());
166*8a1915b0SAlex Lorenz   MST.incorporateFunction(*MF.getFunction());
1676799e9b3SAlex Lorenz   if (const auto *JumpTableInfo = MF.getJumpTableInfo())
1686799e9b3SAlex Lorenz     convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
1696799e9b3SAlex Lorenz   int I = 0;
1704f093bf1SAlex Lorenz   for (const auto &MBB : MF) {
17133f0aef3SAlex Lorenz     // TODO: Allow printing of non sequentially numbered MBBs.
17233f0aef3SAlex Lorenz     // This is currently needed as the basic block references get their index
17333f0aef3SAlex Lorenz     // from MBB.getNumber(), thus it should be sequential so that the parser can
17433f0aef3SAlex Lorenz     // map back to the correct MBBs when parsing the output.
17533f0aef3SAlex Lorenz     assert(MBB.getNumber() == I++ &&
17633f0aef3SAlex Lorenz            "Can't print MBBs that aren't sequentially numbered");
177ec6b26b9SAlex Lorenz     (void)I;
1784f093bf1SAlex Lorenz     yaml::MachineBasicBlock YamlMBB;
179900b5cb2SAlex Lorenz     convert(MST, YamlMBB, MBB);
1804f093bf1SAlex Lorenz     YamlMF.BasicBlocks.push_back(YamlMBB);
1814f093bf1SAlex Lorenz   }
182345c1449SAlex Lorenz   yaml::Output Out(OS);
183345c1449SAlex Lorenz   Out << YamlMF;
184345c1449SAlex Lorenz }
185345c1449SAlex Lorenz 
18654565cf0SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
18728148ba8SAlex Lorenz                          const MachineRegisterInfo &RegInfo,
18828148ba8SAlex Lorenz                          const TargetRegisterInfo *TRI) {
18954565cf0SAlex Lorenz   MF.IsSSA = RegInfo.isSSA();
19054565cf0SAlex Lorenz   MF.TracksRegLiveness = RegInfo.tracksLiveness();
19154565cf0SAlex Lorenz   MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
19228148ba8SAlex Lorenz 
19328148ba8SAlex Lorenz   // Print the virtual register definitions.
19428148ba8SAlex Lorenz   for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
19528148ba8SAlex Lorenz     unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
19628148ba8SAlex Lorenz     yaml::VirtualRegisterDefinition VReg;
19728148ba8SAlex Lorenz     VReg.ID = I;
19828148ba8SAlex Lorenz     VReg.Class =
19928148ba8SAlex Lorenz         StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
200ab4cbcfdSAlex Lorenz     unsigned PreferredReg = RegInfo.getSimpleHint(Reg);
201ab4cbcfdSAlex Lorenz     if (PreferredReg)
202ab4cbcfdSAlex Lorenz       printReg(PreferredReg, VReg.PreferredRegister, TRI);
20328148ba8SAlex Lorenz     MF.VirtualRegisters.push_back(VReg);
20428148ba8SAlex Lorenz   }
20512045a4bSAlex Lorenz 
20612045a4bSAlex Lorenz   // Print the live ins.
20712045a4bSAlex Lorenz   for (auto I = RegInfo.livein_begin(), E = RegInfo.livein_end(); I != E; ++I) {
20812045a4bSAlex Lorenz     yaml::MachineFunctionLiveIn LiveIn;
20912045a4bSAlex Lorenz     printReg(I->first, LiveIn.Register, TRI);
21012045a4bSAlex Lorenz     if (I->second)
21112045a4bSAlex Lorenz       printReg(I->second, LiveIn.VirtualRegister, TRI);
21212045a4bSAlex Lorenz     MF.LiveIns.push_back(LiveIn);
21312045a4bSAlex Lorenz   }
21454565cf0SAlex Lorenz }
21554565cf0SAlex Lorenz 
21660541c1dSAlex Lorenz void MIRPrinter::convert(yaml::MachineFrameInfo &YamlMFI,
21760541c1dSAlex Lorenz                          const MachineFrameInfo &MFI) {
21860541c1dSAlex Lorenz   YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
21960541c1dSAlex Lorenz   YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
22060541c1dSAlex Lorenz   YamlMFI.HasStackMap = MFI.hasStackMap();
22160541c1dSAlex Lorenz   YamlMFI.HasPatchPoint = MFI.hasPatchPoint();
22260541c1dSAlex Lorenz   YamlMFI.StackSize = MFI.getStackSize();
22360541c1dSAlex Lorenz   YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment();
22460541c1dSAlex Lorenz   YamlMFI.MaxAlignment = MFI.getMaxAlignment();
22560541c1dSAlex Lorenz   YamlMFI.AdjustsStack = MFI.adjustsStack();
22660541c1dSAlex Lorenz   YamlMFI.HasCalls = MFI.hasCalls();
22760541c1dSAlex Lorenz   YamlMFI.MaxCallFrameSize = MFI.getMaxCallFrameSize();
22860541c1dSAlex Lorenz   YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment();
22960541c1dSAlex Lorenz   YamlMFI.HasVAStart = MFI.hasVAStart();
23060541c1dSAlex Lorenz   YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc();
23160541c1dSAlex Lorenz }
23260541c1dSAlex Lorenz 
233f6bc8667SAlex Lorenz void MIRPrinter::convertStackObjects(yaml::MachineFunction &MF,
2341bb48de1SAlex Lorenz                                      const MachineFrameInfo &MFI,
2351bb48de1SAlex Lorenz                                      const TargetRegisterInfo *TRI) {
236de491f05SAlex Lorenz   // Process fixed stack objects.
237f6bc8667SAlex Lorenz   unsigned ID = 0;
238de491f05SAlex Lorenz   for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
239de491f05SAlex Lorenz     if (MFI.isDeadObjectIndex(I))
240de491f05SAlex Lorenz       continue;
241de491f05SAlex Lorenz 
242de491f05SAlex Lorenz     yaml::FixedMachineStackObject YamlObject;
2437feaf7c6SAlex Lorenz     YamlObject.ID = ID;
244de491f05SAlex Lorenz     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
245de491f05SAlex Lorenz                           ? yaml::FixedMachineStackObject::SpillSlot
246de491f05SAlex Lorenz                           : yaml::FixedMachineStackObject::DefaultType;
247de491f05SAlex Lorenz     YamlObject.Offset = MFI.getObjectOffset(I);
248de491f05SAlex Lorenz     YamlObject.Size = MFI.getObjectSize(I);
249de491f05SAlex Lorenz     YamlObject.Alignment = MFI.getObjectAlignment(I);
250de491f05SAlex Lorenz     YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
251de491f05SAlex Lorenz     YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
252de491f05SAlex Lorenz     MF.FixedStackObjects.push_back(YamlObject);
2537feaf7c6SAlex Lorenz     StackObjectOperandMapping.insert(
2547feaf7c6SAlex Lorenz         std::make_pair(I, FrameIndexOperand::createFixed(ID++)));
255de491f05SAlex Lorenz   }
256de491f05SAlex Lorenz 
257de491f05SAlex Lorenz   // Process ordinary stack objects.
258de491f05SAlex Lorenz   ID = 0;
259f6bc8667SAlex Lorenz   for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I) {
260f6bc8667SAlex Lorenz     if (MFI.isDeadObjectIndex(I))
261f6bc8667SAlex Lorenz       continue;
262f6bc8667SAlex Lorenz 
263f6bc8667SAlex Lorenz     yaml::MachineStackObject YamlObject;
2647feaf7c6SAlex Lorenz     YamlObject.ID = ID;
26537643a04SAlex Lorenz     if (const auto *Alloca = MFI.getObjectAllocation(I))
26637643a04SAlex Lorenz       YamlObject.Name.Value =
26737643a04SAlex Lorenz           Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>";
268f6bc8667SAlex Lorenz     YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
269f6bc8667SAlex Lorenz                           ? yaml::MachineStackObject::SpillSlot
270418f3ec1SAlex Lorenz                           : MFI.isVariableSizedObjectIndex(I)
271418f3ec1SAlex Lorenz                                 ? yaml::MachineStackObject::VariableSized
272f6bc8667SAlex Lorenz                                 : yaml::MachineStackObject::DefaultType;
273f6bc8667SAlex Lorenz     YamlObject.Offset = MFI.getObjectOffset(I);
274f6bc8667SAlex Lorenz     YamlObject.Size = MFI.getObjectSize(I);
275f6bc8667SAlex Lorenz     YamlObject.Alignment = MFI.getObjectAlignment(I);
276f6bc8667SAlex Lorenz 
277f6bc8667SAlex Lorenz     MF.StackObjects.push_back(YamlObject);
2787feaf7c6SAlex Lorenz     StackObjectOperandMapping.insert(std::make_pair(
2797feaf7c6SAlex Lorenz         I, FrameIndexOperand::create(YamlObject.Name.Value, ID++)));
280f6bc8667SAlex Lorenz   }
2811bb48de1SAlex Lorenz 
2821bb48de1SAlex Lorenz   for (const auto &CSInfo : MFI.getCalleeSavedInfo()) {
2831bb48de1SAlex Lorenz     yaml::StringValue Reg;
2841bb48de1SAlex Lorenz     printReg(CSInfo.getReg(), Reg, TRI);
2851bb48de1SAlex Lorenz     auto StackObjectInfo = StackObjectOperandMapping.find(CSInfo.getFrameIdx());
2861bb48de1SAlex Lorenz     assert(StackObjectInfo != StackObjectOperandMapping.end() &&
2871bb48de1SAlex Lorenz            "Invalid stack object index");
2881bb48de1SAlex Lorenz     const FrameIndexOperand &StackObject = StackObjectInfo->second;
2891bb48de1SAlex Lorenz     if (StackObject.IsFixed)
2901bb48de1SAlex Lorenz       MF.FixedStackObjects[StackObject.ID].CalleeSavedRegister = Reg;
2911bb48de1SAlex Lorenz     else
2921bb48de1SAlex Lorenz       MF.StackObjects[StackObject.ID].CalleeSavedRegister = Reg;
2931bb48de1SAlex Lorenz   }
294f6bc8667SAlex Lorenz }
295f6bc8667SAlex Lorenz 
296ab980499SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
297ab980499SAlex Lorenz                          const MachineConstantPool &ConstantPool) {
298ab980499SAlex Lorenz   unsigned ID = 0;
299ab980499SAlex Lorenz   for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) {
300ab980499SAlex Lorenz     // TODO: Serialize target specific constant pool entries.
301ab980499SAlex Lorenz     if (Constant.isMachineConstantPoolEntry())
302ab980499SAlex Lorenz       llvm_unreachable("Can't print target specific constant pool entries yet");
303ab980499SAlex Lorenz 
304ab980499SAlex Lorenz     yaml::MachineConstantPoolValue YamlConstant;
305ab980499SAlex Lorenz     std::string Str;
306ab980499SAlex Lorenz     raw_string_ostream StrOS(Str);
307ab980499SAlex Lorenz     Constant.Val.ConstVal->printAsOperand(StrOS);
308ab980499SAlex Lorenz     YamlConstant.ID = ID++;
309ab980499SAlex Lorenz     YamlConstant.Value = StrOS.str();
310ab980499SAlex Lorenz     YamlConstant.Alignment = Constant.getAlignment();
311ab980499SAlex Lorenz     MF.Constants.push_back(YamlConstant);
312ab980499SAlex Lorenz   }
313ab980499SAlex Lorenz }
314ab980499SAlex Lorenz 
315900b5cb2SAlex Lorenz void MIRPrinter::convert(ModuleSlotTracker &MST,
3166799e9b3SAlex Lorenz                          yaml::MachineJumpTable &YamlJTI,
3176799e9b3SAlex Lorenz                          const MachineJumpTableInfo &JTI) {
3186799e9b3SAlex Lorenz   YamlJTI.Kind = JTI.getEntryKind();
3196799e9b3SAlex Lorenz   unsigned ID = 0;
3206799e9b3SAlex Lorenz   for (const auto &Table : JTI.getJumpTables()) {
3216799e9b3SAlex Lorenz     std::string Str;
3226799e9b3SAlex Lorenz     yaml::MachineJumpTable::Entry Entry;
3236799e9b3SAlex Lorenz     Entry.ID = ID++;
3246799e9b3SAlex Lorenz     for (const auto *MBB : Table.MBBs) {
3256799e9b3SAlex Lorenz       raw_string_ostream StrOS(Str);
3267feaf7c6SAlex Lorenz       MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
3277feaf7c6SAlex Lorenz           .printMBBReference(*MBB);
3286799e9b3SAlex Lorenz       Entry.Blocks.push_back(StrOS.str());
3296799e9b3SAlex Lorenz       Str.clear();
3306799e9b3SAlex Lorenz     }
3316799e9b3SAlex Lorenz     YamlJTI.Entries.push_back(Entry);
3326799e9b3SAlex Lorenz   }
3336799e9b3SAlex Lorenz }
3346799e9b3SAlex Lorenz 
3356799e9b3SAlex Lorenz void MIRPrinter::convert(ModuleSlotTracker &MST,
336900b5cb2SAlex Lorenz                          yaml::MachineBasicBlock &YamlMBB,
3374f093bf1SAlex Lorenz                          const MachineBasicBlock &MBB) {
33833f0aef3SAlex Lorenz   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
33933f0aef3SAlex Lorenz   YamlMBB.ID = (unsigned)MBB.getNumber();
340*8a1915b0SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock()) {
341*8a1915b0SAlex Lorenz     if (BB->hasName()) {
342*8a1915b0SAlex Lorenz       YamlMBB.Name.Value = BB->getName();
343*8a1915b0SAlex Lorenz     } else {
344*8a1915b0SAlex Lorenz       int Slot = MST.getLocalSlot(BB);
345*8a1915b0SAlex Lorenz       if (Slot == -1)
346*8a1915b0SAlex Lorenz         YamlMBB.IRBlock.Value = "<badref>";
3474f093bf1SAlex Lorenz       else
348*8a1915b0SAlex Lorenz         YamlMBB.IRBlock.Value = (Twine("%ir-block.") + Twine(Slot)).str();
349*8a1915b0SAlex Lorenz     }
350*8a1915b0SAlex Lorenz   }
3514f093bf1SAlex Lorenz   YamlMBB.Alignment = MBB.getAlignment();
3524f093bf1SAlex Lorenz   YamlMBB.AddressTaken = MBB.hasAddressTaken();
3534f093bf1SAlex Lorenz   YamlMBB.IsLandingPad = MBB.isLandingPad();
354eb5112bfSAlex Lorenz   for (const auto *SuccMBB : MBB.successors()) {
355f09df00dSAlex Lorenz     std::string Str;
356f09df00dSAlex Lorenz     raw_string_ostream StrOS(Str);
3577feaf7c6SAlex Lorenz     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
3587feaf7c6SAlex Lorenz         .printMBBReference(*SuccMBB);
359f09df00dSAlex Lorenz     YamlMBB.Successors.push_back(StrOS.str());
360f09df00dSAlex Lorenz   }
3619fab370dSAlex Lorenz   // Print the live in registers.
3629fab370dSAlex Lorenz   const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
3639fab370dSAlex Lorenz   assert(TRI && "Expected target register info");
3649fab370dSAlex Lorenz   for (auto I = MBB.livein_begin(), E = MBB.livein_end(); I != E; ++I) {
3659fab370dSAlex Lorenz     std::string Str;
3669fab370dSAlex Lorenz     raw_string_ostream StrOS(Str);
3679fab370dSAlex Lorenz     printReg(*I, StrOS, TRI);
3689fab370dSAlex Lorenz     YamlMBB.LiveIns.push_back(StrOS.str());
3699fab370dSAlex Lorenz   }
3708e0a1b48SAlex Lorenz   // Print the machine instructions.
3718e0a1b48SAlex Lorenz   YamlMBB.Instructions.reserve(MBB.size());
3728e0a1b48SAlex Lorenz   std::string Str;
3738e0a1b48SAlex Lorenz   for (const auto &MI : MBB) {
3748e0a1b48SAlex Lorenz     raw_string_ostream StrOS(Str);
3757feaf7c6SAlex Lorenz     MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping).print(MI);
3768e0a1b48SAlex Lorenz     YamlMBB.Instructions.push_back(StrOS.str());
3778e0a1b48SAlex Lorenz     Str.clear();
3788e0a1b48SAlex Lorenz   }
3798e0a1b48SAlex Lorenz }
3808e0a1b48SAlex Lorenz 
3818f6f4285SAlex Lorenz void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
3828f6f4285SAlex Lorenz   const auto *TRI = MF.getSubtarget().getRegisterInfo();
3838f6f4285SAlex Lorenz   unsigned I = 0;
3848f6f4285SAlex Lorenz   for (const uint32_t *Mask : TRI->getRegMasks())
3858f6f4285SAlex Lorenz     RegisterMaskIds.insert(std::make_pair(Mask, I++));
3868f6f4285SAlex Lorenz }
3878f6f4285SAlex Lorenz 
3888e0a1b48SAlex Lorenz void MIPrinter::print(const MachineInstr &MI) {
3898e0a1b48SAlex Lorenz   const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
390f3db51deSAlex Lorenz   const auto *TRI = SubTarget.getRegisterInfo();
391f3db51deSAlex Lorenz   assert(TRI && "Expected target register info");
3928e0a1b48SAlex Lorenz   const auto *TII = SubTarget.getInstrInfo();
3938e0a1b48SAlex Lorenz   assert(TII && "Expected target instruction info");
394f4baeb51SAlex Lorenz   if (MI.isCFIInstruction())
395f4baeb51SAlex Lorenz     assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
3968e0a1b48SAlex Lorenz 
397f3db51deSAlex Lorenz   unsigned I = 0, E = MI.getNumOperands();
398f3db51deSAlex Lorenz   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
399f3db51deSAlex Lorenz          !MI.getOperand(I).isImplicit();
400f3db51deSAlex Lorenz        ++I) {
401f3db51deSAlex Lorenz     if (I)
402f3db51deSAlex Lorenz       OS << ", ";
403f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
404f3db51deSAlex Lorenz   }
405f3db51deSAlex Lorenz 
406f3db51deSAlex Lorenz   if (I)
407f3db51deSAlex Lorenz     OS << " = ";
408e5a44660SAlex Lorenz   if (MI.getFlag(MachineInstr::FrameSetup))
409e5a44660SAlex Lorenz     OS << "frame-setup ";
4108e0a1b48SAlex Lorenz   OS << TII->getName(MI.getOpcode());
411e5a44660SAlex Lorenz   // TODO: Print the bundling instruction flags, machine mem operands.
412f3db51deSAlex Lorenz   if (I < E)
413f3db51deSAlex Lorenz     OS << ' ';
414f3db51deSAlex Lorenz 
415f3db51deSAlex Lorenz   bool NeedComma = false;
416f3db51deSAlex Lorenz   for (; I < E; ++I) {
417f3db51deSAlex Lorenz     if (NeedComma)
418f3db51deSAlex Lorenz       OS << ", ";
419f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
420f3db51deSAlex Lorenz     NeedComma = true;
421f3db51deSAlex Lorenz   }
42246d760d1SAlex Lorenz 
42346d760d1SAlex Lorenz   if (MI.getDebugLoc()) {
42446d760d1SAlex Lorenz     if (NeedComma)
42546d760d1SAlex Lorenz       OS << ',';
42646d760d1SAlex Lorenz     OS << " debug-location ";
42746d760d1SAlex Lorenz     MI.getDebugLoc()->printAsOperand(OS, MST);
42846d760d1SAlex Lorenz   }
429f3db51deSAlex Lorenz }
430f3db51deSAlex Lorenz 
4315d26fa83SAlex Lorenz void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
4325d26fa83SAlex Lorenz   OS << "%bb." << MBB.getNumber();
4335d26fa83SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock()) {
4345d26fa83SAlex Lorenz     if (BB->hasName())
4355d26fa83SAlex Lorenz       OS << '.' << BB->getName();
4365d26fa83SAlex Lorenz   }
4375d26fa83SAlex Lorenz }
4385d26fa83SAlex Lorenz 
4397feaf7c6SAlex Lorenz void MIPrinter::printStackObjectReference(int FrameIndex) {
4407feaf7c6SAlex Lorenz   auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
4417feaf7c6SAlex Lorenz   assert(ObjectInfo != StackObjectOperandMapping.end() &&
4427feaf7c6SAlex Lorenz          "Invalid frame index");
4437feaf7c6SAlex Lorenz   const FrameIndexOperand &Operand = ObjectInfo->second;
4447feaf7c6SAlex Lorenz   if (Operand.IsFixed) {
4457feaf7c6SAlex Lorenz     OS << "%fixed-stack." << Operand.ID;
4467feaf7c6SAlex Lorenz     return;
4477feaf7c6SAlex Lorenz   }
4487feaf7c6SAlex Lorenz   OS << "%stack." << Operand.ID;
4497feaf7c6SAlex Lorenz   if (!Operand.Name.empty())
4507feaf7c6SAlex Lorenz     OS << '.' << Operand.Name;
4517feaf7c6SAlex Lorenz }
4527feaf7c6SAlex Lorenz 
453f3db51deSAlex Lorenz void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
454f3db51deSAlex Lorenz   switch (Op.getType()) {
455f3db51deSAlex Lorenz   case MachineOperand::MO_Register:
456cb268d46SAlex Lorenz     // TODO: Print the other register flags.
457cb268d46SAlex Lorenz     if (Op.isImplicit())
458cb268d46SAlex Lorenz       OS << (Op.isDef() ? "implicit-def " : "implicit ");
459cbbfd0b1SAlex Lorenz     if (Op.isDead())
460cbbfd0b1SAlex Lorenz       OS << "dead ";
461495ad879SAlex Lorenz     if (Op.isKill())
462495ad879SAlex Lorenz       OS << "killed ";
4634d026b89SAlex Lorenz     if (Op.isUndef())
4644d026b89SAlex Lorenz       OS << "undef ";
465f3db51deSAlex Lorenz     printReg(Op.getReg(), OS, TRI);
4662eacca86SAlex Lorenz     // Print the sub register.
4672eacca86SAlex Lorenz     if (Op.getSubReg() != 0)
4682eacca86SAlex Lorenz       OS << ':' << TRI->getSubRegIndexName(Op.getSubReg());
469f3db51deSAlex Lorenz     break;
470240fc1e0SAlex Lorenz   case MachineOperand::MO_Immediate:
471240fc1e0SAlex Lorenz     OS << Op.getImm();
472240fc1e0SAlex Lorenz     break;
47333f0aef3SAlex Lorenz   case MachineOperand::MO_MachineBasicBlock:
4745d26fa83SAlex Lorenz     printMBBReference(*Op.getMBB());
47533f0aef3SAlex Lorenz     break;
4767feaf7c6SAlex Lorenz   case MachineOperand::MO_FrameIndex:
4777feaf7c6SAlex Lorenz     printStackObjectReference(Op.getIndex());
4787feaf7c6SAlex Lorenz     break;
479ab980499SAlex Lorenz   case MachineOperand::MO_ConstantPoolIndex:
480ab980499SAlex Lorenz     OS << "%const." << Op.getIndex();
481ab980499SAlex Lorenz     // TODO: Print offset and target flags.
482ab980499SAlex Lorenz     break;
48331d70683SAlex Lorenz   case MachineOperand::MO_JumpTableIndex:
48431d70683SAlex Lorenz     OS << "%jump-table." << Op.getIndex();
48531d70683SAlex Lorenz     // TODO: Print target flags.
48631d70683SAlex Lorenz     break;
4876ede3744SAlex Lorenz   case MachineOperand::MO_ExternalSymbol:
4886ede3744SAlex Lorenz     OS << '$';
4896ede3744SAlex Lorenz     printLLVMNameWithoutPrefix(OS, Op.getSymbolName());
4906ede3744SAlex Lorenz     // TODO: Print the target flags.
4916ede3744SAlex Lorenz     break;
4925d6108e4SAlex Lorenz   case MachineOperand::MO_GlobalAddress:
493900b5cb2SAlex Lorenz     Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
4945d6108e4SAlex Lorenz     // TODO: Print offset and target flags.
4955d6108e4SAlex Lorenz     break;
4968f6f4285SAlex Lorenz   case MachineOperand::MO_RegisterMask: {
4978f6f4285SAlex Lorenz     auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
4988f6f4285SAlex Lorenz     if (RegMaskInfo != RegisterMaskIds.end())
4998f6f4285SAlex Lorenz       OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
5008f6f4285SAlex Lorenz     else
5018f6f4285SAlex Lorenz       llvm_unreachable("Can't print this machine register mask yet.");
5028f6f4285SAlex Lorenz     break;
5038f6f4285SAlex Lorenz   }
50435e44469SAlex Lorenz   case MachineOperand::MO_Metadata:
50535e44469SAlex Lorenz     Op.getMetadata()->printAsOperand(OS, MST);
50635e44469SAlex Lorenz     break;
507f4baeb51SAlex Lorenz   case MachineOperand::MO_CFIIndex: {
508f4baeb51SAlex Lorenz     const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI();
5098cfc6867SAlex Lorenz     print(MMI.getFrameInstructions()[Op.getCFIIndex()], TRI);
510f4baeb51SAlex Lorenz     break;
511f4baeb51SAlex Lorenz   }
512f3db51deSAlex Lorenz   default:
513f3db51deSAlex Lorenz     // TODO: Print the other machine operands.
514f3db51deSAlex Lorenz     llvm_unreachable("Can't print this machine operand at the moment");
515f3db51deSAlex Lorenz   }
5164f093bf1SAlex Lorenz }
5174f093bf1SAlex Lorenz 
5188cfc6867SAlex Lorenz static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS,
5198cfc6867SAlex Lorenz                              const TargetRegisterInfo *TRI) {
5208cfc6867SAlex Lorenz   int Reg = TRI->getLLVMRegNum(DwarfReg, true);
5218cfc6867SAlex Lorenz   if (Reg == -1) {
5228cfc6867SAlex Lorenz     OS << "<badreg>";
5238cfc6867SAlex Lorenz     return;
5248cfc6867SAlex Lorenz   }
5258cfc6867SAlex Lorenz   printReg(Reg, OS, TRI);
5268cfc6867SAlex Lorenz }
5278cfc6867SAlex Lorenz 
5288cfc6867SAlex Lorenz void MIPrinter::print(const MCCFIInstruction &CFI,
5298cfc6867SAlex Lorenz                       const TargetRegisterInfo *TRI) {
530f4baeb51SAlex Lorenz   switch (CFI.getOperation()) {
5318cfc6867SAlex Lorenz   case MCCFIInstruction::OpOffset:
5328cfc6867SAlex Lorenz     OS << ".cfi_offset ";
5338cfc6867SAlex Lorenz     if (CFI.getLabel())
5348cfc6867SAlex Lorenz       OS << "<mcsymbol> ";
5358cfc6867SAlex Lorenz     printCFIRegister(CFI.getRegister(), OS, TRI);
5368cfc6867SAlex Lorenz     OS << ", " << CFI.getOffset();
5378cfc6867SAlex Lorenz     break;
5385b0d5f6fSAlex Lorenz   case MCCFIInstruction::OpDefCfaRegister:
5395b0d5f6fSAlex Lorenz     OS << ".cfi_def_cfa_register ";
5405b0d5f6fSAlex Lorenz     if (CFI.getLabel())
5415b0d5f6fSAlex Lorenz       OS << "<mcsymbol> ";
5425b0d5f6fSAlex Lorenz     printCFIRegister(CFI.getRegister(), OS, TRI);
5435b0d5f6fSAlex Lorenz     break;
544f4baeb51SAlex Lorenz   case MCCFIInstruction::OpDefCfaOffset:
545f4baeb51SAlex Lorenz     OS << ".cfi_def_cfa_offset ";
546f4baeb51SAlex Lorenz     if (CFI.getLabel())
547f4baeb51SAlex Lorenz       OS << "<mcsymbol> ";
548f4baeb51SAlex Lorenz     OS << CFI.getOffset();
549f4baeb51SAlex Lorenz     break;
550f4baeb51SAlex Lorenz   default:
551f4baeb51SAlex Lorenz     // TODO: Print the other CFI Operations.
552f4baeb51SAlex Lorenz     OS << "<unserializable cfi operation>";
553f4baeb51SAlex Lorenz     break;
554f4baeb51SAlex Lorenz   }
555f4baeb51SAlex Lorenz }
556f4baeb51SAlex Lorenz 
557345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const Module &M) {
558345c1449SAlex Lorenz   yaml::Output Out(OS);
559345c1449SAlex Lorenz   Out << const_cast<Module &>(M);
560345c1449SAlex Lorenz }
561345c1449SAlex Lorenz 
562345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
563345c1449SAlex Lorenz   MIRPrinter Printer(OS);
564345c1449SAlex Lorenz   Printer.print(MF);
565345c1449SAlex Lorenz }
566