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"
17345c1449SAlex Lorenz #include "llvm/CodeGen/MachineFunction.h"
1854565cf0SAlex Lorenz #include "llvm/CodeGen/MachineRegisterInfo.h"
19345c1449SAlex Lorenz #include "llvm/CodeGen/MIRYamlMapping.h"
204f093bf1SAlex Lorenz #include "llvm/IR/BasicBlock.h"
21345c1449SAlex Lorenz #include "llvm/IR/Module.h"
22345c1449SAlex Lorenz #include "llvm/Support/MemoryBuffer.h"
23345c1449SAlex Lorenz #include "llvm/Support/raw_ostream.h"
24345c1449SAlex Lorenz #include "llvm/Support/YAMLTraits.h"
258e0a1b48SAlex Lorenz #include "llvm/Target/TargetInstrInfo.h"
268e0a1b48SAlex Lorenz #include "llvm/Target/TargetSubtargetInfo.h"
27345c1449SAlex Lorenz 
28345c1449SAlex Lorenz using namespace llvm;
29345c1449SAlex Lorenz 
30345c1449SAlex Lorenz namespace {
31345c1449SAlex Lorenz 
32345c1449SAlex Lorenz /// This class prints out the machine functions using the MIR serialization
33345c1449SAlex Lorenz /// format.
34345c1449SAlex Lorenz class MIRPrinter {
35345c1449SAlex Lorenz   raw_ostream &OS;
368f6f4285SAlex Lorenz   DenseMap<const uint32_t *, unsigned> RegisterMaskIds;
37345c1449SAlex Lorenz 
38345c1449SAlex Lorenz public:
39345c1449SAlex Lorenz   MIRPrinter(raw_ostream &OS) : OS(OS) {}
40345c1449SAlex Lorenz 
41345c1449SAlex Lorenz   void print(const MachineFunction &MF);
424f093bf1SAlex Lorenz 
4354565cf0SAlex Lorenz   void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
445d6108e4SAlex Lorenz   void convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
455d6108e4SAlex Lorenz                const MachineBasicBlock &MBB);
468f6f4285SAlex Lorenz 
478f6f4285SAlex Lorenz private:
488f6f4285SAlex Lorenz   void initRegisterMaskIds(const MachineFunction &MF);
49345c1449SAlex Lorenz };
50345c1449SAlex Lorenz 
518e0a1b48SAlex Lorenz /// This class prints out the machine instructions using the MIR serialization
528e0a1b48SAlex Lorenz /// format.
538e0a1b48SAlex Lorenz class MIPrinter {
545d6108e4SAlex Lorenz   const Module &M;
558e0a1b48SAlex Lorenz   raw_ostream &OS;
568f6f4285SAlex Lorenz   const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
578e0a1b48SAlex Lorenz 
588e0a1b48SAlex Lorenz public:
598f6f4285SAlex Lorenz   MIPrinter(const Module &M, raw_ostream &OS,
608f6f4285SAlex Lorenz             const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds)
618f6f4285SAlex Lorenz       : M(M), OS(OS), RegisterMaskIds(RegisterMaskIds) {}
628e0a1b48SAlex Lorenz 
638e0a1b48SAlex Lorenz   void print(const MachineInstr &MI);
645d26fa83SAlex Lorenz   void printMBBReference(const MachineBasicBlock &MBB);
65f3db51deSAlex Lorenz   void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
668e0a1b48SAlex Lorenz };
678e0a1b48SAlex Lorenz 
68345c1449SAlex Lorenz } // end anonymous namespace
69345c1449SAlex Lorenz 
70345c1449SAlex Lorenz namespace llvm {
71345c1449SAlex Lorenz namespace yaml {
72345c1449SAlex Lorenz 
73345c1449SAlex Lorenz /// This struct serializes the LLVM IR module.
74345c1449SAlex Lorenz template <> struct BlockScalarTraits<Module> {
75345c1449SAlex Lorenz   static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
76345c1449SAlex Lorenz     Mod.print(OS, nullptr);
77345c1449SAlex Lorenz   }
78345c1449SAlex Lorenz   static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
79345c1449SAlex Lorenz     llvm_unreachable("LLVM Module is supposed to be parsed separately");
80345c1449SAlex Lorenz     return "";
81345c1449SAlex Lorenz   }
82345c1449SAlex Lorenz };
83345c1449SAlex Lorenz 
84345c1449SAlex Lorenz } // end namespace yaml
85345c1449SAlex Lorenz } // end namespace llvm
86345c1449SAlex Lorenz 
87345c1449SAlex Lorenz void MIRPrinter::print(const MachineFunction &MF) {
888f6f4285SAlex Lorenz   initRegisterMaskIds(MF);
898f6f4285SAlex Lorenz 
90345c1449SAlex Lorenz   yaml::MachineFunction YamlMF;
91345c1449SAlex Lorenz   YamlMF.Name = MF.getName();
925b5f9753SAlex Lorenz   YamlMF.Alignment = MF.getAlignment();
935b5f9753SAlex Lorenz   YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
945b5f9753SAlex Lorenz   YamlMF.HasInlineAsm = MF.hasInlineAsm();
9554565cf0SAlex Lorenz   convert(YamlMF, MF.getRegInfo());
9633f0aef3SAlex Lorenz 
9733f0aef3SAlex Lorenz   int I = 0;
985d6108e4SAlex Lorenz   const auto &M = *MF.getFunction()->getParent();
994f093bf1SAlex Lorenz   for (const auto &MBB : MF) {
10033f0aef3SAlex Lorenz     // TODO: Allow printing of non sequentially numbered MBBs.
10133f0aef3SAlex Lorenz     // This is currently needed as the basic block references get their index
10233f0aef3SAlex Lorenz     // from MBB.getNumber(), thus it should be sequential so that the parser can
10333f0aef3SAlex Lorenz     // map back to the correct MBBs when parsing the output.
10433f0aef3SAlex Lorenz     assert(MBB.getNumber() == I++ &&
10533f0aef3SAlex Lorenz            "Can't print MBBs that aren't sequentially numbered");
106ec6b26b9SAlex Lorenz     (void)I;
1074f093bf1SAlex Lorenz     yaml::MachineBasicBlock YamlMBB;
1085d6108e4SAlex Lorenz     convert(M, YamlMBB, MBB);
1094f093bf1SAlex Lorenz     YamlMF.BasicBlocks.push_back(YamlMBB);
1104f093bf1SAlex Lorenz   }
111345c1449SAlex Lorenz   yaml::Output Out(OS);
112345c1449SAlex Lorenz   Out << YamlMF;
113345c1449SAlex Lorenz }
114345c1449SAlex Lorenz 
11554565cf0SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
11654565cf0SAlex Lorenz                          const MachineRegisterInfo &RegInfo) {
11754565cf0SAlex Lorenz   MF.IsSSA = RegInfo.isSSA();
11854565cf0SAlex Lorenz   MF.TracksRegLiveness = RegInfo.tracksLiveness();
11954565cf0SAlex Lorenz   MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
12054565cf0SAlex Lorenz }
12154565cf0SAlex Lorenz 
1225d6108e4SAlex Lorenz void MIRPrinter::convert(const Module &M, yaml::MachineBasicBlock &YamlMBB,
1234f093bf1SAlex Lorenz                          const MachineBasicBlock &MBB) {
12433f0aef3SAlex Lorenz   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
12533f0aef3SAlex Lorenz   YamlMBB.ID = (unsigned)MBB.getNumber();
1264f093bf1SAlex Lorenz   // TODO: Serialize unnamed BB references.
1274f093bf1SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock())
1284f093bf1SAlex Lorenz     YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>";
1294f093bf1SAlex Lorenz   else
1304f093bf1SAlex Lorenz     YamlMBB.Name = "";
1314f093bf1SAlex Lorenz   YamlMBB.Alignment = MBB.getAlignment();
1324f093bf1SAlex Lorenz   YamlMBB.AddressTaken = MBB.hasAddressTaken();
1334f093bf1SAlex Lorenz   YamlMBB.IsLandingPad = MBB.isLandingPad();
134*f09df00dSAlex Lorenz   for (const auto *MBB : MBB.successors()) {
135*f09df00dSAlex Lorenz     std::string Str;
136*f09df00dSAlex Lorenz     raw_string_ostream StrOS(Str);
137*f09df00dSAlex Lorenz     MIPrinter(M, StrOS, RegisterMaskIds).printMBBReference(*MBB);
138*f09df00dSAlex Lorenz     YamlMBB.Successors.push_back(StrOS.str());
139*f09df00dSAlex Lorenz   }
1408e0a1b48SAlex Lorenz 
1418e0a1b48SAlex Lorenz   // Print the machine instructions.
1428e0a1b48SAlex Lorenz   YamlMBB.Instructions.reserve(MBB.size());
1438e0a1b48SAlex Lorenz   std::string Str;
1448e0a1b48SAlex Lorenz   for (const auto &MI : MBB) {
1458e0a1b48SAlex Lorenz     raw_string_ostream StrOS(Str);
1468f6f4285SAlex Lorenz     MIPrinter(M, StrOS, RegisterMaskIds).print(MI);
1478e0a1b48SAlex Lorenz     YamlMBB.Instructions.push_back(StrOS.str());
1488e0a1b48SAlex Lorenz     Str.clear();
1498e0a1b48SAlex Lorenz   }
1508e0a1b48SAlex Lorenz }
1518e0a1b48SAlex Lorenz 
1528f6f4285SAlex Lorenz void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
1538f6f4285SAlex Lorenz   const auto *TRI = MF.getSubtarget().getRegisterInfo();
1548f6f4285SAlex Lorenz   unsigned I = 0;
1558f6f4285SAlex Lorenz   for (const uint32_t *Mask : TRI->getRegMasks())
1568f6f4285SAlex Lorenz     RegisterMaskIds.insert(std::make_pair(Mask, I++));
1578f6f4285SAlex Lorenz }
1588f6f4285SAlex Lorenz 
1598e0a1b48SAlex Lorenz void MIPrinter::print(const MachineInstr &MI) {
1608e0a1b48SAlex Lorenz   const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
161f3db51deSAlex Lorenz   const auto *TRI = SubTarget.getRegisterInfo();
162f3db51deSAlex Lorenz   assert(TRI && "Expected target register info");
1638e0a1b48SAlex Lorenz   const auto *TII = SubTarget.getInstrInfo();
1648e0a1b48SAlex Lorenz   assert(TII && "Expected target instruction info");
1658e0a1b48SAlex Lorenz 
166f3db51deSAlex Lorenz   unsigned I = 0, E = MI.getNumOperands();
167f3db51deSAlex Lorenz   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
168f3db51deSAlex Lorenz          !MI.getOperand(I).isImplicit();
169f3db51deSAlex Lorenz        ++I) {
170f3db51deSAlex Lorenz     if (I)
171f3db51deSAlex Lorenz       OS << ", ";
172f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
173f3db51deSAlex Lorenz   }
174f3db51deSAlex Lorenz 
175f3db51deSAlex Lorenz   if (I)
176f3db51deSAlex Lorenz     OS << " = ";
1778e0a1b48SAlex Lorenz   OS << TII->getName(MI.getOpcode());
178f3db51deSAlex Lorenz   // TODO: Print the instruction flags, machine mem operands.
179f3db51deSAlex Lorenz   if (I < E)
180f3db51deSAlex Lorenz     OS << ' ';
181f3db51deSAlex Lorenz 
182f3db51deSAlex Lorenz   bool NeedComma = false;
183f3db51deSAlex Lorenz   for (; I < E; ++I) {
184f3db51deSAlex Lorenz     if (NeedComma)
185f3db51deSAlex Lorenz       OS << ", ";
186f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
187f3db51deSAlex Lorenz     NeedComma = true;
188f3db51deSAlex Lorenz   }
189f3db51deSAlex Lorenz }
190f3db51deSAlex Lorenz 
191f3db51deSAlex Lorenz static void printReg(unsigned Reg, raw_ostream &OS,
192f3db51deSAlex Lorenz                      const TargetRegisterInfo *TRI) {
193f3db51deSAlex Lorenz   // TODO: Print Stack Slots.
194f3db51deSAlex Lorenz   // TODO: Print virtual registers.
19512b554e6SAlex Lorenz   if (!Reg)
19612b554e6SAlex Lorenz     OS << '_';
19712b554e6SAlex Lorenz   else if (Reg < TRI->getNumRegs())
198f3db51deSAlex Lorenz     OS << '%' << StringRef(TRI->getName(Reg)).lower();
199f3db51deSAlex Lorenz   else
200f3db51deSAlex Lorenz     llvm_unreachable("Can't print this kind of register yet");
201f3db51deSAlex Lorenz }
202f3db51deSAlex Lorenz 
2035d26fa83SAlex Lorenz void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
2045d26fa83SAlex Lorenz   OS << "%bb." << MBB.getNumber();
2055d26fa83SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock()) {
2065d26fa83SAlex Lorenz     if (BB->hasName())
2075d26fa83SAlex Lorenz       OS << '.' << BB->getName();
2085d26fa83SAlex Lorenz   }
2095d26fa83SAlex Lorenz }
2105d26fa83SAlex Lorenz 
211f3db51deSAlex Lorenz void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
212f3db51deSAlex Lorenz   switch (Op.getType()) {
213f3db51deSAlex Lorenz   case MachineOperand::MO_Register:
214f3db51deSAlex Lorenz     // TODO: Print register flags.
215f3db51deSAlex Lorenz     printReg(Op.getReg(), OS, TRI);
216f3db51deSAlex Lorenz     // TODO: Print sub register.
217f3db51deSAlex Lorenz     break;
218240fc1e0SAlex Lorenz   case MachineOperand::MO_Immediate:
219240fc1e0SAlex Lorenz     OS << Op.getImm();
220240fc1e0SAlex Lorenz     break;
22133f0aef3SAlex Lorenz   case MachineOperand::MO_MachineBasicBlock:
2225d26fa83SAlex Lorenz     printMBBReference(*Op.getMBB());
22333f0aef3SAlex Lorenz     break;
2245d6108e4SAlex Lorenz   case MachineOperand::MO_GlobalAddress:
2255d6108e4SAlex Lorenz     // FIXME: Make this faster - print as operand will create a slot tracker to
2265d6108e4SAlex Lorenz     // print unnamed values for the whole module every time it's called, which
2275d6108e4SAlex Lorenz     // is inefficient.
2285d6108e4SAlex Lorenz     Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, &M);
2295d6108e4SAlex Lorenz     // TODO: Print offset and target flags.
2305d6108e4SAlex Lorenz     break;
2318f6f4285SAlex Lorenz   case MachineOperand::MO_RegisterMask: {
2328f6f4285SAlex Lorenz     auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
2338f6f4285SAlex Lorenz     if (RegMaskInfo != RegisterMaskIds.end())
2348f6f4285SAlex Lorenz       OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
2358f6f4285SAlex Lorenz     else
2368f6f4285SAlex Lorenz       llvm_unreachable("Can't print this machine register mask yet.");
2378f6f4285SAlex Lorenz     break;
2388f6f4285SAlex Lorenz   }
239f3db51deSAlex Lorenz   default:
240f3db51deSAlex Lorenz     // TODO: Print the other machine operands.
241f3db51deSAlex Lorenz     llvm_unreachable("Can't print this machine operand at the moment");
242f3db51deSAlex Lorenz   }
2434f093bf1SAlex Lorenz }
2444f093bf1SAlex Lorenz 
245345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const Module &M) {
246345c1449SAlex Lorenz   yaml::Output Out(OS);
247345c1449SAlex Lorenz   Out << const_cast<Module &>(M);
248345c1449SAlex Lorenz }
249345c1449SAlex Lorenz 
250345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
251345c1449SAlex Lorenz   MIRPrinter Printer(OS);
252345c1449SAlex Lorenz   Printer.print(MF);
253345c1449SAlex Lorenz }
254