blob: 78ef8c75537f141ee0d8026173868a0ce6640743 [file] [log] [blame]
Chris Lattner2f7c9632001-06-06 20:29:01 +00001//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=//
2//
3// This library implements the functionality defined in llvm/Assembly/Writer.h
4//
5// This library uses the Analysis library to figure out offsets for
6// variables in the method tables...
7//
8// TODO: print out the type name instead of the full type if a particular type
9// is in the symbol table...
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Assembly/Writer.h"
14#include "llvm/Analysis/SlotCalculator.h"
15#include "llvm/Module.h"
16#include "llvm/Method.h"
17#include "llvm/BasicBlock.h"
18#include "llvm/ConstPoolVals.h"
19#include "llvm/iOther.h"
20#include "llvm/iMemory.h"
21
Chris Lattner2e9fee42001-07-12 23:35:26 +000022void DebugValue(const Value *V) {
23 cerr << V << endl;
24}
25
26
Chris Lattner2f7c9632001-06-06 20:29:01 +000027class AssemblyWriter : public ModuleAnalyzer {
28 ostream &Out;
29 SlotCalculator &Table;
30public:
31 inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
32 }
33
34 inline void write(const Module *M) { processModule(M); }
35 inline void write(const Method *M) { processMethod(M); }
36 inline void write(const BasicBlock *BB) { processBasicBlock(BB); }
37 inline void write(const Instruction *I) { processInstruction(I); }
38 inline void write(const ConstPoolVal *CPV) { processConstant(CPV); }
39
40protected:
41 virtual bool visitMethod(const Method *M);
42 virtual bool processConstPool(const ConstantPool &CP, bool isMethod);
43 virtual bool processConstant(const ConstPoolVal *CPV);
44 virtual bool processMethod(const Method *M);
45 virtual bool processMethodArgument(const MethodArgument *MA);
46 virtual bool processBasicBlock(const BasicBlock *BB);
47 virtual bool processInstruction(const Instruction *I);
48
49private :
50 void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
51};
52
53
54
55// visitMethod - This member is called after the above two steps, visting each
56// method, because they are effectively values that go into the constant pool.
57//
58bool AssemblyWriter::visitMethod(const Method *M) {
59 return false;
60}
61
62bool AssemblyWriter::processConstPool(const ConstantPool &CP, bool isMethod) {
63 // Done printing arguments...
64 if (isMethod) Out << ")\n";
65
66 ModuleAnalyzer::processConstPool(CP, isMethod);
67
68 if (isMethod)
69 Out << "begin";
70 else
71 Out << "implementation\n";
72 return false;
73}
74
75
76// processConstant - Print out a constant pool entry...
77//
78bool AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
79 Out << "\t";
80
81 // Print out name if it exists...
82 if (CPV->hasName())
83 Out << "%" << CPV->getName() << " = ";
84
85 // Print out the opcode...
86 Out << CPV->getType();
87
88 // Write the value out now...
89 writeOperand(CPV, false, false);
90
91 if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
92 int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
93 Out << "\t\t; <" << CPV->getType() << ">:";
94 if (Slot >= 0) Out << Slot;
95 else Out << "<badref>";
96 }
97
98 Out << endl;
99 return false;
100}
101
102// processMethod - Process all aspects of a method.
103//
104bool AssemblyWriter::processMethod(const Method *M) {
105 // Print out the return type and name...
106 Out << "\n" << M->getReturnType() << " \"" << M->getName() << "\"(";
107 Table.incorporateMethod(M);
108 ModuleAnalyzer::processMethod(M);
109 Table.purgeMethod();
110 Out << "end\n";
111 return false;
112}
113
114// processMethodArgument - This member is called for every argument that
115// is passed into the method. Simply print it out
116//
117bool AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
118 // Insert commas as we go... the first arg doesn't get a comma
119 if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";
120
121 // Output type...
122 Out << Arg->getType();
123
124 // Output name, if available...
125 if (Arg->hasName())
126 Out << " %" << Arg->getName();
127 else if (Table.getValSlot(Arg) < 0)
128 Out << "<badref>";
129
130 return false;
131}
132
133// processBasicBlock - This member is called for each basic block in a methd.
134//
135bool AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
136 if (BB->hasName()) { // Print out the label if it exists...
Chris Lattnera2f01872001-06-07 16:58:55 +0000137 Out << "\n" << BB->getName() << ":";
Chris Lattner2f7c9632001-06-06 20:29:01 +0000138 } else {
139 int Slot = Table.getValSlot(BB);
Chris Lattnera2f01872001-06-07 16:58:55 +0000140 Out << "\n; <label>:";
Chris Lattner2f7c9632001-06-06 20:29:01 +0000141 if (Slot >= 0)
Chris Lattnera2f01872001-06-07 16:58:55 +0000142 Out << Slot; // Extra newline seperates out label's
Chris Lattner2f7c9632001-06-06 20:29:01 +0000143 else
Chris Lattnera2f01872001-06-07 16:58:55 +0000144 Out << "<badref>";
Chris Lattner2f7c9632001-06-06 20:29:01 +0000145 }
Chris Lattnera2f01872001-06-07 16:58:55 +0000146 Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n"; // Output # uses
Chris Lattner2f7c9632001-06-06 20:29:01 +0000147
148 ModuleAnalyzer::processBasicBlock(BB);
149 return false;
150}
151
152// processInstruction - This member is called for each Instruction in a methd.
153//
154bool AssemblyWriter::processInstruction(const Instruction *I) {
155 Out << "\t";
156
157 // Print out name if it exists...
158 if (I && I->hasName())
159 Out << "%" << I->getName() << " = ";
160
161 // Print out the opcode...
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000162 Out << I->getOpcodeName();
Chris Lattner2f7c9632001-06-06 20:29:01 +0000163
164 // Print out the type of the operands...
Chris Lattnera073acb2001-07-07 08:36:50 +0000165 const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;
Chris Lattner2f7c9632001-06-06 20:29:01 +0000166
167 // Special case conditional branches to swizzle the condition out to the front
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000168 if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000169 writeOperand(I->getOperand(2), true);
170 Out << ",";
171 writeOperand(Operand, true);
172 Out << ",";
173 writeOperand(I->getOperand(1), true);
174
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000175 } else if (I->getOpcode() == Instruction::Switch) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000176 // Special case switch statement to get formatting nice and correct...
177 writeOperand(Operand , true); Out << ",";
178 writeOperand(I->getOperand(1), true); Out << " [";
179
Chris Lattnera073acb2001-07-07 08:36:50 +0000180 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000181 Out << "\n\t\t";
Chris Lattnera073acb2001-07-07 08:36:50 +0000182 writeOperand(I->getOperand(op ), true); Out << ",";
Chris Lattner2f7c9632001-06-06 20:29:01 +0000183 writeOperand(I->getOperand(op+1), true);
184 }
185 Out << "\n\t]";
Chris Lattner4cee8d82001-06-27 23:41:11 +0000186 } else if (I->isPHINode()) {
Chris Lattner931ef3b2001-06-11 15:04:20 +0000187 Out << " " << Operand->getType();
Chris Lattner2f7c9632001-06-06 20:29:01 +0000188
Chris Lattner931ef3b2001-06-11 15:04:20 +0000189 Out << " ["; writeOperand(Operand, false); Out << ",";
Chris Lattner4b94e232001-06-21 05:29:56 +0000190 writeOperand(I->getOperand(1), false); Out << " ]";
Chris Lattnera073acb2001-07-07 08:36:50 +0000191 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
192 Out << ", [";
193 writeOperand(I->getOperand(op ), false); Out << ",";
Chris Lattner4b94e232001-06-21 05:29:56 +0000194 writeOperand(I->getOperand(op+1), false); Out << " ]";
Chris Lattner931ef3b2001-06-11 15:04:20 +0000195 }
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000196 } else if (I->getOpcode() == Instruction::Ret && !Operand) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000197 Out << " void";
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000198 } else if (I->getOpcode() == Instruction::Call) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000199 writeOperand(Operand, true);
200 Out << "(";
Chris Lattnera073acb2001-07-07 08:36:50 +0000201 if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
202 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000203 Out << ",";
Chris Lattnera073acb2001-07-07 08:36:50 +0000204 writeOperand(I->getOperand(op), true);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000205 }
206
207 Out << " )";
Chris Lattnerb1ca9cb2001-07-07 19:24:15 +0000208 } else if (I->getOpcode() == Instruction::Malloc ||
209 I->getOpcode() == Instruction::Alloca) {
Chris Lattnera073acb2001-07-07 08:36:50 +0000210 Out << " " << ((const PointerType*)I->getType())->getValueType();
211 if (I->getNumOperands()) {
212 Out << ",";
213 writeOperand(I->getOperand(0), true);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000214 }
Chris Lattnera6821822001-07-08 04:57:15 +0000215 } else if (I->getOpcode() == Instruction::Cast) {
216 writeOperand(Operand, true);
217 Out << " to " << I->getType();
Chris Lattner2f7c9632001-06-06 20:29:01 +0000218 } else if (Operand) { // Print the normal way...
219
220 // PrintAllTypes - Instructions who have operands of all the same type
221 // omit the type from all but the first operand. If the instruction has
222 // different type operands (for example br), then they are all printed.
223 bool PrintAllTypes = false;
224 const Type *TheType = Operand->getType();
Chris Lattner2f7c9632001-06-06 20:29:01 +0000225
Chris Lattnera073acb2001-07-07 08:36:50 +0000226 for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
227 Operand = I->getOperand(i);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000228 if (Operand->getType() != TheType) {
229 PrintAllTypes = true; // We have differing types! Print them all!
230 break;
231 }
232 }
233
234 if (!PrintAllTypes)
235 Out << " " << I->getOperand(0)->getType();
236
Chris Lattnera073acb2001-07-07 08:36:50 +0000237 for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000238 if (i) Out << ",";
Chris Lattnera073acb2001-07-07 08:36:50 +0000239 writeOperand(I->getOperand(i), PrintAllTypes);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000240 }
241 }
242
243 // Print a little comment after the instruction indicating which slot it
244 // occupies.
245 //
Chris Lattnera2f01872001-06-07 16:58:55 +0000246 if (I->getType() != Type::VoidTy) {
247 Out << "\t\t; <" << I->getType() << ">";
Chris Lattner2f7c9632001-06-06 20:29:01 +0000248
Chris Lattnera2f01872001-06-07 16:58:55 +0000249 if (!I->hasName()) {
250 int Slot = Table.getValSlot(I); // Print out the def slot taken...
251 if (Slot >= 0) Out << ":" << Slot;
252 else Out << ":<badref>";
253 }
Chris Lattner2f7c9632001-06-06 20:29:01 +0000254 Out << "\t[#uses=" << I->use_size() << "]"; // Output # uses
255 }
Chris Lattner2f7c9632001-06-06 20:29:01 +0000256 Out << endl;
257
258 return false;
259}
260
261
262void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
263 bool PrintName) {
264 if (PrintType)
265 Out << " " << Operand->getType();
266
267 if (Operand->hasName() && PrintName) {
268 Out << " %" << Operand->getName();
269 } else {
270 int Slot = Table.getValSlot(Operand);
271
Chris Lattnera073acb2001-07-07 08:36:50 +0000272 if (const ConstPoolVal *CPV = Operand->castConstant()) {
273 Out << " " << CPV->getStrValue();
Chris Lattner2f7c9632001-06-06 20:29:01 +0000274 } else {
275 if (Slot >= 0) Out << " %" << Slot;
276 else if (PrintName)
277 Out << "<badref>"; // Not embeded into a location?
278 }
279 }
280}
281
282
283//===----------------------------------------------------------------------===//
284// External Interface declarations
285//===----------------------------------------------------------------------===//
286
287
288
289void WriteToAssembly(const Module *M, ostream &o) {
290 if (M == 0) { o << "<null> module\n"; return; }
291 SlotCalculator SlotTable(M, true);
292 AssemblyWriter W(o, SlotTable);
293
294 W.write(M);
295}
296
297void WriteToAssembly(const Method *M, ostream &o) {
298 if (M == 0) { o << "<null> method\n"; return; }
299 SlotCalculator SlotTable(M->getParent(), true);
300 AssemblyWriter W(o, SlotTable);
301
302 W.write(M);
303}
304
305
306void WriteToAssembly(const BasicBlock *BB, ostream &o) {
307 if (BB == 0) { o << "<null> basic block\n"; return; }
308
309 SlotCalculator SlotTable(BB->getParent(), true);
310 AssemblyWriter W(o, SlotTable);
311
312 W.write(BB);
313}
314
315void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
316 if (CPV == 0) { o << "<null> constant pool value\n"; return; }
317
318 SlotCalculator *SlotTable;
319
320 // A Constant pool value may have a parent that is either a method or a
321 // module. Untangle this now...
322 //
Chris Lattner32e96bc2001-07-14 06:10:33 +0000323 if (const Method *Meth = CPV->getParentV()->castMethod()) {
324 SlotTable = new SlotCalculator(Meth, true);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000325 } else {
Chris Lattner4cee8d82001-06-27 23:41:11 +0000326 SlotTable =
Chris Lattner32e96bc2001-07-14 06:10:33 +0000327 new SlotCalculator(CPV->getParentV()->castModuleAsserting(), true);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000328 }
329
330 AssemblyWriter W(o, *SlotTable);
331 W.write(CPV);
332
333 delete SlotTable;
334}
335
336void WriteToAssembly(const Instruction *I, ostream &o) {
337 if (I == 0) { o << "<null> instruction\n"; return; }
338
339 SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
340 true);
341 AssemblyWriter W(o, SlotTable);
342
343 W.write(I);
344}