Next PPC long double bits. First cut at constants.
[oota-llvm.git] / lib / VMCore / AsmWriter.cpp
index f747760900ff9929443189174aab4f7757c8ee76..9592151c6d924aed9b7865330e1c42882eb6f466 100644 (file)
@@ -33,6 +33,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Streams.h"
 #include <algorithm>
+#include <cctype>
 using namespace llvm;
 
 namespace llvm {
@@ -135,10 +136,10 @@ public:
 
 }  // end namespace llvm
 
-const char PrintModulePass::ID = 0;
+char PrintModulePass::ID = 0;
 static RegisterPass<PrintModulePass>
 X("printm", "Print module to stderr");
-const char PrintFunctionPass::ID = 0;
+char PrintFunctionPass::ID = 0;
 static RegisterPass<PrintFunctionPass>
 Y("print","Print function to stderr");
 
@@ -178,17 +179,42 @@ static SlotMachine *createSlotMachine(const Value *V) {
 
 /// NameNeedsQuotes - Return true if the specified llvm name should be wrapped
 /// with ""'s.
-static bool NameNeedsQuotes(const std::string &Name) {
-  if (Name[0] >= '0' && Name[0] <= '9') return true;
-  // Scan to see if we have any characters that are not on the "white list"
+static std::string QuoteNameIfNeeded(const std::string &Name) {
+  std::string result;
+  bool needsQuotes = Name[0] >= '0' && Name[0] <= '9';
+  // Scan the name to see if it needs quotes and to replace funky chars with
+  // their octal equivalent.
   for (unsigned i = 0, e = Name.size(); i != e; ++i) {
     char C = Name[i];
     assert(C != '"' && "Illegal character in LLVM value name!");
-    if ((C < 'a' || C > 'z') && (C < 'A' || C > 'Z') && (C < '0' || C > '9') &&
-        C != '-' && C != '.' && C != '_')
-      return true;
+    if (isalnum(C) || C == '-' || C == '.' || C == '_')
+      result += C;
+    else if (C == '\\')  {
+      needsQuotes = true;
+      result += "\\\\";
+    } else if (isprint(C)) {
+      needsQuotes = true;
+      result += C;
+    } else {
+      needsQuotes = true;
+      result += "\\";
+      char hex1 = (C >> 4) & 0x0F;
+      if (hex1 < 10)
+        result += hex1 + '0';
+      else 
+        result += hex1 - 10 + 'A';
+      char hex2 = C & 0x0F;
+      if (hex2 < 10)
+        result += hex2 + '0';
+      else 
+        result += hex2 - 10 + 'A';
+    }
+  }
+  if (needsQuotes) {
+    result.insert(0,"\"");
+    result += '"';
   }
-  return false;
+  return result;
 }
 
 enum PrefixType {
@@ -202,20 +228,11 @@ enum PrefixType {
 /// surrounded with ""'s (if it has special chars in it).
 static std::string getLLVMName(const std::string &Name, PrefixType Prefix) {
   assert(!Name.empty() && "Cannot get empty name!");
-
-  // First character cannot start with a number...
-  if (NameNeedsQuotes(Name)) {
-    if (Prefix == GlobalPrefix)
-      return "@\"" + Name + "\"";
-    return "\"" + Name + "\"";
-  }
-
-  // If we get here, then the identifier is legal to use as a "VarID".
   switch (Prefix) {
   default: assert(0 && "Bad prefix!");
-  case GlobalPrefix: return '@' + Name;
-  case LabelPrefix:  return Name;
-  case LocalPrefix:  return '%' + Name;
+  case GlobalPrefix: return '@' + QuoteNameIfNeeded(Name);
+  case LabelPrefix:  return QuoteNameIfNeeded(Name);
+  case LocalPrefix:  return '%' + QuoteNameIfNeeded(Name);
   }      
 }
 
@@ -464,32 +481,68 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
     else 
       Out << CI->getValue().toStringSigned(10);
   } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
-    // We would like to output the FP constant value in exponential notation,
-    // but we cannot do this if doing so will lose precision.  Check here to
-    // make sure that we only output it in exponential format if we can parse
-    // the value back and get the same value.
-    //
-    std::string StrVal = ftostr(CFP->getValue());
-
-    // Check to make sure that the stringized number is not some string like
-    // "Inf" or NaN, that atof will accept, but the lexer will not.  Check that
-    // the string matches the "[-+]?[0-9]" regex.
-    //
-    if ((StrVal[0] >= '0' && StrVal[0] <= '9') ||
-        ((StrVal[0] == '-' || StrVal[0] == '+') &&
-         (StrVal[1] >= '0' && StrVal[1] <= '9')))
-      // Reparse stringized version!
-      if (atof(StrVal.c_str()) == CFP->getValue()) {
-        Out << StrVal;
-        return;
+    if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble ||
+        &CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle) {
+      // We would like to output the FP constant value in exponential notation,
+      // but we cannot do this if doing so will lose precision.  Check here to
+      // make sure that we only output it in exponential format if we can parse
+      // the value back and get the same value.
+      //
+      bool isDouble = &CFP->getValueAPF().getSemantics()==&APFloat::IEEEdouble;
+      double Val = (isDouble) ? CFP->getValueAPF().convertToDouble() :
+                                CFP->getValueAPF().convertToFloat();
+      std::string StrVal = ftostr(CFP->getValueAPF());
+
+      // Check to make sure that the stringized number is not some string like
+      // "Inf" or NaN, that atof will accept, but the lexer will not.  Check
+      // that the string matches the "[-+]?[0-9]" regex.
+      //
+      if ((StrVal[0] >= '0' && StrVal[0] <= '9') ||
+          ((StrVal[0] == '-' || StrVal[0] == '+') &&
+           (StrVal[1] >= '0' && StrVal[1] <= '9'))) {
+        // Reparse stringized version!
+        if (atof(StrVal.c_str()) == Val) {
+          Out << StrVal;
+          return;
+        }
       }
-
-    // Otherwise we could not reparse it to exactly the same value, so we must
-    // output the string in hexadecimal format!
-    assert(sizeof(double) == sizeof(uint64_t) &&
-           "assuming that double is 64 bits!");
-    Out << "0x" << utohexstr(DoubleToBits(CFP->getValue()));
-
+      // Otherwise we could not reparse it to exactly the same value, so we must
+      // output the string in hexadecimal format!
+      assert(sizeof(double) == sizeof(uint64_t) &&
+             "assuming that double is 64 bits!");
+      Out << "0x" << utohexstr(DoubleToBits(Val));
+    } else {
+      // Some form of long double.  These appear as a magic letter identifying
+      // the type, then a fixed number of hex digits.
+      Out << "0x";
+      if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended)
+        Out << 'K';
+      else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
+        Out << 'L';
+      else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
+        Out << 'M';
+      else
+        assert(0 && "Unsupported floating point type");
+      // api needed to prevent premature destruction
+      APInt api = CFP->getValueAPF().convertToAPInt();
+      const uint64_t* p = api.getRawData();
+      uint64_t word = *p;
+      int shiftcount=60;
+      int width = api.getBitWidth();
+      for (int j=0; j<width; j+=4, shiftcount-=4) {
+        unsigned int nibble = (word>>shiftcount) & 15;
+        if (nibble < 10)
+          Out << (unsigned char)(nibble + '0');
+        else
+          Out << (unsigned char)(nibble - 10 + 'A');
+        if (shiftcount == 0) {
+          word = *(++p);
+          shiftcount = 64;
+          if (width-j-4 < 64)
+            shiftcount = width-j-4;
+        }
+      }
+    }
   } else if (isa<ConstantAggregateZero>(CV)) {
     Out << "zeroinitializer";
   } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
@@ -978,32 +1031,28 @@ void AssemblyWriter::printFunction(const Function *F) {
   if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out);
 
   if (F->isDeclaration())
-    switch (F->getLinkage()) {
-    case GlobalValue::DLLImportLinkage:    Out << "declare dllimport "; break;
-    case GlobalValue::ExternalWeakLinkage: Out << "declare extern_weak "; break;
-    default: Out << "declare ";
-    }
-  else {
+    Out << "declare ";
+  else
     Out << "define ";
-    switch (F->getLinkage()) {
-    case GlobalValue::InternalLinkage:     Out << "internal "; break;
-    case GlobalValue::LinkOnceLinkage:     Out << "linkonce "; break;
-    case GlobalValue::WeakLinkage:         Out << "weak "; break;
-    case GlobalValue::AppendingLinkage:    Out << "appending "; break;
-    case GlobalValue::DLLImportLinkage:    Out << "dllimport "; break;
-    case GlobalValue::DLLExportLinkage:    Out << "dllexport "; break;
-    case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;      
-    case GlobalValue::ExternalLinkage: break;
-    case GlobalValue::GhostLinkage:
-      cerr << "GhostLinkage not allowed in AsmWriter!\n";
-      abort();
-    }
-    switch (F->getVisibility()) {
-    default: assert(0 && "Invalid visibility style!");
-    case GlobalValue::DefaultVisibility: break;
-    case GlobalValue::HiddenVisibility: Out << "hidden "; break;
-    case GlobalValue::ProtectedVisibility: Out << "protected "; break;
-    }
+    
+  switch (F->getLinkage()) {
+  case GlobalValue::InternalLinkage:     Out << "internal "; break;
+  case GlobalValue::LinkOnceLinkage:     Out << "linkonce "; break;
+  case GlobalValue::WeakLinkage:         Out << "weak "; break;
+  case GlobalValue::AppendingLinkage:    Out << "appending "; break;
+  case GlobalValue::DLLImportLinkage:    Out << "dllimport "; break;
+  case GlobalValue::DLLExportLinkage:    Out << "dllexport "; break;
+  case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;      
+  case GlobalValue::ExternalLinkage: break;
+  case GlobalValue::GhostLinkage:
+    cerr << "GhostLinkage not allowed in AsmWriter!\n";
+    abort();
+  }
+  switch (F->getVisibility()) {
+  default: assert(0 && "Invalid visibility style!");
+  case GlobalValue::DefaultVisibility: break;
+  case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+  case GlobalValue::ProtectedVisibility: Out << "protected "; break;
   }
 
   // Print the calling convention.