Merge lp://qastaging/~epics-core/epics-base/fix-calc-bit-manipulation into lp://qastaging/~epics-core/epics-base/3.14
Proposed by
Ralph Lange
Status: | Merged |
---|---|
Approved by: | Andrew Johnson |
Approved revision: | 12615 |
Merged at revision: | 12611 |
Proposed branch: | lp://qastaging/~epics-core/epics-base/fix-calc-bit-manipulation |
Merge into: | lp://qastaging/~epics-core/epics-base/3.14 |
Diff against target: |
371 lines (+141/-53) 3 files modified
src/libCom/calc/calcPerform.c (+35/-22) src/libCom/calc/postfix.c (+15/-12) src/libCom/test/epicsCalcTest.cpp (+91/-19) |
To merge this branch: | bzr merge lp://qastaging/~epics-core/epics-base/fix-calc-bit-manipulation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ralph Lange | Approve | ||
Andrew Johnson | Approve | ||
Review via email: mp+286515@code.qastaging.launchpad.net |
Description of the change
Fix for bug lp:1514520
- Pulls a backport of a 3.15 change to the calc engine, setting the internal integer format to the size-fixed epicsInt32 type.
- Adds tests that show the behavior described in the bug report.
- Applies the original patch by Dirk from that bug report.
To be able to apply this to 3.14, I had to backport the change to the sized-fixed integers. For sanity.
When applying to 3.15, that first commit has to be omitted.
One thing that I am not sure of: left shifts (zeroes filled in) are handled different than right shifts (ones filled in, assuming a signed integer operation).
The documentation (AppDevGuide) leaves it open.
To post a comment you must log in.
Added an epicsUInt32 utop variable to calcPerform() to reduce the number of casts, and added some code comments.
Previous versions have always handled shifts as signed quantities, so the sign bit is extended on right-shifts. I changed the left-shift code to match, although it doesn't actually make any difference.
The shift operators also need to have their shift count limited to avoid Undefined Behavior; I see 2 realistic possibilities: ANDing the shift count with 31; or return 0 on shift-overflow but when right-shifting a negative quantity return -1 on shift-overflow. The first is the fastest and simplest to code, but the second one might be regarded as be more logical. Any preferences or alternative suggestions? I have implemented the first option for now.
The large positive decimal values in your tests are causing the same overflows when converted from double to integer that Dirk originally reported, they always convert to 0x80000000 on my RHEL systems so some tests fail. The paragraph before Dirk's "The fix is:" line explains that you have to use negative values for bit 31 to be set, which my tests agree with. The negative versions that work are 0xaaaaaaaa = -1431655766, 0xffff0000 = -65536. Note that postfix() compiles double literals into a LITERAL_INT op-code if the value can be safely held in an epicsInt32, so adding ".0" has no effect; but using ".1" instead does work, the fraction gets truncated.
Also fixed some minor white-space issues.