C++, CBE, and TLOF support for ConstantDataSequential

llvm-svn: 148805
This commit is contained in:
Chris Lattner 2012-01-24 14:17:05 +00:00
parent 70c46f210a
commit c67dced045
4 changed files with 125 additions and 20 deletions

View File

@ -215,6 +215,8 @@ namespace {
bool printConstExprCast(const ConstantExpr *CE, bool Static);
void printConstantArray(ConstantArray *CPA, bool Static);
void printConstantVector(ConstantVector *CV, bool Static);
void printConstantDataSequential(ConstantDataSequential *CDS, bool Static);
/// isAddressExposed - Return true if the specified value's name needs to
/// have its address taken in order to get a C value of the correct type.
@ -556,20 +558,10 @@ raw_ostream &CWriter::printType(raw_ostream &Out, Type *Ty,
}
void CWriter::printConstantArray(ConstantArray *CPA, bool Static) {
// As a special case, print the array as a string if it is an array of
// ubytes or an array of sbytes with positive values.
//
Type *ETy = CPA->getType()->getElementType();
bool isString = (ETy == Type::getInt8Ty(CPA->getContext()) ||
ETy == Type::getInt8Ty(CPA->getContext()));
// Make sure the last character is a null char, as automatically added by C
if (isString && (CPA->getNumOperands() == 0 ||
!cast<Constant>(*(CPA->op_end()-1))->isNullValue()))
isString = false;
if (isString) {
if (CPA->isCString()) {
Out << '\"';
// Keep track of whether the last number was a hexadecimal escape.
bool LastWasHex = false;
@ -637,6 +629,66 @@ void CWriter::printConstantVector(ConstantVector *CP, bool Static) {
Out << " }";
}
void CWriter::printConstantDataSequential(ConstantDataSequential *CDS,
bool Static) {
// As a special case, print the array as a string if it is an array of
// ubytes or an array of sbytes with positive values.
//
if (CDS->isCString()) {
Out << '\"';
// Keep track of whether the last number was a hexadecimal escape.
bool LastWasHex = false;
StringRef Bytes = CDS->getAsCString();
// Do not include the last character, which we know is null
for (unsigned i = 0, e = Bytes.size(); i != e; ++i) {
unsigned char C = Bytes[i];
// Print it out literally if it is a printable character. The only thing
// to be careful about is when the last letter output was a hex escape
// code, in which case we have to be careful not to print out hex digits
// explicitly (the C compiler thinks it is a continuation of the previous
// character, sheesh...)
//
if (isprint(C) && (!LastWasHex || !isxdigit(C))) {
LastWasHex = false;
if (C == '"' || C == '\\')
Out << "\\" << (char)C;
else
Out << (char)C;
} else {
LastWasHex = false;
switch (C) {
case '\n': Out << "\\n"; break;
case '\t': Out << "\\t"; break;
case '\r': Out << "\\r"; break;
case '\v': Out << "\\v"; break;
case '\a': Out << "\\a"; break;
case '\"': Out << "\\\""; break;
case '\'': Out << "\\\'"; break;
default:
Out << "\\x";
Out << (char)(( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'));
Out << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
LastWasHex = true;
break;
}
}
}
Out << '\"';
} else {
Out << "{ ";
printConstant(CDS->getElementAsConstant(0), Static);
for (unsigned i = 1, e = CDS->getNumOperands(); i != e; ++i) {
Out << ", ";
printConstant(CDS->getElementAsConstant(i), Static);
}
Out << " }";
}
}
// isFPCSafeToPrint - Returns true if we may assume that CFP may be written out
// textually as a double (rather than as a reference to a stack-allocated
// variable). We decide this by converting CFP to a string and back into a
@ -1024,6 +1076,9 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
Out << "{ "; // Arrays are wrapped in struct types.
if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
printConstantArray(CA, Static);
} else if (ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(CPV)) {
printConstantDataSequential(CDS, Static);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
ArrayType *AT = cast<ArrayType>(CPV->getType());
@ -1051,6 +1106,9 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
}
if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
printConstantVector(CV, Static);
} else if (ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(CPV)) {
printConstantDataSequential(CDS, Static);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
VectorType *VT = cast<VectorType>(CPV->getType());

View File

@ -698,9 +698,7 @@ void CppWriter::printConstant(const Constant *CV) {
printCFP(CFP);
Out << ";";
} else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
if (CA->isString() &&
CA->getType()->getElementType() ==
Type::getInt8Ty(CA->getContext())) {
if (CA->isString()) {
Out << "Constant* " << constName <<
" = ConstantArray::get(mod->getContext(), \"";
std::string tmp = CA->getAsString();
@ -757,6 +755,41 @@ void CppWriter::printConstant(const Constant *CV) {
} else if (isa<UndefValue>(CV)) {
Out << "UndefValue* " << constName << " = UndefValue::get("
<< typeName << ");";
} else if (const ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(CV)) {
if (CDS->isString()) {
Out << "Constant *" << constName <<
" = ConstantDataArray::getString(mod->getContext(), \"";
StringRef Str = CA->getAsString();
bool nullTerminate = false;
if (Str.back() == 0) {
Str = Str.drop_back();
nullTerminate = true;
}
printEscapedString(Str);
// Determine if we want null termination or not.
if (nullTerminate)
Out << "\", true);";
else
Out << "\", false);";// No null terminator
} else {
// TODO: Could generate more efficient code generating CDS calls instead.
Out << "std::vector<Constant*> " << constName << "_elems;";
nl(Out);
for (unsigned i = 0; i != CDS->getNumElements(); ++i) {
Constant *Elt = CDS->getElementAsConstant(i);
printConstant(Elt);
Out << constName << "_elems.push_back(" << getCppName(Elt) << ");";
nl(Out);
}
Out << "Constant* " << constName;
if (isa<ArrayType>(CDS->getType()))
Out << " = ConstantArray::get(";
else
Out << " = ConstantVector::get(";
Out << typeName << ", " << constName << "_elems);";
}
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
Out << "std::vector<Constant*> " << constName << "_indices;";

View File

@ -73,12 +73,12 @@ static bool isSuitableForBSS(const GlobalVariable *GV, bool NoZerosInBSS) {
/// IsNullTerminatedString - Return true if the specified constant (which is
/// known to have a type that is an array of 1/2/4 byte elements) ends with a
/// nul value and contains no other nuls in it.
/// nul value and contains no other nuls in it. Note that this is more general
/// than ConstantDataSequential::isString because we allow 2 & 4 byte strings.
static bool IsNullTerminatedString(const Constant *C) {
ArrayType *ATy = cast<ArrayType>(C->getType());
// First check: is we have constant array of i8 terminated with zero
// First check: is we have constant array terminated with zero
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
ArrayType *ATy = cast<ArrayType>(C->getType());
if (ATy->getNumElements() == 0) return false;
ConstantInt *Null =
@ -94,10 +94,23 @@ static bool IsNullTerminatedString(const Constant *C) {
return false;
return true;
}
if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C)) {
unsigned NumElts = CDS->getNumElements();
assert(NumElts != 0 && "Can't have an empty CDS");
if (CDS->getElementAsInteger(NumElts-1) != 0)
return false; // Not null terminated.
// Verify that the null doesn't occur anywhere else in the string.
for (unsigned i = 0; i != NumElts-1; ++i)
if (CDS->getElementAsInteger(i) == 0)
return false;
return true;
}
// Another possibility: [1 x i8] zeroinitializer
if (isa<ConstantAggregateZero>(C))
return ATy->getNumElements() == 1;
return cast<ArrayType>(C->getType())->getNumElements() == 1;
return false;
}

View File

@ -2048,7 +2048,8 @@ static bool isAllZeros(StringRef Arr) {
/// we *want* an underlying "char*" to avoid TBAA type punning violations.
Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) {
assert(isElementTypeCompatible(cast<SequentialType>(Ty)->getElementType()));
// If the elements are all zero, return a CAZ, which is more dense.
// If the elements are all zero or there are no elements, return a CAZ, which
// is more dense and canonical.
if (isAllZeros(Elements))
return ConstantAggregateZero::get(Ty);