Remove some overzealous checks that were rejecting
[oota-llvm.git] / lib / CodeGen / AsmPrinter / AsmPrinter.cpp
index 03a61d42cd16d52d10ecbc8367f156b3b2b2481d..018544150902066b594c91ec690e531e1752fd30 100644 (file)
@@ -47,11 +47,6 @@ AsmPrinter::~AsmPrinter() {
                     E = GCMetadataPrinters.end(); I != E; ++I)
     delete I->second;
 }
-    
-std::string AsmPrinter::getSectionForFunction(const Function &F) const {
-  return TAI->getTextSection();
-}
-
 
 /// SwitchToTextSection - Switch to the specified text section of the executable
 /// if we are not already in it!
@@ -105,6 +100,37 @@ void AsmPrinter::SwitchToDataSection(const char *NewSection,
   IsInTextSection = false;
 }
 
+/// SwitchToSection - Switch to the specified section of the executable if we
+/// are not already in it!
+void AsmPrinter::SwitchToSection(const Section* NS) {
+  const std::string& NewSection = NS->getName();
+
+  // If we're already in this section, we're done.
+  if (CurrentSection == NewSection) return;
+
+  // Close the current section, if applicable.
+  if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+    O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
+
+  // FIXME: Make CurrentSection a Section* in the future
+  CurrentSection = NewSection;
+  CurrentSection_ = NS;
+
+  if (!CurrentSection.empty()) {
+    // If section is named we need to switch into it via special '.section'
+    // directive and also append funky flags. Otherwise - section name is just
+    // some magic assembler directive.
+    if (NS->isNamed())
+      O << TAI->getSwitchToSectionDirective()
+        << CurrentSection
+        << TAI->getSectionFlags(NS->getFlags());
+    else
+      O << CurrentSection;
+    O << TAI->getDataSectionStartSuffix() << '\n';
+  }
+
+  IsInTextSection = (NS->getFlags() & SectionFlags::Code);
+}
 
 void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
   MachineFunctionPass::getAnalysisUsage(AU);
