diff options
Diffstat (limited to 'llvm/lib/VMCore')
-rw-r--r-- | llvm/lib/VMCore/ConstantRange.cpp | 332 | ||||
-rw-r--r-- | llvm/lib/VMCore/LeakDetector.cpp | 125 | ||||
-rw-r--r-- | llvm/lib/VMCore/Mangler.cpp | 127 |
3 files changed, 584 insertions, 0 deletions
diff --git a/llvm/lib/VMCore/ConstantRange.cpp b/llvm/lib/VMCore/ConstantRange.cpp new file mode 100644 index 00000000000..3b91c5bc7a0 --- /dev/null +++ b/llvm/lib/VMCore/ConstantRange.cpp @@ -0,0 +1,332 @@ +//===-- ConstantRange.cpp - ConstantRange implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges (other integral ranges use min/max values for special range values): +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ConstantRange.h" +#include "llvm/Constants.h" +#include "llvm/Instruction.h" +#include "llvm/Type.h" +#include <iostream> + +using namespace llvm; + +static ConstantIntegral *Next(ConstantIntegral *CI) { + if (CI->getType() == Type::BoolTy) + return CI == ConstantBool::True ? ConstantBool::False : ConstantBool::True; + + Constant *Result = ConstantExpr::getAdd(CI, + ConstantInt::get(CI->getType(), 1)); + return cast<ConstantIntegral>(Result); +} + +static bool LT(ConstantIntegral *A, ConstantIntegral *B) { + Constant *C = ConstantExpr::getSetLT(A, B); + assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??"); + return cast<ConstantBool>(C)->getValue(); +} + +static bool LTE(ConstantIntegral *A, ConstantIntegral *B) { + Constant *C = ConstantExpr::getSetLE(A, B); + assert(isa<ConstantBool>(C) && "Constant folding of integrals not impl??"); + return cast<ConstantBool>(C)->getValue(); +} + +static bool GT(ConstantIntegral *A, ConstantIntegral *B) { return LT(B, A); } + +static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B) { + return LT(A, B) ? A : B; +} +static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B) { + return GT(A, B) ? A : B; +} + +/// Initialize a full (the default) or empty set for the specified type. +/// +ConstantRange::ConstantRange(const Type *Ty, bool Full) { + assert(Ty->isIntegral() && + "Cannot make constant range of non-integral type!"); + if (Full) + Lower = Upper = ConstantIntegral::getMaxValue(Ty); + else + Lower = Upper = ConstantIntegral::getMinValue(Ty); +} + +/// Initialize a range to hold the single specified value. +/// +ConstantRange::ConstantRange(Constant *V) + : Lower(cast<ConstantIntegral>(V)), Upper(Next(cast<ConstantIntegral>(V))) { +} + +/// Initialize a range of values explicitly... this will assert out if +/// Lower==Upper and Lower != Min or Max for its type (or if the two constants +/// have different types) +/// +ConstantRange::ConstantRange(Constant *L, Constant *U) + : Lower(cast<ConstantIntegral>(L)), Upper(cast<ConstantIntegral>(U)) { + assert(Lower->getType() == Upper->getType() && + "Incompatible types for ConstantRange!"); + + // Make sure that if L & U are equal that they are either Min or Max... + assert((L != U || (L == ConstantIntegral::getMaxValue(L->getType()) || + L == ConstantIntegral::getMinValue(L->getType()))) && + "Lower == Upper, but they aren't min or max for type!"); +} + +/// Initialize a set of values that all satisfy the condition with C. +/// +ConstantRange::ConstantRange(unsigned SetCCOpcode, ConstantIntegral *C) { + switch (SetCCOpcode) { + default: assert(0 && "Invalid SetCC opcode to ConstantRange ctor!"); + case Instruction::SetEQ: Lower = C; Upper = Next(C); return; + case Instruction::SetNE: Upper = C; Lower = Next(C); return; + case Instruction::SetLT: + Lower = ConstantIntegral::getMinValue(C->getType()); + Upper = C; + return; + case Instruction::SetGT: + Lower = Next(C); + Upper = ConstantIntegral::getMinValue(C->getType()); // Min = Next(Max) + return; + case Instruction::SetLE: + Lower = ConstantIntegral::getMinValue(C->getType()); + Upper = Next(C); + return; + case Instruction::SetGE: + Lower = C; + Upper = ConstantIntegral::getMinValue(C->getType()); // Min = Next(Max) + return; + } +} + +/// getType - Return the LLVM data type of this range. +/// +const Type *ConstantRange::getType() const { return Lower->getType(); } + +/// isFullSet - Return true if this set contains all of the elements possible +/// for this data-type +bool ConstantRange::isFullSet() const { + return Lower == Upper && Lower == ConstantIntegral::getMaxValue(getType()); +} + +/// isEmptySet - Return true if this set contains no members. +/// +bool ConstantRange::isEmptySet() const { + return Lower == Upper && Lower == ConstantIntegral::getMinValue(getType()); +} + +/// isWrappedSet - Return true if this set wraps around the top of the range, +/// for example: [100, 8) +/// +bool ConstantRange::isWrappedSet() const { + return GT(Lower, Upper); +} + + +/// getSingleElement - If this set contains a single element, return it, +/// otherwise return null. +ConstantIntegral *ConstantRange::getSingleElement() const { + if (Upper == Next(Lower)) // Is it a single element range? + return Lower; + return 0; +} + +/// getSetSize - Return the number of elements in this set. +/// +uint64_t ConstantRange::getSetSize() const { + if (isEmptySet()) return 0; + if (getType() == Type::BoolTy) { + if (Lower != Upper) // One of T or F in the set... + return 1; + return 2; // Must be full set... + } + + // Simply subtract the bounds... + Constant *Result = ConstantExpr::getSub(Upper, Lower); + return cast<ConstantInt>(Result)->getRawValue(); +} + +/// contains - Return true if the specified value is in the set. +/// +bool ConstantRange::contains(ConstantInt *Val) const { + if (Lower == Upper) { + if (isFullSet()) return true; + return false; + } + + if (!isWrappedSet()) + return LTE(Lower, Val) && LT(Val, Upper); + return LTE(Lower, Val) || LT(Val, Upper); +} + + + +/// subtract - Subtract the specified constant from the endpoints of this +/// constant range. +ConstantRange ConstantRange::subtract(ConstantInt *CI) const { + assert(CI->getType() == getType() && getType()->isInteger() && + "Cannot subtract from different type range or non-integer!"); + // If the set is empty or full, don't modify the endpoints. + if (Lower == Upper) return *this; + return ConstantRange(ConstantExpr::getSub(Lower, CI), + ConstantExpr::getSub(Upper, CI)); +} + + +// intersect1Wrapped - This helper function is used to intersect two ranges when +// it is known that LHS is wrapped and RHS isn't. +// +static ConstantRange intersect1Wrapped(const ConstantRange &LHS, + const ConstantRange &RHS) { + assert(LHS.isWrappedSet() && !RHS.isWrappedSet()); + + // Check to see if we overlap on the Left side of RHS... + // + if (LT(RHS.getLower(), LHS.getUpper())) { + // We do overlap on the left side of RHS, see if we overlap on the right of + // RHS... + if (GT(RHS.getUpper(), LHS.getLower())) { + // Ok, the result overlaps on both the left and right sides. See if the + // resultant interval will be smaller if we wrap or not... + // + if (LHS.getSetSize() < RHS.getSetSize()) + return LHS; + else + return RHS; + + } else { + // No overlap on the right, just on the left. + return ConstantRange(RHS.getLower(), LHS.getUpper()); + } + + } else { + // We don't overlap on the left side of RHS, see if we overlap on the right + // of RHS... + if (GT(RHS.getUpper(), LHS.getLower())) { + // Simple overlap... + return ConstantRange(LHS.getLower(), RHS.getUpper()); + } else { + // No overlap... + return ConstantRange(LHS.getType(), false); + } + } +} + +/// intersect - Return the range that results from the intersection of this +/// range with another range. +/// +ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { + assert(getType() == CR.getType() && "ConstantRange types don't agree!"); + // Handle common special cases + if (isEmptySet() || CR.isFullSet()) return *this; + if (isFullSet() || CR.isEmptySet()) return CR; + + if (!isWrappedSet()) { + if (!CR.isWrappedSet()) { + ConstantIntegral *L = Max(Lower, CR.Lower); + ConstantIntegral *U = Min(Upper, CR.Upper); + + if (LT(L, U)) // If range isn't empty... + return ConstantRange(L, U); + else + return ConstantRange(getType(), false); // Otherwise, return empty set + } else + return intersect1Wrapped(CR, *this); + } else { // We know "this" is wrapped... + if (!CR.isWrappedSet()) + return intersect1Wrapped(*this, CR); + else { + // Both ranges are wrapped... + ConstantIntegral *L = Max(Lower, CR.Lower); + ConstantIntegral *U = Min(Upper, CR.Upper); + return ConstantRange(L, U); + } + } + return *this; +} + +/// union - Return the range that results from the union of this range with +/// another range. The resultant range is guaranteed to include the elements of +/// both sets, but may contain more. For example, [3, 9) union [12,15) is [3, +/// 15), which includes 9, 10, and 11, which were not included in either set +/// before. +/// +ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { + assert(getType() == CR.getType() && "ConstantRange types don't agree!"); + + assert(0 && "Range union not implemented yet!"); + + return *this; +} + +/// zeroExtend - Return a new range in the specified integer type, which must +/// be strictly larger than the current type. The returned range will +/// correspond to the possible range of values if the source range had been +/// zero extended. +ConstantRange ConstantRange::zeroExtend(const Type *Ty) const { + assert(getLower()->getType()->getPrimitiveSize() < Ty->getPrimitiveSize() && + "Not a value extension"); + if (isFullSet()) { + // Change a source full set into [0, 1 << 8*numbytes) + unsigned SrcTySize = getLower()->getType()->getPrimitiveSize(); + return ConstantRange(Constant::getNullValue(Ty), + ConstantUInt::get(Ty, 1ULL << SrcTySize*8)); + } + + Constant *Lower = getLower(); + Constant *Upper = getUpper(); + if (Lower->getType()->isInteger() && !Lower->getType()->isUnsigned()) { + // Ensure we are doing a ZERO extension even if the input range is signed. + Lower = ConstantExpr::getCast(Lower, Ty->getUnsignedVersion()); + Upper = ConstantExpr::getCast(Upper, Ty->getUnsignedVersion()); + } + + return ConstantRange(ConstantExpr::getCast(Lower, Ty), + ConstantExpr::getCast(Upper, Ty)); +} + +/// truncate - Return a new range in the specified integer type, which must be +/// strictly smaller than the current type. The returned range will +/// correspond to the possible range of values if the source range had been +/// truncated to the specified type. +ConstantRange ConstantRange::truncate(const Type *Ty) const { + assert(getLower()->getType()->getPrimitiveSize() > Ty->getPrimitiveSize() && + "Not a value truncation"); + uint64_t Size = 1ULL << Ty->getPrimitiveSize()*8; + if (isFullSet() || getSetSize() >= Size) + return ConstantRange(getType()); + + return ConstantRange(ConstantExpr::getCast(getLower(), Ty), + ConstantExpr::getCast(getUpper(), Ty)); +} + + +/// print - Print out the bounds to a stream... +/// +void ConstantRange::print(std::ostream &OS) const { + OS << "[" << *Lower << "," << *Upper << " )"; +} + +/// dump - Allow printing from a debugger easily... +/// +void ConstantRange::dump() const { + print(std::cerr); +} diff --git a/llvm/lib/VMCore/LeakDetector.cpp b/llvm/lib/VMCore/LeakDetector.cpp new file mode 100644 index 00000000000..dbdb7dd70f2 --- /dev/null +++ b/llvm/lib/VMCore/LeakDetector.cpp @@ -0,0 +1,125 @@ +//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LeakDetector class. +// +//===----------------------------------------------------------------------===// + +#include "Support/LeakDetector.h" +#include "llvm/Value.h" +#include <iostream> +#include <set> +using namespace llvm; + +namespace { + template <class T> + struct PrinterTrait { + static void print(const T* P) { std::cerr << P; } + }; + + template<> + struct PrinterTrait<Value> { + static void print(const Value* P) { std::cerr << *P; } + }; + + template <typename T> + struct LeakDetectorImpl { + LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { } + + // Because the most common usage pattern, by far, is to add a + // garbage object, then remove it immediately, we optimize this + // case. When an object is added, it is not added to the set + // immediately, it is added to the CachedValue Value. If it is + // immediately removed, no set search need be performed. + void addGarbage(const T* o) { + if (Cache) { + assert(Ts.count(Cache) == 0 && "Object already in set!"); + Ts.insert(Cache); + } + Cache = o; + } + + void removeGarbage(const T* o) { + if (o == Cache) + Cache = 0; // Cache hit + else + Ts.erase(o); + } + + bool hasGarbage(const std::string& Message) { + addGarbage(0); // Flush the Cache + + assert(Cache == 0 && "No value should be cached anymore!"); + + if (!Ts.empty()) { + std::cerr + << "Leaked " << Name << " objects found: " << Message << ":\n"; + for (typename std::set<const T*>::iterator I = Ts.begin(), + E = Ts.end(); I != E; ++I) { + std::cerr << "\t"; + PrinterTrait<T>::print(*I); + std::cerr << "\n"; + } + std::cerr << '\n'; + + // Clear out results so we don't get duplicate warnings on + // next call... + Ts.clear(); + return true; + } + return false; + } + + private: + std::set<const T*> Ts; + const T* Cache; + const char* const Name; + }; + + typedef LeakDetectorImpl<void> Objects; + typedef LeakDetectorImpl<Value> LLVMObjects; + + Objects& getObjects() { + static Objects *o = 0; + if (o == 0) + o = new Objects("GENERIC"); + return *o; + } + + LLVMObjects& getLLVMObjects() { + static LLVMObjects *o = 0; + if (o == 0) + o = new LLVMObjects("LLVM"); + return *o; + } +} + +void LeakDetector::addGarbageObjectImpl(void *Object) { + getObjects().addGarbage(Object); +} + +void LeakDetector::addGarbageObjectImpl(const Value *Object) { + getLLVMObjects().addGarbage(Object); +} + +void LeakDetector::removeGarbageObjectImpl(void *Object) { + getObjects().removeGarbage(Object); +} + +void LeakDetector::removeGarbageObjectImpl(const Value *Object) { + getLLVMObjects().removeGarbage(Object); +} + +void LeakDetector::checkForGarbageImpl(const std::string &Message) { + // use non-short-circuit version so that both checks are performed + if (getObjects().hasGarbage(Message) | + getLLVMObjects().hasGarbage(Message)) + std::cerr << "\nThis is probably because you removed an object, but didn't " + "delete it. Please check your code for memory leaks.\n"; +} diff --git a/llvm/lib/VMCore/Mangler.cpp b/llvm/lib/VMCore/Mangler.cpp new file mode 100644 index 00000000000..bf989b41ce8 --- /dev/null +++ b/llvm/lib/VMCore/Mangler.cpp @@ -0,0 +1,127 @@ +//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for CWriter and assembly backends. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Mangler.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "Support/StringExtras.h" +using namespace llvm; + +static char HexDigit(int V) { + return V < 10 ? V+'0' : V+'A'-10; +} + +static std::string MangleLetter(unsigned char C) { + return std::string("_")+HexDigit(C >> 4) + HexDigit(C & 15) + "_"; +} + +/// makeNameProper - We don't want identifier names non-C-identifier characters +/// in them, so mangle them as appropriate. +/// +std::string Mangler::makeNameProper(const std::string &X) { + std::string Result; + + // Mangle the first letter specially, don't allow numbers... + if ((X[0] < 'a' || X[0] > 'z') && (X[0] < 'A' || X[0] > 'Z') && X[0] != '_') + Result += MangleLetter(X[0]); + else + Result += X[0]; + + for (std::string::const_iterator I = X.begin()+1, E = X.end(); I != E; ++I) + if ((*I < 'a' || *I > 'z') && (*I < 'A' || *I > 'Z') && + (*I < '0' || *I > '9') && *I != '_') + Result += MangleLetter(*I); + else + Result += *I; + return Result; +} + +/// getTypeID - Return a unique ID for the specified LLVM type. +/// +unsigned Mangler::getTypeID(const Type *Ty) { + unsigned &E = TypeMap[Ty]; + if (E == 0) E = ++TypeCounter; + return E; +} + + +std::string Mangler::getValueName(const Value *V) { + // Check to see whether we've already named V. + ValueMap::iterator VI = Memo.find(V); + if (VI != Memo.end()) { + return VI->second; // Return the old name for V. + } + + std::string name; + if (V->hasName()) { // Print out the label if it exists... + // Name mangling occurs as follows: + // - If V is an intrinsic function, do not change name at all + // - If V is not a global, mangling always occurs. + // - Otherwise, mangling occurs when any of the following are true: + // 1) V has internal linkage + // 2) V's name would collide if it is not mangled. + // + const GlobalValue* gv = dyn_cast<GlobalValue>(V); + if (gv && isa<Function>(gv) && cast<Function>(gv)->getIntrinsicID()) { + name = gv->getName(); // Is an intrinsic function + } else if (gv && !gv->hasInternalLinkage() && !MangledGlobals.count(gv)) { + name = makeNameProper(gv->getName()); + if (AddUnderscorePrefix) name = "_" + name; + } else { + // Non-global, or global with internal linkage / colliding name + // -> mangle. + unsigned TypeUniqueID = getTypeID(V->getType()); + name = "l" + utostr(TypeUniqueID) + "_" + makeNameProper(V->getName()); + } + } else { + name = "ltmp_" + utostr(Count++) + "_" + utostr(getTypeID(V->getType())); + } + + Memo[V] = name; + return name; +} + +void Mangler::InsertName(GlobalValue *GV, + std::map<std::string, GlobalValue*> &Names) { + if (!GV->hasName()) { // We must mangle unnamed globals. + MangledGlobals.insert(GV); + return; + } + + // Figure out if this is already used. + GlobalValue *&ExistingValue = Names[GV->getName()]; + if (!ExistingValue) { + ExistingValue = GV; + } else { + // If GV is external but the existing one is static, mangle the existing one + if (GV->hasExternalLinkage() && !ExistingValue->hasExternalLinkage()) { + MangledGlobals.insert(ExistingValue); + ExistingValue = GV; + } else { + // Otherwise, mangle GV + MangledGlobals.insert(GV); + } + } +} + + +Mangler::Mangler(Module &m, bool addUnderscorePrefix) + : M(m), AddUnderscorePrefix(addUnderscorePrefix), TypeCounter(0), Count(0) { + // Calculate which global values have names that will collide when we throw + // away type information. + std::map<std::string, GlobalValue*> Names; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + InsertName(I, Names); + for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) + InsertName(I, Names); +} |