diff options
Diffstat (limited to 'include/llvm/Analysis')
| -rw-r--r-- | include/llvm/Analysis/AliasAnalysis.h | 21 | ||||
| -rw-r--r-- | include/llvm/Analysis/CFGPrinter.h | 32 | ||||
| -rw-r--r-- | include/llvm/Analysis/CaptureTracking.h | 6 | ||||
| -rw-r--r-- | include/llvm/Analysis/DebugInfo.h | 92 | ||||
| -rw-r--r-- | include/llvm/Analysis/InstructionSimplify.h | 10 | ||||
| -rw-r--r-- | include/llvm/Analysis/LibCallAliasAnalysis.h | 3 | ||||
| -rw-r--r-- | include/llvm/Analysis/LoopInfo.h | 20 | ||||
| -rw-r--r-- | include/llvm/Analysis/MemoryDependenceAnalysis.h | 24 | ||||
| -rw-r--r-- | include/llvm/Analysis/PostDominators.h | 5 | ||||
| -rw-r--r-- | include/llvm/Analysis/ValueTracking.h | 25 |
10 files changed, 150 insertions, 88 deletions
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index be7d5ee37b80..2d43bddf7e0b 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -94,13 +94,12 @@ public: virtual AliasResult alias(const Value *V1, unsigned V1Size, const Value *V2, unsigned V2Size); - /// getMustAliases - If there are any pointers known that must alias this - /// pointer, return them now. This allows alias-set based alias analyses to - /// perform a form a value numbering (which is exposed by load-vn). If an - /// alias analysis supports this, it should ADD any must aliased pointers to - /// the specified vector. - /// - virtual void getMustAliases(Value *P, std::vector<Value*> &RetVals); + /// isNoAlias - A trivial helper function to check to see if the specified + /// pointers are no-alias. + bool isNoAlias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return alias(V1, V1Size, V2, V2Size) == NoAlias; + } /// pointsToConstantMemory - If the specified pointer is known to point into /// constant global memory, return true. This allows disambiguation of store @@ -262,14 +261,6 @@ public: /// virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); - /// hasNoModRefInfoForCalls - Return true if the analysis has no mod/ref - /// information for pairs of function calls (other than "pure" and "const" - /// functions). This can be used by clients to avoid many pointless queries. - /// Remember that if you override this and chain to another analysis, you must - /// make sure that it doesn't have mod/ref info either. - /// - virtual bool hasNoModRefInfoForCalls() const; - public: /// Convenience functions... ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index 440d18267daf..6ad2e5a5b1f9 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -24,23 +24,29 @@ namespace llvm { template<> struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + static std::string getGraphName(const Function *F) { return "CFG for '" + F->getNameStr() + "' function"; } - static std::string getNodeLabel(const BasicBlock *Node, - const Function *Graph, - bool ShortNames) { - if (ShortNames && !Node->getName().empty()) - return Node->getNameStr() + ":"; + static std::string getSimpleNodeLabel(const BasicBlock *Node, + const Function *Graph) { + if (!Node->getName().empty()) + return Node->getNameStr(); std::string Str; raw_string_ostream OS(Str); - if (ShortNames) { - WriteAsOperand(OS, Node, false); - return OS.str(); - } + WriteAsOperand(OS, Node, false); + return OS.str(); + } + + static std::string getCompleteNodeLabel(const BasicBlock *Node, + const Function *Graph) { + std::string Str; + raw_string_ostream OS(Str); if (Node->getName().empty()) { WriteAsOperand(OS, Node, false); @@ -65,6 +71,14 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { return OutStr; } + std::string getNodeLabel(const BasicBlock *Node, + const Function *Graph) { + if (isSimple()) + return getSimpleNodeLabel(Node, Graph); + else + return getCompleteNodeLabel(Node, Graph); + } + static std::string getEdgeSourceLabel(const BasicBlock *Node, succ_const_iterator I) { // Label source of conditional branches with "T" or "F" diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index a0ff503a0393..493ecf517141 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -21,8 +21,12 @@ namespace llvm { /// by the enclosing function (which is required to exist). This routine can /// be expensive, so consider caching the results. The boolean ReturnCaptures /// specifies whether returning the value (or part of it) from the function + /// counts as capturing it or not. The boolean StoreCaptures specified whether + /// storing the value (or part of it) into memory anywhere automatically /// counts as capturing it or not. - bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures); + bool PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, + bool StoreCaptures); } // end namespace llvm diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 3c40d65a485a..866ed8a8757e 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -55,7 +55,7 @@ namespace llvm { /// not, the debug info is corrupt and we ignore it. DIDescriptor(MDNode *N, unsigned RequiredTag); - const char *getStringField(unsigned Elt) const; + StringRef getStringField(unsigned Elt) const; unsigned getUnsignedField(unsigned Elt) const { return (unsigned)getUInt64Field(Elt); } @@ -137,8 +137,8 @@ namespace llvm { } virtual ~DIScope() {} - const char *getFilename() const; - const char *getDirectory() const; + StringRef getFilename() const; + StringRef getDirectory() const; }; /// DICompileUnit - A wrapper for a compile unit. @@ -150,9 +150,9 @@ namespace llvm { } unsigned getLanguage() const { return getUnsignedField(2); } - const char *getFilename() const { return getStringField(3); } - const char *getDirectory() const { return getStringField(4); } - const char *getProducer() const { return getStringField(5); } + StringRef getFilename() const { return getStringField(3); } + StringRef getDirectory() const { return getStringField(4); } + StringRef getProducer() const { return getStringField(5); } /// isMain - Each input file is encoded as a separate compile unit in LLVM /// debugging information output. However, many target specific tool chains @@ -165,7 +165,7 @@ namespace llvm { bool isMain() const { return getUnsignedField(6); } bool isOptimized() const { return getUnsignedField(7); } - const char *getFlags() const { return getStringField(8); } + StringRef getFlags() const { return getStringField(8); } unsigned getRunTimeVersion() const { return getUnsignedField(9); } /// Verify - Verify that a compile unit is well formed. @@ -183,7 +183,7 @@ namespace llvm { explicit DIEnumerator(MDNode *N = 0) : DIDescriptor(N, dwarf::DW_TAG_enumerator) {} - const char *getName() const { return getStringField(1); } + StringRef getName() const { return getStringField(1); } uint64_t getEnumValue() const { return getUInt64Field(2); } }; @@ -217,7 +217,7 @@ namespace llvm { virtual ~DIType() {} DIDescriptor getContext() const { return getDescriptorField(1); } - const char *getName() const { return getStringField(2); } + StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); } unsigned getLineNumber() const { return getUnsignedField(4); } uint64_t getSizeInBits() const { return getUInt64Field(5); } @@ -317,9 +317,9 @@ namespace llvm { virtual ~DIGlobal() {} DIDescriptor getContext() const { return getDescriptorField(2); } - const char *getName() const { return getStringField(3); } - const char *getDisplayName() const { return getStringField(4); } - const char *getLinkageName() const { return getStringField(5); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); } unsigned getLineNumber() const { return getUnsignedField(7); } DIType getType() const { return getFieldAs<DIType>(8); } @@ -342,16 +342,16 @@ namespace llvm { } DIDescriptor getContext() const { return getDescriptorField(2); } - const char *getName() const { return getStringField(3); } - const char *getDisplayName() const { return getStringField(4); } - const char *getLinkageName() const { return getStringField(5); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); } unsigned getLineNumber() const { return getUnsignedField(7); } DICompositeType getType() const { return getFieldAs<DICompositeType>(8); } /// getReturnTypeName - Subprogram return types are encoded either as /// DIType or as DICompositeType. - const char *getReturnTypeName() const { + StringRef getReturnTypeName() const { DICompositeType DCT(getFieldAs<DICompositeType>(8)); if (!DCT.isNull()) { DIArray A = DCT.getTypeArray(); @@ -366,8 +366,8 @@ namespace llvm { /// compile unit, like 'static' in C. unsigned isLocalToUnit() const { return getUnsignedField(9); } unsigned isDefinition() const { return getUnsignedField(10); } - const char *getFilename() const { return getCompileUnit().getFilename();} - const char *getDirectory() const { return getCompileUnit().getDirectory();} + StringRef getFilename() const { return getCompileUnit().getFilename();} + StringRef getDirectory() const { return getCompileUnit().getDirectory();} /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; @@ -406,7 +406,7 @@ namespace llvm { } DIDescriptor getContext() const { return getDescriptorField(1); } - const char *getName() const { return getStringField(2); } + StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); } unsigned getLineNumber() const { return getUnsignedField(4); } DIType getType() const { return getFieldAs<DIType>(5); } @@ -444,8 +444,8 @@ namespace llvm { DbgNode = 0; } DIScope getContext() const { return getFieldAs<DIScope>(1); } - const char *getDirectory() const { return getContext().getDirectory(); } - const char *getFilename() const { return getContext().getFilename(); } + StringRef getDirectory() const { return getContext().getDirectory(); } + StringRef getFilename() const { return getContext().getFilename(); } }; /// DILocation - This object holds location information. This object @@ -458,8 +458,8 @@ namespace llvm { unsigned getColumnNumber() const { return getUnsignedField(1); } DIScope getScope() const { return getFieldAs<DIScope>(2); } DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); } - const char *getFilename() const { return getScope().getFilename(); } - const char *getDirectory() const { return getScope().getDirectory(); } + StringRef getFilename() const { return getScope().getFilename(); } + StringRef getDirectory() const { return getScope().getDirectory(); } }; /// DIFactory - This object assists with the construction of the various @@ -489,26 +489,26 @@ namespace llvm { /// CreateCompileUnit - Create a new descriptor for the specified compile /// unit. DICompileUnit CreateCompileUnit(unsigned LangID, - const char * Filename, - const char * Directory, - const char * Producer, + StringRef Filename, + StringRef Directory, + StringRef Producer, bool isMain = false, bool isOptimized = false, - const char *Flags = "", + StringRef Flags = "", unsigned RunTimeVer = 0); /// CreateEnumerator - Create a single enumerator value. - DIEnumerator CreateEnumerator(const char * Name, uint64_t Val); + DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicType(DIDescriptor Context, const char * Name, + DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, unsigned Encoding); /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicTypeEx(DIDescriptor Context, const char * Name, + DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, Constant *OffsetInBits, unsigned Flags, @@ -517,7 +517,7 @@ namespace llvm { /// CreateDerivedType - Create a derived type like const qualified type, /// pointer, typedef, etc. DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context, - const char * Name, + StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -527,7 +527,7 @@ namespace llvm { /// CreateDerivedType - Create a derived type like const qualified type, /// pointer, typedef, etc. DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context, - const char * Name, + StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, Constant *SizeInBits, Constant *AlignInBits, @@ -536,7 +536,7 @@ namespace llvm { /// CreateCompositeType - Create a composite type like array, struct, etc. DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context, - const char * Name, + StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, uint64_t SizeInBits, @@ -548,7 +548,7 @@ namespace llvm { /// CreateCompositeType - Create a composite type like array, struct, etc. DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, - const char * Name, + StringRef Name, DICompileUnit CompileUnit, unsigned LineNumber, Constant *SizeInBits, @@ -560,25 +560,25 @@ namespace llvm { /// CreateSubprogram - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. - DISubprogram CreateSubprogram(DIDescriptor Context, const char * Name, - const char * DisplayName, - const char * LinkageName, + DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name, + StringRef DisplayName, + StringRef LinkageName, DICompileUnit CompileUnit, unsigned LineNo, DIType Type, bool isLocalToUnit, bool isDefinition); /// CreateGlobalVariable - Create a new descriptor for the specified global. DIGlobalVariable - CreateGlobalVariable(DIDescriptor Context, const char * Name, - const char * DisplayName, - const char * LinkageName, + CreateGlobalVariable(DIDescriptor Context, StringRef Name, + StringRef DisplayName, + StringRef LinkageName, DICompileUnit CompileUnit, unsigned LineNo, DIType Type, bool isLocalToUnit, bool isDefinition, llvm::GlobalVariable *GV); /// CreateVariable - Create a new descriptor for the specified variable. DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, - const char * Name, + StringRef Name, DICompileUnit CompileUnit, unsigned LineNo, DIType Type); @@ -598,6 +598,10 @@ namespace llvm { DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, DIScope S, DILocation OrigLoc); + /// CreateLocation - Creates a debug info location. + DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, + DIScope S, MDNode *OrigLoc = 0); + /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, BasicBlock *InsertAtEnd); @@ -669,6 +673,12 @@ bool getLocationInfo(const Value *V, std::string &DisplayName, DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI, DebugLocTracker &DebugLocInfo); + /// getDISubprogram - Find subprogram that is enclosing this scope. + DISubprogram getDISubprogram(MDNode *Scope); + + /// getDICompositeType - Find underlying composite type. + DICompositeType getDICompositeType(DIType T); + class DebugInfoFinder { public: diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index aa5c0f554bc9..13314e6ea0e5 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -20,6 +20,11 @@ namespace llvm { class Instruction; class Value; class TargetData; + + /// SimplifyAddInst - Given operands for an Add, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const TargetData *TD = 0); /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. @@ -42,6 +47,11 @@ namespace llvm { const TargetData *TD = 0); + /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, + const TargetData *TD = 0); + //=== Helper functions for higher up the class hierarchy. diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index 7944af3b8a5a..01f108d29042 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -49,9 +49,6 @@ namespace llvm { return false; } - /// hasNoModRefInfoForCalls - We can provide mod/ref information against - /// non-escaping allocations. - virtual bool hasNoModRefInfoForCalls() const { return false; } private: ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, CallSite CS, Value *P, unsigned Size); diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 6504bdce4283..9969d999e13e 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -269,8 +269,6 @@ public: /// getLoopLatch - If there is a single latch block for this loop, return it. /// A latch block is a block that contains a branch back to the header. - /// A loop header in normal form has two edges into it: one from a preheader - /// and one from a latch block. BlockT *getLoopLatch() const { BlockT *Header = getHeader(); typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; @@ -278,20 +276,12 @@ public: InvBlockTraits::child_begin(Header); typename InvBlockTraits::ChildIteratorType PE = InvBlockTraits::child_end(Header); - if (PI == PE) return 0; // no preds? - BlockT *Latch = 0; - if (contains(*PI)) - Latch = *PI; - ++PI; - if (PI == PE) return 0; // only one pred? - - if (contains(*PI)) { - if (Latch) return 0; // multiple backedges - Latch = *PI; - } - ++PI; - if (PI != PE) return 0; // more than two preds + for (; PI != PE; ++PI) + if (contains(*PI)) { + if (Latch) return 0; + Latch = *PI; + } return Latch; } diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 205c34ab5c89..6b300fd9503e 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -30,6 +30,7 @@ namespace llvm { class TargetData; class MemoryDependenceAnalysis; class PredIteratorCache; + class DominatorTree; /// MemDepResult - A memory dependence query can return one of three different /// answers, described below. @@ -244,6 +245,29 @@ namespace llvm { BasicBlock *BB, SmallVectorImpl<NonLocalDepEntry> &Result); + /// GetPHITranslatedValue - Find an available version of the specified value + /// PHI translated across the specified edge. If MemDep isn't able to + /// satisfy this request, it returns null. + Value *GetPHITranslatedValue(Value *V, + BasicBlock *CurBB, BasicBlock *PredBB, + const TargetData *TD) const; + + /// GetAvailablePHITranslatedValue - Return the value computed by + /// PHITranslatePointer if it dominates PredBB, otherwise return null. + Value *GetAvailablePHITranslatedValue(Value *V, + BasicBlock *CurBB, BasicBlock *PredBB, + const TargetData *TD, + const DominatorTree &DT) const; + + /// InsertPHITranslatedPointer - Insert a computation of the PHI translated + /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB + /// block. All newly created instructions are added to the NewInsts list. + Value *InsertPHITranslatedPointer(Value *V, + BasicBlock *CurBB, BasicBlock *PredBB, + const TargetData *TD, + const DominatorTree &DT, + SmallVectorImpl<Instruction*> &NewInsts) const; + /// removeInstruction - Remove an instruction from the dependence analysis, /// updating the dependence of instructions that previously depended on it. void removeInstruction(Instruction *InstToRemove); diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 42a16e74a247..ea14b2da9ce9 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -81,7 +81,10 @@ template <> struct GraphTraits<PostDominatorTree*> } static nodes_iterator nodes_begin(PostDominatorTree *N) { - return df_begin(getEntryNode(N)); + if (getEntryNode(N)) + return df_begin(getEntryNode(N)); + else + return df_end(getEntryNode(N)); } static nodes_iterator nodes_end(PostDominatorTree *N) { diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 038d442cc6b9..5f3c671d0f48 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -19,6 +19,7 @@ #include <string> namespace llvm { + template <typename T> class SmallVectorImpl; class Value; class Instruction; class APInt; @@ -77,6 +78,26 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + /// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose + /// it into a base pointer with a constant offset and a number of scaled + /// symbolic offsets. + /// + /// The scaled symbolic offsets (represented by pairs of a Value* and a scale + /// in the VarIndices vector) are Value*'s that are known to be scaled by the + /// specified amount, but which may have other unrepresented high bits. As + /// such, the gep cannot necessarily be reconstructed from its decomposed + /// form. + /// + /// When TargetData is around, this function is capable of analyzing + /// everything that Value::getUnderlyingObject() can look through. When not, + /// it just looks through pointer casts. + /// + const Value *DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, + SmallVectorImpl<std::pair<const Value*, int64_t> > &VarIndices, + const TargetData *TD); + + + /// FindScalarValue - Given an aggregrate and an sequence of indices, see if /// the scalar value indexed is already around as a register, for example if /// it were inserted directly into the aggregrate. @@ -86,16 +107,14 @@ namespace llvm { Value *FindInsertedValue(Value *V, const unsigned *idx_begin, const unsigned *idx_end, - LLVMContext &Context, Instruction *InsertBefore = 0); /// This is a convenience wrapper for finding values indexed by a single index /// only. inline Value *FindInsertedValue(Value *V, const unsigned Idx, - LLVMContext &Context, Instruction *InsertBefore = 0) { const unsigned Idxs[1] = { Idx }; - return FindInsertedValue(V, &Idxs[0], &Idxs[1], Context, InsertBefore); + return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); } /// GetConstantStringInfo - This function computes the length of a |
