Minor fix I omitted to check in.
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9AsmPrinter.cpp
1 //===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
2 //
3 // This file implements all of the stuff neccesary to output a .s file from
4 // LLVM.  The code in this file assumes that the specified module has already
5 // been compiled into the internal data structures of the Module.
6 //
7 // The entry point of this file is the UltraSparc::emitAssembly method.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "SparcInternals.h"
12 #include "llvm/Analysis/SlotCalculator.h"
13 #include "llvm/Transforms/Linker.h"
14 #include "llvm/CodeGen/MachineInstr.h"
15 #include "llvm/GlobalVariable.h"
16 #include "llvm/GlobalValue.h"
17 #include "llvm/ConstPoolVals.h"
18 #include "llvm/DerivedTypes.h"
19 #include "llvm/BasicBlock.h"
20 #include "llvm/Method.h"
21 #include "llvm/Module.h"
22 #include "llvm/Support/HashExtras.h"
23 #include "llvm/Support/StringExtras.h"
24
25 namespace {
26
27
28 class SparcAsmPrinter {
29   typedef hash_map<const Value*, int> ValIdMap;
30   typedef ValIdMap::      iterator ValIdMapIterator;
31   typedef ValIdMap::const_iterator ValIdMapConstIterator;
32   
33   ostream &Out;
34   SlotCalculator Table;   // map anonymous values to unique integer IDs
35   ValIdMap valToIdMap;    // used for values not handled by SlotCalculator 
36   const UltraSparc &Target;
37   
38   enum Sections {
39     Unknown,
40     Text,
41     ReadOnlyData,
42     InitRWData,
43     UninitRWData,
44   } CurSection;
45   
46 public:
47   inline SparcAsmPrinter(ostream &o, const Module *M, const UltraSparc &t)
48     : Out(o), Table(SlotCalculator(M, true)), Target(t), CurSection(Unknown) {
49     emitModule(M);
50   }
51
52 private :
53   void emitModule(const Module *M);
54   void emitMethod(const Method *M);
55   void emitGlobalsAndConstants(const Module* module);
56   //void processMethodArgument(const MethodArgument *MA);
57   void emitBasicBlock(const BasicBlock *BB);
58   void emitMachineInst(const MachineInstr *MI);
59   
60   void printGlobalVariable(const GlobalVariable* GV);
61   void printConstant(const ConstPoolVal* CV, string valID = string(""));
62   
63   unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
64   void printOneOperand(const MachineOperand &Op);
65
66   bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
67   bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
68   
69   // enterSection - Use this method to enter a different section of the output
70   // executable.  This is used to only output neccesary section transitions.
71   //
72   void enterSection(enum Sections S) {
73     if (S == CurSection) return;        // Only switch section if neccesary
74     CurSection = S;
75
76     Out << "\n\t.section ";
77     switch (S)
78       {
79       default: assert(0 && "Bad section name!");
80       case Text:         Out << "\".text\""; break;
81       case ReadOnlyData: Out << "\".rodata\",#alloc"; break;
82       case InitRWData:   Out << "\".data\",#alloc,#write"; break;
83       case UninitRWData: Out << "\".bss\",#alloc,#write\nBbss.bss:"; break;
84       }
85     Out << "\n";
86   }
87
88   string getEscapedString(const string &S) {
89     string Result;
90
91     for (unsigned i = 0; i < S.size(); ++i) {
92       char C = S[i];
93       if ((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
94           (C >= '0' && C <= '9')) {
95         Result += C;
96       } else {
97         Result += '_';
98         Result += char('0' + ((unsigned char)C >> 4));
99         Result += char('0' + (C & 0xF));
100       }
101     }
102     return Result;
103   }
104
105   // getID - Return a valid identifier for the specified value.  Base it on
106   // the name of the identifier if possible, use a numbered value based on
107   // prefix otherwise.  FPrefix is always prepended to the output identifier.
108   //
109   string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
110     string FP(FPrefix ? FPrefix : "");  // "Forced prefix"
111     if (V->hasName()) {
112       return FP + getEscapedString(V->getName());
113     } else {
114       int valId = Table.getValSlot(V);
115       if (valId == -1) {
116         ValIdMapConstIterator I = valToIdMap.find(V);
117         valId = (I == valToIdMap.end())? (valToIdMap[V] = valToIdMap.size())
118                                        : (*I).second;
119       }
120       return FP + string(Prefix) + itostr(valId);
121     }
122   }
123   
124   // getID Wrappers - Ensure consistent usage...
125   string getID(const Module *M) {
126     return getID(M, "LLVMModule_");
127   }
128   string getID(const Method *M) {
129     return getID(M, "LLVMMethod_");
130   }
131   string getID(const BasicBlock *BB) {
132     return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
133   }
134   string getID(const GlobalVariable *GV) {
135     return getID(GV, "LLVMGlobal_", ".G_");
136   }
137   string getID(const ConstPoolVal *CV) {
138     return getID(CV, "LLVMConst_", ".C_");
139   }
140   
141   unsigned getOperandMask(unsigned Opcode) {
142     switch (Opcode) {
143     case SUBcc:   return 1 << 3;  // Remove CC argument
144     case BA:    case BRZ:         // Remove Arg #0, which is always null or xcc
145     case BRLEZ: case BRLZ:
146     case BRNZ:  case BRGZ:
147     case BRGEZ:   return 1 << 0;
148
149     default:      return 0;       // By default, don't hack operands...
150     }
151   }
152 };
153
154 inline bool
155 SparcAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
156                                        unsigned int opNum) {
157   switch (MI->getOpCode()) {
158   case JMPLCALL:
159   case JMPLRET: return (opNum == 0);
160   default:      return false;
161   }
162 }
163
164
165 inline bool
166 SparcAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
167                                        unsigned int opNum) {
168   if (Target.getInstrInfo().isLoad(MI->getOpCode()))
169     return (opNum == 0);
170   else if (Target.getInstrInfo().isStore(MI->getOpCode()))
171     return (opNum == 1);
172   else
173     return false;
174 }
175
176
177 #define PrintOp1PlusOp2(Op1, Op2) \
178   printOneOperand(Op1); Out << "+"; printOneOperand(Op2);
179
180
181 unsigned int
182 SparcAsmPrinter::printOperands(const MachineInstr *MI,
183                                unsigned int opNum)
184 {
185   const MachineOperand& Op = MI->getOperand(opNum);
186   
187   if (OpIsBranchTargetLabel(MI, opNum))
188     {
189       PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
190       return 2;
191     }
192   else if (OpIsMemoryAddressBase(MI, opNum))
193     {
194       Out << "[";
195       PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
196       Out << "]";
197       return 2;
198     }
199   else
200     {
201       printOneOperand(Op);
202       return 1;
203     }
204 }
205
206
207 void
208 SparcAsmPrinter::printOneOperand(const MachineOperand &Op)
209 {
210   switch (Op.getOperandType())
211     {
212     case MachineOperand::MO_VirtualRegister:
213     case MachineOperand::MO_CCRegister:
214     case MachineOperand::MO_MachineRegister:
215       {
216         int RegNum = (int)Op.getAllocatedRegNum();
217         
218         // ****this code is temporary till NULL Values are fixed
219         if (RegNum == 10000) {
220           Out << "<NULL VALUE>";
221         } else {
222           Out << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
223         }
224         break;
225       }
226     
227     case MachineOperand::MO_PCRelativeDisp:
228       {
229         const Value *Val = Op.getVRegValue();
230         if (!Val)
231           Out << "\t<*NULL Value*>";
232         else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
233           Out << getID(BB);
234         else if (const Method *M = dyn_cast<const Method>(Val))
235           Out << getID(M);
236         else if (const GlobalVariable *GV=dyn_cast<const GlobalVariable>(Val))
237           Out << getID(GV);
238         else if (const ConstPoolVal *CV = dyn_cast<const ConstPoolVal>(Val))
239           Out << getID(CV);
240         else
241           Out << "<unknown value=" << Val << ">";
242         break;
243       }
244     
245     case MachineOperand::MO_SignExtendedImmed:
246     case MachineOperand::MO_UnextendedImmed:
247       Out << Op.getImmedValue();
248       break;
249     
250     default:
251       Out << Op;      // use dump field
252       break;
253     }
254 }
255
256
257 void
258 SparcAsmPrinter::emitMachineInst(const MachineInstr *MI)
259 {
260   unsigned Opcode = MI->getOpCode();
261
262   if (TargetInstrDescriptors[Opcode].iclass & M_DUMMY_PHI_FLAG)
263     return;  // IGNORE PHI NODES
264
265   Out << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
266
267   unsigned Mask = getOperandMask(Opcode);
268   
269   bool NeedComma = false;
270   unsigned N = 1;
271   for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
272     if (! ((1 << OpNum) & Mask)) {        // Ignore this operand?
273       if (NeedComma) Out << ", ";         // Handle comma outputing
274       NeedComma = true;
275       N = printOperands(MI, OpNum);
276     }
277   else
278     N = 1;
279   
280   Out << endl;
281 }
282
283 void
284 SparcAsmPrinter::emitBasicBlock(const BasicBlock *BB)
285 {
286   // Emit a label for the basic block
287   Out << getID(BB) << ":\n";
288
289   // Get the vector of machine instructions corresponding to this bb.
290   const MachineCodeForBasicBlock &MIs = BB->getMachineInstrVec();
291   MachineCodeForBasicBlock::const_iterator MII = MIs.begin(), MIE = MIs.end();
292
293   // Loop over all of the instructions in the basic block...
294   for (; MII != MIE; ++MII)
295     emitMachineInst(*MII);
296   Out << "\n";  // Seperate BB's with newlines
297 }
298
299 void
300 SparcAsmPrinter::emitMethod(const Method *M)
301 {
302   if (M->isExternal()) return;
303
304   // Make sure the slot table has information about this method...
305   Table.incorporateMethod(M);
306
307   string MethName = getID(M);
308   Out << "!****** Outputing Method: " << MethName << " ******\n";
309   enterSection(Text);
310   Out << "\t.align\t4\n\t.global\t" << MethName << "\n";
311   //Out << "\t.type\t" << MethName << ",#function\n";
312   Out << "\t.type\t" << MethName << ", 2\n";
313   Out << MethName << ":\n";
314
315   // Output code for all of the basic blocks in the method...
316   for (Method::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
317     emitBasicBlock(*I);
318
319   // Output a .size directive so the debugger knows the extents of the function
320   Out << ".EndOf_" << MethName << ":\n\t.size "
321       << MethName << ", .EndOf_"
322       << MethName << "-" << MethName << endl;
323
324   // Put some spaces between the methods
325   Out << "\n\n";
326
327   // Forget all about M.
328   Table.purgeMethod();
329 }
330
331 inline bool
332 ArrayTypeIsString(ArrayType* arrayType)
333 {
334   return (arrayType->getElementType() == Type::UByteTy ||
335           arrayType->getElementType() == Type::SByteTy);
336 }
337
338 inline const string TypeToDataDirective(const Type* type) {
339   switch(type->getPrimitiveID()) {
340   case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
341     return ".byte";
342   case Type::UShortTyID: case Type::ShortTyID:
343     return ".half";
344   case Type::UIntTyID: case Type::IntTyID:
345     return ".word";
346   case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
347     return ".xword";
348   case Type::FloatTyID:
349     return ".float";
350   case Type::DoubleTyID:
351     return ".double";
352   case Type::ArrayTyID:
353     if (ArrayTypeIsString((ArrayType*) type))
354       return ".ascii";
355     else
356       return "<InvaliDataTypeForPrinting>";
357   default:
358     return "<InvaliDataTypeForPrinting>";
359   }
360 }
361
362 inline unsigned int ConstantToSize(const ConstPoolVal* CV,
363                                    const TargetMachine& target) {
364   if (ConstPoolArray* AV = dyn_cast<ConstPoolArray>(CV))
365     if (ArrayTypeIsString((ArrayType*) CV->getType()))
366       return 1 + AV->getNumOperands();
367   
368   return target.findOptimalStorageSize(CV->getType());
369 }
370
371
372 inline
373 unsigned int TypeToSize(const Type* type, const TargetMachine& target)
374 {
375   return target.findOptimalStorageSize(type);
376 }
377
378
379 inline unsigned int
380 TypeToAlignment(const Type* type, const TargetMachine& target)
381 {
382   if (type->getPrimitiveID() == Type::ArrayTyID &&
383       ArrayTypeIsString((ArrayType*) type))
384     return target.findOptimalStorageSize(Type::LongTy);
385   
386   return target.findOptimalStorageSize(type);
387 }
388
389
390 void
391 SparcAsmPrinter::printConstant(const ConstPoolVal* CV, string valID)
392 {
393   if (valID.length() == 0)
394     valID = getID(CV);
395   
396   Out << "\t.align\t" << TypeToAlignment(CV->getType(), Target)
397       << endl;
398   
399   Out << valID << ":" << endl;
400   
401   Out << "\t"
402       << TypeToDataDirective(CV->getType()) << "\t"
403       << CV->getStrValue(true) << endl;
404   
405   Out << "\t.type" << "\t" << valID << ",#object" << endl;
406   Out << "\t.size" << "\t" << valID << ","
407       << ConstantToSize(CV, Target) << endl;
408 }
409
410
411 void
412 SparcAsmPrinter::printGlobalVariable(const GlobalVariable* GV)
413 {
414   Out << "\t.global\t" << getID(GV) << endl;
415   
416   if (GV->hasInitializer())
417     printConstant(GV->getInitializer(), getID(GV));
418   else {
419     Out << "\t.align" << TypeToAlignment(GV->getType()->getValueType(), Target)
420         << getID(GV) << ":" << endl;
421     
422     Out << "\t.type" << "\t" << getID(GV) << ",#object" << endl;
423     Out << "\t.size" << "\t" << getID(GV) << ","
424         << TypeToSize(GV->getType()->getValueType(), Target)
425         << endl;
426   }
427 }
428
429
430 static void
431 FoldConstPools(const Module *M,
432                hash_set<const ConstPoolVal*>& moduleConstPool) {
433   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
434     const hash_set<const ConstPoolVal*>& pool =
435       (*I)->getMachineCode().getConstantPoolValues();
436     moduleConstPool.insert(pool.begin(), pool.end());
437   }
438 }
439
440
441 void
442 SparcAsmPrinter::emitGlobalsAndConstants(const Module *M)
443 {
444   // First, get the constants there were marked by the code generator for
445   // inclusion in the assembly code data area and fold them all into a
446   // single constant pool since there may be lots of duplicates.  Also,
447   // lets force these constants into the slot table so that we can get
448   // unique names for unnamed constants also.
449   // 
450   hash_set<const ConstPoolVal*> moduleConstPool;
451   FoldConstPools(M, moduleConstPool);
452   
453   // Now, emit the three data sections separately; the cost of I/O should
454   // make up for the cost of extra passes over the globals list!
455   // 
456   // Read-only data section (implies initialized)
457   for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
458     {
459       const GlobalVariable* GV = *GI;
460       if (GV->hasInitializer() && GV->isConstant())
461         {
462           if (GI == M->gbegin())
463             enterSection(ReadOnlyData);
464           printGlobalVariable(GV);
465         }
466   }
467   
468   for (hash_set<const ConstPoolVal*>::const_iterator I=moduleConstPool.begin(),
469          E = moduleConstPool.end();  I != E; ++I)
470     printConstant(*I);
471   
472   // Initialized read-write data section
473   for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
474     {
475       const GlobalVariable* GV = *GI;
476       if (GV->hasInitializer() && ! GV->isConstant())
477         {
478           if (GI == M->gbegin())
479             enterSection(InitRWData);
480           printGlobalVariable(GV);
481         }
482   }
483
484   // Uninitialized read-write data section
485   for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
486     {
487       const GlobalVariable* GV = *GI;
488       if (! GV->hasInitializer())
489         {
490           if (GI == M->gbegin())
491             enterSection(UninitRWData);
492           printGlobalVariable(GV);
493         }
494   }
495
496   Out << endl;
497 }
498
499
500 void
501 SparcAsmPrinter::emitModule(const Module *M)
502 {
503   // TODO: Look for a filename annotation on M to emit a .file directive
504   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
505     emitMethod(*I);
506   
507   emitGlobalsAndConstants(M);
508 }
509
510 }  // End anonymous namespace
511
512
513 //
514 // emitAssembly - Output assembly language code (a .s file) for the specified
515 // method. The specified method must have been compiled before this may be
516 // used.
517 //
518 void
519 UltraSparc::emitAssembly(const Module *M, ostream &Out) const
520 {
521   SparcAsmPrinter Print(Out, M, *this);
522 }