mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Minor refactoring of GEP handling in isDereferenceablePointer
For GEP instructions isDereferenceablePointer checks that all indices are constant and within bounds. Replace this index calculation logic to a call to accumulateConstantOffset. Separated from the http://reviews.llvm.org/D9791 Reviewed By: sanjoy Differential Revision: http://reviews.llvm.org/D9874 llvm-svn: 239299
This commit is contained in:
parent
e570ae0867
commit
c17a17c081
@ -2967,38 +2967,25 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
|
||||
|
||||
// For GEPs, determine if the indexing lands within the allocated object.
|
||||
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
||||
Type *VTy = GEP->getType();
|
||||
Type *Ty = VTy->getPointerElementType();
|
||||
const Value *Base = GEP->getPointerOperand();
|
||||
|
||||
// Conservatively require that the base pointer be fully dereferenceable.
|
||||
if (!Visited.insert(GEP->getOperand(0)).second)
|
||||
if (!Visited.insert(Base).second)
|
||||
return false;
|
||||
if (!isDereferenceablePointer(GEP->getOperand(0), DL, CtxI,
|
||||
if (!isDereferenceablePointer(Base, DL, CtxI,
|
||||
DT, TLI, Visited))
|
||||
return false;
|
||||
// Check the indices.
|
||||
gep_type_iterator GTI = gep_type_begin(GEP);
|
||||
for (User::const_op_iterator I = GEP->op_begin()+1,
|
||||
E = GEP->op_end(); I != E; ++I) {
|
||||
Value *Index = *I;
|
||||
Type *Ty = *GTI++;
|
||||
// Struct indices can't be out of bounds.
|
||||
if (isa<StructType>(Ty))
|
||||
continue;
|
||||
ConstantInt *CI = dyn_cast<ConstantInt>(Index);
|
||||
if (!CI)
|
||||
return false;
|
||||
// Zero is always ok.
|
||||
if (CI->isZero())
|
||||
continue;
|
||||
// Check to see that it's within the bounds of an array.
|
||||
ArrayType *ATy = dyn_cast<ArrayType>(Ty);
|
||||
if (!ATy)
|
||||
return false;
|
||||
if (CI->getValue().getActiveBits() > 64)
|
||||
return false;
|
||||
if (CI->getZExtValue() >= ATy->getNumElements())
|
||||
return false;
|
||||
}
|
||||
// Indices check out; this is dereferenceable.
|
||||
return true;
|
||||
|
||||
APInt Offset(DL.getPointerTypeSizeInBits(VTy), 0);
|
||||
if (!GEP->accumulateConstantOffset(DL, Offset))
|
||||
return false;
|
||||
|
||||
// Check if the load is within the bounds of the underlying object.
|
||||
uint64_t LoadSize = DL.getTypeStoreSize(Ty);
|
||||
Type *BaseType = Base->getType()->getPointerElementType();
|
||||
return (Offset + LoadSize).ule(DL.getTypeAllocSize(BaseType));
|
||||
}
|
||||
|
||||
// For gc.relocate, look through relocations
|
||||
|
@ -10,6 +10,9 @@ declare zeroext i1 @return_i1()
|
||||
@globalstr = global [6 x i8] c"hello\00"
|
||||
@globali32ptr = external global i32*
|
||||
|
||||
%struct.A = type { [8 x i8], [5 x i8] }
|
||||
@globalstruct = external global %struct.A
|
||||
|
||||
define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" {
|
||||
; CHECK: The following are dereferenceable:
|
||||
; CHECK: %globalptr
|
||||
@ -22,6 +25,8 @@ define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-e
|
||||
; CHECK-NOT: %d2_load
|
||||
; CHECK-NOT: %d_or_null_load
|
||||
; CHECK: %d_or_null_non_null_load
|
||||
; CHECK: %within_allocation
|
||||
; CHECK-NOT: %outside_allocation
|
||||
entry:
|
||||
%globalptr = getelementptr inbounds [6 x i8], [6 x i8]* @globalstr, i32 0, i32 0
|
||||
%load1 = load i8, i8* %globalptr
|
||||
@ -54,6 +59,14 @@ entry:
|
||||
%d_or_null_non_null_load = load i32*, i32** @globali32ptr, !nonnull !2, !dereferenceable_or_null !0
|
||||
%load10 = load i32, i32* %d_or_null_non_null_load
|
||||
|
||||
; It's OK to overrun static array size as long as we stay within underlying object size
|
||||
%within_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 0, i64 10
|
||||
%load11 = load i8, i8* %within_allocation
|
||||
|
||||
; GEP is outside the underlying object size
|
||||
%outside_allocation = getelementptr inbounds %struct.A, %struct.A* @globalstruct, i64 0, i32 1, i64 10
|
||||
%load12 = load i8, i8* %outside_allocation
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user