-
Notifications
You must be signed in to change notification settings - Fork 274
Add generic gcc overflow builtins #5249
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
Add generic gcc overflow builtins #5249
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #5249 +/- ##
===========================================
+ Coverage 67.42% 67.43% +<.01%
===========================================
Files 1162 1162
Lines 95637 95682 +45
===========================================
+ Hits 64484 64522 +38
- Misses 31153 31160 +7
Continue to review full report at Codecov.
|
93dd661
to
4638bbe
Compare
I had considered replacing the implementation of the non-generic |
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.
LGTM
src/ansi-c/c_typecheck_expr.cpp
Outdated
{ | ||
auto const &argument = expr.arguments()[arg_index]; | ||
bool const arg_has_correct_type = | ||
(arg_index < 2) ? (argument.type().id() == ID_signedbv || |
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.
Trying to do this in a single loop makes this a little complex to read. Would it be better to handle the argument type-check (seeing as their are only 3 args) as two separate blocks, one block to check arg 0 and 1, and one to check arg 2, with each block setting the arg_has_correct_type flag, then the error message block could stay the same (but not be in a loop).
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.
Hm, maybe? Could you sketch out how you’d do it?
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.
Sorry, yeah, some pseudo code would have been better :-)
bool correct_type=true;
// Typecheck args 0 and 1
for(int i = 0; i<1; i++) {
correct_type &= is_correct_type(arg[i])
}
// Typecheck arg 2
correct_type &= is_correct_result_type(arg[2]);
// Error message if typecheck fails
if(!correct_type) {
// user error message here
}
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.
So basically the same logic you have, but without the tertiary operator which you effectively use to encode additional state in the argument index :-)
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.
Oh, and I think you may be able to use the existing utility functions is_signed_or_unsigned_bitvector
, is_c_integral_type
and is_c_integral_pointer_type
here too ?
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 didn’t know about these, I’ll see about clarifying it using your suggestions.
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.
Looks good - couple of queries around code structure (but not necessarily blockers). It might also be nice if some of the test cases also explored the case where arg 0 and arg 1 are not the same type... As far as I can tell from GCC docs, those first two arguments can be arbitrary (different) integral types, whereas I think all the test cases here use the same type for both arguments. I think everything will work fine if they are different, but would be nice to have one or two test cases that show that :-)
src/ansi-c/c_typecheck_expr.cpp
Outdated
std::ostringstream error_message; | ||
error_message << expr.source_location().as_string() << ": " | ||
<< identifier << " has signature " << identifier | ||
<< "(integral, integral, integral*), " |
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.
GCC docs show: (type1 a, type2 b, type3 *res)
- implying a, b and res can all be different integral types, so might be worth writing this as (integral1, integral2, integral3 *)
? What does gcc give as an error message in this case?
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.
Version dependent I suppose. gcc 10
says
test.c:4:46: error: argument 2 in call to function ‘__builtin_sub_overflow’ does not have integral type
I was kind of inspired by C++ concept syntax for this, but if you think it’s confusing I can change it to something else.
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.
Well, I prefer what you have than what GCC has :-) No big deal.
GCC has builtin operators `__builtin_add_overflow`, `__builtin_sub_overflow` and `__builtin_mul_overflow` that perform an arithmetic operation and check for overflow at the same time. This adds support for these operators.
4638bbe
to
47ae446
Compare
GCC has builtin operators
__builtin_add_overflow
,__builtin_sub_overflow
and
__builtin_mul_overflow
that perform an arithmetic operation andcheck for overflow at the same time. This adds support for these
operators.