Missing piece of fix for Bug 333
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9AsmPrinter.cpp
1 //===-- EmitAssembly.cpp - Emit SparcV9 Specific .s File -------------------==//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements all of the stuff necessary to output a .s file from
11 // LLVM.  The code in this file assumes that the specified module has already
12 // been compiled into the internal data structures of the Module.
13 //
14 // This code largely consists of two LLVM Pass's: a FunctionPass and a Pass.
15 // The FunctionPass is pipelined together with all of the rest of the code
16 // generation stages, and the Pass runs at the end to emit code for global
17 // variables and such.
18 //
19 //===----------------------------------------------------------------------===//
20
21 #include "llvm/Constants.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/Module.h"
24 #include "llvm/Pass.h"
25 #include "llvm/Assembly/Writer.h"
26 #include "llvm/CodeGen/MachineConstantPool.h"
27 #include "llvm/CodeGen/MachineFunction.h"
28 #include "llvm/CodeGen/MachineFunctionInfo.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/Support/Mangler.h"
31 #include "Support/StringExtras.h"
32 #include "Support/Statistic.h"
33 #include "SparcV9Internals.h"
34 #include <string>
35 using namespace llvm;
36
37 namespace {
38   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
39
40   //===--------------------------------------------------------------------===//
41   // Utility functions
42
43   /// getAsCString - Return the specified array as a C compatible string, only
44   /// if the predicate isString() is true.
45   ///
46   std::string getAsCString(const ConstantArray *CVA) {
47     assert(CVA->isString() && "Array is not string compatible!");
48
49     std::string Result = "\"";
50     for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
51       unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
52
53       if (C == '"') {
54         Result += "\\\"";
55       } else if (C == '\\') {
56         Result += "\\\\";
57       } else if (isprint(C)) {
58         Result += C;
59       } else {
60         Result += '\\';    // print all other chars as octal value
61         // Convert C to octal representation
62         Result += ((C >> 6) & 7) + '0';
63         Result += ((C >> 3) & 7) + '0';
64         Result += ((C >> 0) & 7) + '0';
65       }
66     }
67     Result += "\"";
68
69     return Result;
70   }
71
72   inline bool ArrayTypeIsString(const ArrayType* arrayType) {
73     return (arrayType->getElementType() == Type::UByteTy ||
74             arrayType->getElementType() == Type::SByteTy);
75   }
76
77   inline const std::string
78   TypeToDataDirective(const Type* type) {
79     switch(type->getPrimitiveID())
80     {
81     case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
82       return ".byte";
83     case Type::UShortTyID: case Type::ShortTyID:
84       return ".half";
85     case Type::UIntTyID: case Type::IntTyID:
86       return ".word";
87     case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
88       return ".xword";
89     case Type::FloatTyID:
90       return ".word";
91     case Type::DoubleTyID:
92       return ".xword";
93     case Type::ArrayTyID:
94       if (ArrayTypeIsString((ArrayType*) type))
95         return ".ascii";
96       else
97         return "<InvaliDataTypeForPrinting>";
98     default:
99       return "<InvaliDataTypeForPrinting>";
100     }
101   }
102
103   /// Get the size of the constant for the given target.
104   /// If this is an unsized array, return 0.
105   /// 
106   inline unsigned int
107   ConstantToSize(const Constant* CV, const TargetMachine& target) {
108     if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) {
109       const ArrayType *aty = cast<ArrayType>(CVA->getType());
110       if (ArrayTypeIsString(aty))
111         return 1 + CVA->getNumOperands();
112     }
113   
114     return target.findOptimalStorageSize(CV->getType());
115   }
116
117   /// Align data larger than one L1 cache line on L1 cache line boundaries.
118   /// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
119   /// 
120   inline unsigned int
121   SizeToAlignment(unsigned int size, const TargetMachine& target) {
122     const unsigned short cacheLineSize = 16;
123     if (size > (unsigned) cacheLineSize / 2)
124       return cacheLineSize;
125     else
126       for (unsigned sz=1; /*no condition*/; sz *= 2)
127         if (sz >= size)
128           return sz;
129   }
130
131   /// Get the size of the type and then use SizeToAlignment.
132   /// 
133   inline unsigned int
134   TypeToAlignment(const Type* type, const TargetMachine& target) {
135     return SizeToAlignment(target.findOptimalStorageSize(type), target);
136   }
137
138   /// Get the size of the constant and then use SizeToAlignment.
139   /// Handles strings as a special case;
140   inline unsigned int
141   ConstantToAlignment(const Constant* CV, const TargetMachine& target) {
142     if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
143       if (ArrayTypeIsString(cast<ArrayType>(CVA->getType())))
144         return SizeToAlignment(1 + CVA->getNumOperands(), target);
145   
146     return TypeToAlignment(CV->getType(), target);
147   }
148
149 } // End anonymous namespace
150
151
152
153 //===---------------------------------------------------------------------===//
154 //   Code abstracted away from the AsmPrinter
155 //===---------------------------------------------------------------------===//
156
157 namespace {
158   class AsmPrinter {
159     // Mangle symbol names appropriately
160     Mangler *Mang;
161
162   public:
163     std::ostream &toAsm;
164     const TargetMachine &Target;
165   
166     enum Sections {
167       Unknown,
168       Text,
169       ReadOnlyData,
170       InitRWData,
171       ZeroInitRWData,
172     } CurSection;
173
174     AsmPrinter(std::ostream &os, const TargetMachine &T)
175       : /* idTable(0), */ toAsm(os), Target(T), CurSection(Unknown) {}
176   
177     ~AsmPrinter() {
178       delete Mang;
179     }
180
181     // (start|end)(Module|Function) - Callback methods invoked by subclasses
182     void startModule(Module &M) {
183       Mang = new Mangler(M);
184     }
185
186     void PrintZeroBytesToPad(int numBytes) {
187       //
188       // Always use single unsigned bytes for padding.  We don't know upon
189       // what data size the beginning address is aligned, so using anything
190       // other than a byte may cause alignment errors in the assembler.
191       //
192       while (numBytes--)
193         printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
194     }
195
196     /// Print a single constant value.
197     ///
198     void printSingleConstantValue(const Constant* CV);
199
200     /// Print a constant value or values (it may be an aggregate).
201     /// Uses printSingleConstantValue() to print each individual value.
202     ///
203     void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0);
204
205     // Print a constant (which may be an aggregate) prefixed by all the
206     // appropriate directives.  Uses printConstantValueOnly() to print the
207     // value or values.
208     void printConstant(const Constant* CV, std::string valID = "") {
209       if (valID.length() == 0)
210         valID = getID(CV);
211   
212       toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
213   
214       // Print .size and .type only if it is not a string.
215       if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
216         if (CVA->isString()) {
217           // print it as a string and return
218           toAsm << valID << ":\n";
219           toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
220           return;
221         }
222   
223       toAsm << "\t.type" << "\t" << valID << ",#object\n";
224
225       unsigned int constSize = ConstantToSize(CV, Target);
226       if (constSize)
227         toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n";
228   
229       toAsm << valID << ":\n";
230   
231       printConstantValueOnly(CV);
232     }
233
234     // enterSection - Use this method to enter a different section of the output
235     // executable.  This is used to only output necessary section transitions.
236     //
237     void enterSection(enum Sections S) {
238       if (S == CurSection) return;        // Only switch section if necessary
239       CurSection = S;
240
241       toAsm << "\n\t.section ";
242       switch (S)
243       {
244       default: assert(0 && "Bad section name!");
245       case Text:         toAsm << "\".text\""; break;
246       case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
247       case InitRWData:   toAsm << "\".data\",#alloc,#write"; break;
248       case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break;
249       }
250       toAsm << "\n";
251     }
252
253     // getID Wrappers - Ensure consistent usage
254     // Symbol names in SparcV9 assembly language have these rules:
255     // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
256     // (b) A name beginning in "." is treated as a local name.
257     std::string getID(const Function *F) {
258       return Mang->getValueName(F);
259     }
260     std::string getID(const BasicBlock *BB) {
261       return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB);
262     }
263     std::string getID(const GlobalVariable *GV) {
264       return Mang->getValueName(GV);
265     }
266     std::string getID(const Constant *CV) {
267       return ".C_" + Mang->getValueName(CV);
268     }
269     std::string getID(const GlobalValue *GV) {
270       if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
271         return getID(V);
272       else if (const Function *F = dyn_cast<Function>(GV))
273         return getID(F);
274       assert(0 && "Unexpected type of GlobalValue!");
275       return "";
276     }
277
278     // Combines expressions 
279     inline std::string ConstantArithExprToString(const ConstantExpr* CE,
280                                                  const TargetMachine &TM,
281                                                  const std::string &op) {
282       return "(" + valToExprString(CE->getOperand(0), TM) + op
283         + valToExprString(CE->getOperand(1), TM) + ")";
284     }
285
286     /// ConstantExprToString() - Convert a ConstantExpr to an asm expression
287     /// and return this as a string.
288     ///
289     std::string ConstantExprToString(const ConstantExpr* CE,
290                                      const TargetMachine& target);
291
292     /// valToExprString - Helper function for ConstantExprToString().
293     /// Appends result to argument string S.
294     /// 
295     std::string valToExprString(const Value* V, const TargetMachine& target);
296   };
297 } // End anonymous namespace
298
299
300 /// Print a single constant value.
301 ///
302 void AsmPrinter::printSingleConstantValue(const Constant* CV) {
303   assert(CV->getType() != Type::VoidTy &&
304          CV->getType() != Type::TypeTy &&
305          CV->getType() != Type::LabelTy &&
306          "Unexpected type for Constant");
307   
308   assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
309          && "Aggregate types should be handled outside this function");
310   
311   toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t";
312   
313   if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(CV)) {
314     // This is a constant address for a global variable or method.
315     // Use the name of the variable or method as the address value.
316     assert(isa<GlobalValue>(CPR->getValue()) && "Unexpected non-global");
317     toAsm << getID(CPR->getValue()) << "\n";
318   } else if (isa<ConstantPointerNull>(CV)) {
319     // Null pointer value
320     toAsm << "0\n";
321   } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) { 
322     // Constant expression built from operators, constants, and symbolic addrs
323     toAsm << ConstantExprToString(CE, Target) << "\n";
324   } else if (CV->getType()->isPrimitiveType()) {
325     // Check primitive types last
326     if (CV->getType()->isFloatingPoint()) {
327       // FP Constants are printed as integer constants to avoid losing
328       // precision...
329       double Val = cast<ConstantFP>(CV)->getValue();
330       if (CV->getType() == Type::FloatTy) {
331         float FVal = (float)Val;
332         char *ProxyPtr = (char*)&FVal;        // Abide by C TBAA rules
333         toAsm << *(unsigned int*)ProxyPtr;            
334       } else if (CV->getType() == Type::DoubleTy) {
335         char *ProxyPtr = (char*)&Val;         // Abide by C TBAA rules
336         toAsm << *(uint64_t*)ProxyPtr;            
337       } else {
338         assert(0 && "Unknown floating point type!");
339       }
340         
341       toAsm << "\t! " << CV->getType()->getDescription()
342             << " value: " << Val << "\n";
343     } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
344       toAsm << (int)CB->getValue() << "\n";
345     } else {
346       WriteAsOperand(toAsm, CV, false, false) << "\n";
347     }
348   } else {
349     assert(0 && "Unknown elementary type for constant");
350   }
351 }
352
353 /// Print a constant value or values (it may be an aggregate).
354 /// Uses printSingleConstantValue() to print each individual value.
355 ///
356 void AsmPrinter::printConstantValueOnly(const Constant* CV,
357                                         int numPadBytesAfter) {
358   if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
359     if (CVA->isString()) {
360       // print the string alone and return
361       toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
362     } else {
363       // Not a string.  Print the values in successive locations
364       const std::vector<Use> &constValues = CVA->getValues();
365       for (unsigned i=0; i < constValues.size(); i++)
366         printConstantValueOnly(cast<Constant>(constValues[i].get()));
367     }
368   } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
369     // Print the fields in successive locations. Pad to align if needed!
370     const StructLayout *cvsLayout =
371       Target.getTargetData().getStructLayout(CVS->getType());
372     const std::vector<Use>& constValues = CVS->getValues();
373     unsigned sizeSoFar = 0;
374     for (unsigned i=0, N = constValues.size(); i < N; i++) {
375       const Constant* field = cast<Constant>(constValues[i].get());
376
377       // Check if padding is needed and insert one or more 0s.
378       unsigned fieldSize =
379         Target.getTargetData().getTypeSize(field->getType());
380       int padSize = ((i == N-1? cvsLayout->StructSize
381                       : cvsLayout->MemberOffsets[i+1])
382                      - cvsLayout->MemberOffsets[i]) - fieldSize;
383       sizeSoFar += (fieldSize + padSize);
384
385       // Now print the actual field value
386       printConstantValueOnly(field, padSize);
387     }
388     assert(sizeSoFar == cvsLayout->StructSize &&
389            "Layout of constant struct may be incorrect!");
390   } else if (isa<ConstantAggregateZero>(CV)) {
391     PrintZeroBytesToPad(Target.getTargetData().getTypeSize(CV->getType()));
392   } else
393     printSingleConstantValue(CV);
394
395   if (numPadBytesAfter)
396     PrintZeroBytesToPad(numPadBytesAfter);
397 }
398
399 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression
400 /// and return this as a string.
401 ///
402 std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE,
403                                              const TargetMachine& target) {
404   std::string S;
405   switch(CE->getOpcode()) {
406   case Instruction::GetElementPtr:
407     { // generate a symbolic expression for the byte address
408       const Value* ptrVal = CE->getOperand(0);
409       std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
410       const TargetData &TD = target.getTargetData();
411       S += "(" + valToExprString(ptrVal, target) + ") + ("
412         + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
413       break;
414     }
415
416   case Instruction::Cast:
417     // Support only non-converting casts for now, i.e., a no-op.
418     // This assertion is not a complete check.
419     assert(target.getTargetData().getTypeSize(CE->getType()) ==
420            target.getTargetData().getTypeSize(CE->getOperand(0)->getType()));
421     S += "(" + valToExprString(CE->getOperand(0), target) + ")";
422     break;
423
424   case Instruction::Add:
425     S += ConstantArithExprToString(CE, target, ") + (");
426     break;
427
428   case Instruction::Sub:
429     S += ConstantArithExprToString(CE, target, ") - (");
430     break;
431
432   case Instruction::Mul:
433     S += ConstantArithExprToString(CE, target, ") * (");
434     break;
435
436   case Instruction::Div:
437     S += ConstantArithExprToString(CE, target, ") / (");
438     break;
439
440   case Instruction::Rem:
441     S += ConstantArithExprToString(CE, target, ") % (");
442     break;
443
444   case Instruction::And:
445     // Logical && for booleans; bitwise & otherwise
446     S += ConstantArithExprToString(CE, target,
447                                    ((CE->getType() == Type::BoolTy)? ") && (" : ") & ("));
448     break;
449
450   case Instruction::Or:
451     // Logical || for booleans; bitwise | otherwise
452     S += ConstantArithExprToString(CE, target,
453                                    ((CE->getType() == Type::BoolTy)? ") || (" : ") | ("));
454     break;
455
456   case Instruction::Xor:
457     // Bitwise ^ for all types
458     S += ConstantArithExprToString(CE, target, ") ^ (");
459     break;
460
461   default:
462     assert(0 && "Unsupported operator in ConstantExprToString()");
463     break;
464   }
465
466   return S;
467 }
468
469 /// valToExprString - Helper function for ConstantExprToString().
470 /// Appends result to argument string S.
471 /// 
472 std::string AsmPrinter::valToExprString(const Value* V,
473                                         const TargetMachine& target) {
474   std::string S;
475   bool failed = false;
476   if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
477     if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
478       S += std::string(CB == ConstantBool::True ? "1" : "0");
479     else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
480       S += itostr(CI->getValue());
481     else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
482       S += utostr(CI->getValue());
483     else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
484       S += ftostr(CFP->getValue());
485     else if (isa<ConstantPointerNull>(CV))
486       S += "0";
487     else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
488       S += valToExprString(CPR->getValue(), target);
489     else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
490       S += ConstantExprToString(CE, target);
491     else
492       failed = true;
493   } else if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
494     S += getID(GV);
495   } else
496     failed = true;
497
498   if (failed) {
499     assert(0 && "Cannot convert value to string");
500     S += "<illegal-value>";
501   }
502   return S;
503 }
504
505
506 //===----------------------------------------------------------------------===//
507 //   SparcV9AsmPrinter Code
508 //===----------------------------------------------------------------------===//
509
510 namespace {
511
512   struct SparcV9AsmPrinter : public FunctionPass, public AsmPrinter {
513     inline SparcV9AsmPrinter(std::ostream &os, const TargetMachine &t)
514       : AsmPrinter(os, t) {}
515
516     const Function *currFunction;
517
518     const char *getPassName() const {
519       return "Output SparcV9 Assembly for Functions";
520     }
521
522     virtual bool doInitialization(Module &M) {
523       startModule(M);
524       return false;
525     }
526
527     virtual bool runOnFunction(Function &F) {
528       currFunction = &F;
529       emitFunction(F);
530       return false;
531     }
532
533     virtual bool doFinalization(Module &M) {
534       emitGlobals(M);
535       return false;
536     }
537
538     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
539       AU.setPreservesAll();
540     }
541
542     void emitFunction(const Function &F);
543   private :
544     void emitBasicBlock(const MachineBasicBlock &MBB);
545     void emitMachineInst(const MachineInstr *MI);
546   
547     unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
548     void printOneOperand(const MachineOperand &Op, MachineOpCode opCode);
549
550     bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
551     bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
552   
553     unsigned getOperandMask(unsigned Opcode) {
554       switch (Opcode) {
555       case V9::SUBccr:
556       case V9::SUBcci:   return 1 << 3;  // Remove CC argument
557       default:      return 0;       // By default, don't hack operands...
558       }
559     }
560
561     void emitGlobals(const Module &M);
562     void printGlobalVariable(const GlobalVariable *GV);
563   };
564
565 } // End anonymous namespace
566
567 inline bool
568 SparcV9AsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
569                                        unsigned int opNum) {
570   switch (MI->getOpcode()) {
571   case V9::JMPLCALLr:
572   case V9::JMPLCALLi:
573   case V9::JMPLRETr:
574   case V9::JMPLRETi:
575     return (opNum == 0);
576   default:
577     return false;
578   }
579 }
580
581 inline bool
582 SparcV9AsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
583                                        unsigned int opNum) {
584   if (Target.getInstrInfo().isLoad(MI->getOpcode()))
585     return (opNum == 0);
586   else if (Target.getInstrInfo().isStore(MI->getOpcode()))
587     return (opNum == 1);
588   else
589     return false;
590 }
591
592
593 #define PrintOp1PlusOp2(mop1, mop2, opCode) \
594   printOneOperand(mop1, opCode); \
595   toAsm << "+"; \
596   printOneOperand(mop2, opCode);
597
598 unsigned int
599 SparcV9AsmPrinter::printOperands(const MachineInstr *MI,
600                                unsigned int opNum)
601 {
602   const MachineOperand& mop = MI->getOperand(opNum);
603   
604   if (OpIsBranchTargetLabel(MI, opNum)) {
605     PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
606     return 2;
607   } else if (OpIsMemoryAddressBase(MI, opNum)) {
608     toAsm << "[";
609     PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
610     toAsm << "]";
611     return 2;
612   } else {
613     printOneOperand(mop, MI->getOpcode());
614     return 1;
615   }
616 }
617
618 void
619 SparcV9AsmPrinter::printOneOperand(const MachineOperand &mop,
620                                  MachineOpCode opCode)
621 {
622   bool needBitsFlag = true;
623   
624   if (mop.isHiBits32())
625     toAsm << "%lm(";
626   else if (mop.isLoBits32())
627     toAsm << "%lo(";
628   else if (mop.isHiBits64())
629     toAsm << "%hh(";
630   else if (mop.isLoBits64())
631     toAsm << "%hm(";
632   else
633     needBitsFlag = false;
634   
635   switch (mop.getType())
636     {
637     case MachineOperand::MO_VirtualRegister:
638     case MachineOperand::MO_CCRegister:
639     case MachineOperand::MO_MachineRegister:
640       {
641         int regNum = (int)mop.getReg();
642         
643         if (regNum == Target.getRegInfo().getInvalidRegNum()) {
644           // better to print code with NULL registers than to die
645           toAsm << "<NULL VALUE>";
646         } else {
647           toAsm << "%" << Target.getRegInfo().getUnifiedRegName(regNum);
648         }
649         break;
650       }
651     
652     case MachineOperand::MO_ConstantPoolIndex:
653       {
654         toAsm << ".CPI_" << getID(currFunction)
655               << "_" << mop.getConstantPoolIndex();
656         break;
657       }
658
659     case MachineOperand::MO_PCRelativeDisp:
660       {
661         const Value *Val = mop.getVRegValue();
662         assert(Val && "\tNULL Value in SparcV9AsmPrinter");
663         
664         if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
665           toAsm << getID(BB);
666         else if (const Function *F = dyn_cast<Function>(Val))
667           toAsm << getID(F);
668         else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val))
669           toAsm << getID(GV);
670         else if (const Constant *CV = dyn_cast<Constant>(Val))
671           toAsm << getID(CV);
672         else
673           assert(0 && "Unrecognized value in SparcV9AsmPrinter");
674         break;
675       }
676     
677     case MachineOperand::MO_SignExtendedImmed:
678       toAsm << mop.getImmedValue();
679       break;
680
681     case MachineOperand::MO_UnextendedImmed:
682       toAsm << (uint64_t) mop.getImmedValue();
683       break;
684     
685     default:
686       toAsm << mop;      // use dump field
687       break;
688     }
689   
690   if (needBitsFlag)
691     toAsm << ")";
692 }
693
694 void SparcV9AsmPrinter::emitMachineInst(const MachineInstr *MI) {
695   unsigned Opcode = MI->getOpcode();
696
697   if (Target.getInstrInfo().isDummyPhiInstr(Opcode))
698     return;  // IGNORE PHI NODES
699
700   toAsm << "\t" << Target.getInstrInfo().getName(Opcode) << "\t";
701
702   unsigned Mask = getOperandMask(Opcode);
703   
704   bool NeedComma = false;
705   unsigned N = 1;
706   for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
707     if (! ((1 << OpNum) & Mask)) {        // Ignore this operand?
708       if (NeedComma) toAsm << ", ";         // Handle comma outputting
709       NeedComma = true;
710       N = printOperands(MI, OpNum);
711     } else
712       N = 1;
713   
714   toAsm << "\n";
715   ++EmittedInsts;
716 }
717
718 void SparcV9AsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) {
719   // Emit a label for the basic block
720   toAsm << getID(MBB.getBasicBlock()) << ":\n";
721
722   // Loop over all of the instructions in the basic block...
723   for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end();
724        MII != MIE; ++MII)
725     emitMachineInst(MII);
726   toAsm << "\n";  // Separate BB's with newlines
727 }
728
729 void SparcV9AsmPrinter::emitFunction(const Function &F) {
730   std::string methName = getID(&F);
731   toAsm << "!****** Outputing Function: " << methName << " ******\n";
732
733   // Emit constant pool for this function
734   const MachineConstantPool *MCP = MachineFunction::get(&F).getConstantPool();
735   const std::vector<Constant*> &CP = MCP->getConstants();
736
737   enterSection(AsmPrinter::ReadOnlyData);
738   for (unsigned i = 0, e = CP.size(); i != e; ++i) {
739     std::string cpiName = ".CPI_" + methName + "_" + utostr(i);
740     printConstant(CP[i], cpiName);
741   }
742
743   enterSection(AsmPrinter::Text);
744   toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
745   //toAsm << "\t.type\t" << methName << ",#function\n";
746   toAsm << "\t.type\t" << methName << ", 2\n";
747   toAsm << methName << ":\n";
748
749   // Output code for all of the basic blocks in the function...
750   MachineFunction &MF = MachineFunction::get(&F);
751   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I)
752     emitBasicBlock(*I);
753
754   // Output a .size directive so the debugger knows the extents of the function
755   toAsm << ".EndOf_" << methName << ":\n\t.size "
756            << methName << ", .EndOf_"
757            << methName << "-" << methName << "\n";
758
759   // Put some spaces between the functions
760   toAsm << "\n\n";
761 }
762
763 void SparcV9AsmPrinter::printGlobalVariable(const GlobalVariable* GV) {
764   if (GV->hasExternalLinkage())
765     toAsm << "\t.global\t" << getID(GV) << "\n";
766   
767   if (GV->hasInitializer() && ! GV->getInitializer()->isNullValue()) {
768     printConstant(GV->getInitializer(), getID(GV));
769   } else {
770     toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
771                                                 Target) << "\n";
772     toAsm << "\t.type\t" << getID(GV) << ",#object\n";
773     toAsm << "\t.reserve\t" << getID(GV) << ","
774           << Target.findOptimalStorageSize(GV->getType()->getElementType())
775           << "\n";
776   }
777 }
778
779 void SparcV9AsmPrinter::emitGlobals(const Module &M) {
780   // Output global variables...
781   for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI)
782     if (! GI->isExternal()) {
783       assert(GI->hasInitializer());
784       if (GI->isConstant())
785         enterSection(AsmPrinter::ReadOnlyData);   // read-only, initialized data
786       else if (GI->getInitializer()->isNullValue())
787         enterSection(AsmPrinter::ZeroInitRWData); // read-write zero data
788       else
789         enterSection(AsmPrinter::InitRWData);     // read-write non-zero data
790
791       printGlobalVariable(GI);
792     }
793
794   toAsm << "\n";
795 }
796
797 FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out,
798                                          const TargetMachine &TM) {
799   return new SparcV9AsmPrinter(Out, TM);
800 }