Implement changes from Chris's feedback.
[oota-llvm.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
index 31daab18d920a27ef05a1e6e3507d9f67e15a389..4d516438defde116dec41fa9fe3522a4cc29f72c 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
+#include "llvm/MDNode.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/DwarfWriter.h"
@@ -29,6 +30,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetAsmInfo.h"
@@ -45,13 +47,12 @@ namespace {
 
   const std::string bss_section(".bss");
 
-  struct VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
+  class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
     std::set<std::string> FnStubs, GVStubs;
-
-    SPUAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) :
-      AsmPrinter(O, TM, T)
-    {
-    }
+  public:
+    explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
+                           const TargetAsmInfo *T, bool V) :
+      AsmPrinter(O, TM, T, V) {}
 
     virtual const char *getPassName() const {
       return "STI CBEA SPU Assembly Printer";
@@ -90,13 +91,13 @@ namespace {
         printOp(MO);
       }
     }
-    
+
     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                          unsigned AsmVariant, const char *ExtraCode);
     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                                unsigned AsmVariant, const char *ExtraCode);
-   
-   
+
+
     void
     printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
     {
@@ -115,7 +116,7 @@ namespace {
       assert(value < (1 << 8) && "Invalid u7 argument");
       O << value;
     }
+
     void
     printShufAddr(const MachineInstr *MI, unsigned OpNo)
     {
@@ -143,7 +144,7 @@ namespace {
     {
       O << (unsigned)MI->getOperand(OpNo).getImm();
     }
-    
+
     void
     printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
       // When used as the base register, r0 reads constant zero rather than
@@ -185,9 +186,8 @@ namespace {
     void
     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
     {
-      const MachineOperand &MO = MI->getOperand(OpNo);
-      assert(MO.isImm() &&
-             "printDFormAddr first operand is not immedate");
+      assert(MI->getOperand(OpNo).isImm() &&
+             "printDFormAddr first operand is not immediate");
       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
       int16_t value16 = int16_t(value);
       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
@@ -286,27 +286,22 @@ namespace {
   };
 
   /// LinuxAsmPrinter - SPU assembly printer, customized for Linux
-  struct VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
-  
+  class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
     DwarfWriter *DW;
-    MachineModuleInfo *MMI;
-
-    LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
-                    const TargetAsmInfo *T) :
-      SPUAsmPrinter(O, TM, T),
-      DW(0),
-      MMI(0)
-    { }
+  public:
+    explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
+                             const TargetAsmInfo *T, bool V)
+      : SPUAsmPrinter(O, TM, T, V), DW(0) {}
 
     virtual const char *getPassName() const {
       return "STI CBEA SPU Assembly Printer";
     }
-    
+
     bool runOnMachineFunction(MachineFunction &F);
     bool doInitialization(Module &M);
     //! Dump globals, perform cleanup after function emission
     bool doFinalization(Module &M);
-    
+
     void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesAll();
       AU.addRequired<MachineModuleInfo>();
@@ -325,8 +320,7 @@ namespace {
 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
   switch (MO.getType()) {
   case MachineOperand::MO_Immediate:
-    cerr << "printOp() does not handle immediate values\n";
-    abort();
+    llvm_report_error("printOp() does not handle immediate values");
     return;
 
   case MachineOperand::MO_MachineBasicBlock:
@@ -366,9 +360,6 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
       }
     }
     O << Name;
-    
-    if (GV->hasExternalWeakLinkage())
-      ExtWeakSymbols.insert(GV);
     return;
   }
 
@@ -381,15 +372,15 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                    unsigned AsmVariant, 
+                                    unsigned AsmVariant,
                                     const char *ExtraCode) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0) return true; // Unknown modifier.
-    
+
     switch (ExtraCode[0]) {
     default: return true;  // Unknown modifier.
-    case 'L': // Write second word of DImode reference.  
+    case 'L': // Write second word of DImode reference.
       // Verify that this operand has two consecutive registers.
       if (!MI->getOperand(OpNo).isReg() ||
           OpNo+1 == MI->getNumOperands() ||
@@ -399,14 +390,14 @@ bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
       break;
     }
   }
-  
+
   printOperand(MI, OpNo);
   return false;
 }
 
 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
                                           unsigned OpNo,
