Skip to content

Commit 000c3cb

Browse files
authored
Merge pull request #478 from smackers/no-warn-assume
[WIP] Optionally model the LLVM assume statement in Boogie
2 parents bf6245d + e642e4b commit 000c3cb

File tree

11 files changed

+117
-0
lines changed

11 files changed

+117
-0
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ env:
3636
- TRAVIS_ENV="--exhaustive --folder=memory-safety"
3737
- TRAVIS_ENV="--exhaustive --folder=pthread"
3838
- TRAVIS_ENV="--exhaustive --folder=strings"
39+
- TRAVIS_ENV="--exhaustive --folder=special"
3940

4041
before_install:
4142
- sudo rm -rf /usr/local/clang-7.0.0

include/smack/SmackOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "smack/SmackWarnings.h"
1111

1212
namespace smack {
13+
enum class LLVMAssumeType { none, use, check };
14+
1315
class SmackOptions {
1416
public:
1517
static const llvm::cl::list<std::string> EntryPoints;
@@ -28,6 +30,7 @@ class SmackOptions {
2830
static const llvm::cl::opt<bool> FloatEnabled;
2931
static const llvm::cl::opt<bool> MemorySafety;
3032
static const llvm::cl::opt<bool> IntegerOverflow;
33+
static const llvm::cl::opt<LLVMAssumeType> LLVMAssumes;
3134
static const llvm::cl::opt<bool> AddTiming;
3235

3336
static bool isEntryPoint(std::string);

lib/smack/SmackInstGenerator.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,28 @@ void SmackInstGenerator::visitIntrinsicInst(llvm::IntrinsicInst &ii) {
902902
};
903903
};
904904

905+
// Optionally generate a boogie assume statement from assume statements in
906+
// LLVM. Currently this behavior is experimental and must be enabled by
907+
// passing the -llvm-assumes flag. The default behavior of this
908+
// function is to ignore the assume statement, specified by the "none"
909+
// argument. If the check argument is given, an additional assertion is
910+
// generated to check the validity of the assumption.
911+
static const auto assume = [this](CallInst *ci) {
912+
if (SmackOptions::LLVMAssumes != LLVMAssumeType::none) {
913+
auto arg = rep->expr(ci->getArgOperand(0));
914+
auto llvmTrue =
915+
SmackOptions::BitPrecise ? Expr::lit(1, 1) : Expr::lit(1LL);
916+
auto chkStmt = Expr::eq(arg, llvmTrue);
917+
if (SmackOptions::LLVMAssumes == LLVMAssumeType::check)
918+
emit(Stmt::assert_(chkStmt));
919+
else
920+
emit(Stmt::assume(chkStmt));
921+
} else {
922+
// Skip assume statements
923+
return;
924+
}
925+
};
926+
905927
static const auto f16UpCast = conditionalModel(
906928
[this](CallInst *ci) {
907929
// translation: $f := $fpext.bvhalf.*($rmode, $bitcast.bv16.bvhalf($i));
@@ -1130,6 +1152,7 @@ void SmackInstGenerator::visitIntrinsicInst(llvm::IntrinsicInst &ii) {
11301152

11311153
static const std::map<llvm::Intrinsic::ID, std::function<void(CallInst *)>>
11321154
stmtMap{
1155+
{llvm::Intrinsic::assume, assume},
11331156
{llvm::Intrinsic::bitreverse, assignBvExpr(bitreverse)},
11341157
{llvm::Intrinsic::bswap, assignBvExpr(bswap)},
11351158
{llvm::Intrinsic::convert_from_fp16, f16UpCast},

lib/smack/SmackOptions.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ const llvm::cl::opt<bool>
6666
const llvm::cl::opt<bool> SmackOptions::IntegerOverflow(
6767
"integer-overflow", llvm::cl::desc("Enable integer overflow checks"));
6868

69+
const llvm::cl::opt<LLVMAssumeType> SmackOptions::LLVMAssumes(
70+
"llvm-assumes",
71+
llvm::cl::desc(
72+
"Optionally enable generation of Boogie assumes from LLVM assumes"),
73+
llvm::cl::values(clEnumValN(LLVMAssumeType::none, "none",
74+
"disable generation of assume statements"),
75+
clEnumValN(LLVMAssumeType::use, "use",
76+
"enable generation of assume statements"),
77+
clEnumValN(LLVMAssumeType::check, "check",
78+
"enable checking of assume statements")));
79+
6980
bool SmackOptions::isEntryPoint(std::string name) {
7081
for (auto EP : EntryPoints)
7182
if (name == EP)

share/smack/top.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ def arguments():
197197
translate_group.add_argument('--integer-overflow', action='store_true', default=False,
198198
help='enable integer overflow checks')
199199

200+
translate_group.add_argument('--llvm-assumes', choices=['none', 'use', 'check'], default='none',
201+
help='optionally enable generation of Boogie assume statements from LLVM assume statements ' +
202+
'(none=no generation [default], use=generate assume statements, check=check assume statements)')
203+
200204
translate_group.add_argument('--float', action="store_true", default=False,
201205
help='enable bit-precise floating-point functions')
202206

@@ -351,6 +355,7 @@ def llvm_to_bpl(args):
351355
if args.no_memory_splitting: cmd += ['-no-memory-splitting']
352356
if args.memory_safety: cmd += ['-memory-safety']
353357
if args.integer_overflow: cmd += ['-integer-overflow']
358+
if args.llvm_assumes: cmd += ['-llvm-assumes=' + args.llvm_assumes]
354359
if args.float: cmd += ['-float']
355360
if args.modular: cmd += ['-modular']
356361
try_command(cmd, console=True)

test/special/assume.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "smack.h"
2+
3+
// @expect verified
4+
// @flag --llvm-assumes=use
5+
6+
int main(void) {
7+
unsigned int y = 2 * (unsigned int)__VERIFIER_nondet_unsigned_short();
8+
// This assumption is used for verification, even though bit-precise
9+
// is not enabled, the assertion will pass.
10+
__builtin_assume((y & 1) == 0);
11+
__VERIFIER_assert((y & 1) == 0);
12+
}

test/special/assume2.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "smack.h"
2+
3+
// @expect verified
4+
// @flag --llvm-assumes=use
5+
6+
int main(void) {
7+
unsigned int y = (2 * (unsigned int)__VERIFIER_nondet_unsigned_short()) + 1;
8+
// This assumption is used for verification, even though the assumption
9+
// is false, the assertion will pass.
10+
__builtin_assume((y & 1) == 0);
11+
__VERIFIER_assert((y & 1) == 0);
12+
}

test/special/assume_check.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "smack.h"
2+
3+
// @expect verified
4+
// @flag --llvm-assumes=check
5+
// @flag --bit-precise
6+
7+
int main(void) {
8+
unsigned int y = 2 * (unsigned int)__VERIFIER_nondet_unsigned_short();
9+
// This assumption is checked under bit-precise and is verified.
10+
__builtin_assume((y & 1) == 0);
11+
__VERIFIER_assert((y & 1) == 0);
12+
}

test/special/assume_check2.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "smack.h"
2+
3+
// @expect verified
4+
// @flag --llvm-assumes=check
5+
// @flag --bit-precise
6+
7+
int main(void) {
8+
unsigned int y = (2 * (unsigned int)__VERIFIER_nondet_unsigned_short()) + 1;
9+
// This assumption is checked at verification time, and since bit-precise
10+
// is enabled, and y is clearly odd, the check will pass.
11+
__builtin_assume((y & 1) == 1);
12+
__VERIFIER_assert((y & 1) == 1);
13+
}

test/special/assume_check_fail.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "smack.h"
2+
3+
// @expect error
4+
// @flag --llvm-assumes=check
5+
// @flag --bit-precise
6+
7+
int main(void) {
8+
unsigned int y = (2 * (unsigned int)__VERIFIER_nondet_unsigned_short()) + 1;
9+
// This assumption is checked at verification time, and since bit-precise
10+
// is enabled, and y is clearly odd, the assumption should be shown false.
11+
__builtin_assume((y & 1) == 0);
12+
__VERIFIER_assert((y & 1) == 0);
13+
}

test/special/assume_fail.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "smack.h"
2+
3+
// @expect error
4+
// @flag --llvm-assumes=none
5+
6+
int main(void) {
7+
unsigned int y = 2 * (unsigned int)__VERIFIER_nondet_unsigned_short();
8+
// This assumption is not used, and since bit-precise is not enabled,
9+
// verification will fail.
10+
__builtin_assume((y & 1) == 0);
11+
__VERIFIER_assert((y & 1) == 0);
12+
}

0 commit comments

Comments
 (0)