Fix to assert 'ret->gtGetOp1() == nullptr' failure in morph.cpp
authorsivarv <sivarv@microsoft.com>
Wed, 3 Feb 2016 14:47:52 +0000 (06:47 -0800)
committersivarv <sivarv@microsoft.com>
Thu, 4 Feb 2016 00:50:58 +0000 (16:50 -0800)
commitb0a84660664c73a26a379e8fb934b228f0fb4cf2
tree7bdb86b3d57382ffefc2b9cbb8c11aa0b422ac6c
parentc92c399cee4c2c772093b67cb6f6cac3d705adc8
Fix to assert 'ret->gtGetOp1() == nullptr' failure in morph.cpp

Investigation reveals that the assumption of GT_RETURN stmnt for methods returning struct through hidden RetBuf argument will be of the form GT_RETURN(TYP_VOID, op1=nullptr, op2=nullptr) is incorrect when running under profiler.

Profiler Leave callback requires that methods with struct return, return RetBuf in RAX. For this reason when required to generate Profiler callbacks, importer generates GT_RETURN(BY_REF, addr of retBuf) - see impReturnInstruction()

There is also another issue that fgAddInternal() which adds oneReturn block doesn't take into account of running under profiler and hence doesn't create genReturnLocal var and as a result oneReturn block doesn't return address of retBufArg. When running under profiler what should happen for a method returning struct via hidden RetBuf is as follows:

Say BB01 is any block ending in GT_RETURN(TYP_BYREF, addr of RetBuf). fgAddInternal() will decide to use oneReturn block since running under profiler. Since the method returns addr of RetBuf it should create a genReturnLocal of type TYP_BYREF. fgMorphBlocks() on finding genReturnLocal is valid, will replace GT_RETURN with as assignment of "genReturnLocal = add of RetBuf" and make BB01 to branch to oneReturn block.

Since fgAddInternal() doesn't take into account of running under profiler, it doesn't create genReturnLocal for methods having hidden RetBuf arg. Hence fgMorphBlocks() will find genReturnLocal is not valid and asserts that GT_RETURN must be of TYP_VOID with its op1=op2=nullptr, which is not the case and hence the assert.

Note that this assert will repro only when running under profiler because importer generates GT_RETURN(TYP_BYREF, addr of RetBuf) for methods with hidden RetBuf arg only when required to generate profiler callbacks.

Fix: Take into account of whether asked to generate Profiler callbacks create genReturnLocal.
Also took this opportunity cleaned up unnecessary code that was executing for unix and added new abstractions to check whether the method being compiled has ret val.

Note in case of unix there is no need to call struct classification logic to normalize struct return type returned in a single register because it is already done in lvaInitTypeRef() and assigned to compRetNativeType.
src/jit/compiler.h
src/jit/flowgraph.cpp
src/jit/morph.cpp