-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
py/objint_longlong: Fix left shift of negative values. #17734
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
base: master
Are you sure you want to change the base?
Conversation
Hmm, so running the
(I don't see these locally, but I have a different gcc locally.) This looks a lot like the problem @koxudaxi was describing in #17649... |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #17734 +/- ##
=======================================
Coverage 98.41% 98.41%
=======================================
Files 171 171
Lines 22210 22210
=======================================
Hits 21857 21857
Misses 353 353 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code size report:
|
Previous comment was wrong, left shifting a negative value is UB in C. Use the same approach as small int shifts (from runtime.c). Signed-off-by: Angus Gratton <angus@redyak.com.au>
Skip the tests if MicroPython can't represent >64-bit integers (these tests repeatedly left shift values by 8 bits). It would be possible to have these tests work in this case I think, as the results are always masked to shorter values. But quite fiddly. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
d2517f1
to
09c6e9b
Compare
Have pulled out the CI change to its own PR. |
|| lhs_val > (LLONG_MAX >> rhs_val) | ||
|| lhs_val < (LLONG_MIN >> rhs_val); | ||
if (!overflow) { | ||
result = (unsigned long long)lhs_val << rhs_val; |
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.
Does this need a cast to unsigned? lhs_val
can still be negative here, but that should be OK.
int("0x10000000000000000", 16) | ||
except: | ||
print("SKIP") # No support for >64-bit integers | ||
raise SystemExit |
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.
Instead of this, could rename the test to end with _intbig.py
. Eg following tests/micropython/viper_misc_intbig.py
and tests/micropython/viper_const_intbig.py
etc.
Another option to fix the overflow check would be: if ((int)rhs_val > 62) {
overflow = 1;
} else {
rhs_val = 1ll << (int)rhs_val;
overflow = mp_mul_ll_overflow(lhs_val, rhs_val, &result);
} I am not sure which one would generate the shortest code, given that the compiler might be able to merge the call to |
Summary
Closes #17702, thanks to @jepler for running these additional checks.
Note: First version of this PR enabled UBSan for longlong tests, but this surfaced another issue so has been spun out to #17735.
Testing
Trade-offs and Alternatives