DwarfWriter reading basic type information from llvm-gcc4 code.
[oota-llvm.git] / lib / VMCore / AsmWriter.cpp
index 6db1a9a26c1947ead79a87f1cd6b80f8e1c9ef8b..ec70454e0bb353f162bca0bf2380687b180d3581 100644 (file)
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Assembly/PrintModulePass.h"
 #include "llvm/Assembly/AsmAnnotationWriter.h"
+#include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/InlineAsm.h"
 #include "llvm/Instruction.h"
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/MathExtras.h"
 #include <algorithm>
 using namespace llvm;
 
 namespace llvm {
 
+// Make virtual table appear in this compilation unit.
+AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {}
+
 /// This class provides computation of slot numbers for LLVM Assembly writing.
 /// @brief LLVM Assembly Writing Slot Computation.
 class SlotMachine {
@@ -393,6 +399,21 @@ std::ostream &llvm::WriteTypeSymbolic(std::ostream &Out, const Type *Ty,
   }
 }
 
+// PrintEscapedString - Print each character of the specified string, escaping
+// it if it is not printable or if it is an escape char.
+static void PrintEscapedString(const std::string &Str, std::ostream &Out) {
+  for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+    unsigned char C = Str[i];
+    if (isprint(C) && C != '"' && C != '\\') {
+      Out << C;
+    } else {
+      Out << '\\'
+          << (char) ((C/16  < 10) ? ( C/16 +'0') : ( C/16 -10+'A'))
+          << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
+    }
+  }
+}
+
 /// @brief Internal constant writer.
 static void WriteConstantInt(std::ostream &Out, const Constant *CV,
                              bool PrintName,
@@ -427,18 +448,9 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
 
     // Otherwise we could not reparse it to exactly the same value, so we must
     // output the string in hexadecimal format!
-    //
-    // Behave nicely in the face of C TBAA rules... see:
-    // http://www.nullstone.com/htmls/category/aliastyp.htm
-    //
-    union {
-      double D;
-      uint64_t U;
-    } V;
-    V.D = CFP->getValue();
     assert(sizeof(double) == sizeof(uint64_t) &&
            "assuming that double is 64 bits!");
-    Out << "0x" << utohexstr(V.U);
+    Out << "0x" << utohexstr(DoubleToBits(CFP->getValue()));
 
   } else if (isa<ConstantAggregateZero>(CV)) {
     Out << "zeroinitializer";
@@ -447,29 +459,9 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
     // ubytes or an array of sbytes with positive values.
     //
     const Type *ETy = CA->getType()->getElementType();
-    bool isString = (ETy == Type::SByteTy || ETy == Type::UByteTy);
-
-    if (ETy == Type::SByteTy)
-      for (unsigned i = 0; i < CA->getNumOperands(); ++i)
-        if (cast<ConstantSInt>(CA->getOperand(i))->getValue() < 0) {
-          isString = false;
-          break;
-        }
-
-    if (isString) {
+    if (CA->isString()) {
       Out << "c\"";
-      for (unsigned i = 0; i < CA->getNumOperands(); ++i) {
-        unsigned char C =
-          (unsigned char)cast<ConstantInt>(CA->getOperand(i))->getRawValue();
-
-        if (isprint(C) && C != '"' && C != '\\') {
-          Out << C;
-        } else {
-          Out << '\\'
-              << (char) ((C/16  < 10) ? ( C/16 +'0') : ( C/16 -10+'A'))
-              << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
-        }
-      }
+      PrintEscapedString(CA->getAsString(), Out);
       Out << "\"";
 
     } else {                // Cannot output in string format...
@@ -564,9 +556,18 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V,
     Out << getLLVMName(V->getName());
   else {
     const Constant *CV = dyn_cast<Constant>(V);
-    if (CV && !isa<GlobalValue>(CV))
+    if (CV && !isa<GlobalValue>(CV)) {
       WriteConstantInt(Out, CV, PrintName, TypeTable, Machine);
-    else {
+    } else if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
+      Out << "asm ";
+      if (IA->hasSideEffects())
+        Out << "sideeffect ";
+      Out << '"';
+      PrintEscapedString(IA->getAsmString(), Out);
+      Out << "\", \"";
+      PrintEscapedString(IA->getConstraintString(), Out);
+      Out << '"';
+    } else {
       int Slot;
       if (Machine) {
         Slot = Machine->getSlot(V);
@@ -784,6 +785,26 @@ void AssemblyWriter::printModule(const Module *M) {
   if (!M->getTargetTriple().empty())
     Out << "target triple = \"" << M->getTargetTriple() << "\"\n";
 
+  if (!M->getModuleInlineAsm().empty()) {
+    // Split the string into lines, to make it easier to read the .ll file.
+    std::string Asm = M->getModuleInlineAsm();
+    size_t CurPos = 0;
+    size_t NewLine = Asm.find_first_of('\n', CurPos);
+    while (NewLine != std::string::npos) {
+      // We found a newline, print the portion of the asm string from the
+      // last newline up to this newline.
+      Out << "module asm \"";
+      PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine),
+                         Out);
+      Out << "\"\n";
+      CurPos = NewLine+1;
+      NewLine = Asm.find_first_of('\n', CurPos);
+    }
+    Out << "module asm \"";
+    PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out);
+    Out << "\"\n";
+  }
+  
   // Loop over the dependent libraries and emit them.
   Module::lib_iterator LI = M->lib_begin();
   Module::lib_iterator LE = M->lib_end();
@@ -836,7 +857,12 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
     assert(C &&  "GlobalVar initializer isn't constant?");
     writeOperand(GV->getInitializer(), false, isa<GlobalValue>(C));
   }
-
+  
+  if (GV->hasSection())
+    Out << ", section \"" << GV->getSection() << '"';
+  if (GV->getAlignment())
+    Out << ", align " << GV->getAlignment();
+  
   printInfoComment(*GV);
   Out << "\n";
 }
@@ -915,6 +941,14 @@ void AssemblyWriter::printFunction(const Function *F) {
       abort();
     }
 
+  // Print the calling convention.
+  switch (F->getCallingConv()) {
+  case CallingConv::C: break;   // default
+  case CallingConv::Fast: Out << "fastcc "; break;
+  case CallingConv::Cold: Out << "coldcc "; break;
+  default: Out << "cc" << F->getCallingConv() << " "; break;
+  }
+
   printType(F->getReturnType()) << ' ';
   if (!F->getName().empty())
     Out << getLLVMName(F->getName());
@@ -936,6 +970,11 @@ void AssemblyWriter::printFunction(const Function *F) {
   }
   Out << ')';
 
+  if (F->hasSection())
+    Out << " section \"" << F->getSection() << '"';
+  if (F->getAlignment())
+    Out << " align " << F->getAlignment();
+
   if (F->isExternal()) {
     Out << "\n";
   } else {
@@ -1090,7 +1129,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
     }
   } else if (isa<ReturnInst>(I) && !Operand) {
     Out << " void";
-  } else if (isa<CallInst>(I)) {
+  } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
+    // Print the calling convention being used.
+    switch (CI->getCallingConv()) {
+    case CallingConv::C: break;   // default
+    case CallingConv::Fast: Out << " fastcc"; break;
+    case CallingConv::Cold: Out << " coldcc"; break;
+    default: Out << " cc" << CI->getCallingConv(); break;
+    }
+
     const PointerType  *PTy = cast<PointerType>(Operand->getType());
     const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
     const Type       *RetTy = FTy->getReturnType();
@@ -1108,7 +1155,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
       writeOperand(Operand, true);
     }
     Out << '(';
