aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCristian Cadar <c.cadar@imperial.ac.uk>2013-09-25 05:58:04 -0700
committerCristian Cadar <c.cadar@imperial.ac.uk>2013-09-25 05:58:04 -0700
commit1510c721187f1e838d30fca376af2ab5af90ee6c (patch)
tree962e05f3c908ef7584836c668576b274d027d8c2
parent95521073b1a6c0eec2719a4c355c83506b325693 (diff)
parentfc29e256039d1af4979fd0a5c7170de84b19818b (diff)
downloadklee-1510c721187f1e838d30fca376af2ab5af90ee6c.tar.gz
Merge pull request #27 from antiAgainst/intrinsic-trap
Lower intrinsic instruction "llvm.trap" to a call of the abort() function.
-rw-r--r--lib/Module/IntrinsicCleaner.cpp25
-rw-r--r--lib/Module/Passes.h2
-rw-r--r--test/Feature/IntrinsicTrap.ll28
3 files changed, 52 insertions, 3 deletions
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp
index 9c2f4455..64a47e1b 100644
--- a/lib/Module/IntrinsicCleaner.cpp
+++ b/lib/Module/IntrinsicCleaner.cpp
@@ -60,11 +60,11 @@ bool IntrinsicCleanerPass::runOnModule(Module &M) {
bool dirty = false;
for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f)
for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b)
- dirty |= runOnBasicBlock(*b);
+ dirty |= runOnBasicBlock(*b, M);
return dirty;
}
-bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) {
+bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
bool dirty = false;
#if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
@@ -195,6 +195,27 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) {
ii->eraseFromParent();
dirty = true;
break;
+
+ case Intrinsic::trap: {
+ // Intrisic instruction "llvm.trap" found. Directly lower it to
+ // a call of the abort() function.
+ Function *F = cast<Function>(
+ M.getOrInsertFunction(
+ "abort", Type::getVoidTy(getGlobalContext()), NULL));
+ F->setDoesNotReturn();
+ F->setDoesNotThrow();
+
+ CallInst::Create(F, Twine(), ii);
+ new UnreachableInst(getGlobalContext(), ii);
+
+ ii->eraseFromParent();
+
+ if (Function *Declare = M.getFunction("llvm.trap"))
+ Declare->eraseFromParent();
+
+ dirty = true;
+ break;
+ }
default:
if (LowerIntrinsics)
diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h
index ebe89b2b..d83e57ec 100644
--- a/lib/Module/Passes.h
+++ b/lib/Module/Passes.h
@@ -82,7 +82,7 @@ class IntrinsicCleanerPass : public llvm::ModulePass {
llvm::IntrinsicLowering *IL;
bool LowerIntrinsics;
- bool runOnBasicBlock(llvm::BasicBlock &b);
+ bool runOnBasicBlock(llvm::BasicBlock &b, llvm::Module &M);
public:
#if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
IntrinsicCleanerPass(const llvm::TargetData &TD,
diff --git a/test/Feature/IntrinsicTrap.ll b/test/Feature/IntrinsicTrap.ll
new file mode 100644
index 00000000..5af46225
--- /dev/null
+++ b/test/Feature/IntrinsicTrap.ll
@@ -0,0 +1,28 @@
+; RUN: llvm-as %s -f -o %t1.bc
+; RUN: %klee -disable-opt %t1.bc
+; RUN: grep abort() klee-last/assembly.ll | wc -l | grep -q 2
+; RUN: echo "llvm.trap()" > %t2.ll
+; RUN: grep llvm.trap() klee-last/assembly.ll %t2.ll | wc -l | grep -q 1
+
+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-f128:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+ %a = add i32 1, 2
+ %b = add i32 %a, 3
+ %c = icmp ne i32 %b, 6
+ br i1 %c, label %btrue, label %bfalse
+
+btrue:
+ call void @llvm.trap() noreturn nounwind
+ unreachable
+
+bfalse:
+ br label %return
+
+return:
+ ret i32 0
+}
+
+declare void @llvm.trap() noreturn nounwind