AsmWriter.cpp revision d8c2e42aeff8bdb3ac905b4721b3d3ca1f904cfa
1//===-- 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 22void DebugValue(const Value *V) { 23 cerr << V << endl; 24} 25 26 27class 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... 137 Out << "\n" << BB->getName() << ":"; 138 } else { 139 int Slot = Table.getValSlot(BB); 140 Out << "\n; <label>:"; 141 if (Slot >= 0) 142 Out << Slot; // Extra newline seperates out label's 143 else 144 Out << "<badref>"; 145 } 146 Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n"; // Output # uses 147 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... 162 Out << I->getOpcodeName(); 163 164 // Print out the type of the operands... 165 const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0; 166 167 // Special case conditional branches to swizzle the condition out to the front 168 if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) { 169 writeOperand(I->getOperand(2), true); 170 Out << ","; 171 writeOperand(Operand, true); 172 Out << ","; 173 writeOperand(I->getOperand(1), true); 174 175 } else if (I->getOpcode() == Instruction::Switch) { 176 // Special case switch statement to get formatting nice and correct... 177 writeOperand(Operand , true); Out << ","; 178 writeOperand(I->getOperand(1), true); Out << " ["; 179 180 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) { 181 Out << "\n\t\t"; 182 writeOperand(I->getOperand(op ), true); Out << ","; 183 writeOperand(I->getOperand(op+1), true); 184 } 185 Out << "\n\t]"; 186 } else if (I->isPHINode()) { 187 Out << " " << Operand->getType(); 188 189 Out << " ["; writeOperand(Operand, false); Out << ","; 190 writeOperand(I->getOperand(1), false); Out << " ]"; 191 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) { 192 Out << ", ["; 193 writeOperand(I->getOperand(op ), false); Out << ","; 194 writeOperand(I->getOperand(op+1), false); Out << " ]"; 195 } 196 } else if (I->getOpcode() == Instruction::Ret && !Operand) { 197 Out << " void"; 198 } else if (I->getOpcode() == Instruction::Call) { 199 writeOperand(Operand, true); 200 Out << "("; 201 if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true); 202 for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) { 203 Out << ","; 204 writeOperand(I->getOperand(op), true); 205 } 206 207 Out << " )"; 208 } else if (I->getOpcode() == Instruction::Malloc || 209 I->getOpcode() == Instruction::Alloca) { 210 Out << " " << ((const PointerType*)I->getType())->getValueType(); 211 if (I->getNumOperands()) { 212 Out << ","; 213 writeOperand(I->getOperand(0), true); 214 } 215 } else if (I->getOpcode() == Instruction::Cast) { 216 writeOperand(Operand, true); 217 Out << " to " << I->getType(); 218 } 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(); 225 226 for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) { 227 Operand = I->getOperand(i); 228 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 237 for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) { 238 if (i) Out << ","; 239 writeOperand(I->getOperand(i), PrintAllTypes); 240 } 241 } 242 243 // Print a little comment after the instruction indicating which slot it 244 // occupies. 245 // 246 if (I->getType() != Type::VoidTy) { 247 Out << "\t\t; <" << I->getType() << ">"; 248 249 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 } 254 Out << "\t[#uses=" << I->use_size() << "]"; // Output # uses 255 } 256 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 272 if (const ConstPoolVal *CPV = Operand->castConstant()) { 273 Out << " " << CPV->getStrValue(); 274 } 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 // 323 if (CPV->getParent() == 0 || CPV->getParent()->isMethod()) { 324 SlotTable = new SlotCalculator((Method*)CPV->getParent(), true); 325 } else { 326 SlotTable = 327 new SlotCalculator(CPV->getParent()->castModuleAsserting(), true); 328 } 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} 345