Add AsmPrinter (aka MCLowering) support for ConstantDataSequential,

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
This commit is contained in:
Chris Lattner 2012-01-24 09:31:43 +00:00
parent 6233907312
commit 9e631da253
3 changed files with 105 additions and 45 deletions

View 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();

View 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),

View 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 {