-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Implement interpreter CEE_ADD_OVF and CEE_SUB_OVF opcodes #116694
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
Implement interpreter CEE_ADD_OVF and CEE_SUB_OVF opcodes #116694
Conversation
These are needed for a couple of coreclr tests
Tagging subscribers to this area: @BrzVlad, @janvorli, @kg |
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.
Pull Request Overview
This PR adds overflow-checking support for the CEE_ADD_OVF and CEE_SUB_OVF IL opcodes by defining new internal opcodes, wiring them through the compiler, and handling them in the interpreter.
- Introduces signed and unsigned overflow variants for 32-bit and 64-bit adds/subtracts in
interpexec.cpp
. - Registers new overflow opcodes in
intops.def
. - Maps the IL overflow opcodes to the new internal opcodes in
compiler.cpp
.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
src/coreclr/vm/interpexec.cpp | Implements safe-int overflow logic for add/sub ops |
src/coreclr/interpreter/intops.def | Defines new INTOP_ADD_OVF* and INTOP_SUB_OVF* entries |
src/coreclr/interpreter/compiler.cpp | Maps CEE_ADD_OVF* and CEE_SUB_OVF* to internal ops |
Comments suppressed due to low confidence (2)
src/coreclr/vm/interpexec.cpp:983
- We should add dedicated interpreter tests for each new overflow variant (add/sub, 32-bit/64-bit, signed/unsigned) to verify both normal and overflow paths and prevent regressions.
case INTOP_ADD_OVF_I4:
src/coreclr/interpreter/compiler.cpp:3975
- Currently this always emits the 32-bit overflow opcode; double-check that for 64-bit integer operands the compiler emits
INTOP_ADD_OVF_I8
(and similarly for subtraction) to match the interpreter’s handling.
case CEE_ADD_OVF:
int32_t i1 = LOCAL_VAR(ip[2], int32_t); | ||
int32_t i2 = LOCAL_VAR(ip[3], int32_t); | ||
int32_t i3; | ||
if (!ClrSafeInt<int32_t>::addition(i1, i2, i3)) | ||
COMPlusThrow(kOverflowException); | ||
LOCAL_VAR(ip[1], int32_t) = i3; | ||
ip += 4; | ||
break; | ||
} | ||
case INTOP_ADD_OVF_I8: | ||
{ | ||
int64_t i1 = LOCAL_VAR(ip[2], int64_t); | ||
int64_t i2 = LOCAL_VAR(ip[3], int64_t); | ||
int64_t i3; | ||
if (!ClrSafeInt<int64_t>::addition(i1, i2, i3)) | ||
COMPlusThrow(kOverflowException); | ||
LOCAL_VAR(ip[1], int64_t) = i3; |
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.
[nitpick] These four overflow handling blocks (signed/unsigned, 32/64) are nearly identical—consider extracting a templated helper or macro (e.g., HandleOverflowOp<T>(...)
) to reduce duplication and keep future adjustments in sync.
int32_t i1 = LOCAL_VAR(ip[2], int32_t); | |
int32_t i2 = LOCAL_VAR(ip[3], int32_t); | |
int32_t i3; | |
if (!ClrSafeInt<int32_t>::addition(i1, i2, i3)) | |
COMPlusThrow(kOverflowException); | |
LOCAL_VAR(ip[1], int32_t) = i3; | |
ip += 4; | |
break; | |
} | |
case INTOP_ADD_OVF_I8: | |
{ | |
int64_t i1 = LOCAL_VAR(ip[2], int64_t); | |
int64_t i2 = LOCAL_VAR(ip[3], int64_t); | |
int64_t i3; | |
if (!ClrSafeInt<int64_t>::addition(i1, i2, i3)) | |
COMPlusThrow(kOverflowException); | |
LOCAL_VAR(ip[1], int64_t) = i3; | |
HandleOverflowOp<int32_t>(ip, 2, 3, 1); | |
ip += 4; | |
break; | |
} | |
case INTOP_ADD_OVF_I8: | |
{ | |
HandleOverflowOp<int64_t>(ip, 2, 3, 1); |
Copilot uses AI. Check for mistakes.
These are needed for a couple of coreclr tests