diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-02-01 04:51:17 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-02-01 04:51:17 +0000 |
commit | 91766fe066efe6e0969ba805a2e3726a70ed34a3 (patch) | |
tree | 4341aed84ba24607ccb4c8426dfd695b2e484abb | |
parent | de5e5ec3045a73a06b1054417f9ac6c02929e9ce (diff) |
Revert Chris' commits up to r149348 that started causing VMCoreTests unit test to fail.
These are:
r149348
r149351
r149352
r149354
r149356
r149357
r149361
r149362
r149364
r149365
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149470 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Analysis/ValueTracking.h | 18 | ||||
-rw-r--r-- | include/llvm/Constants.h | 36 | ||||
-rw-r--r-- | lib/Analysis/ConstantFolding.cpp | 6 | ||||
-rw-r--r-- | lib/Analysis/ValueTracking.cpp | 179 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 3 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 26 | ||||
-rw-r--r-- | lib/Bitcode/Writer/ValueEnumerator.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 33 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 17 | ||||
-rw-r--r-- | lib/Target/CBackend/CBackend.cpp | 74 | ||||
-rw-r--r-- | lib/Target/CppBackend/CPPBackend.cpp | 47 | ||||
-rw-r--r-- | lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/Scalar/SimplifyLibCalls.cpp | 116 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 29 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 196 | ||||
-rw-r--r-- | lib/VMCore/Core.cpp | 4 | ||||
-rw-r--r-- | lib/VMCore/IRBuilder.cpp | 2 | ||||
-rw-r--r-- | tools/bugpoint/Miscompilation.cpp | 3 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 4 |
19 files changed, 531 insertions, 268 deletions
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 25150cdb0f..300f51df37 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -17,13 +17,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/DataTypes.h" +#include <string> namespace llvm { + template <typename T> class SmallVectorImpl; class Value; class Instruction; class APInt; class TargetData; - class StringRef; /// ComputeMaskedBits - Determine which of the bits specified in Mask are /// known to be either zero or one and return them in the KnownZero/KnownOne @@ -124,13 +125,16 @@ namespace llvm { return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); } - /// getConstantStringInfo - This function computes the length of a + /// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true - /// and returns the string in Str. If unsuccessful, it returns false. This - /// does not include the trailing nul character. - bool getConstantStringInfo(const Value *V, StringRef &Str, - uint64_t Offset = 0); - + /// and returns the string in Str. If unsuccessful, it returns false. If + /// StopAtNul is set to true (the default), the returned string is truncated + /// by a nul character in the global. If StopAtNul is false, the nul + /// character is included in the result string. + bool GetConstantStringInfo(const Value *V, std::string &Str, + uint64_t Offset = 0, + bool StopAtNul = true); + /// GetStringLength - If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. uint64_t GetStringLength(Value *V); diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index a4723d37f0..43f625a68f 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -352,6 +352,17 @@ public: // ConstantArray accessors static Constant *get(ArrayType *T, ArrayRef<Constant*> V); + /// This method constructs a ConstantArray and initializes it with a text + /// string. The default behavior (AddNull==true) causes a null terminator to + /// be placed at the end of the array. This effectively increases the length + /// of the array by one (you've been warned). However, in some situations + /// this is not desired so if AddNull==false then the string is copied without + /// null termination. + + // FIXME Remove this. + static Constant *get(LLVMContext &Context, StringRef Initializer, + bool AddNull = true); + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -362,6 +373,31 @@ public: return reinterpret_cast<ArrayType*>(Value::getType()); } + // FIXME: String methods will eventually be removed. + + + /// isString - This method returns true if the array is an array of i8 and + /// the elements of the array are all ConstantInt's. + bool isString() const; + + /// isCString - This method returns true if the array is a string (see + /// @verbatim + /// isString) and it ends in a null byte \0 and does not contains any other + /// @endverbatim + /// null bytes except its terminator. + bool isCString() const; + + /// getAsString - If this array is isString(), then this method converts the + /// array to an std::string and returns it. Otherwise, it asserts out. + /// + std::string getAsString() const; + + /// getAsCString - If this array is isCString(), then this method converts the + /// array (without the trailing null byte) to an std::string and returns it. + /// Otherwise, it asserts out. + /// + std::string getAsCString() const; + virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 48e75a1d5d..121e334c4c 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -476,9 +476,9 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, // Instead of loading constant c string, use corresponding integer value // directly if string length is small enough. - StringRef Str; - if (TD && getConstantStringInfo(CE, Str) && !Str.empty()) { - unsigned StrLen = Str.size(); + std::string Str; + if (TD && GetConstantStringInfo(CE, Str) && !Str.empty()) { + unsigned StrLen = Str.length(); Type *Ty = cast<PointerType>(CE->getType())->getElementType(); unsigned NumBits = Ty->getPrimitiveSizeInBits(); // Replace load with immediate integer if the result is an integer or fp diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 4c18bdf1e5..6403f03b01 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -1369,21 +1369,25 @@ Value *llvm::isBytewiseValue(Value *V) { } } - // A ConstantDataArray/Vector is splatable if all its members are equal and - // also splatable. - if (ConstantDataSequential *CA = dyn_cast<ConstantDataSequential>(V)) { - Value *Elt = CA->getElementAsConstant(0); - Value *Val = isBytewiseValue(Elt); + // A ConstantArray is splatable if all its members are equal and also + // splatable. + if (ConstantArray *CA = dyn_cast<ConstantArray>(V)) { + if (CA->getNumOperands() == 0) + return 0; + + Value *Val = isBytewiseValue(CA->getOperand(0)); if (!Val) return 0; - for (unsigned I = 1, E = CA->getNumElements(); I != E; ++I) - if (CA->getElementAsConstant(I) != Elt) + for (unsigned I = 1, E = CA->getNumOperands(); I != E; ++I) + if (CA->getOperand(I-1) != CA->getOperand(I)) return 0; return Val; } + // FIXME: Vector types (e.g., <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>). + // Conceptually, we could handle things like: // %a = zext i8 %X to i16 // %b = shl i16 %a, 8 @@ -1603,19 +1607,33 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, } -/// getConstantStringInfo - This function computes the length of a +/// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true /// and returns the string in Str. If unsuccessful, it returns false. -bool llvm::getConstantStringInfo(const Value *V, StringRef &Str, - uint64_t Offset) { - assert(V); - - // Look through bitcast instructions and geps. - V = V->stripPointerCasts(); +bool llvm::GetConstantStringInfo(const Value *V, std::string &Str, + uint64_t Offset, bool StopAtNul) { + // If V is NULL then return false; + if (V == NULL) return false; + + // Look through bitcast instructions. + if (const BitCastInst *BCI = dyn_cast<BitCastInst>(V)) + return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); - // If the value is a GEP instructionor constant expression, treat it as an - // offset. - if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way. + const User *GEP = 0; + if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) { + GEP = GEPI; + } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { + if (CE->getOpcode() == Instruction::BitCast) + return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); + if (CE->getOpcode() != Instruction::GetElementPtr) + return false; + GEP = CE; + } + + if (GEP) { // Make sure the GEP has exactly three arguments. if (GEP->getNumOperands() != 3) return false; @@ -1640,45 +1658,51 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str, StartIdx = CI->getZExtValue(); else return false; - return getConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset); + return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, + StopAtNul); } // The GEP instruction, constant or instruction, must reference a global // variable that is a constant and is initialized. The referenced constant // initializer is the array that we'll use for optimization. - const GlobalVariable *GV = dyn_cast<GlobalVariable>(V); + const GlobalVariable* GV = dyn_cast<GlobalVariable>(V); if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) return false; - + const Constant *GlobalInit = GV->getInitializer(); + // Handle the all-zeros case - if (GV->getInitializer()->isNullValue()) { + if (GlobalInit->isNullValue()) { // This is a degenerate case. The initializer is constant zero so the // length of the string must be zero. - Str = ""; + Str.clear(); return true; } // Must be a Constant Array - const ConstantDataArray *Array = - dyn_cast<ConstantDataArray>(GV->getInitializer()); - if (Array == 0 || !Array->isString()) + const ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit); + if (Array == 0 || !Array->getType()->getElementType()->isIntegerTy(8)) return false; // Get the number of elements in the array - uint64_t NumElts = Array->getType()->getArrayNumElements(); - - // Start out with the entire array in the StringRef. - Str = Array->getAsString(); - + uint64_t NumElts = Array->getType()->getNumElements(); + if (Offset > NumElts) return false; - // Skip over 'offset' bytes. - Str = Str.substr(Offset); - // Trim off the \0 and anything after it. If the array is not nul terminated, - // we just return the whole end of string. The client may know some other way - // that the string is length-bound. - Str = Str.substr(0, Str.find('\0')); + // Traverse the constant array from 'Offset' which is the place the GEP refers + // to in the array. + Str.reserve(NumElts-Offset); + for (unsigned i = Offset; i != NumElts; ++i) { + const Constant *Elt = Array->getOperand(i); + const ConstantInt *CI = dyn_cast<ConstantInt>(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return false; + if (StopAtNul && CI->isZero()) + return true; // we found end of string, success! + Str += (char)CI->getZExtValue(); + } + + // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. return true; } @@ -1690,7 +1714,8 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str, /// the specified pointer, return 'len+1'. If we can't, return 0. static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) { // Look through noop bitcast instructions. - V = V->stripPointerCasts(); + if (BitCastInst *BCI = dyn_cast<BitCastInst>(V)) + return GetStringLengthH(BCI->getOperand(0), PHIs); // If this is a PHI node, there are two cases: either we have already seen it // or we haven't. @@ -1726,13 +1751,83 @@ static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) { if (Len1 != Len2) return 0; return Len1; } - - // Otherwise, see if we can read the string. - StringRef StrData; - if (!getConstantStringInfo(V, StrData)) + + // As a special-case, "@string = constant i8 0" is also a string with zero + // length, not wrapped in a bitcast or GEP. + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + if (GV->getInitializer()->isNullValue()) return 1; + return 0; + } + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return unknown. + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { + if (CE->getOpcode() != Instruction::GetElementPtr) + return 0; + GEP = CE; + } else { return 0; + } + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return 0; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(1))) { + if (!Idx->isZero()) + return 0; + } else + return 0; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return 0; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer() || + GV->mayBeOverridden()) + return 0; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case, which is a degenerate case. The + // initializer is constant zero so the length of the string must be zero. + if (isa<ConstantAggregateZero>(GlobalInit)) + return 1; // Len = 0 offset by 1. + + // Must be a Constant Array + ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit); + if (!Array || !Array->getType()->getElementType()->isIntegerTy(8)) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + // Traverse the constant array from StartIdx (derived above) which is + // the place the GEP refers to in the array. + for (unsigned i = StartIdx; i != NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast<ConstantInt>(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return 0; + if (CI->isZero()) + return i-StartIdx+1; // We found end of string, success! + } - return StrData.size()+1; + return 0; // The array isn't null terminated, conservatively return 'unknown'. } /// GetStringLength - If we can compute the length of the string pointed to by diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 24ef216a6d..efd48e1c14 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2018,8 +2018,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { } case lltok::kw_c: // c "foo" Lex.Lex(); - ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(), - false); + ID.ConstantVal = ConstantArray::get(Context, Lex.getStrVal(), false); if (ParseToken(lltok::StringConstant, "expected string")) return true; ID.Kind = ValID::t_Constant; return false; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 50c990a670..d58f7cf73d 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -845,6 +845,32 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, } else { assert (0 && "Unknown FP type!"); } + } else if (isa<ConstantArray>(C) && cast<ConstantArray>(C)->isString()) { + const ConstantArray *CA = cast<ConstantArray>(C); + // Emit constant strings specially. + unsigned NumOps = CA->getNumOperands(); + // If this is a null-terminated string, use the denser CSTRING encoding. + if (CA->getOperand(NumOps-1)->isNullValue()) { + Code = bitc::CST_CODE_CSTRING; + --NumOps; // Don't encode the null, which isn't allowed by char6. + } else { + Code = bitc::CST_CODE_STRING; + AbbrevToUse = String8Abbrev; + } + bool isCStr7 = Code == bitc::CST_CODE_CSTRING; + bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned char V = cast<ConstantInt>(CA->getOperand(i))->getZExtValue(); + Record.push_back(V); + isCStr7 &= (V & 128) == 0; + if (isCStrChar6) + isCStrChar6 = BitCodeAbbrevOp::isChar6(V); + } + + if (isCStrChar6) + AbbrevToUse = CString6Abbrev; + else if (isCStr7) + AbbrevToUse = CString7Abbrev; } else if (isa<ConstantDataSequential>(C) && cast<ConstantDataSequential>(C)->isString()) { const ConstantDataSequential *Str = cast<ConstantDataSequential>(C); diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 1ed9004eb5..1c4d670b27 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -321,6 +321,10 @@ void ValueEnumerator::EnumerateValue(const Value *V) { if (const Constant *C = dyn_cast<Constant>(V)) { if (isa<GlobalValue>(C)) { // Initializers for globals are handled explicitly elsewhere. + } else if (isa<ConstantArray>(C) && cast<ConstantArray>(C)->isString()) { + // Do not enumerate the initializers for an array of simple characters. + // The initializers just pollute the value table, and we emit the strings + // specially. } else if (C->getNumOperands()) { // If a constant has operands, enumerate them. This makes sure that if a // constant has uses (for example an array of const ints), that they are diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3e7de0afed..4c093665c8 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1675,18 +1675,31 @@ static void EmitGlobalConstantDataSequential(const ConstantDataSequential *CDS, static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, AsmPrinter &AP) { - // See if we can aggregate some values. Make sure it can be - // represented as a series of bytes of the constant value. - int Value = isRepeatedByteSequence(CA, AP.TM); + if (AddrSpace != 0 || !CA->isString()) { + // Not a string. Print the values in successive locations. - if (Value != -1) { - uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); - AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); - } - else { - for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) - EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + // See if we can aggregate some values. Make sure it can be + // represented as a series of bytes of the constant value. + int Value = isRepeatedByteSequence(CA, AP.TM); + + if (Value != -1) { + uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); + AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); + } + else { + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + } + return; } + + // Otherwise, it can be emitted as .ascii. + SmallVector<char, 128> TmpVec; + TmpVec.reserve(CA->getNumOperands()); + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + TmpVec.push_back(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); + + AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace); } static void EmitGlobalConstantVector(const ConstantVector *CV, diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index fe1a86131c..18de13dc0a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3299,7 +3299,7 @@ static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG, /// string ptr. static SDValue getMemsetStringVal(EVT VT, DebugLoc dl, SelectionDAG &DAG, const TargetLowering &TLI, - StringRef Str, unsigned Offset) { + std::string &Str, unsigned Offset) { // Handle vector with all elements zero. if (Str.empty()) { if (VT.isInteger()) @@ -3323,10 +3323,7 @@ static SDValue getMemsetStringVal(EVT VT, DebugLoc dl, SelectionDAG &DAG, if (TLI.isLittleEndian()) Offset = Offset + MSB - 1; for (unsigned i = 0; i != MSB; ++i) { - Val = (Val << 8); - - if (Offset < Str.size()) - Val |= (unsigned char)Str[Offset]; + Val = (Val << 8) | (unsigned char)Str[Offset]; Offset += TLI.isLittleEndian() ? -1 : 1; } return DAG.getConstant(Val, VT); @@ -3343,7 +3340,7 @@ static SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, /// isMemSrcFromString - Returns true if memcpy source is a string constant. /// -static bool isMemSrcFromString(SDValue Src, StringRef &Str) { +static bool isMemSrcFromString(SDValue Src, std::string &Str) { unsigned SrcDelta = 0; GlobalAddressSDNode *G = NULL; if (Src.getOpcode() == ISD::GlobalAddress) @@ -3357,9 +3354,9 @@ static bool isMemSrcFromString(SDValue Src, StringRef &Str) { if (!G) return false; - if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal())) - if (getConstantStringInfo(GV, Str, SrcDelta)) - return true; + const GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal()); + if (GV && GetConstantStringInfo(GV, Str, SrcDelta, false)) + return true; return false; } @@ -3464,7 +3461,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, unsigned SrcAlign = DAG.InferPtrAlignment(Src); if (Align > SrcAlign) SrcAlign = Align; - StringRef Str; + std::string Str; bool CopyFromStr = isMemSrcFromString(Src, Str); bool isZeroStr = CopyFromStr && Str.empty(); unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemcpy(OptSize); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 67d06faa99..8c83bc349a 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -558,21 +558,73 @@ raw_ostream &CWriter::printType(raw_ostream &Out, Type *Ty, } void CWriter::printConstantArray(ConstantArray *CPA, bool Static) { - Out << "{ "; - printConstant(cast<Constant>(CPA->getOperand(0)), Static); - for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) { - Out << ", "; - printConstant(cast<Constant>(CPA->getOperand(i)), 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 (CPA->isCString()) { + Out << '\"'; + // Keep track of whether the last number was a hexadecimal escape. + bool LastWasHex = false; + + // Do not include the last character, which we know is null + for (unsigned i = 0, e = CPA->getNumOperands()-1; i != e; ++i) { + unsigned char C = cast<ConstantInt>(CPA->getOperand(i))->getZExtValue(); + + // 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 << '{'; + if (CPA->getNumOperands()) { + Out << ' '; + printConstant(cast<Constant>(CPA->getOperand(0)), Static); + for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast<Constant>(CPA->getOperand(i)), Static); + } + } + Out << " }"; } - Out << " }"; } void CWriter::printConstantVector(ConstantVector *CP, bool Static) { - Out << "{ "; - printConstant(cast<Constant>(CP->getOperand(0)), Static); - for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { - Out << ", "; - printConstant(cast<Constant>(CP->getOperand(i)), Static); + Out << '{'; + if (CP->getNumOperands()) { + Out << ' '; + printConstant(cast<Constant>(CP->getOperand(0)), Static); + for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast<Constant>(CP->getOperand(i)), Static); + } } Out << " }"; } diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 539da58ae3..de73a72ac4 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -698,17 +698,36 @@ void CppWriter::printConstant(const Constant *CV) { printCFP(CFP); Out << ";"; } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { - Out << "std::vector<Constant*> " << constName << "_elems;"; - nl(Out); - unsigned N = CA->getNumOperands(); - for (unsigned i = 0; i < N; ++i) { - printConstant(CA->getOperand(i)); // recurse to print operands - Out << constName << "_elems.push_back(" - << getCppName(CA->getOperand(i)) << ");"; + if (CA->isString()) { + Out << "Constant* " << constName << + " = ConstantArray::get(mod->getContext(), \""; + std::string tmp = CA->getAsString(); + bool nullTerminate = false; + if (tmp[tmp.length()-1] == 0) { + tmp.erase(tmp.length()-1); + nullTerminate = true; + } + printEscapedString(tmp); + // Determine if we want null termination or not. + if (nullTerminate) + Out << "\", true"; // Indicate that the null terminator should be + // added. + else + Out << "\", false";// No null terminator + Out << ");"; + } else { + Out << "std::vector<Constant*> " << constName << "_elems;"; nl(Out); + unsigned N = CA->getNumOperands(); + for (unsigned i = 0; i < N; ++i) { + printConstant(CA->getOperand(i)); // recurse to print operands + Out << constName << "_elems.push_back(" + << getCppName(CA->getOperand(i)) << ");"; + nl(Out); + } + Out << "Constant* " << constName << " = ConstantArray::get(" + << typeName << ", " << constName << "_elems);"; } - Out << "Constant* " << constName << " = ConstantArray::get(" - << typeName << ", " << constName << "_elems);"; } else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) { Out << "std::vector<Constant*> " << constName << "_fields;"; nl(Out); @@ -721,14 +740,14 @@ void CppWriter::printConstant(const Constant *CV) { } Out << "Constant* " << constName << " = ConstantStruct::get(" << typeName << ", " << constName << "_fields);"; - } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(CV)) { + } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) { Out << "std::vector<Constant*> " << constName << "_elems;"; nl(Out); - unsigned N = CV->getNumOperands(); + unsigned N = CP->getNumOperands(); for (unsigned i = 0; i < N; ++i) { - printConstant(CV->getOperand(i)); + printConstant(CP->getOperand(i)); Out << constName << "_elems.push_back(" - << getCppName(CV->getOperand(i)) << ");"; + << getCppName(CP->getOperand(i)) << ");"; nl(Out); } Out << "Constant* " << constName << " = ConstantVector::get(" @@ -741,7 +760,7 @@ void CppWriter::printConstant(const Constant *CV) { if (CDS->isString()) { Out << "Constant *" << constName << " = ConstantDataArray::getString(mod->getContext(), \""; - StringRef Str = CDS->getAsString(); + StringRef Str = CA->getAsString(); bool nullTerminate = false; if (Str.back() == 0) { Str = Str.drop_back(); diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index b8ead89a8f..c6386009ef 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -213,7 +213,7 @@ const char *AddressSanitizer::getPassName() const { // Create a constant for Str so that we can pass it to the run-time lib. static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { - Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); + Constant *StrConst = ConstantArray::get(M.getContext(), Str); return new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 9c49ec1c84..dcfcf1a876 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -256,18 +256,19 @@ struct StrChrOpt : public LibCallOptimization { ConstantInt::get(TD->getIntPtrType(*Context), Len), B, TD); } - + // Otherwise, the character is a constant, see if the first argument is // a string literal. If so, we can constant fold. - StringRef Str; - if (!getConstantStringInfo(SrcStr, Str)) + std::string Str; + if (!GetConstantStringInfo(SrcStr, Str)) return 0; - // Compute the offset, make sure to handle the case when we're searching for - // zero (a weird way to spell strlen). - size_t I = CharC->getSExtValue() == 0 ? - Str.size() : Str.find(CharC->getSExtValue()); - if (I == StringRef::npos) // Didn't find the char. strchr returns null. + // strchr can find the nul character. + Str += '\0'; |