Teach the coallescer to coallesce live intervals joined by an arbitrary
[oota-llvm.git] / lib / CodeGen / AsmPrinter.cpp
index 6e5dab7851fdc0791e19c298e2a134280ff6bc34..266f82a0916409897f2d3230f41bbaa3c6fc2446 100644 (file)
@@ -52,12 +52,14 @@ AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm)
   DataSectionStartSuffix(""),
   SectionEndDirectiveSuffix(0),
   ConstantPoolSection("\t.section .rodata\n"),
-  JumpTableSection("\t.section .rodata\n"),
+  JumpTableDataSection("\t.section .rodata\n"),
+  JumpTableTextSection("\t.text\n"),
   StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"),
   StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"),
   FourByteConstantSection(0),
   EightByteConstantSection(0),
   SixteenByteConstantSection(0),
+  SetDirective(0),
   LCOMMDirective(0),
   COMMDirective("\t.comm\t"),
   COMMDirectiveTakesAlignment(true),
@@ -89,7 +91,7 @@ void AsmPrinter::SwitchToTextSection(const char *NewSection,
     O << CurrentSection << TextSectionStartSuffix << '\n';
 }
 
-/// SwitchToTextSection - Switch to the specified text section of the executable
+/// SwitchToDataSection - Switch to the specified data section of the executable
 /// if we are not already in it!
 ///
 void AsmPrinter::SwitchToDataSection(const char *NewSection,
@@ -210,28 +212,54 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI) {
   if (JT.empty()) return;
   const TargetData *TD = TM.getTargetData();
   
-  // FIXME: someday we need to handle PIC jump tables
-  assert((TM.getRelocationModel() == Reloc::Static ||
-          TM.getRelocationModel() == Reloc::DynamicNoPIC) &&
-         "Unhandled relocation model emitting jump table information!");
+  // JTEntryDirective is a string to print sizeof(ptr) for non-PIC jump tables,
+  // and 32 bits for PIC since PIC jump table entries are differences, not
+  // pointers to blocks.
+  const char *JTEntryDirective = Data32bitsDirective;
   
-  SwitchToDataSection(JumpTableSection, 0);
+  // Pick the directive to use to print the jump table entries, and switch to 
+  // the appropriate section.
+  if (TM.getRelocationModel() == Reloc::PIC_) {
+    SwitchToTextSection(JumpTableTextSection, 0);
+  } else {
+    SwitchToDataSection(JumpTableDataSection, 0);
+    if (TD->getPointerSize() == 8)
+      JTEntryDirective = Data64bitsDirective;
+  }
   EmitAlignment(Log2_32(TD->getPointerAlignment()));
   
-  // Pick the directive to use based on the pointer size. FIXME: when we support
-  // PIC jumptables, this should always use the 32-bit directive for label
-  // differences. 
-  const char *PtrDataDirective = Data32bitsDirective;
-  if (TD->getPointerSize() == 8)
-    PtrDataDirective = Data64bitsDirective;
-
   for (unsigned i = 0, e = JT.size(); i != e; ++i) {
+    const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs;
+
+    // For PIC codegen, if possible we want to use the SetDirective to reduce
+    // the number of relocations the assembler will generate for the jump table.
+    // Set directives are all printed before the jump table itself.
+    std::set<MachineBasicBlock*> EmittedSets;
+    if (SetDirective && TM.getRelocationModel() == Reloc::PIC_)
+      for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii)
+        if (EmittedSets.insert(JTBBs[ii]).second)
+          printSetLabel(i, JTBBs[ii]);
+    
     O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << '_' << i 
       << ":\n";
-    const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs;
+    
     for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
-      O << PtrDataDirective << ' ';
-      printBasicBlockLabel(JTBBs[ii]);
+      O << JTEntryDirective << ' ';
+      // If we have emitted set directives for the jump table entries, print 
+      // them rather than the entries themselves.  If we're emitting PIC, then
+      // emit the table entries as differences between two text section labels.
+      // If we're emitting non-PIC code, then emit the entries as direct
+      // references to the target basic blocks.
+      if (!EmittedSets.empty()) {
+        O << PrivateGlobalPrefix << getFunctionNumber() << '_' << i << "_set_"
+          << JTBBs[ii]->getNumber();
+      } else if (TM.getRelocationModel() == Reloc::PIC_) {
+        printBasicBlockLabel(JTBBs[ii], false, false);
+        O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber() 
+          << '_' << i;
+      } else {
+        printBasicBlockLabel(JTBBs[ii], false, false);
+      }
       O << '\n';
     }
   }