@@ -149,7 +175,7 @@ bool AsmPrinter::doFinalization(Module &M) {
 
   if (TAI->getSetDirective()) {
     if (!M.alias_empty())
-      SwitchToTextSection(TAI->getTextSection());
+      SwitchToSection(TAI->getTextSection());
 
     O << '\n';
     for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
@@ -159,7 +185,7 @@ bool AsmPrinter::doFinalization(Module &M) {
 
       const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal());
       Target = Mang->getValueName(GV);
-      
+
       if (I->hasExternalLinkage() || !TAI->getWeakRefDirective())
         O << "\t.globl\t" << Name << '\n';
       else if (I->hasWeakLinkage())
@@ -167,13 +193,7 @@ bool AsmPrinter::doFinalization(Module &M) {
       else if (!I->hasInternalLinkage())
         assert(0 && "Invalid alias linkage");
 
-      if (I->hasHiddenVisibility()) {
-        if (const char *Directive = TAI->getHiddenDirective())
-          O << Directive << Name << '\n';
-      } else if (I->hasProtectedVisibility()) {
-        if (const char *Directive = TAI->getProtectedDirective())
-          O << Directive << Name << '\n';
-      }
+      printVisibility(Name, I->getVisibility());
 
       O << TAI->getSetDirective() << ' ' << Name << ", " << Target << '\n';
 
@@ -229,60 +249,50 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
   const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
   if (CP.empty()) return;
 
-  // Some targets require 4-, 8-, and 16- byte constant literals to be placed
-  // in special sections.
-  std::vector<std::pair<MachineConstantPoolEntry,unsigned> > FourByteCPs;
-  std::vector<std::pair<MachineConstantPoolEntry,unsigned> > EightByteCPs;
-  std::vector<std::pair<MachineConstantPoolEntry,unsigned> > SixteenByteCPs;
-  std::vector<std::pair<MachineConstantPoolEntry,unsigned> > OtherCPs;
-  std::vector<std::pair<MachineConstantPoolEntry,unsigned> > TargetCPs;
+  // Calculate sections for constant pool entries. We collect entries to go into
+  // the same section together to reduce amount of section switch statements.
+  typedef
+    std::multimap<const Section*,
+                  std::pair<MachineConstantPoolEntry, unsigned> > CPMap;
+  CPMap  CPs;
+  SmallPtrSet<const Section*, 5> Sections;
+
   for (unsigned i = 0, e = CP.size(); i != e; ++i) {
     MachineConstantPoolEntry CPE = CP[i];
-    const Type *Ty = CPE.getType();
-    if (TAI->getFourByteConstantSection() &&
-        TM.getTargetData()->getABITypeSize(Ty) == 4)
-      FourByteCPs.push_back(std::make_pair(CPE, i));
-    else if (TAI->getEightByteConstantSection() &&
-             TM.getTargetData()->getABITypeSize(Ty) == 8)
-      EightByteCPs.push_back(std::make_pair(CPE, i));
-    else if (TAI->getSixteenByteConstantSection() &&
-             TM.getTargetData()->getABITypeSize(Ty) == 16)
-      SixteenByteCPs.push_back(std::make_pair(CPE, i));
-    else
-      OtherCPs.push_back(std::make_pair(CPE, i));
+    const Section* S = TAI->SelectSectionForMachineConst(CPE.getType());
+    CPs.insert(std::make_pair(S, std::make_pair(CPE, i)));
+    Sections.insert(S);
   }
 
-  unsigned Alignment = MCP->getConstantPoolAlignment();
-  EmitConstantPool(Alignment, TAI->getFourByteConstantSection(), FourByteCPs);
-  EmitConstantPool(Alignment, TAI->getEightByteConstantSection(), EightByteCPs);
-  EmitConstantPool(Alignment, TAI->getSixteenByteConstantSection(),
-                   SixteenByteCPs);
-  EmitConstantPool(Alignment, TAI->getConstantPoolSection(), OtherCPs);
-}
+  // Now print stuff into the calculated sections.
+  for (SmallPtrSet<const Section*, 5>::iterator IS = Sections.begin(),
+         ES = Sections.end(); IS != ES; ++IS) {
+    SwitchToSection(*IS);
+    EmitAlignment(MCP->getConstantPoolAlignment());
 
-void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section,
-               std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP) {
-  if (CP.empty()) return;
+    std::pair<CPMap::iterator, CPMap::iterator> II = CPs.equal_range(*IS);
+    for (CPMap::iterator I = II.first, E = II.second; I != E; ++I) {
+      CPMap::iterator J = next(I);
+      MachineConstantPoolEntry Entry = I->second.first;
+      unsigned index = I->second.second;
 
-  SwitchToDataSection(Section);
-  EmitAlignment(Alignment);
-  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
-    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
-      << CP[i].second << ":\t\t\t\t\t";
+      O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+        << index << ":\t\t\t\t\t";
     // O << TAI->getCommentString() << ' ' << 
     //      WriteTypeSymbolic(O, CP[i].first.getType(), 0);
-    O << '\n';
-    if (CP[i].first.isMachineConstantPoolEntry())
-      EmitMachineConstantPoolValue(CP[i].first.Val.MachineCPVal);
-     else
-      EmitGlobalConstant(CP[i].first.Val.ConstVal);
-    if (i != e-1) {
-      const Type *Ty = CP[i].first.getType();
-      unsigned EntSize =
-        TM.getTargetData()->getABITypeSize(Ty);
-      unsigned ValEnd = CP[i].first.getOffset() + EntSize;
+      O << '\n';
+      if (Entry.isMachineConstantPoolEntry())
+        EmitMachineConstantPoolValue(Entry.Val.MachineCPVal);
+      else
+        EmitGlobalConstant(Entry.Val.ConstVal);
+
       // Emit inter-object padding for alignment.
-      EmitZeros(CP[i+1].first.getOffset()-ValEnd);
+      if (J != E) {
+        const Type *Ty = Entry.getType();
+        unsigned EntSize = TM.getTargetData()->getABITypeSize(Ty);
+        unsigned ValEnd = Entry.getOffset() + EntSize;
+        EmitZeros(J->second.first.getOffset()-ValEnd);
+      }
     }
   }
 }
@@ -311,7 +321,7 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
     // function body itself, otherwise the label differences won't make sense.
     // We should also do if the section name is NULL or function is declared in
     // discardable section.
-    SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
+    SwitchToSection(TAI->SectionForGlobal(F));
   } else {
     SwitchToDataSection(JumpTableDataSection);
   }
@@ -451,8 +461,9 @@ const GlobalValue * AsmPrinter::findGlobalValue(const Constant *CV) {
 }
 
 /// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each
-/// global in the specified llvm.used list as being used with this directive.
-/// Non-globals (i.e. internal linkage) should not be emitted.
+/// global in the specified llvm.used list for which emitUsedDirectiveFor
+/// is true, as being used with this directive.
+
 void AsmPrinter::EmitLLVMUsedList(Constant *List) {
   const char *Directive = TAI->getUsedDirective();
 
@@ -462,7 +473,7 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) {
   
   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
     const GlobalValue *GV = findGlobalValue(InitList->getOperand(i));
-    if (GV && !GV->hasInternalLinkage()) {
+    if (TAI->emitUsedDirectiveFor(GV, Mang)) {
       O << Directive;
       EmitConstantValueOnly(InitList->getOperand(i));
       O << '\n';
@@ -958,7 +969,7 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
     // precision...
     if (CFP->getType() == Type::DoubleTy) {
       double Val = CFP->getValueAPF().convertToDouble();  // for comment only
-      uint64_t i = CFP->getValueAPF().convertToAPInt().getZExtValue();
+      uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
       if (TAI->getData64bitsDirective())
         O << TAI->getData64bitsDirective() << i << '\t'
           << TAI->getCommentString() << " double value: " << Val << '\n';
@@ -981,16 +992,19 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
     } else if (CFP->getType() == Type::FloatTy) {
       float Val = CFP->getValueAPF().convertToFloat();  // for comment only
       O << TAI->getData32bitsDirective()
-        << CFP->getValueAPF().convertToAPInt().getZExtValue()
+        << CFP->getValueAPF().bitcastToAPInt().getZExtValue()
         << '\t' << TAI->getCommentString() << " float " << Val << '\n';
       return;
     } else if (CFP->getType() == Type::X86_FP80Ty) {
       // all long double variants are printed as hex
       // api needed to prevent premature destruction
-      APInt api = CFP->getValueAPF().convertToAPInt();
+      APInt api = CFP->getValueAPF().bitcastToAPInt();
       const uint64_t *p = api.getRawData();
+      // Convert to double so we can print the approximate val as a comment.
       APFloat DoubleVal = CFP->getValueAPF();
-      DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
+      bool ignored;
+      DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
+                        &ignored);
       if (TD->isBigEndian()) {
         O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
           << '\t' << TAI->getCommentString()
@@ -1031,7 +1045,7 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
     } else if (CFP->getType() == Type::PPC_FP128Ty) {
       // all long double variants are printed as hex
       // api needed to prevent premature destruction
-      APInt api = CFP->getValueAPF().convertToAPInt();
+      APInt api = CFP->getValueAPF().bitcastToAPInt();
       const uint64_t *p = api.getRawData();
       if (TD->isBigEndian()) {
         O << TAI->getData32bitsDirective() << uint32_t(p[0] >> 32)
@@ -1062,26 +1076,41 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
       }
       return;
     } else assert(0 && "Floating point constant type not handled");
-  } else if (CV->getType() == Type::Int64Ty) {
+  } else if (CV->getType()->isInteger() &&
+             cast<IntegerType>(CV->getType())->getBitWidth() >= 64) {
     if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
-      uint64_t Val = CI->getZExtValue();
-
-      if (TAI->getData64bitsDirective())
-        O << TAI->getData64bitsDirective() << Val << '\n';
-      else if (TD->isBigEndian()) {
-        O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
-          << '\t' << TAI->getCommentString()
-          << " Double-word most significant word " << Val << '\n';
-        O << TAI->getData32bitsDirective() << unsigned(Val)
-          << '\t' << TAI->getCommentString()
-          << " Double-word least significant word " << Val << '\n';
-      } else {
-        O << TAI->getData32bitsDirective() << unsigned(Val)
-          << '\t' << TAI->getCommentString()
-          << " Double-word least significant word " << Val << '\n';
-        O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
-          << '\t' << TAI->getCommentString()
-          << " Double-word most significant word " << Val << '\n';
+      unsigned BitWidth = CI->getBitWidth();
+      assert(isPowerOf2_32(BitWidth) &&
+             "Non-power-of-2-sized integers not handled!");
+
+      // We don't expect assemblers to support integer data directives
+      // for more than 64 bits, so we emit the data in at most 64-bit
+      // quantities at a time.
+      const uint64_t *RawData = CI->getValue().getRawData();
+      for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
+        uint64_t Val;
+        if (TD->isBigEndian())
+          Val = RawData[e - i - 1];
+        else
+          Val = RawData[i];
+
+        if (TAI->getData64bitsDirective())
+          O << TAI->getData64bitsDirective() << Val << '\n';
+        else if (TD->isBigEndian()) {
+          O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
+            << '\t' << TAI->getCommentString()
+            << " Double-word most significant word " << Val << '\n';
+          O << TAI->getData32bitsDirective() << unsigned(Val)
+            << '\t' << TAI->getCommentString()
+            << " Double-word least significant word " << Val << '\n';
+        } else {
+          O << TAI->getData32bitsDirective() << unsigned(Val)
+            << '\t' << TAI->getCommentString()
+            << " Double-word least significant word " << Val << '\n';
+          O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
+            << '\t' << TAI->getCommentString()
+            << " Double-word most significant word " << Val << '\n';
+        }
       }
       return;
     }
@@ -1153,11 +1182,11 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
   
   // Count the number of register definitions.
   unsigned NumDefs = 0;
-  for (; MI->getOperand(NumDefs).isRegister() && MI->getOperand(NumDefs).isDef();
+  for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
        ++NumDefs)
     assert(NumDefs != NumOperands-1 && "No asm string?");
   
-  assert(MI->getOperand(NumDefs).isExternalSymbol() && "No asm string?");
+  assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
 
   // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
   const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
@@ -1217,21 +1246,17 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
         break;
       case '|':
         ++LastEmitted;  // consume '|' character.
-        if (CurVariant == -1) {
-          cerr << "Found '|' character outside of variant in inline asm "
-               << "string: '" << AsmStr << "'\n";
-          exit(1);
-        }
-        ++CurVariant;   // We're in the next variant.
+        if (CurVariant == -1)
+          O << '|';       // this is gcc's behavior for | outside a variant
+        else
+          ++CurVariant;   // We're in the next variant.
         break;
       case ')':         // $) -> same as GCC's } char.
         ++LastEmitted;  // consume ')' character.
-        if (CurVariant == -1) {
-          cerr << "Found '}' character outside of variant in inline asm "
-               << "string: '" << AsmStr << "'\n";
-          exit(1);
-        }
-        CurVariant = -1;
+        if (CurVariant == -1)
+          O << '}';     // this is gcc's behavior for } outside a variant
+        else 
+          CurVariant = -1;
         break;
       }
       if (Done) break;
@@ -1309,7 +1334,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
                                  false, false, false);
           else {
             AsmPrinter *AP = const_cast<AsmPrinter*>(this);
-            if ((OpFlags & 7) == 4 /*ADDR MODE*/) {
+            if ((OpFlags & 7) == 4) {
               Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
                                                 Modifier[0] ? Modifier : 0);
             } else {
@@ -1440,6 +1465,8 @@ void AsmPrinter::printDataDirective(const Type *type) {
       assert(TAI->getData64bitsDirective() &&
              "Target cannot handle 64-bit constant exprs!");
       O << TAI->getData64bitsDirective();
+    } else {
+      assert(0 && "Target cannot handle given data directive width!");
     }
     break;
   }