aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Constants.h9
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp123
-rw-r--r--lib/VMCore/Constants.cpp18
3 files changed, 105 insertions, 45 deletions
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index 21400e774d..510847ff23 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -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();
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index eccd8fb6c8..ff6da1248b 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1557,6 +1557,19 @@ static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace,
/// 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.
static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
@@ -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),
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 0525882828..9f1abbd17b 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -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 {