-
Notifications
You must be signed in to change notification settings - Fork 274
Conversion of bitwise exprt
s to SMT terms in new SMT backend
#6676
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
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #6676 +/- ##
===========================================
+ Coverage 76.82% 76.89% +0.06%
===========================================
Files 1582 1582
Lines 182758 183170 +412
===========================================
+ Hits 140403 140840 +437
+ Misses 42355 42330 -25
Continue to review full report at Codecov.
|
251b047
to
48d1e7e
Compare
bitwise_and_expr.operands().cbegin(), | ||
bitwise_and_expr.operands().cend(), | ||
[](exprt operand) | ||
{ return can_cast_type<integer_bitvector_typet>(operand.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.
This would exclude C booleans which are non integer bit vectors. Is there a reason we shouldn't support using C booleans with bitwise operations?
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'm playing with this a bit and I'll get back to you on this one.
{ | ||
UNIMPLEMENTED_FEATURE( | ||
"Bitwise \"AND\" conversion requires that all operands have the same " | ||
"sort" + |
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 use of UNIMPLEMENTED_FEATURE
macro doesn't read well to me. The previous version would make sense in the new context. However the new text describes a condition, not an unimplemented feature. The condition in the text does not match the condition in the code either.
- The
std::all_of
check is checking the types, not the sorts. Which is an important distinction as the exprs have types, whereas the smt terms have sorts. - The text refers to all operands having the same sort, but this condition can be reached if all the operands have the same, but unimplemented type, such as
bool_typet
as an arbitrarily chosen example.
My preference for resolving this comment would be that you just leave the original UNIMPLEMENTED_FEATURE
macro unchanged and put your new code above it, rather than putting it in an else block, or changing its text.
This comment also applies to other sections marked with a 🐸 emoji.
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 can see your point about the wording, and of course I'm happy to change it to the previous wording inside the UNIMPLEMENTED_FEATURE
macro, but I see no benefit to removing the else block.
To the contrary, I have a very keen preference for the else
block to stay there, because it makes the structure of the code more obvious.
Both with and without the else
branch, the function handles two potential cases so far (one in which we can process the type of the input parameter, and one in which we don't). The presence of the else
branch makes this fact explicit, revealing this hidden structure, compared to relying to the default behaviour of having the function fall through to an unimplemented feature macro to signify.
I'm open to changing this if there exist readability/technical issues that make the change you suggest superior to the existing structure.
@@ -416,3 +416,75 @@ TEST_CASE( | |||
REQUIRE_THROWS(convert_expr_to_smt(unary_minus_exprt{true_exprt{}})); | |||
} | |||
} | |||
|
|||
SCENARIO( |
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 are your new tests using SCENARIO
, GIVEN
, WHEN
and THEN
rather than TEST_CASE
and SECTION
like the existing tests? It seems really wordy to me rather than adding that much extra value. But that could just be a personal preference thing. It does mean that the tests for similar features are now written in a mixture of styles, which could make it more difficult to compare them.
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.
Hi Thomas, these are BDD style tests.
I found this useful when I was approaching this given that I implemented this in a Test-Driven/Behaviour-Driven style.
In catch-2, SCENARIO
, GIVEN
, WHEN
, etc all map to SECTION
, but I find them superior in at least to ways:
- The behaviour intent reads better, allowing the test to document the expected behaviour in a way that reads naturally.
- The testing failures get reported in a much better way (in my opinion), allowing a developer to understand exactly what's going wrong. A test failure using these looks like this:
-------------------------------------------------------------------------------
Scenario: Arithmetic Right-shift expressions are converted to SMT terms
Given: An integer bitvector
When: We construct an ashr_exprt and with a shift of 0 places
Then: When we convert it, we should be getting an arithmetic shift-right
term
-------------------------------------------------------------------------------
/Users/fotiskoutoulakis/Devel/cbmc/unit/solvers/smt2_incremental/convert_expr_to_smt.cpp:793
...............................................................................
/Users/fotiskoutoulakis/Devel/cbmc/unit/solvers/smt2_incremental/convert_expr_to_smt.cpp:803: FAILED:
REQUIRE( constructed_term == expected_term )
Compared to a normal SECTION
test, which gives none of the above context information.
Now granted, part of that might contain an element of style preference, but given that the tests are relatively exhaustive (in terms of behaviour driven by them) and it's a bit late in the development cycle of this PR, I suggest we don't change the tests now.
If you are very heavily opposed to them, we could change them as part of another 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 am happy for the style to stay as is. I don't think the bike-shedding involved here is really worth spending time on.
With either style of test, if I see a failing test either the only piece of information I need is the general area of functionality, or I am likely need to do some interactive debugging and I can see what the test context is from the code anyway. Therefore I think the situations in which the added context will be useful are limited. Which is why I feel dubious about the benefit of the added contextual information, in exchange for the code bloat.
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( |
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.
🐸
} | ||
else | ||
{ | ||
UNIMPLEMENTED_FEATURE( |
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.
🐸
|
||
// Both of the above tests have been testing the positive case so far - | ||
// where everything goes more or less how we expect. Let's see how it does | ||
// with a negative case - where one of the terms is bad or otherwise |
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 comment seems "chatty" rather than actually useful. This isn't part of a slide presentation 😉
48d1e7e
to
3509c42
Compare
…ile. The rationale for that is that it's going to be used by functions that need to see it defined within the translation unit, and at its current location it's invisible to some of the functions defined above that.
@@ -416,3 +416,75 @@ TEST_CASE( | |||
REQUIRE_THROWS(convert_expr_to_smt(unary_minus_exprt{true_exprt{}})); | |||
} | |||
} | |||
|
|||
SCENARIO( |
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 am happy for the style to stay as is. I don't think the bike-shedding involved here is really worth spending time on.
With either style of test, if I see a failing test either the only piece of information I need is the general area of functionality, or I am likely need to do some interactive debugging and I can see what the test context is from the code anyway. Therefore I think the situations in which the added context will be useful are limited. Which is why I feel dubious about the benefit of the added contextual information, in exchange for the code bloat.
/// \param expr: The expression of which the operands we evaluate for type | ||
/// equality. | ||
template <typename target_typet> | ||
static bool operands_are_of_same_type(const exprt &expr) |
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'd suggest removing the word same
from the name of this function because it does not in fact check the operands have the same (equal) type. For example - operands_are_of_same_type<bitvector_typet>(expr)
, will pass if expr
has operands of types bv_typet{8}
and bv_typet{16}
even though these 2 types are distinct. This is not a short coming of our validation because the bit vector theory operators check for matched widths. But it does mean that the current name of this function is somewhat misleading.
3509c42
to
05e1fd6
Compare
This PR adds support for the conversion of bitwise
exprt
s to the various SMT terms that they correspond to.The following operators have been implemented: