diff options
author | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 17:19:09 +0000 |
---|---|---|
committer | Nuno Lopes <nunoplopes@sapo.pt> | 2012-05-22 17:19:09 +0000 |
commit | 5c525b59d5e0036a778d278eeff4832edfd41357 (patch) | |
tree | eb0e146a3ad637e382f3af8527aa385327b643e0 /include/llvm/Transforms/Utils/Local.h | |
parent | 23e75da7e0622528be3c3908b5fe3ae8857cdf65 (diff) | |
download | external_llvm-5c525b59d5e0036a778d278eeff4832edfd41357.zip external_llvm-5c525b59d5e0036a778d278eeff4832edfd41357.tar.gz external_llvm-5c525b59d5e0036a778d278eeff4832edfd41357.tar.bz2 |
add a new pass to instrument loads and stores for run-time bounds checking
move EmitGEPOffset from InstCombine to Transforms/Utils/Local.h
(a draft of this) patch reviewed by Andrew, thanks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157261 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Transforms/Utils/Local.h')
-rw-r--r-- | include/llvm/Transforms/Utils/Local.h | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 7f99dbc..936d58e 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -15,6 +15,11 @@ #ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H #define LLVM_TRANSFORMS_UTILS_LOCAL_H +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Operator.h" + namespace llvm { class User; @@ -160,6 +165,62 @@ static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { return getOrEnforceKnownAlignment(V, 0, TD); } +/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the +/// code necessary to compute the offset from the base pointer (without adding +/// in the base pointer). Return the result as a signed integer of intptr size. +template<typename IRBuilderTy> +Value *EmitGEPOffset(IRBuilderTy *Builder, const TargetData &TD, User *GEP) { + gep_type_iterator GTI = gep_type_begin(GEP); + Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); + Value *Result = Constant::getNullValue(IntPtrTy); + + // If the GEP is inbounds, we know that none of the addressing operations will + // overflow in an unsigned sense. + bool isInBounds = cast<GEPOperator>(GEP)->isInBounds(); + + // Build a mask for high order bits. + unsigned IntPtrWidth = TD.getPointerSizeInBits(); + uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); + + for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; + ++i, ++GTI) { + Value *Op = *i; + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + if (ConstantInt *OpC = dyn_cast<ConstantInt>(Op)) { + if (OpC->isZero()) continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + + if (Size) + Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".offs"); + continue; + } + + Constant *Scale = ConstantInt::get(IntPtrTy, Size); + Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); + Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); + // Emit an add instruction. + Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); + continue; + } + // Convert to correct type. + if (Op->getType() != IntPtrTy) + Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); + if (Size != 1) { + // We'll let instcombine(mul) convert this to a shl if possible. + Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".idx", isInBounds /*NUW*/); + } + + // Emit an add instruction. + Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); + } + return Result; +} + ///===---------------------------------------------------------------------===// /// Dbg Intrinsic utilities /// |