about summary refs log tree commit diff homepage
path: root/test/Intrinsics
diff options
context:
space:
mode:
authorDan Liew <daniel.liew@imperial.ac.uk>2015-12-19 11:21:15 +0000
committerDan Liew <daniel.liew@imperial.ac.uk>2015-12-19 22:04:50 +0000
commitd95825bef428b631099440d01a3955e7f6276b16 (patch)
tree8806a8b2628a9e111e84eeb0af7f351f519c81cb /test/Intrinsics
parentd348aee430c8308a29d5edadd4c38e7fee1abadc (diff)
downloadklee-d95825bef428b631099440d01a3955e7f6276b16.tar.gz
Implement support for lowering the ``llvm.objectsize`` intrinsic
introduced in LLVM 2.7. Previously KLEE would emit the following error
message when ``IntrinsicLowering::LowerIntrinsicCall()`` was called on
the intrinsic

```
LLVM ERROR: Code generator does not support intrinsic function 'llvm.objectsize.i64.p0i8'!
```

The ``IntrinsicCleaner`` pass now lowers this intrinsic to a constant
integer depending on the second argument to the intrinsic. This
corresponds to the case where the size of the object pointed to by the
first argument is unknown.

An alternative design would be to handle this intrinsic in the Executor
where is actually possible to know the size of objects during execution.
However that would be much more complicated because if the pointer is
symbolic we would have to fork for every object that could be pointed
to.

The implementation is similar to #260 but we handle the second argument
to the intrinsic correctly and also have a simple test case.

Unfortunately we have to have a different version of the test case
for LLVM 2.9 because the expected suffix for the intrinsic is different
in LLVM 2.9.
Diffstat (limited to 'test/Intrinsics')
-rw-r--r--test/Intrinsics/objectsize.ll36
-rw-r--r--test/Intrinsics/objectsize.llvm29.ll34
2 files changed, 70 insertions, 0 deletions
diff --git a/test/Intrinsics/objectsize.ll b/test/Intrinsics/objectsize.ll
new file mode 100644
index 00000000..8b75ce8f
--- /dev/null
+++ b/test/Intrinsics/objectsize.ll
@@ -0,0 +1,36 @@
+; Unfortunately LLVM 2.9 has a different suffix for the ``llvm.objectsize`` instrinsic
+; so this LLVM IR fails to verify for that version.
+;
+; REQUIRES: not-llvm-2.9
+; RUN: %llvmas %s -o=%t.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee -exit-on-error --output-dir=%t.klee-out -disable-opt %t.bc
+; ModuleID = 'objectsize.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind uwtable {
+entry:
+  %a = alloca i8*, align 8
+  %0 = load i8** %a, align 8
+  %1 = call i64 @llvm.objectsize.i64.p0i8(i8* %0, i1 true)
+  %cmp = icmp ne i64 %1, 0
+  br i1 %cmp, label %abort.block, label %continue.block
+
+continue.block:
+  %2 = load i8** %a, align 8
+  %3 = call i64 @llvm.objectsize.i64.p0i8(i8* %2, i1 false)
+  %cmp1 = icmp ne i64 %3, -1
+  br i1 %cmp1, label %abort.block, label %exit.block
+
+exit.block:
+  ret i32 0
+
+abort.block:
+  call void @abort()
+  unreachable
+}
+
+declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readnone
+
+declare void @abort() noreturn nounwind
diff --git a/test/Intrinsics/objectsize.llvm29.ll b/test/Intrinsics/objectsize.llvm29.ll
new file mode 100644
index 00000000..386eaddb
--- /dev/null
+++ b/test/Intrinsics/objectsize.llvm29.ll
@@ -0,0 +1,34 @@
+; FIXME: Remove this test case when we drop LLVM 2.9 support
+; REQUIRES: llvm-2.9
+; RUN: %llvmas %s -o=%t.bc
+; RUN: rm -rf %t.klee-out
+; RUN: %klee -exit-on-error --output-dir=%t.klee-out -disable-opt %t.bc
+; ModuleID = 'objectsize.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+  %a = alloca i8*, align 8
+  %0 = load i8** %a, align 8
+  %1 = call i64 @llvm.objectsize.i64(i8* %0, i1 true)
+  %cmp = icmp ne i64 %1, 0
+  br i1 %cmp, label %abort.block, label %continue.block
+
+continue.block:
+  %2 = load i8** %a, align 8
+  %3 = call i64 @llvm.objectsize.i64(i8* %2, i1 false)
+  %cmp1 = icmp ne i64 %3, -1
+  br i1 %cmp1, label %abort.block, label %exit.block
+
+exit.block:
+  ret i32 0
+
+abort.block:
+  call void @abort()
+  unreachable
+}
+
+declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readnone
+
+declare void @abort() noreturn nounwind