Add AsmPrinter (aka MCLowering) support for ConstantDataSequential,
authorChris Lattner <sabre@nondot.org>
Tue, 24 Jan 2012 09:31:43 +0000 (09:31 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 24 Jan 2012 09:31:43 +0000 (09:31 +0000)
and clean up some other misc stuff.  Unlike ConstantArray, we will
prefer to emit .fill directives for "String" arrays that all have
the same value, since they are denser than emitting a .ascii

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148793 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Constants.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/VMCore/Constants.cpp

index 21400e774d4ba3258d585d83a8635f979c1e44d4..510847ff23c266c784265a6fcab0cb62dabca088 100644 (file)
@@ -640,7 +640,10 @@ public:
   /// getAsString - If this array is isString(), then this method returns the
   /// array as a StringRef.  Otherwise, it asserts out.
   ///
-  StringRef getAsString() const;
+  StringRef getAsString() const {
+    assert(isString() && "Not a string");
+    return getRawDataValues();
+  }
   
   /// getAsCString - If this array is isCString(), then this method returns the
   /// array (without the trailing null byte) as a StringRef. Otherwise, it
@@ -652,6 +655,10 @@ public:
     return Str.substr(0, Str.size()-1);
   }
   
+  /// getRawDataValues - Return the raw, underlying, bytes of this data.  Note
+  /// that this is an extremely tricky thing to work with, as it exposes the
+  /// host endianness of the data elements.
+  StringRef getRawDataValues() const;
   
   virtual void destroyConstant();
   
index eccd8fb6c8064096582d1f2563ffeff927e1651e..ff6da1248bbd1269ad1a6dd3923c89c871b3d184 100644 (file)
@@ -1554,6 +1554,19 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) {
 static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace,
                                    AsmPrinter &AP);
 
+/// isRepeatedByteSequence - Determine whether the given value is
+/// composed of a repeated sequence of identical bytes and return the
+/// byte value.  If it is not a repeated sequence, return -1.
+static int isRepeatedByteSequence(const ConstantDataSequential *V) {
+  StringRef Data = V->getRawDataValues();
+  assert(!Data.empty() && "Empty aggregates should be CAZ node");
+  char C = Data[0];
+  for (unsigned i = 1, e = Data.size(); i != e; ++i)
+    if (Data[i] != C) return -1;
+  return C;
+}
+
+
 /// isRepeatedByteSequence - Determine whether the given value is
 /// composed of a repeated sequence of identical bytes and return the
 /// byte value.  If it is not a repeated sequence, return -1.
@@ -1582,8 +1595,7 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) {
   if (const ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
     // Make sure all array elements are sequences of the same repeated
     // byte.
-    if (CA->getNumOperands() == 0) return -1;
-
+    assert(CA->getNumOperands() != 0 && "Should be a CAZ");
     int Byte = isRepeatedByteSequence(CA->getOperand(0), TM);
     if (Byte == -1) return -1;
 
@@ -1594,10 +1606,70 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) {
     }
     return Byte;
   }
+  
+  if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(V))
+    return isRepeatedByteSequence(CDS);
 
   return -1;
 }
 