@@ -379,23 +407,29 @@ void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
       break;
     }
     case Instruction::Cast: {
-      // Support only non-converting or widening casts for now, that is, ones
-      // that do not involve a change in value.  This assertion is really gross,
-      // and may not even be a complete check.
+      // Support only foldable casts to/from pointers that can be eliminated by
+      // changing the pointer to the appropriately sized integer type.
       Constant *Op = CE->getOperand(0);
       const Type *OpTy = Op->getType(), *Ty = CE->getType();
 
-      // Remember, kids, pointers can be losslessly converted back and forth
-      // into 32-bit or wider integers, regardless of signedness. :-P
-      assert(((isa<PointerType>(OpTy)
-               && (Ty == Type::LongTy || Ty == Type::ULongTy
-                   || Ty == Type::IntTy || Ty == Type::UIntTy))
-              || (isa<PointerType>(Ty)
-                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
-                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
-              || (((TD->getTypeSize(Ty) >= TD->getTypeSize(OpTy))
-                   && OpTy->isLosslesslyConvertibleTo(Ty))))
-             && "FIXME: Don't yet support this kind of constant cast expr");
+      // Handle casts to pointers by changing them into casts to the appropriate
+      // integer type.  This promotes constant folding and simplifies this code.
+      if (isa<PointerType>(Ty)) {
+        const Type *IntPtrTy = TD->getIntPtrType();
+        Op = ConstantExpr::getCast(Op, IntPtrTy);
+        return EmitConstantValueOnly(Op);
+      }
+      
+      // We know the dest type is not a pointer.  Is the src value a pointer or
+      // integral?
+      if (isa<PointerType>(OpTy) || OpTy->isIntegral()) {
+        // We can emit the pointer value into this slot if the slot is an
+        // integer slot greater or equal to the size of the pointer.
+        if (Ty->isIntegral() && TD->getTypeSize(Ty) >= TD->getTypeSize(OpTy))
+          return EmitConstantValueOnly(Op);
+      }
+      
+      assert(0 && "FIXME: Don't yet support this kind of constant cast expr");
       EmitConstantValueOnly(Op);
       break;
     }
@@ -609,7 +643,6 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
 /// printInlineAsm - This method formats and prints the specified machine
 /// instruction that is an inline asm.
 void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
-  O << InlineAsmStart << "\n\t";
   unsigned NumOperands = MI->getNumOperands();
   
   // Count the number of register definitions.
@@ -622,6 +655,14 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
   // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
   const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
 
+  // If this asmstr is empty, don't bother printing the #APP/#NOAPP markers.
+  if (AsmStr[0] == 0) {
+    O << "\n";  // Tab already printed, avoid double indenting next instr.
+    return;
+  }
+  
+  O << InlineAsmStart << "\n\t";
+
   // The variant of the current asmprinter: FIXME: change.
   int AsmPrinterVariant = 0;
   
@@ -799,3 +840,17 @@ void AsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB,
   if (printComment)
     O << '\t' << CommentString << MBB->getBasicBlock()->getName();
 }
+
+/// printSetLabel - This method prints a set label for the specified
+/// MachineBasicBlock
+void AsmPrinter::printSetLabel(unsigned uid, 
+                               const MachineBasicBlock *MBB) const {
+  if (!SetDirective)
+    return;
+  
+  O << SetDirective << ' ' << PrivateGlobalPrefix << getFunctionNumber() 
+    << '_' << uid << "_set_" << MBB->getNumber() << ',';
+  printBasicBlockLabel(MBB, false, false);
+  O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber() 
+    << '_' << uid << '\n';
+}