-                                          unsigned AsmVariant, 
+                                          unsigned AsmVariant,
                                           const char *ExtraCode) {
   if (ExtraCode && ExtraCode[0])
     return true; // Unknown modifier.
@@ -428,9 +419,11 @@ void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
 bool
 LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
 {
+  this->MF = &MF;
+
   SetupMachineFunction(MF);
   O << "\n\n";
-  
+
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
 
@@ -438,18 +431,21 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
   const Function *F = MF.getFunction();
 
   SwitchToSection(TAI->SectionForGlobal(F));
-  EmitAlignment(3, F);
+  EmitAlignment(MF.getAlignment(), F);
 
   switch (F->getLinkage()) {
   default: assert(0 && "Unknown linkage type!");
+  case Function::PrivateLinkage:
   case Function::InternalLinkage:  // Symbols default to internal.
     break;
   case Function::ExternalLinkage:
     O << "\t.global\t" << CurrentFnName << "\n"
       << "\t.type\t" << CurrentFnName << ", @function\n";
     break;
-  case Function::WeakLinkage:
-  case Function::LinkOnceLinkage:
+  case Function::WeakAnyLinkage:
+  case Function::WeakODRLinkage:
+  case Function::LinkOnceAnyLinkage:
+  case Function::LinkOnceODRLinkage:
     O << "\t.global\t" << CurrentFnName << "\n";
     O << "\t.weak_definition\t" << CurrentFnName << "\n";
     break;
@@ -478,10 +474,10 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
 
   // Print out jump tables referenced by the function.
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-  
+
   // Emit post-function debug information.
   DW->EndFunction(&MF);
-  
+
   // We didn't modify anything.
   return false;
 }
@@ -489,17 +485,13 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
 
 bool LinuxAsmPrinter::doInitialization(Module &M) {
   bool Result = AsmPrinter::doInitialization(M);
+  DW = getAnalysisIfAvailable<DwarfWriter>();
   SwitchToTextSection("\t.text");
-  // Emit initial debug information.
-  DW = getAnalysisToUpdate<DwarfWriter>();
-  assert(DW && "Dwarf Writer is not available");
-  MMI = getAnalysisToUpdate<MachineModuleInfo>();
-  DW->BeginModule(&M, MMI, O, this, TAI);
   return Result;
 }
 
 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \n or \0.
+/// Don't print things like \\n or \\0.
 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
        Name != E; ++Name)
@@ -509,7 +501,7 @@ static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
 
 /*!
   Emit a global variable according to its section, alignment, etc.
-  
+
   \note This code was shamelessly copied from the PowerPC's assembly printer,
   which sort of screams for some kind of refactorization of common code.
  */
@@ -528,16 +520,18 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
   printVisibility(name, GVar->getVisibility());
 
   Constant *C = GVar->getInitializer();
+  if (isa<MDNode>(C) || isa<MDString>(C))
+    return;
   const Type *Type = C->getType();
-  unsigned Size = TD->getABITypeSize(Type);
+  unsigned Size = TD->getTypeAllocSize(Type);
   unsigned Align = TD->getPreferredAlignmentLog(GVar);
 
   SwitchToSection(TAI->SectionForGlobal(GVar));
 
   if (C->isNullValue() && /* FIXME: Verify correct */
       !GVar->hasSection() &&
-      (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() ||
-       GVar->mayBeOverridden())) {
+      (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
+       GVar->isWeakForLinker())) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
 
       if (GVar->hasExternalLinkage()) {
@@ -545,7 +539,7 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
         O << "\t.type " << name << ", @object\n";
         O << name << ":\n";
         O << "\t.zero " << Size << '\n';
-      } else if (GVar->hasInternalLinkage()) {
+      } else if (GVar->hasLocalLinkage()) {
         O << TAI->getLCOMMDirective() << name << ',' << Size;
       } else {
         O << ".comm " << name << ',' << Size;
@@ -558,8 +552,10 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
 
   switch (GVar->getLinkage()) {
     // Should never be seen for the CellSPU platform...
-   case GlobalValue::LinkOnceLinkage:
-   case GlobalValue::WeakLinkage:
+   case GlobalValue::LinkOnceAnyLinkage:
+   case GlobalValue::LinkOnceODRLinkage:
+   case GlobalValue::WeakAnyLinkage:
+   case GlobalValue::WeakODRLinkage:
    case GlobalValue::CommonLinkage:
     O << "\t.global " << name << '\n'
       << "\t.type " << name << ", @object\n"
@@ -573,11 +569,11 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
     O << "\t.global " << name << '\n'
       << "\t.type " << name << ", @object\n";
     // FALL THROUGH
+   case GlobalValue::PrivateLinkage:
    case GlobalValue::InternalLinkage:
     break;
    default:
-    cerr << "Unknown linkage type!";
-    abort();
+    llvm_report_error("Unknown linkage type!");
   }
 
   EmitAlignment(Align, GVar);
@@ -585,12 +581,6 @@ void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
   PrintUnmangledNameSafely(GVar, O);
   O << "'\n";
 
-  // If the initializer is a extern weak symbol, remember to emit the weak
-  // reference!
-  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
-    if (GV->hasExternalWeakLinkage())
-      ExtWeakSymbols.insert(GV);
-
   EmitGlobalConstant(C);
   O << '\n';
 }
@@ -601,11 +591,6 @@ bool LinuxAsmPrinter::doFinalization(Module &M) {
        I != E; ++I)
     printModuleLevelGV(I);
 
-  // TODO
-
-  // Emit initial debug information.
-  DW->EndModule();
-
   return AsmPrinter::doFinalization(M);
 }
 
@@ -614,7 +599,18 @@ bool LinuxAsmPrinter::doFinalization(Module &M) {
 /// that the Linux SPU assembler can deal with.
 ///
 FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
-                                            SPUTargetMachine &tm) {
-  return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo());
+                                            SPUTargetMachine &tm,
+                                            bool verbose) {
+  return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
 }
 
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
+
+namespace {
+  static struct Register {
+    Register() {
+      SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);
+    }
+  } Registrator;
+}