From 29cc6cb4d1aa22f0a27edf4e5b363071a83a65d8 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 24 Jan 2012 14:17:05 +0000 Subject: C++, CBE, and TLOF support for ConstantDataSequential git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148805 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CBackend/CBackend.cpp | 80 ++++++++++++++++++++++++++++----- lib/Target/CppBackend/CPPBackend.cpp | 39 ++++++++++++++-- lib/Target/TargetLoweringObjectFile.cpp | 23 +++++++--- lib/VMCore/Constants.cpp | 3 +- 4 files changed, 125 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index f4eb14a8b8..4b86ee4d31 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -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(*(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(CPV)) { printConstantArray(CA, Static); + } else if (ConstantDataSequential *CDS = + dyn_cast(CPV)) { + printConstantDataSequential(CDS, Static); } else { assert(isa(CPV) || isa(CPV)); ArrayType *AT = cast(CPV->getType()); @@ -1051,6 +1106,9 @@ void CWriter::printConstant(Constant *CPV, bool Static) { } if (ConstantVector *CV = dyn_cast(CPV)) { printConstantVector(CV, Static); + } else if (ConstantDataSequential *CDS = + dyn_cast(CPV)) { + printConstantDataSequential(CDS, Static); } else { assert(isa(CPV) || isa(CPV)); VectorType *VT = cast(CPV->getType()); diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 25e675b8f4..de73a72ac4 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -698,9 +698,7 @@ void CppWriter::printConstant(const Constant *CV) { printCFP(CFP); Out << ";"; } else if (const ConstantArray *CA = dyn_cast(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(CV)) { Out << "UndefValue* " << constName << " = UndefValue::get(" << typeName << ");"; + } else if (const ConstantDataSequential *CDS = + dyn_cast(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 " << 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(CDS->getType())) + Out << " = ConstantArray::get("; + else + Out << " = ConstantVector::get("; + Out << typeName << ", " << constName << "_elems);"; + } } else if (const ConstantExpr *CE = dyn_cast(CV)) { if (CE->getOpcode() == Instruction::GetElementPtr) { Out << "std::vector " << constName << "_indices;"; diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 70abe5a052..ec3b1946f3 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -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(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(C)) { + ArrayType *ATy = cast(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(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(C)) - return ATy->getNumElements() == 1; + return cast(C->getType())->getNumElements() == 1; return false; } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 5151105e05..1976832294 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -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(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); -- cgit v1.2.3