diff options
-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'; + + // Compute the offset. + size_t I = Str.find(CharC->getSExtValue()); + if (I == std::string::npos) // Didn't find the char. strchr returns null. return Constant::getNullValue(CI->getType()); // strchr(s+n,c) -> gep(s+n+i,c) @@ -295,18 +296,20 @@ struct StrRChrOpt : public LibCallOptimization { if (!CharC) return 0; - StringRef Str; - if (!getConstantStringInfo(SrcStr, Str)) { + std::string Str; + if (!GetConstantStringInfo(SrcStr, Str)) { // strrchr(s, 0) -> strchr(s, 0) if (TD && CharC->isZero()) return EmitStrChr(SrcStr, '\0', B, TD); return 0; } + // strrchr can find the nul character. + Str += '\0'; + // Compute the offset. - size_t I = CharC->getSExtValue() == 0 ? - Str.size() : Str.rfind(CharC->getSExtValue()); - if (I == StringRef::npos) // Didn't find the char. Return null. + size_t I = Str.rfind(CharC->getSExtValue()); + if (I == std::string::npos) // Didn't find the char. Return null. return Constant::getNullValue(CI->getType()); // strrchr(s+n,c) -> gep(s+n+i,c) @@ -331,13 +334,14 @@ struct StrCmpOpt : public LibCallOptimization { if (Str1P == Str2P) // strcmp(x,x) -> 0 return ConstantInt::get(CI->getType(), 0); - StringRef Str1, Str2; - bool HasStr1 = getConstantStringInfo(Str1P, Str1); - bool HasStr2 = getConstantStringInfo(Str2P, Str2); + std::string Str1, Str2; + bool HasStr1 = GetConstantStringInfo(Str1P, Str1); + bool HasStr2 = GetConstantStringInfo(Str2P, Str2); // strcmp(x, y) -> cnst (if both x and y are constant strings) if (HasStr1 && HasStr2) - return ConstantInt::get(CI->getType(), Str1.compare(Str2)); + return ConstantInt::get(CI->getType(), + StringRef(Str1).compare(Str2)); if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x return B.CreateNeg(B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), @@ -393,14 +397,14 @@ struct StrNCmpOpt : public LibCallOptimization { if (TD && Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1) return EmitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, TD); - StringRef Str1, Str2; - bool HasStr1 = getConstantStringInfo(Str1P, Str1); - bool HasStr2 = getConstantStringInfo(Str2P, Str2); + std::string Str1, Str2; + bool HasStr1 = GetConstantStringInfo(Str1P, Str1); + bool HasStr2 = GetConstantStringInfo(Str2P, Str2); // strncmp(x, y) -> cnst (if both x and y are constant strings) if (HasStr1 && HasStr2) { - StringRef SubStr1 = Str1.substr(0, Length); - StringRef SubStr2 = Str2.substr(0, Length); + StringRef SubStr1 = StringRef(Str1).substr(0, Length); + StringRef SubStr2 = StringRef(Str2).substr(0, Length); return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2)); } @@ -545,9 +549,9 @@ struct StrPBrkOpt : public LibCallOptimization { FT->getReturnType() != FT->getParamType(0)) return 0; - StringRef S1, S2; - bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1); - bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2); + std::string S1, S2; + bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1); + bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2); // strpbrk(s, "") -> NULL // strpbrk("", s) -> NULL @@ -605,9 +609,9 @@ struct StrSpnOpt : public LibCallOptimization { !FT->getReturnType()->isIntegerTy()) return 0; - StringRef S1, S2; - bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1); - bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2); + std::string S1, S2; + bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1); + bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2); // strspn(s, "") -> 0 // strspn("", s) -> 0 @@ -615,11 +619,8 @@ struct StrSpnOpt : public LibCallOptimization { return Constant::getNullValue(CI->getType()); // Constant folding. - if (HasS1 && HasS2) { - size_t Pos = S1.find_first_not_of(S2); - if (Pos == StringRef::npos) Pos = S1.size(); - return ConstantInt::get(CI->getType(), Pos); - } + if (HasS1 && HasS2) + return ConstantInt::get(CI->getType(), strspn(S1.c_str(), S2.c_str())); return 0; } @@ -637,20 +638,17 @@ struct StrCSpnOpt : public LibCallOptimization { !FT->getReturnType()->isIntegerTy()) return 0; - StringRef S1, S2; - bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1); - bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2); + std::string S1, S2; + bool HasS1 = GetConstantStringInfo(CI->getArgOperand(0), S1); + bool HasS2 = GetConstantStringInfo(CI->getArgOperand(1), S2); // strcspn("", s) -> 0 if (HasS1 && S1.empty()) return Constant::getNullValue(CI->getType()); // Constant folding. - if (HasS1 && HasS2) { - size_t Pos = S1.find_first_of(S2); - if (Pos == StringRef::npos) Pos = S1.size(); - return ConstantInt::get(CI->getType(), Pos); - } + if (HasS1 && HasS2) + return ConstantInt::get(CI->getType(), strcspn(S1.c_str(), S2.c_str())); // strcspn(s, "") -> strlen(s) if (TD && HasS2 && S2.empty()) @@ -694,9 +692,9 @@ struct StrStrOpt : public LibCallOptimization { } // See if either input string is a constant string. - StringRef SearchStr, ToFindStr; - bool HasStr1 = getConstantStringInfo(CI->getArgOperand(0), SearchStr); - bool HasStr2 = getConstantStringInfo(CI->getArgOperand(1), ToFindStr); + std::string SearchStr, ToFindStr; + bool HasStr1 = GetConstantStringInfo(CI->getArgOperand(0), SearchStr); + bool HasStr2 = GetConstantStringInfo(CI->getArgOperand(1), ToFindStr); // fold strstr(x, "") -> x. if (HasStr2 && ToFindStr.empty()) @@ -706,7 +704,7 @@ struct StrStrOpt : public LibCallOptimization { if (HasStr1 && HasStr2) { std::string::size_type Offset = SearchStr.find(ToFindStr); - if (Offset == StringRef::npos) // strstr("foo", "bar") -> null + if (Offset == std::string::npos) // strstr("foo", "bar") -> null return Constant::getNullValue(CI->getType()); // strstr("abcd", "bc") -> gep((char*)"abcd", 1) @@ -758,11 +756,11 @@ struct MemCmpOpt : public LibCallOptimization { } // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) - StringRef LHSStr, RHSStr; - if (getConstantStringInfo(LHS, LHSStr) && - getConstantStringInfo(RHS, RHSStr)) { + std::string LHSStr, RHSStr; + if (GetConstantStringInfo(LHS, LHSStr) && + GetConstantStringInfo(RHS, RHSStr)) { // Make sure we're not reading out-of-bounds memory. - if (Len > LHSStr.size() || Len > RHSStr.size()) + if (Len > LHSStr.length() || Len > RHSStr.length()) return 0; uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); return ConstantInt::get(CI->getType(), Ret); @@ -1118,8 +1116,8 @@ struct PrintFOpt : public LibCallOptimization { Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Check for a fixed format string. - StringRef FormatStr; - if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr)) + std::string FormatStr; + if (!GetConstantStringInfo(CI->getArgOperand(0), FormatStr)) return 0; // Empty format string -> noop. @@ -1145,7 +1143,7 @@ struct PrintFOpt : public LibCallOptimization { FormatStr.find('%') == std::string::npos) { // no format characters. // Create a string literal with no \n on it. We expect the constant merge // pass to be run after this pass, to merge duplicate strings. - FormatStr = FormatStr.drop_back(); + FormatStr.erase(FormatStr.end()-1); Value *GV = B.CreateGlobalString(FormatStr, "str"); EmitPutS(GV, B, TD); return CI->use_empty() ? (Value*)CI : @@ -1205,8 +1203,8 @@ struct SPrintFOpt : public LibCallOptimization { Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Check for a fixed format string. - StringRef FormatStr; - if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr)) + std::string FormatStr; + if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr)) return 0; // If we just have a format string (nothing else crazy) transform it. @@ -1360,8 +1358,8 @@ struct FPrintFOpt : public LibCallOptimization { Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, IRBuilder<> &B) { // All the optimizations depend on the format string. - StringRef FormatStr; - if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr)) + std::string FormatStr; + if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr)) return 0; // fprintf(F, "foo") --> fwrite("foo", 3, 1, F) @@ -1444,8 +1442,8 @@ struct PutsOpt : public LibCallOptimization { return 0; // Check for a constant string. - StringRef Str; - if (!getConstantStringInfo(CI->getArgOperand(0), Str)) + std::string Str; + if (!GetConstantStringInfo(CI->getArgOperand(0), Str)) return 0; if (Str.empty() && CI->use_empty()) { @@ -2415,8 +2413,6 @@ bool SimplifyLibCalls::doInitialization(Module &M) { // * stpcpy(str, "literal") -> // llvm.memcpy(str,"literal",strlen("literal")+1,1) // -// strchr: -// * strchr(p, 0) -> strlen(p) // tan, tanf, tanl: // * tan(atan(x)) -> x // diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 1dd1254f65..eb0f66196d 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -827,21 +827,30 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { + // As a special case, print the array as a string if it is an array of + // i8 with ConstantInt values. + // Type *ETy = CA->getType()->getElementType(); - Out << '['; - TypePrinter.print(ETy, Out); - Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(0), - &TypePrinter, Machine, - Context); - for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { - Out << ", "; + if (CA->isString()) { + Out << "c\""; + PrintEscapedString(CA->getAsString(), Out); + Out << '"'; + } else { // Cannot output in string format... + Out << '['; TypePrinter.print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine, + WriteAsOperandInternal(Out, CA->getOperand(0), + &TypePrinter, Machine, Context); + for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { + Out << ", "; + TypePrinter.print(ETy, Out); + Out << ' '; + WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine, + Context); + } + Out << ']'; } - Out << ']'; return; } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 7d423c04a6..f7884c6862 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -176,7 +176,7 @@ Constant *Constant::getAggregateElement(unsigned Elt) const { return UV->getElementValue(Elt); if (const ConstantDataSequential *CDS =dyn_cast<ConstantDataSequential>(this)) - return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt) : 0; + return CDS->getElementAsConstant(Elt); return 0; } @@ -666,13 +666,6 @@ UndefValue *UndefValue::getElementValue(unsigned Idx) const { // ConstantXXX Classes //===----------------------------------------------------------------------===// -template <typename ItTy, typename EltTy> -static bool rangeOnlyContains(ItTy Start, ItTy End, EltTy Elt) { - for (; Start != End; ++Start) - if (*Start != Elt) - return false; - return true; -} ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) : Constant(T, ConstantArrayVal, @@ -687,97 +680,54 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { - // Empty arrays are canonicalized to ConstantAggregateZero. - if (V.empty()) - return ConstantAggregateZero::get(Ty); - for (unsigned i = 0, e = V.size(); i != e; ++i) { assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer"); } LLVMContextImpl *pImpl = Ty->getContext().pImpl; - - // If this is an all-zero array, return a ConstantAggregateZero object. If - // all undef, return an UndefValue, if "all simple", then return a - // ConstantDataArray. - Constant *C = V[0]; - if (isa<UndefValue>(C) && rangeOnlyContains(V.begin(), V.end(), C)) - return UndefValue::get(Ty); + // If this is an all-zero array, return a ConstantAggregateZero object + bool isAllZero = true; + bool isUndef = false; + if (!V.empty()) { + Constant *C = V[0]; + isAllZero = C->isNullValue(); + isUndef = isa<UndefValue>(C); + + if (isAllZero || isUndef) + for (unsigned i = 1, e = V.size(); i != e; ++i) + if (V[i] != C) { + isAllZero = false; + isUndef = false; + break; + } + } - if (C->isNullValue() && rangeOnlyContains(V.begin(), V.end(), C)) + if (isAllZero) return ConstantAggregateZero::get(Ty); + if (isUndef) + return UndefValue::get(Ty); + return pImpl->ArrayConstants.getOrCreate(Ty, V); +} - // Check to see if all of the elements are ConstantFP or ConstantInt and if - // the element type is compatible with ConstantDataVector. If so, use it. - if (ConstantDataSequential::isElementTypeCompatible(C->getType())) { - // We speculatively build the elements here even if it turns out that there - // is a constantexpr or something else weird in the array, since it is so - // uncommon for that to happen. - if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) { - if (CI->getType()->isIntegerTy(8)) { - SmallVector<uint8_t, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) - Elts.push_back(CI->getZExtValue()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } else if (CI->getType()->isIntegerTy(16)) { - SmallVector<uint16_t, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) - Elts.push_back(CI->getZExtValue()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } else if (CI->getType()->isIntegerTy(32)) { - SmallVector<uint32_t, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) - Elts.push_back(CI->getZExtValue()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } else if (CI->getType()->isIntegerTy(64)) { - SmallVector<uint64_t, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantInt *CI = dyn_cast<ConstantInt>(V[i])) - Elts.push_back(CI->getZExtValue()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } - } - - if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { - if (CFP->getType()->isFloatTy()) { - SmallVector<float, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToFloat()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } else if (CFP->getType()->isDoubleTy()) { - SmallVector<double, 16> Elts; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToDouble()); - else - break; - if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); - } - } - } +/// ConstantArray::get(const string&) - Return an array that is initialized to +/// contain the specified string. If length is zero then a null terminator is +/// added to the specified string so that it may be used in a natural way. +/// Otherwise, the length parameter specifies how much of the string to use +/// and it won't be null terminated. +/// +Constant *ConstantArray::get(LLVMContext &Context, StringRef Str, + bool AddNull) { + SmallVector<Constant*, 8> ElementVals; + ElementVals.reserve(Str.size() + size_t(AddNull)); + for (unsigned i = 0; i < Str.size(); ++i) + ElementVals.push_back(ConstantInt::get(Type::getInt8Ty(Context), Str[i])); - // Otherwise, we really do want to create a ConstantArray. - return pImpl->ArrayConstants.getOrCreate(Ty, V); + // Add a null terminator to the string... + if (AddNull) + ElementVals.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0)); + + ArrayType *ATy = ArrayType::get(Type::getInt8Ty(Context), ElementVals.size()); + return get(ATy, ElementVals); } /// getTypeForElements - Return an anonymous struct type to use for a constant @@ -889,7 +839,8 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { // Check to see if all of the elements are ConstantFP or ConstantInt and if // the element type is compatible with ConstantDataVector. If so, use it. - if (ConstantDataSequential::isElementTypeCompatible(C->getType())) { + if (ConstantDataSequential::isElementTypeCompatible(C->getType()) && + (isa<ConstantFP>(C) || isa<ConstantInt>(C))) { // We speculatively build the elements here even if it turns out that there // is a constantexpr or something else weird in the array, since it is so // uncommon for that to happen. @@ -1195,6 +1146,69 @@ void ConstantArray::destroyConstant() { destroyConstantImpl(); } +/// isString - This method returns true if the array is an array of i8, and +/// if the elements of the array are all ConstantInt's. +bool ConstantArray::isString() const { + // Check the element type for i8... + if (!getType()->getElementType()->isIntegerTy(8)) + return false; + // Check the elements to make sure they are all integers, not constant + // expressions. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!isa<ConstantInt>(getOperand(i))) + return false; + return true; +} + +/// isCString - This method returns true if the array is a string (see +/// isString) and it ends in a null byte \\0 and does not contains any other +/// null bytes except its terminator. +bool ConstantArray::isCString() const { + // Check the element type for i8... + if (!getType()->getElementType()->isIntegerTy(8)) + return false; + + // Last element must be a null. + if (!getOperand(getNumOperands()-1)->isNullValue()) + return false; + // Other elements must be non-null integers. + for (unsigned i = 0, e = getNumOperands()-1; i != e; ++i) { + if (!isa<ConstantInt>(getOperand(i))) + return false; + if (getOperand(i)->isNullValue()) + return false; + } + return true; +} + + +/// convertToString - Helper function for getAsString() and getAsCString(). +static std::string convertToString(const User *U, unsigned len) { + std::string Result; + Result.reserve(len); + for (unsigned i = 0; i != len; ++i) + Result.push_back((char)cast<ConstantInt>(U->getOperand(i))->getZExtValue()); + return Result; +} + +/// 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 ConstantArray::getAsString() const { + assert(isString() && "Not a string!"); + return convertToString(this, getNumOperands()); +} + + +/// 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 ConstantArray::getAsCString() const { + assert(isCString() && "Not a string!"); + return convertToString(this, getNumOperands() - 1); +} + //---- ConstantStruct::get() implementation... // diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index c376546521..ea4e95205b 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -634,8 +634,8 @@ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, LLVMBool DontNullTerminate) { /* Inverted the sense of AddNull because ', 0)' is a better mnemonic for null termination than ', 1)'. */ - return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), - DontNullTerminate == 0)); + return wrap(ConstantArray::get(*unwrap(C), StringRef(Str, Length), + DontNullTerminate == 0)); } LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, LLVMValueRef *ConstantVals, diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp index b45923489a..0994394aef 100644 --- a/lib/VMCore/IRBuilder.cpp +++ b/lib/VMCore/IRBuilder.cpp @@ -24,7 +24,7 @@ using namespace llvm; /// specified. If Name is specified, it is the name of the global variable /// created. Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { - Constant *StrConstant = ConstantDataArray::getString(Context, Str); + Constant *StrConstant = ConstantArray::get(Context, Str, true); Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), true, GlobalValue::PrivateLinkage, diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 82a3a862a2..7ff16dbf95 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -820,8 +820,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file - Constant *InitArray = - ConstantDataArray::getString(F->getContext(), F->getName()); + Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); GlobalVariable *funcName = new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 8ce8cd2f1a..af5a0a66f5 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -190,9 +190,9 @@ bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { Constant *op = ce->getOperand(0); if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { Constant *cn = gvn->getInitializer(); - if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) { + if (ConstantArray *ca = dyn_cast<ConstantArray>(cn)) { if (ca->isCString()) { - name = ".objc_class_name_" + ca->getAsCString().str(); + name = ".objc_class_name_" + ca->getAsCString(); return true; } } |