-    if (I.getNumOperands() > 1) writeOperand(I.getOperand(1), true);
+    if (CI->getNumOperands() > 1) writeOperand(CI->getOperand(1), true);
     for (unsigned op = 2, Eop = I.getNumOperands(); op < Eop; ++op) {
       Out << ',';
       writeOperand(I.getOperand(op), true);
@@ -1120,6 +1167,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
     const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
     const Type       *RetTy = FTy->getReturnType();
 
+    // Print the calling convention being used.
+    switch (II->getCallingConv()) {
+    case CallingConv::C: break;   // default
+    case CallingConv::Fast: Out << " fastcc"; break;
+    case CallingConv::Cold: Out << " coldcc"; break;
+    default: Out << " cc" << II->getCallingConv(); break;
+    }
+
     // If possible, print out the short form of the invoke instruction. We can
     // only do this if the first argument is a pointer to a nonvararg function,
     // and if the return type is not a pointer to a function.
@@ -1152,6 +1207,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
       Out << ',';
       writeOperand(AI->getArraySize(), true);
     }
+    if (AI->getAlignment()) {
+      Out << ", align " << AI->getAlignment();
+    }
   } else if (isa<CastInst>(I)) {
     if (Operand) writeOperand(Operand, true);   // Work with broken code
     Out << " to ";
@@ -1160,10 +1218,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
     if (Operand) writeOperand(Operand, true);   // Work with broken code
     Out << ", ";
     printType(I.getType());
-  } else if (const VANextInst *VAN = dyn_cast<VANextInst>(&I)) {
-    if (Operand) writeOperand(Operand, true);   // Work with broken code
-    Out << ", ";
-    printType(VAN->getArgType());
   } else if (Operand) {   // Print the normal way...
 
     // PrintAllTypes - Instructions who have operands of all the same type
@@ -1225,6 +1279,10 @@ void Function::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const {
   W.write(this);
 }
 
+void InlineAsm::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const {
+  WriteAsOperand(o, this, true, true, 0);
+}
+
 void BasicBlock::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const {
   SlotMachine SlotTable(getParent());
   AssemblyWriter W(o, SlotTable,