about summary refs log tree commit diff homepage
path: root/lib
diff options
context:
space:
mode:
authorMartin Nowack <martin_nowack@tu-dresden.de>2017-10-29 22:06:16 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-02-18 12:49:41 +0000
commitf751f9351f0176a3109e260a6e8e9727fc9fb4ea (patch)
tree802068a39fe5266b5d80719001becae26f4f0593 /lib
parent51183b4370eb2a081c440b6ff32acc4e5f50890e (diff)
downloadklee-f751f9351f0176a3109e260a6e8e9727fc9fb4ea.tar.gz
Fix getelementptr for array or vector indices
Rewrote code based on: llvm::GEPOperator::accumulateConstantOffset():
Handle signed offset correctly.
Diffstat (limited to 'lib')
-rw-r--r--lib/Core/ExecutorUtil.cpp51
1 files changed, 26 insertions, 25 deletions
diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp
index 4f51ecb6..92dee5ac 100644
--- a/lib/Core/ExecutorUtil.cpp
+++ b/lib/Core/ExecutorUtil.cpp
@@ -19,18 +19,22 @@
 #include "klee/Internal/Module/KModule.h"
 
 #include "klee/Internal/Support/ErrorHandling.h"
-#include "klee/util/GetElementPtrTypeIterator.h"
 
-#include "llvm/IR/Function.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Operator.h"
+#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5)
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#else
+#include "llvm/IR/GetElementPtrTypeIterator.h"
+#endif
 #include "llvm/Support/raw_ostream.h"
 
 #include <cassert>
 
-using namespace klee;
 using namespace llvm;
 
 namespace klee {
@@ -188,34 +192,31 @@ namespace klee {
 
     case Instruction::GetElementPtr: {
       ref<ConstantExpr> base = op1->ZExt(Context::get().getPointerWidth());
-
       for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce);
            ii != ie; ++ii) {
-        ref<ConstantExpr> addend = 
-          ConstantExpr::alloc(0, Context::get().getPointerWidth());
-
-        if (StructType *st = dyn_cast<StructType>(*ii)) {
-          const StructLayout *sl = kmodule->targetData->getStructLayout(st);
-          const ConstantInt *ci = cast<ConstantInt>(ii.getOperand());
-
-          addend = ConstantExpr::alloc(sl->getElementOffset((unsigned)
-                                                            ci->getZExtValue()),
-                                       Context::get().getPointerWidth());
-        } else {
-          const SequentialType *set = cast<SequentialType>(*ii);
-          ref<ConstantExpr> index = 
+        ref<ConstantExpr> indexOp =
             evalConstant(cast<Constant>(ii.getOperand()), ki);
-          unsigned elementSize = 
-            kmodule->targetData->getTypeStoreSize(set->getElementType());
+        if (indexOp->isZero())
+          continue;
 
-          index = index->ZExt(Context::get().getPointerWidth());
-          addend = index->Mul(ConstantExpr::alloc(elementSize, 
-                                                  Context::get().getPointerWidth()));
+        // Handle a struct index, which adds its field offset to the pointer.
+        if (StructType *STy = dyn_cast<StructType>(*ii)) {
+          unsigned ElementIdx = indexOp->getZExtValue();
+          const StructLayout *SL = kmodule->targetData->getStructLayout(STy);
+          base = base->Add(
+              ConstantExpr::alloc(APInt(Context::get().getPointerWidth(),
+                                        SL->getElementOffset(ElementIdx))));
+          continue;
         }
 
-        base = base->Add(addend);
+        // For array or vector indices, scale the index by the size of the type.
+        // Indices can be negative
+        base = base->Add(indexOp->SExt(Context::get().getPointerWidth())
+                             ->Mul(ConstantExpr::alloc(
+                                 APInt(Context::get().getPointerWidth(),
+                                       kmodule->targetData->getTypeAllocSize(
+                                           ii.getIndexedType())))));
       }
-
       return base;
     }