Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
When I start using ILASM from VS environment instead of ILASM from the CoreCLR build, I ran into an assertion for a test, JIT\IL_Conformance\Old\directed\ldloca_s_r8: https://github.com/dotnet/coreclr/blob/master/src/jit/codegenxarch.cpp#L7400-L7404 The MSILs from both ILASMs are technically identical, but only difference is the presence of PDB file due to https://github.com/dotnet/coreclr/issues/2982. When PDB file is present, JIT ensures spilling individual il instructions for good debugging experience. As shown below, in the case of NoPDB, the type for the local address on stack (from ldloca) is converted to an integer type since it is used for type cast to double. Note initially (when creating addr node) JIT starts from TY_BYREF conservatively for such var address. On the other hand in the case of PDB which failed to assert, JIT spills this address node to a local var. By the time JIT imports conv.r8, JIT uses the local var with TY_BYREF. The existing "IsVarAddr" API didn't capture such case so it ended up with feeding local var with byref type to cast operation, which is unexpected. There may be several ways to address this issue. The way I fix is to introduce a flag to local var (I can't simply add a flag to tree-node whose bits run out so conflict with other use). When JIT has to spill such var address (on stack) to a local var, JIT records such bit to the local var. I extends the implementation of ```IsVarAddr``` to ```impIsVarAddrOnStack``` in order to catch this case as well. So, when JIT needs to hammer the type like using "impBashVarAddrsToI", JIT now uses this API, instead. Without PDB (pass) ``` [0] ldloca.s 0 [1] dup [2] conv.r8 * stmtExpr void (top level) (IL 0x000... ???) | /--* cast double <- long --> cast from long to double | | \--* addr long --> This is local adress on stack, so type is hammered to long | | \--* lclVar double V00 loc0 \--* = double ``` With PDB (fail) ``` [0] ldloca.s 0 * stmtExpr void (top level) (IL 0x000... ???) | /--* addr byref | | \--* lclVar double V00 loc0 \--* = byref \--* lclVar byref V256 tmp0 --> Address is spilled to local var. [1] dup * stmtExpr void (top level) (IL 0x002... ???) \--* no_op void [ 2] conv.r8 * stmtExpr void (top level) (IL 0x003... ???) | /--* cast double <- byref --> !Assertion: Can't convert byref to double where the src is lclVar. | | \--* lclVar byref V256 tmp0 \--* = double ``` With PDB after fix (pass) ``` [0] ldloca.s 0 * stmtExpr void (top level) (IL 0x000... ???) | /--* addr byref | | \--* lclVar double V00 loc0 \--* = byref \--* lclVar byref V256 tmp0 --> Address is spilled to local var. JIT sets a bit to it. [1] dup * stmtExpr void (top level) (IL 0x002... ???) \--* no_op void [ 2] conv.r8 * stmtExpr void (top level) (IL 0x003... ???) | /--* cast double <- long --> byref is hammered to long same as the case of noPDB. | | \--* lclVar long V256 tmp0 \--* = double ```
- Loading branch information