Use CBMC's arithmetic operators that return both the result and whether it overflowed#1426
Conversation
0478d4a to
3c1b18e
Compare
| } | ||
|
|
||
| /// Uses CBMC's add-with-overflow operation that performs a single addition | ||
| /// operation |
There was a problem hiding this comment.
Give C or pseudocode example
| // 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.
Why do this here? I'd expect it to happen in arithmetic_overflow_result_type
There was a problem hiding this comment.
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.
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.
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.
Were you going to split this off?
There was a problem hiding this comment.
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.
tedinski
left a comment
There was a problem hiding this comment.
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_bytesrequire 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.