diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 21400e774d4..510847ff23c 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 eccd8fb6c80..ff6da1248bb 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -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(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(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(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(CV)) - if (CE->getOpcode() == Instruction::BitCast) - CV = CE->getOperand(0); - - if (const ConstantVector *V = dyn_cast(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(CV)) - return EmitGlobalConstantArray(CVA, AddrSpace, AP); - - if (const ConstantStruct *CVS = dyn_cast(CV)) - return EmitGlobalConstantStruct(CVS, AddrSpace, AP); - if (const ConstantFP *CFP = dyn_cast(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(CV)) + return EmitGlobalConstantDataSequential(CDS, AddrSpace, AP); + + if (const ConstantArray *CVA = dyn_cast(CV)) + return EmitGlobalConstantArray(CVA, AddrSpace, AP); + if (const ConstantStruct *CVS = dyn_cast(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(CV)) + if (CE->getOpcode() == Instruction::BitCast) + return EmitGlobalConstantImpl(CE->getOperand(0), AddrSpace, AP); + + if (const ConstantVector *V = dyn_cast(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 0525882828e..9f1abbd17bb 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 &CDSConstants = getType()->getContext().pImpl->CDSConstants; StringMap::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(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 {