-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use CBMC's arithmetic operators that return both the result and whether it overflowed #1426
Use CBMC's arithmetic operators that return both the result and whether it overflowed #1426
Conversation
0478d4a
to
3c1b18e
Compare
@@ -1296,6 +1325,12 @@ impl Expr { | |||
ArithmeticOverflowResult { result, overflowed } | |||
} | |||
|
|||
/// Uses CBMC's add-with-overflow operation that performs a single addition | |||
/// operation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Give C
or pseudocode example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// add to symbol table | ||
let res_type = arithmetic_overflow_result_type(op_type.clone()); | ||
let struct_tag = | ||
self.ensure_struct(res_type.tag().unwrap(), res_type.tag().unwrap(), |_, _| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do this here? I'd expect it to happen in arithmetic_overflow_result_type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping to do it in arithmetic_overflow_result_type
, but it doesn't have access to the Gotoc context since it's in the cprover_bindings
crate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe make a helper function
let res_type = self.codegen_arithmetic_overflow_result_type(op_type.clone()); // does the ensure
let struct_tag = res_type.tag().unwrap()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Done.
let check = self.codegen_assert( | ||
res.overflowed.not(), | ||
var.clone() | ||
.member(ARITH_OVERFLOW_OVERFLOWED_FIELD, &self.symbol_table) | ||
.cast_to(Type::c_bool()) | ||
.not(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were you going to split this off?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case wasn't difficult to handle. The other cases, e.g. in count_in_bytes
, codegen_ptr_offset_from_expr
, and codegen_ptr_offset_from_unsigned
are a bit more challenging, and I'm splitting those off to a later PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really hate these macros, but lgtm
Description of changes:
Kani's current implementation of the arithmetic with overflow operators, e.g. std::intrinsics::mul_with_overflow, involves performing the arithmetic operation twice: once to get the result, and another to determine whether it overflowed. CBMC recently introduced a new operation in diffblue/cbmc#6903 that performs a single arithmetic operation that returns a struct with two fields: the result and whether it overflowed. This PR switches the implementation of those intrinsics to the more efficient CBMC operation.
Resolved issues:
Resolves #ISSUE-NUMBER
Call-outs:
I kept the old implementations around (e.g.
cprover_bindings::goto_program::expr::Expr::mul_overflow
) because I haven't replaced all the code that uses them. The remaining usages, e.g. bykani_compiler::codegen_cprover_gotoc::codegen::intrinsic::GotocCtx::count_in_bytes
require a bit more refactoring that I'll leave to a future PR.Testing:
Before: 0.765
After: 0.0788
Speedup: 9.7
Before: 0.090
After: 0.0689
Speedup: 1.3
Before: 0.074
After: 0.060
Speedup: 1.2
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.