+static void EmitGlobalConstantDataSequential(const ConstantDataSequential *CDS,
+                                             unsigned AddrSpace,AsmPrinter &AP){
+  
+  // See if we can aggregate this into a .fill, if so, emit it as such.
+  int Value = isRepeatedByteSequence(CDS, AP.TM);
+  if (Value != -1) {
+    uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CDS->getType());
+    return AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace);
+  }
+  
+  // If this can be emitted with .ascii/.asciz, emit it as such.
+  if (CDS->isString())
+    return AP.OutStreamer.EmitBytes(CDS->getAsString(), AddrSpace);
+
+  // Otherwise, emit the values in successive locations.
+  unsigned ElementByteSize = CDS->getElementByteSize();
+  if (isa<IntegerType>(CDS->getElementType())) {
+    for (unsigned i = 0, e = CDS->getType()->getNumElements(); i != e; ++i) {
+      AP.OutStreamer.EmitIntValue(CDS->getElementAsInteger(i),
+                                  ElementByteSize, AddrSpace);
+    }
+    return;
+  }
+
+  // FP Constants are printed as integer constants to avoid losing
+  // precision.
+  assert(CDS->getElementType()->isFloatTy() ||
+         CDS->getElementType()->isDoubleTy());
+
+  if (ElementByteSize == 4) {
+    for (unsigned i = 0, e = CDS->getType()->getNumElements(); i != e; ++i) {
+      union {
+        float F;
+        uint32_t I;
+      };
+      
+      F = CDS->getElementAsFloat(i);
+      if (AP.isVerbose())
+        AP.OutStreamer.GetCommentOS() << "float " << F << '\n';
+      AP.OutStreamer.EmitIntValue(I, 4, AddrSpace);
+    }
+    return;
+  }
+
+  for (unsigned i = 0, e = CDS->getType()->getNumElements(); i != e; ++i) {
+    union {
+      double F;
+      uint64_t I;
+    };
+    
+    F = CDS->getElementAsDouble(i);
+    if (AP.isVerbose())
+      AP.OutStreamer.GetCommentOS() << "double " << F << '\n';
+    AP.OutStreamer.EmitIntValue(I, 8, AddrSpace);
+  }
+}
+
 static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace,
                                     AsmPrinter &AP) {
   if (AddrSpace != 0 || !CA->isString()) {
@@ -1640,28 +1712,6 @@ static void EmitGlobalConstantVector(const ConstantVector *CV,
     AP.OutStreamer.EmitZeros(Padding, AddrSpace);
 }
 
-static void LowerVectorConstant(const Constant *CV, unsigned AddrSpace,
-                                AsmPrinter &AP) {
-  // Look through bitcasts
-  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
-    if (CE->getOpcode() == Instruction::BitCast)
-      CV = CE->getOperand(0);
-
-  if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
-    return EmitGlobalConstantVector(V, AddrSpace, AP);
-
-  // If we get here, we're stuck; report the problem to the user.
-  // FIXME: Are there any other useful tricks for vectors?
-  {
-    std::string S;
-    raw_string_ostream OS(S);
-    OS << "Unsupported vector expression in static initializer: ";
-    WriteAsOperand(OS, CV, /*PrintType=*/false,
-                   !AP.MF ? 0 : AP.MF->getFunction()->getParent());
-    report_fatal_error(OS.str());
-  }
-}
-
 static void EmitGlobalConstantStruct(const ConstantStruct *CS,
                                      unsigned AddrSpace, AsmPrinter &AP) {
   // Print the fields in successive locations. Pad to align if needed!
@@ -1812,12 +1862,6 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace,
     }
   }
 
-  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
-    return EmitGlobalConstantArray(CVA, AddrSpace, AP);
-
-  if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
-    return EmitGlobalConstantStruct(CVS, AddrSpace, AP);
-
   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
     return EmitGlobalConstantFP(CFP, AddrSpace, AP);
 
@@ -1827,9 +1871,24 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace,
     return;
   }
 
-  if (CV->getType()->isVectorTy())
-    return LowerVectorConstant(CV, AddrSpace, AP);
+  if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
+    return EmitGlobalConstantDataSequential(CDS, AddrSpace, AP);
+  
+  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
+    return EmitGlobalConstantArray(CVA, AddrSpace, AP);
 
+  if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
+    return EmitGlobalConstantStruct(CVS, AddrSpace, AP);
+
+  // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
+  // vectors).
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
+    if (CE->getOpcode() == Instruction::BitCast)
+      return EmitGlobalConstantImpl(CE->getOperand(0), AddrSpace, AP);
+  
+  if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
+    return EmitGlobalConstantVector(V, AddrSpace, AP);
+    
   // Otherwise, it must be a ConstantExpr.  Lower it to an MCExpr, then emit it
   // thread the streamer with EmitValue.
   AP.OutStreamer.EmitValue(LowerConstant(CV, AP),
index 0525882828eb7332a216d25ad449178ce27dbcd7..9f1abbd17bbd186338243cc31351e85becdb2a9d 100644 (file)
@@ -1994,6 +1994,11 @@ Type *ConstantDataSequential::getElementType() const {
   return getType()->getElementType();
 }
 
+StringRef ConstantDataSequential::getRawDataValues() const {
+  return StringRef(DataElements,
+                   getType()->getNumElements()*getElementByteSize());
+}
+
 /// isElementTypeCompatible - Return true if a ConstantDataSequential can be
 /// formed with a vector or array of the specified element type.
 /// ConstantDataArray only works with normal float and int types that are
@@ -2067,14 +2072,12 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) {
 }
 
 void ConstantDataSequential::destroyConstant() {
-  uint64_t ByteSize = getElementByteSize() * getElementType()->getNumElements();
-  
   // Remove the constant from the StringMap.
   StringMap<ConstantDataSequential*> &CDSConstants = 
     getType()->getContext().pImpl->CDSConstants;
   
   StringMap<ConstantDataSequential*>::iterator Slot =
-    CDSConstants.find(StringRef(DataElements, ByteSize));
+    CDSConstants.find(getRawDataValues());
 
   assert(Slot != CDSConstants.end() && "CDS not found in uniquing table");
 
@@ -2226,15 +2229,6 @@ bool ConstantDataSequential::isString() const {
   return isa<ArrayType>(getType()) && getElementType()->isIntegerTy(8);
 }
 
-/// getAsString - If this array is isString(), then this method returns the
-/// array as a StringRef.  Otherwise, it asserts out.
-///
-StringRef ConstantDataSequential::getAsString() const {
-  assert(isString() && "Not a string");
-  return StringRef(DataElements, getType()->getNumElements());
-}
-
-
 /// isCString - This method returns true if the array "isString", ends with a
 /// nul byte, and does not contains any other nul bytes.
 bool ConstantDataSequential::isCString() const {