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;
36345c1449SAlex Lorenz 
37345c1449SAlex Lorenz public:
38345c1449SAlex Lorenz   MIRPrinter(raw_ostream &OS) : OS(OS) {}
39345c1449SAlex Lorenz 
40345c1449SAlex Lorenz   void print(const MachineFunction &MF);
414f093bf1SAlex Lorenz 
4254565cf0SAlex Lorenz   void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
434f093bf1SAlex Lorenz   void convert(yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB);
44345c1449SAlex Lorenz };
45345c1449SAlex Lorenz 
468e0a1b48SAlex Lorenz /// This class prints out the machine instructions using the MIR serialization
478e0a1b48SAlex Lorenz /// format.
488e0a1b48SAlex Lorenz class MIPrinter {
498e0a1b48SAlex Lorenz   raw_ostream &OS;
508e0a1b48SAlex Lorenz 
518e0a1b48SAlex Lorenz public:
528e0a1b48SAlex Lorenz   MIPrinter(raw_ostream &OS) : OS(OS) {}
538e0a1b48SAlex Lorenz 
548e0a1b48SAlex Lorenz   void print(const MachineInstr &MI);
55f3db51deSAlex Lorenz   void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
568e0a1b48SAlex Lorenz };
578e0a1b48SAlex Lorenz 
58345c1449SAlex Lorenz } // end anonymous namespace
59345c1449SAlex Lorenz 
60345c1449SAlex Lorenz namespace llvm {
61345c1449SAlex Lorenz namespace yaml {
62345c1449SAlex Lorenz 
63345c1449SAlex Lorenz /// This struct serializes the LLVM IR module.
64345c1449SAlex Lorenz template <> struct BlockScalarTraits<Module> {
65345c1449SAlex Lorenz   static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
66345c1449SAlex Lorenz     Mod.print(OS, nullptr);
67345c1449SAlex Lorenz   }
68345c1449SAlex Lorenz   static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
69345c1449SAlex Lorenz     llvm_unreachable("LLVM Module is supposed to be parsed separately");
70345c1449SAlex Lorenz     return "";
71345c1449SAlex Lorenz   }
72345c1449SAlex Lorenz };
73345c1449SAlex Lorenz 
74345c1449SAlex Lorenz } // end namespace yaml
75345c1449SAlex Lorenz } // end namespace llvm
76345c1449SAlex Lorenz 
77345c1449SAlex Lorenz void MIRPrinter::print(const MachineFunction &MF) {
78345c1449SAlex Lorenz   yaml::MachineFunction YamlMF;
79345c1449SAlex Lorenz   YamlMF.Name = MF.getName();
805b5f9753SAlex Lorenz   YamlMF.Alignment = MF.getAlignment();
815b5f9753SAlex Lorenz   YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
825b5f9753SAlex Lorenz   YamlMF.HasInlineAsm = MF.hasInlineAsm();
8354565cf0SAlex Lorenz   convert(YamlMF, MF.getRegInfo());
84*33f0aef3SAlex Lorenz 
85*33f0aef3SAlex Lorenz   int I = 0;
864f093bf1SAlex Lorenz   for (const auto &MBB : MF) {
87*33f0aef3SAlex Lorenz     // TODO: Allow printing of non sequentially numbered MBBs.
88*33f0aef3SAlex Lorenz     // This is currently needed as the basic block references get their index
89*33f0aef3SAlex Lorenz     // from MBB.getNumber(), thus it should be sequential so that the parser can
90*33f0aef3SAlex Lorenz     // map back to the correct MBBs when parsing the output.
91*33f0aef3SAlex Lorenz     assert(MBB.getNumber() == I++ &&
92*33f0aef3SAlex Lorenz            "Can't print MBBs that aren't sequentially numbered");
934f093bf1SAlex Lorenz     yaml::MachineBasicBlock YamlMBB;
944f093bf1SAlex Lorenz     convert(YamlMBB, MBB);
954f093bf1SAlex Lorenz     YamlMF.BasicBlocks.push_back(YamlMBB);
964f093bf1SAlex Lorenz   }
97345c1449SAlex Lorenz   yaml::Output Out(OS);
98345c1449SAlex Lorenz   Out << YamlMF;
99345c1449SAlex Lorenz }
100345c1449SAlex Lorenz 
10154565cf0SAlex Lorenz void MIRPrinter::convert(yaml::MachineFunction &MF,
10254565cf0SAlex Lorenz                          const MachineRegisterInfo &RegInfo) {
10354565cf0SAlex Lorenz   MF.IsSSA = RegInfo.isSSA();
10454565cf0SAlex Lorenz   MF.TracksRegLiveness = RegInfo.tracksLiveness();
10554565cf0SAlex Lorenz   MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
10654565cf0SAlex Lorenz }
10754565cf0SAlex Lorenz 
1084f093bf1SAlex Lorenz void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB,
1094f093bf1SAlex Lorenz                          const MachineBasicBlock &MBB) {
110*33f0aef3SAlex Lorenz   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
111*33f0aef3SAlex Lorenz   YamlMBB.ID = (unsigned)MBB.getNumber();
1124f093bf1SAlex Lorenz   // TODO: Serialize unnamed BB references.
1134f093bf1SAlex Lorenz   if (const auto *BB = MBB.getBasicBlock())
1144f093bf1SAlex Lorenz     YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>";
1154f093bf1SAlex Lorenz   else
1164f093bf1SAlex Lorenz     YamlMBB.Name = "";
1174f093bf1SAlex Lorenz   YamlMBB.Alignment = MBB.getAlignment();
1184f093bf1SAlex Lorenz   YamlMBB.AddressTaken = MBB.hasAddressTaken();
1194f093bf1SAlex Lorenz   YamlMBB.IsLandingPad = MBB.isLandingPad();
1208e0a1b48SAlex Lorenz 
1218e0a1b48SAlex Lorenz   // Print the machine instructions.
1228e0a1b48SAlex Lorenz   YamlMBB.Instructions.reserve(MBB.size());
1238e0a1b48SAlex Lorenz   std::string Str;
1248e0a1b48SAlex Lorenz   for (const auto &MI : MBB) {
1258e0a1b48SAlex Lorenz     raw_string_ostream StrOS(Str);
1268e0a1b48SAlex Lorenz     MIPrinter(StrOS).print(MI);
1278e0a1b48SAlex Lorenz     YamlMBB.Instructions.push_back(StrOS.str());
1288e0a1b48SAlex Lorenz     Str.clear();
1298e0a1b48SAlex Lorenz   }
1308e0a1b48SAlex Lorenz }
1318e0a1b48SAlex Lorenz 
1328e0a1b48SAlex Lorenz void MIPrinter::print(const MachineInstr &MI) {
1338e0a1b48SAlex Lorenz   const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
134f3db51deSAlex Lorenz   const auto *TRI = SubTarget.getRegisterInfo();
135f3db51deSAlex Lorenz   assert(TRI && "Expected target register info");
1368e0a1b48SAlex Lorenz   const auto *TII = SubTarget.getInstrInfo();
1378e0a1b48SAlex Lorenz   assert(TII && "Expected target instruction info");
1388e0a1b48SAlex Lorenz 
139f3db51deSAlex Lorenz   unsigned I = 0, E = MI.getNumOperands();
140f3db51deSAlex Lorenz   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
141f3db51deSAlex Lorenz          !MI.getOperand(I).isImplicit();
142f3db51deSAlex Lorenz        ++I) {
143f3db51deSAlex Lorenz     if (I)
144f3db51deSAlex Lorenz       OS << ", ";
145f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
146f3db51deSAlex Lorenz   }
147f3db51deSAlex Lorenz 
148f3db51deSAlex Lorenz   if (I)
149f3db51deSAlex Lorenz     OS << " = ";
1508e0a1b48SAlex Lorenz   OS << TII->getName(MI.getOpcode());
151f3db51deSAlex Lorenz   // TODO: Print the instruction flags, machine mem operands.
152f3db51deSAlex Lorenz   if (I < E)
153f3db51deSAlex Lorenz     OS << ' ';
154f3db51deSAlex Lorenz 
155f3db51deSAlex Lorenz   bool NeedComma = false;
156f3db51deSAlex Lorenz   for (; I < E; ++I) {
157f3db51deSAlex Lorenz     if (NeedComma)
158f3db51deSAlex Lorenz       OS << ", ";
159f3db51deSAlex Lorenz     print(MI.getOperand(I), TRI);
160f3db51deSAlex Lorenz     NeedComma = true;
161f3db51deSAlex Lorenz   }
162f3db51deSAlex Lorenz }
163f3db51deSAlex Lorenz 
164f3db51deSAlex Lorenz static void printReg(unsigned Reg, raw_ostream &OS,
165f3db51deSAlex Lorenz                      const TargetRegisterInfo *TRI) {
166f3db51deSAlex Lorenz   // TODO: Print Stack Slots.
167f3db51deSAlex Lorenz   // TODO: Print virtual registers.
16812b554e6SAlex Lorenz   if (!Reg)
16912b554e6SAlex Lorenz     OS << '_';
17012b554e6SAlex Lorenz   else if (Reg < TRI->getNumRegs())
171f3db51deSAlex Lorenz     OS << '%' << StringRef(TRI->getName(Reg)).lower();
172f3db51deSAlex Lorenz   else
173f3db51deSAlex Lorenz     llvm_unreachable("Can't print this kind of register yet");
174f3db51deSAlex Lorenz }
175f3db51deSAlex Lorenz 
176f3db51deSAlex Lorenz void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
177f3db51deSAlex Lorenz   switch (Op.getType()) {
178f3db51deSAlex Lorenz   case MachineOperand::MO_Register:
179f3db51deSAlex Lorenz     // TODO: Print register flags.
180f3db51deSAlex Lorenz     printReg(Op.getReg(), OS, TRI);
181f3db51deSAlex Lorenz     // TODO: Print sub register.
182f3db51deSAlex Lorenz     break;
183240fc1e0SAlex Lorenz   case MachineOperand::MO_Immediate:
184240fc1e0SAlex Lorenz     OS << Op.getImm();
185240fc1e0SAlex Lorenz     break;
186*33f0aef3SAlex Lorenz   case MachineOperand::MO_MachineBasicBlock:
187*33f0aef3SAlex Lorenz     OS << "%bb." << Op.getMBB()->getNumber();
188*33f0aef3SAlex Lorenz     if (const auto *BB = Op.getMBB()->getBasicBlock()) {
189*33f0aef3SAlex Lorenz       if (BB->hasName())
190*33f0aef3SAlex Lorenz         OS << '.' << BB->getName();
191*33f0aef3SAlex Lorenz     }
192*33f0aef3SAlex Lorenz     break;
193f3db51deSAlex Lorenz   default:
194f3db51deSAlex Lorenz     // TODO: Print the other machine operands.
195f3db51deSAlex Lorenz     llvm_unreachable("Can't print this machine operand at the moment");
196f3db51deSAlex Lorenz   }
1974f093bf1SAlex Lorenz }
1984f093bf1SAlex Lorenz 
199345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const Module &M) {
200345c1449SAlex Lorenz   yaml::Output Out(OS);
201345c1449SAlex Lorenz   Out << const_cast<Module &>(M);
202345c1449SAlex Lorenz }
203345c1449SAlex Lorenz 
204345c1449SAlex Lorenz void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
205345c1449SAlex Lorenz   MIRPrinter Printer(OS);
206345c1449SAlex Lorenz   Printer.print(MF);
207345c1449SAlex Lorenz }
208