blob: d317bd72918fec40f92feead840e1bb354270bc9 [file] [log] [blame]
Chris Lattner00950542001-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"
Chris Lattner70cc3392001-09-10 07:58:01 +000017#include "llvm/GlobalVariable.h"
Chris Lattner00950542001-06-06 20:29:01 +000018#include "llvm/BasicBlock.h"
19#include "llvm/ConstPoolVals.h"
20#include "llvm/iOther.h"
21#include "llvm/iMemory.h"
Chris Lattner007377f2001-09-07 16:36:04 +000022#include "llvm/Support/STLExtras.h"
23#include "llvm/SymbolTable.h"
24#include <algorithm>
Chris Lattner00950542001-06-06 20:29:01 +000025
Chris Lattner622f7402001-07-20 19:15:21 +000026// WriteAsOperand - Write the name of the specified value out to the specified
27// ostream. This can be useful when you just want to print int %reg126, not the
28// whole instruction that generated it.
29//
30ostream &WriteAsOperand(ostream &Out, const Value *V, bool PrintType,
31 bool PrintName, SlotCalculator *Table) {
32 if (PrintType)
33 Out << " " << V->getType();
34
Chris Lattner007377f2001-09-07 16:36:04 +000035 if (PrintName && V->hasName()) {
Chris Lattner622f7402001-07-20 19:15:21 +000036 Out << " %" << V->getName();
37 } else {
Chris Lattner9636a912001-10-01 16:18:37 +000038 if (const ConstPoolVal *CPV = dyn_cast<const ConstPoolVal>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000039 Out << " " << CPV->getStrValue();
40 } else {
41 int Slot;
42 if (Table) {
43 Slot = Table->getValSlot(V);
44 } else {
Chris Lattner9636a912001-10-01 16:18:37 +000045 if (const Type *Ty = dyn_cast<const Type>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000046 return Out << " " << Ty;
Chris Lattner9636a912001-10-01 16:18:37 +000047 } else if (const MethodArgument *MA =dyn_cast<const MethodArgument>(V)){
Chris Lattner622f7402001-07-20 19:15:21 +000048 Table = new SlotCalculator(MA->getParent(), true);
Chris Lattner9636a912001-10-01 16:18:37 +000049 } else if (const Instruction *I = dyn_cast<const Instruction>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000050 Table = new SlotCalculator(I->getParent()->getParent(), true);
Chris Lattner9636a912001-10-01 16:18:37 +000051 } else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000052 Table = new SlotCalculator(BB->getParent(), true);
Chris Lattner9636a912001-10-01 16:18:37 +000053 } else if (const Method *Meth = dyn_cast<const Method>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000054 Table = new SlotCalculator(Meth, true);
Chris Lattner9636a912001-10-01 16:18:37 +000055 } else if (const Module *Mod = dyn_cast<const Module>(V)) {
Chris Lattner622f7402001-07-20 19:15:21 +000056 Table = new SlotCalculator(Mod, true);
57 } else {
58 return Out << "BAD VALUE TYPE!";
59 }
60 Slot = Table->getValSlot(V);
61 delete Table;
62 }
63 if (Slot >= 0) Out << " %" << Slot;
64 else if (PrintName)
65 Out << "<badref>"; // Not embeded into a location?
66 }
67 }
68 return Out;
69}
70
71
Chris Lattnerd8c2e422001-07-12 23:35:26 +000072
Chris Lattner007377f2001-09-07 16:36:04 +000073class AssemblyWriter {
Chris Lattner00950542001-06-06 20:29:01 +000074 ostream &Out;
75 SlotCalculator &Table;
76public:
77 inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
78 }
79
80 inline void write(const Module *M) { processModule(M); }
Chris Lattner70cc3392001-09-10 07:58:01 +000081 inline void write(const GlobalVariable *G) { processGlobal(G); }
Chris Lattner00950542001-06-06 20:29:01 +000082 inline void write(const Method *M) { processMethod(M); }
83 inline void write(const BasicBlock *BB) { processBasicBlock(BB); }
84 inline void write(const Instruction *I) { processInstruction(I); }
85 inline void write(const ConstPoolVal *CPV) { processConstant(CPV); }
86
Chris Lattner00950542001-06-06 20:29:01 +000087private :
Chris Lattner007377f2001-09-07 16:36:04 +000088 void processModule(const Module *M);
89 void processSymbolTable(const SymbolTable &ST);
90 void processConstant(const ConstPoolVal *CPV);
Chris Lattner70cc3392001-09-10 07:58:01 +000091 void processGlobal(const GlobalVariable *GV);
Chris Lattner007377f2001-09-07 16:36:04 +000092 void processMethod(const Method *M);
93 void processMethodArgument(const MethodArgument *MA);
94 void processBasicBlock(const BasicBlock *BB);
95 void processInstruction(const Instruction *I);
Chris Lattner70cc3392001-09-10 07:58:01 +000096
Chris Lattner00950542001-06-06 20:29:01 +000097 void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
98};
99
100
Chris Lattner007377f2001-09-07 16:36:04 +0000101void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
102 bool PrintName) {
103 WriteAsOperand(Out, Operand, PrintType, PrintName, &Table);
Chris Lattner00950542001-06-06 20:29:01 +0000104}
105
Chris Lattner00950542001-06-06 20:29:01 +0000106
Chris Lattner007377f2001-09-07 16:36:04 +0000107void AssemblyWriter::processModule(const Module *M) {
108 // Loop over the symbol table, emitting all named constants...
109 if (M->hasSymbolTable())
110 processSymbolTable(*M->getSymbolTable());
Chris Lattner70cc3392001-09-10 07:58:01 +0000111
112 for_each(M->gbegin(), M->gend(),
113 bind_obj(this, &AssemblyWriter::processGlobal));
Chris Lattner007377f2001-09-07 16:36:04 +0000114
Vikram S. Adve5efa3cc2001-09-18 12:48:16 +0000115 Out << "implementation\n";
116
Chris Lattner007377f2001-09-07 16:36:04 +0000117 // Output all of the methods...
118 for_each(M->begin(), M->end(), bind_obj(this,&AssemblyWriter::processMethod));
119}
120
Chris Lattner70cc3392001-09-10 07:58:01 +0000121void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
Chris Lattner70cc3392001-09-10 07:58:01 +0000122 if (GV->hasName()) Out << "%" << GV->getName() << " = ";
Chris Lattnerd70684f2001-09-18 04:01:05 +0000123
124 if (!GV->hasInitializer()) Out << "uninitialized ";
125
126 Out << (GV->isConstant() ? "constant " : "global ")
127 << GV->getType()->getValueType()->getDescription();
128
129 if (GV->hasInitializer())
130 writeOperand(GV->getInitializer(), false, false);
131
132 Out << endl;
Chris Lattner70cc3392001-09-10 07:58:01 +0000133}
134
Chris Lattner007377f2001-09-07 16:36:04 +0000135
136// processSymbolTable - Run through symbol table looking for named constants
137// if a named constant is found, emit it's declaration...
138//
139void AssemblyWriter::processSymbolTable(const SymbolTable &ST) {
140 for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) {
141 SymbolTable::type_const_iterator I = ST.type_begin(TI->first);
142 SymbolTable::type_const_iterator End = ST.type_end(TI->first);
143
144 for (; I != End; ++I) {
145 const Value *V = I->second;
Chris Lattner1d87bcf2001-10-01 20:11:19 +0000146 if (const ConstPoolVal *CPV = dyn_cast<const ConstPoolVal>(V)) {
Chris Lattner007377f2001-09-07 16:36:04 +0000147 processConstant(CPV);
Chris Lattner1d87bcf2001-10-01 20:11:19 +0000148 } else if (const Type *Ty = dyn_cast<const Type>(V)) {
Chris Lattner007377f2001-09-07 16:36:04 +0000149 Out << "\t%" << I->first << " = type " << Ty->getDescription() << endl;
150 }
151 }
Chris Lattner739a56d2001-07-15 06:35:59 +0000152 }
Chris Lattner00950542001-06-06 20:29:01 +0000153}
154
155
156// processConstant - Print out a constant pool entry...
157//
Chris Lattner007377f2001-09-07 16:36:04 +0000158void AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
159 // Don't print out unnamed constants, they will be inlined
160 if (!CPV->hasName()) return;
Chris Lattner00950542001-06-06 20:29:01 +0000161
Chris Lattner1333ed52001-07-26 16:29:38 +0000162 // Print out name...
163 Out << "\t%" << CPV->getName() << " = ";
Chris Lattner00950542001-06-06 20:29:01 +0000164
Chris Lattner1333ed52001-07-26 16:29:38 +0000165 // Print out the constant type...
Chris Lattner00950542001-06-06 20:29:01 +0000166 Out << CPV->getType();
167
168 // Write the value out now...
169 writeOperand(CPV, false, false);
170
171 if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
172 int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
173 Out << "\t\t; <" << CPV->getType() << ">:";
174 if (Slot >= 0) Out << Slot;
175 else Out << "<badref>";
176 }
177
178 Out << endl;
Chris Lattner00950542001-06-06 20:29:01 +0000179}
180
181// processMethod - Process all aspects of a method.
182//
Chris Lattner007377f2001-09-07 16:36:04 +0000183void AssemblyWriter::processMethod(const Method *M) {
Chris Lattner00950542001-06-06 20:29:01 +0000184 // Print out the return type and name...
Chris Lattner739a56d2001-07-15 06:35:59 +0000185 Out << "\n" << (M->isExternal() ? "declare " : "")
186 << M->getReturnType() << " \"" << M->getName() << "\"(";
Chris Lattner00950542001-06-06 20:29:01 +0000187 Table.incorporateMethod(M);
Chris Lattner007377f2001-09-07 16:36:04 +0000188
189 // Loop over the arguments, processing them...
190 for_each(M->getArgumentList().begin(), M->getArgumentList().end(),
191 bind_obj(this, &AssemblyWriter::processMethodArgument));
192
193
194 // Finish printing arguments...
Chris Lattnerb00c5822001-10-02 03:41:24 +0000195 const MethodType *MT = cast<const MethodType>(M->getType());
Chris Lattner007377f2001-09-07 16:36:04 +0000196 if (MT->isVarArg()) {
197 if (MT->getParamTypes().size()) Out << ", ";
198 Out << "..."; // Output varargs portion of signature!
199 }
200 Out << ")\n";
201
202 if (!M->isExternal()) {
203 // Loop over the symbol table, emitting all named constants...
204 if (M->hasSymbolTable())
205 processSymbolTable(*M->getSymbolTable());
206
207 Out << "begin";
208
209 // Output all of its basic blocks... for the method
210 for_each(M->begin(), M->end(),
211 bind_obj(this, &AssemblyWriter::processBasicBlock));
212
Chris Lattner739a56d2001-07-15 06:35:59 +0000213 Out << "end\n";
Chris Lattner007377f2001-09-07 16:36:04 +0000214 }
215
216 Table.purgeMethod();
Chris Lattner00950542001-06-06 20:29:01 +0000217}
218
219// processMethodArgument - This member is called for every argument that
220// is passed into the method. Simply print it out
221//
Chris Lattner007377f2001-09-07 16:36:04 +0000222void AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
Chris Lattner00950542001-06-06 20:29:01 +0000223 // Insert commas as we go... the first arg doesn't get a comma
224 if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";
225
226 // Output type...
227 Out << Arg->getType();
228
229 // Output name, if available...
230 if (Arg->hasName())
231 Out << " %" << Arg->getName();
232 else if (Table.getValSlot(Arg) < 0)
233 Out << "<badref>";
Chris Lattner00950542001-06-06 20:29:01 +0000234}
235
236// processBasicBlock - This member is called for each basic block in a methd.
237//
Chris Lattner007377f2001-09-07 16:36:04 +0000238void AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
Chris Lattner00950542001-06-06 20:29:01 +0000239 if (BB->hasName()) { // Print out the label if it exists...
Chris Lattnerb9a45782001-06-07 16:58:55 +0000240 Out << "\n" << BB->getName() << ":";
Chris Lattner00950542001-06-06 20:29:01 +0000241 } else {
242 int Slot = Table.getValSlot(BB);
Chris Lattnerb9a45782001-06-07 16:58:55 +0000243 Out << "\n; <label>:";
Chris Lattner00950542001-06-06 20:29:01 +0000244 if (Slot >= 0)
Chris Lattnerb9a45782001-06-07 16:58:55 +0000245 Out << Slot; // Extra newline seperates out label's
Chris Lattner00950542001-06-06 20:29:01 +0000246 else
Chris Lattnerb9a45782001-06-07 16:58:55 +0000247 Out << "<badref>";
Chris Lattner00950542001-06-06 20:29:01 +0000248 }
Chris Lattnerb9a45782001-06-07 16:58:55 +0000249 Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n"; // Output # uses
Chris Lattner00950542001-06-06 20:29:01 +0000250
Chris Lattner007377f2001-09-07 16:36:04 +0000251 // Output all of the instructions in the basic block...
252 for_each(BB->begin(), BB->end(),
253 bind_obj(this, &AssemblyWriter::processInstruction));
Chris Lattner00950542001-06-06 20:29:01 +0000254}
255
256// processInstruction - This member is called for each Instruction in a methd.
257//
Chris Lattner007377f2001-09-07 16:36:04 +0000258void AssemblyWriter::processInstruction(const Instruction *I) {
Chris Lattner00950542001-06-06 20:29:01 +0000259 Out << "\t";
260
261 // Print out name if it exists...
262 if (I && I->hasName())
263 Out << "%" << I->getName() << " = ";
264
265 // Print out the opcode...
Chris Lattnera41f50d2001-07-07 19:24:15 +0000266 Out << I->getOpcodeName();
Chris Lattner00950542001-06-06 20:29:01 +0000267
268 // Print out the type of the operands...
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000269 const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;
Chris Lattner00950542001-06-06 20:29:01 +0000270
271 // Special case conditional branches to swizzle the condition out to the front
Chris Lattnera41f50d2001-07-07 19:24:15 +0000272 if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) {
Chris Lattner00950542001-06-06 20:29:01 +0000273 writeOperand(I->getOperand(2), true);
274 Out << ",";
275 writeOperand(Operand, true);
276 Out << ",";
277 writeOperand(I->getOperand(1), true);
278
Chris Lattnera41f50d2001-07-07 19:24:15 +0000279 } else if (I->getOpcode() == Instruction::Switch) {
Chris Lattner00950542001-06-06 20:29:01 +0000280 // Special case switch statement to get formatting nice and correct...
281 writeOperand(Operand , true); Out << ",";
282 writeOperand(I->getOperand(1), true); Out << " [";
283
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000284 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
Chris Lattner00950542001-06-06 20:29:01 +0000285 Out << "\n\t\t";
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000286 writeOperand(I->getOperand(op ), true); Out << ",";
Chris Lattner00950542001-06-06 20:29:01 +0000287 writeOperand(I->getOperand(op+1), true);
288 }
289 Out << "\n\t]";
Chris Lattnerb00c5822001-10-02 03:41:24 +0000290 } else if (isa<PHINode>(I)) {
Chris Lattnerc24d2082001-06-11 15:04:20 +0000291 Out << " " << Operand->getType();
Chris Lattner00950542001-06-06 20:29:01 +0000292
Chris Lattnerc24d2082001-06-11 15:04:20 +0000293 Out << " ["; writeOperand(Operand, false); Out << ",";
Chris Lattner28d480b2001-06-21 05:29:56 +0000294 writeOperand(I->getOperand(1), false); Out << " ]";
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000295 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
296 Out << ", [";
297 writeOperand(I->getOperand(op ), false); Out << ",";
Chris Lattner28d480b2001-06-21 05:29:56 +0000298 writeOperand(I->getOperand(op+1), false); Out << " ]";
Chris Lattnerc24d2082001-06-11 15:04:20 +0000299 }
Chris Lattnera41f50d2001-07-07 19:24:15 +0000300 } else if (I->getOpcode() == Instruction::Ret && !Operand) {
Chris Lattner00950542001-06-06 20:29:01 +0000301 Out << " void";
Chris Lattnera41f50d2001-07-07 19:24:15 +0000302 } else if (I->getOpcode() == Instruction::Call) {
Chris Lattner00950542001-06-06 20:29:01 +0000303 writeOperand(Operand, true);
304 Out << "(";
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000305 if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
306 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
Chris Lattner00950542001-06-06 20:29:01 +0000307 Out << ",";
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000308 writeOperand(I->getOperand(op), true);
Chris Lattner00950542001-06-06 20:29:01 +0000309 }
310
311 Out << " )";
Chris Lattnera41f50d2001-07-07 19:24:15 +0000312 } else if (I->getOpcode() == Instruction::Malloc ||
313 I->getOpcode() == Instruction::Alloca) {
Chris Lattnerb00c5822001-10-02 03:41:24 +0000314 Out << " " << cast<const PointerType>(I->getType())->getValueType();
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000315 if (I->getNumOperands()) {
316 Out << ",";
317 writeOperand(I->getOperand(0), true);
Chris Lattner00950542001-06-06 20:29:01 +0000318 }
Chris Lattner09083092001-07-08 04:57:15 +0000319 } else if (I->getOpcode() == Instruction::Cast) {
320 writeOperand(Operand, true);
321 Out << " to " << I->getType();
Chris Lattner00950542001-06-06 20:29:01 +0000322 } else if (Operand) { // Print the normal way...
323
324 // PrintAllTypes - Instructions who have operands of all the same type
325 // omit the type from all but the first operand. If the instruction has
326 // different type operands (for example br), then they are all printed.
327 bool PrintAllTypes = false;
328 const Type *TheType = Operand->getType();
Chris Lattner00950542001-06-06 20:29:01 +0000329
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000330 for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
331 Operand = I->getOperand(i);
Chris Lattner00950542001-06-06 20:29:01 +0000332 if (Operand->getType() != TheType) {
333 PrintAllTypes = true; // We have differing types! Print them all!
334 break;
335 }
336 }
337
338 if (!PrintAllTypes)
339 Out << " " << I->getOperand(0)->getType();
340
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000341 for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
Chris Lattner00950542001-06-06 20:29:01 +0000342 if (i) Out << ",";
Chris Lattnerc8b25d42001-07-07 08:36:50 +0000343 writeOperand(I->getOperand(i), PrintAllTypes);
Chris Lattner00950542001-06-06 20:29:01 +0000344 }
345 }
346
347 // Print a little comment after the instruction indicating which slot it
348 // occupies.
349 //
Chris Lattnerb9a45782001-06-07 16:58:55 +0000350 if (I->getType() != Type::VoidTy) {
351 Out << "\t\t; <" << I->getType() << ">";
Chris Lattner00950542001-06-06 20:29:01 +0000352
Chris Lattnerb9a45782001-06-07 16:58:55 +0000353 if (!I->hasName()) {
354 int Slot = Table.getValSlot(I); // Print out the def slot taken...
355 if (Slot >= 0) Out << ":" << Slot;
356 else Out << ":<badref>";
357 }
Chris Lattner00950542001-06-06 20:29:01 +0000358 Out << "\t[#uses=" << I->use_size() << "]"; // Output # uses
359 }
Chris Lattner00950542001-06-06 20:29:01 +0000360 Out << endl;
Chris Lattner00950542001-06-06 20:29:01 +0000361}
362
363
364//===----------------------------------------------------------------------===//
365// External Interface declarations
366//===----------------------------------------------------------------------===//
367
368
369
370void WriteToAssembly(const Module *M, ostream &o) {
371 if (M == 0) { o << "<null> module\n"; return; }
372 SlotCalculator SlotTable(M, true);
373 AssemblyWriter W(o, SlotTable);
374
375 W.write(M);
376}
377
Chris Lattnerb0e45232001-09-10 20:08:19 +0000378void WriteToAssembly(const GlobalVariable *G, ostream &o) {
379 if (G == 0) { o << "<null> global variable\n"; return; }
380 SlotCalculator SlotTable(G->getParent(), true);
381 AssemblyWriter W(o, SlotTable);
382 W.write(G);
383}
384
Chris Lattner00950542001-06-06 20:29:01 +0000385void WriteToAssembly(const Method *M, ostream &o) {
386 if (M == 0) { o << "<null> method\n"; return; }
387 SlotCalculator SlotTable(M->getParent(), true);
388 AssemblyWriter W(o, SlotTable);
389
390 W.write(M);
391}
392
393
394void WriteToAssembly(const BasicBlock *BB, ostream &o) {
395 if (BB == 0) { o << "<null> basic block\n"; return; }
396
397 SlotCalculator SlotTable(BB->getParent(), true);
398 AssemblyWriter W(o, SlotTable);
399
400 W.write(BB);
401}
402
403void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
404 if (CPV == 0) { o << "<null> constant pool value\n"; return; }
Chris Lattner81e29632001-07-28 17:49:02 +0000405 WriteAsOperand(o, CPV, true, true, 0);
Chris Lattner00950542001-06-06 20:29:01 +0000406}
407
408void WriteToAssembly(const Instruction *I, ostream &o) {
409 if (I == 0) { o << "<null> instruction\n"; return; }
410
411 SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
412 true);
413 AssemblyWriter W(o, SlotTable);
414
415 W.write(I);
416}