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 the following assertion in codegenxarch.cpp. ``` noway_assert(op1->OperGet() == GT_LCL_VAR_ADDR || op1->OperGet() == GT_LCL_FLD_ADDR); ``` for the test, JIT\IL_Conformance\Old\directed\ldloca_s_r8. 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 each il instruction 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. 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), and propagate a bit when such var address node is spilled. The assertion is relaxed based on this bit for GT_LCL_VAR. Preivously I attempted to aggressively hammer the type by refactoing ```impBashVarAddrsToI``` in various ways, but it was not straightforward to handle other assertions that are popped up. Without PDB (pass) ``` [0] ldloca.s 0 [1] dup [2] conv.r8 | /--* 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 ```
- Loading branch information