about summary refs log tree commit diff homepage
path: root/lib
diff options
context:
space:
mode:
authorPavel <operasfantom@gmail.com>2022-03-29 12:03:02 +0400
committerCristian Cadar <c.cadar@imperial.ac.uk>2022-07-24 15:40:15 +0100
commitc9de012b07426435b8bd3bb29082fbceddf403a3 (patch)
tree98a388118509085e7e62f5f2361f19fd3fa46870 /lib
parent64dfbcd7073e0286e8c0145e1750f9fe3abc7565 (diff)
downloadklee-c9de012b07426435b8bd3bb29082fbceddf403a3.tar.gz
Support arguments of width 128, 256 and 512 bits for external calls
Diffstat (limited to 'lib')
-rw-r--r--lib/Core/Executor.cpp8
-rw-r--r--lib/Expr/Expr.cpp31
2 files changed, 29 insertions, 10 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 42405982..6fad8830 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -3810,11 +3810,13 @@ void Executor::callExternalFunction(ExecutionState &state,
   }
 
   // normal external function handling path
-  // allocate 128 bits for each argument (+return value) to support fp80's;
+  // allocate 512 bits for each argument (+return value) to support
+  // fp80's and SIMD vectors as parameters for external calls;
   // we could iterate through all the arguments first and determine the exact
   // size we need, but this is faster, and the memory usage isn't significant.
-  uint64_t *args = (uint64_t*) alloca(2*sizeof(*args) * (arguments.size() + 1));
-  memset(args, 0, 2 * sizeof(*args) * (arguments.size() + 1));
+  size_t allocatedBytes = Expr::MaxWidth / 8 * (arguments.size() + 1);
+  uint64_t *args = (uint64_t*) alloca(allocatedBytes);
+  memset(args, 0, allocatedBytes);
   unsigned wordIndex = 2;
   for (std::vector<ref<Expr> >::iterator ai = arguments.begin(), 
        ae = arguments.end(); ai!=ae; ++ai) {
diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp
index 50020fb1..d82cbee3 100644
--- a/lib/Expr/Expr.cpp
+++ b/lib/Expr/Expr.cpp
@@ -16,6 +16,7 @@
 // Core. If we need to do arithmetic, we probably want to use APInt.
 #include "klee/Support/IntEvaluation.h"
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Hashing.h"
 #if LLVM_VERSION_CODE >= LLVM_VERSION(13, 0)
 #include "llvm/ADT/StringExtras.h"
@@ -311,6 +312,9 @@ void Expr::printWidth(llvm::raw_ostream &os, Width width) {
   case Expr::Int32: os << "Expr::Int32"; break;
   case Expr::Int64: os << "Expr::Int64"; break;
   case Expr::Fl80: os << "Expr::Fl80"; break;
+  case Expr::Int128: os << "Expr::Int128"; break;
+  case Expr::Int256: os << "Expr::Int256"; break;
+  case Expr::Int512: os << "Expr::Int512"; break;
   default: os << "<invalid type: " << (unsigned) width << ">";
   }
 }
@@ -336,23 +340,32 @@ void Expr::dump() const {
 
 ref<Expr> ConstantExpr::fromMemory(void *address, Width width) {
   switch (width) {
+  default: assert(0 && "invalid width");
   case  Expr::Bool: return ConstantExpr::create(*(( uint8_t*) address), width);
   case  Expr::Int8: return ConstantExpr::create(*(( uint8_t*) address), width);
   case Expr::Int16: return ConstantExpr::create(*((uint16_t*) address), width);
   case Expr::Int32: return ConstantExpr::create(*((uint32_t*) address), width);
   case Expr::Int64: return ConstantExpr::create(*((uint64_t*) address), width);
   // FIXME: what about machines without x87 support?
-  default:
-    return ConstantExpr::alloc(
-        llvm::APInt(width,
-                    (width + llvm::APFloatBase::integerPartWidth - 1) /
-                        llvm::APFloatBase::integerPartWidth,
-                    (const uint64_t *)address));
+  case Expr::Fl80: {
+    size_t numWords = (width + llvm::APFloatBase::integerPartWidth - 1) /
+                    llvm::APFloatBase::integerPartWidth;
+    return ConstantExpr::alloc(llvm::APInt(
+        width, llvm::ArrayRef<uint64_t>((const uint64_t *)address, numWords)));
+  }
+  case Expr::Int128:
+  case Expr::Int256:
+  case Expr::Int512: {
+    size_t numWords = width / APInt::APINT_BITS_PER_WORD;
+    return ConstantExpr::alloc(llvm::APInt(
+        width, llvm::ArrayRef<uint64_t>((const uint64_t *)address, numWords)));
+  }
   }
 }
 
 void ConstantExpr::toMemory(void *address) {
-  switch (getWidth()) {
+  auto width = getWidth();
+  switch (width) {
   default: assert(0 && "invalid type");
   case  Expr::Bool: *(( uint8_t*) address) = getZExtValue(1); break;
   case  Expr::Int8: *(( uint8_t*) address) = getZExtValue(8); break;
@@ -363,6 +376,10 @@ void ConstantExpr::toMemory(void *address) {
   case Expr::Fl80:
     *((long double*) address) = *(const long double*) value.getRawData();
     break;
+  case Expr::Int128:
+  case Expr::Int256:
+  case Expr::Int512:
+      memcpy(address, value.getRawData(), width / 8);
   }
 }