summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-04-24 23:40:05 +0000
committerBill Wendling <isanbard@gmail.com>2012-04-24 23:40:05 +0000
commit181a72c0c36e95d4dfe692e6b306cda12c824fe3 (patch)
tree0e6f59f491d122c8b3b63640db5f3cbc98cb1cc1
parent98eaa4638aa42fa0846e216bd4f5edd0cfc26b2f (diff)
downloadllvm-181a72c0c36e95d4dfe692e6b306cda12c824fe3.tar.gz
Merging r155466:
------------------------------------------------------------------------ r155466 | chandlerc | 2012-04-24 11:42:47 -0700 (Tue, 24 Apr 2012) | 17 lines Fix a crash on valid (if UB) bitcode that is produced for some global constants in C++11 mode. I have no idea why it required such particular circumstances to get here, the code seems clearly to rely upon unchecked assumptions. Specifically, when we decide to form an index into a struct type, we may have gone through (at least one) zero-length array indexing round, which would have left the offset un-adjusted, and thus not necessarily valid for use when indexing the struct type. This is just an canonicalization step, so the correct thing is to refuse to canonicalize nonsensical GEPs of this form. Implemented, and test case added. Fixes PR12642. Pair debugged and coded with Richard Smith. =] I credit him with most of the debugging, and preventing me from writing the wrong code. ------------------------------------------------------------------------ llvm-svn: 155506
-rw-r--r--llvm/lib/Analysis/ConstantFolding.cpp14
-rw-r--r--llvm/test/Transforms/GlobalOpt/constantfold-initializers.ll5
2 files changed, 16 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7a0a4e1e8246..783c32e6669d 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -681,6 +681,7 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
// This makes it easy to determine if the getelementptr is "inbounds".
// Also, this helps GlobalOpt do SROA on GlobalVariables.
Type *Ty = Ptr->getType();
+ assert(Ty->isPointerTy() && "Forming regular GEP of non-pointer type");
SmallVector<Constant*, 32> NewIdxs;
do {
if (SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
@@ -711,10 +712,17 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef<Constant *> Ops,
}
Ty = ATy->getElementType();
} else if (StructType *STy = dyn_cast<StructType>(Ty)) {
- // Determine which field of the struct the offset points into. The
- // getZExtValue is at least as safe as the StructLayout API because we
- // know the offset is within the struct at this point.
+ // If we end up with an offset that isn't valid for this struct type, we
+ // can't re-form this GEP in a regular form, so bail out. The pointer
+ // operand likely went through casts that are necessary to make the GEP
+ // sensible.
const StructLayout &SL = *TD->getStructLayout(STy);
+ if (Offset.uge(SL.getSizeInBytes()))
+ break;
+
+ // Determine which field of the struct the offset points into. The
+ // getZExtValue is fine as we've already ensured that the offset is
+ // within the range representable by the StructLayout API.
unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue());
NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()),
ElIdx));
diff --git a/llvm/test/Transforms/GlobalOpt/constantfold-initializers.ll b/llvm/test/Transforms/GlobalOpt/constantfold-initializers.ll
index af8fa324db8c..ce6e2c46d627 100644
--- a/llvm/test/Transforms/GlobalOpt/constantfold-initializers.ll
+++ b/llvm/test/Transforms/GlobalOpt/constantfold-initializers.ll
@@ -12,6 +12,11 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
@xs = global [2 x i32] zeroinitializer, align 4
; CHECK: @xs = global [2 x i32] [i32 1, i32 1]
+; PR12642
+%PR12642.struct = type { i8 }
+@PR12642.s = global <{}> zeroinitializer, align 1
+@PR12642.p = constant %PR12642.struct* bitcast (i8* getelementptr (i8* bitcast (<{}>* @PR12642.s to i8*), i64 1) to %PR12642.struct*), align 8
+
define internal void @test1() {
entry:
store i32 1, i32* getelementptr inbounds ([2 x i32]* @xs, i64 0, i64 0)