-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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 back missing conv opcodes when compiling via System.Linq.Expressions #76024
Conversation
Tagging subscribers to this area: @cston Issue DetailsThe conversion opcodes are still necessary when the sign of the value might change, in which case the conversion opcode will do a sign/zero extend to the full i32 storage used by the IL execution stack. For example, before this change, conversions from ushort to short were ignored. Consider expressions converting the value
|
Are there tests you can add? Or do we already have such tests and those tests were indeed failing on the interpreter? |
@stephentoub This issue was hit with already existing SLE tests on interpreter, so I think this is good enough for such a small change. |
Could you please share a minimal IL repro that demonstrates the problem? I am not aware of any ambiguity in the ECMA spec about how to represent the small integer types on the IL stack; or how these values should behave with conversions. If the tests are only failing on interpreter, it sounds like there is an bug in the interpreter that should be fixed. We should not be compensating for it by emitting different IL. |
@jkotas @stephentoub Ok, maybe this issue does need some tests. My change is not really about adding a conversion opcode because mono interpreter is not behaving accordingly (even though this more or less describes how I stumbled across this issue). I opened this PR because SLE ILGen is ignoring certain conversions for what I consider to be dubious reasons. Take this sample for example:
With all execution engines, both CoreCLR and mono, this prints.
The IL of method
The test is attempting to generate the same code via the linq expressions, but the resulting compiled dynamic method skips the conv.i2 opcode and is just
And the conv.i2 opcode is not a nop because, as you can see, the result of the method is different between the compiled and interpreted versions. |
Ah ok, you meant System.Linq.Expressions interpreter. What are the existing System.Linq.Expressions tests that are hitting this issue? All System.Linq.Expressions tests should be running both with |
Well, there is no issue with SLE interpreter only with SLE ILGen. I noticed this issue while running a tweaked version of the mono interpreter on SLE tests. There are no test failures on CI most likely because the return of the lambda expression is still a short ( |
Could you please turn the sample from #76024 (comment) into a test that is failing before this change and passing after this change? |
3c2f462
to
4a304bd
Compare
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. Thanks!
src/libraries/System.Linq.Expressions/tests/Convert/ConvertTests.cs
Outdated
Show resolved
Hide resolved
With expression funcs that return int32 instead of short/byte to prevent implicit conversions.
The conversion opcodes are still necessary when the sign of the value might change, in which case the conversion opcode will do a sign/zero extend to the full i32 storage used by the IL execution stack. For example, before this change, conversions from ushort to short were ignored. Consider expressions converting the value `ushort.MaxValue` to short (testcase ConvertUShortToShortTest). `ushort.MaxValue` will be pushed to execution stack as a i32 ldc of value 0xffff. The conv.i2 opcode would change the value on the stack to 0xffffffff so it shouldn't be omitted.
4a304bd
to
f322b1f
Compare
The conversion opcodes are still necessary when the sign of the value might change, in which case the conversion opcode will do a sign/zero extend to the full i32 storage used by the IL execution stack.
For example, before this change, conversions from ushort to short were ignored. Consider expressions converting the value
ushort.MaxValue
to short (testcase ConvertUShortToShortTest).ushort.MaxValue
will be pushed to execution stack as a i32 ldc of value 0xffff. The conv.i2 opcode would change the value on the stack to 0xffffffff so it shouldn't be omitted.