Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,15 @@ int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArray<Reloc*
m_pILToNativeMap[m_ILToNativeMapSize].source = ICorDebugInfo::STACK_EMPTY;
m_ILToNativeMapSize++;
}

if (ins->flags & INTERP_INST_FLAG_DBG_CALL_INSTRUCTION)
{
InterpCallReturnInfo info;
info.ilOffset = ilOffset;
info.postCallNativeOffset = ConvertOffset(ins->nativeOffset + GetInsLength(ins));
info.returnValueVarOffset = m_pVars[ins->dVar].offset;
m_callReturnInfos.Add(info);
}
}
}

Expand Down Expand Up @@ -1258,10 +1267,12 @@ void InterpCompiler::EmitCode()

PatchRelocations(&relocs);

if (m_numILVars > 0)
int32_t callReturnCount = m_callReturnInfos.GetSize();
int32_t totalVarCount = m_numILVars + callReturnCount;
if (totalVarCount > 0)
{
// This will eventually be freed by the VM, using freeArray.
ICorDebugInfo::NativeVarInfo* eeVars = (ICorDebugInfo::NativeVarInfo*)m_compHnd->allocateArray(m_numILVars * sizeof(ICorDebugInfo::NativeVarInfo));
ICorDebugInfo::NativeVarInfo* eeVars = (ICorDebugInfo::NativeVarInfo*)m_compHnd->allocateArray(totalVarCount * sizeof(ICorDebugInfo::NativeVarInfo));

int j = 0;
for (int i = 0; i < m_numILVars; i++)
Expand All @@ -1276,7 +1287,22 @@ void InterpCompiler::EmitCode()
j++;
}

m_compHnd->setVars(m_methodInfo->ftn, m_numILVars, eeVars);
// Append a CALL_RETURN_ILNUM entry per managed call site so the debugger can read the
// return value when stepping out of the callee.
for (int i = 0; i < callReturnCount; i++)
{
const InterpCallReturnInfo& callReturn = m_callReturnInfos.Get(i);
eeVars[j].startOffset = callReturn.postCallNativeOffset;
eeVars[j].endOffset = callReturn.postCallNativeOffset + 1; // implicit, recomputed on decode
eeVars[j].varNumber = (uint32_t)ICorDebugInfo::CALL_RETURN_ILNUM;
eeVars[j].callReturnValueILOffset = callReturn.ilOffset;
eeVars[j].loc.vlType = ICorDebugInfo::VLT_STK;
eeVars[j].loc.vlStk.vlsBaseReg = ICorDebugInfo::REGNUM_FP;
eeVars[j].loc.vlStk.vlsOffset = callReturn.returnValueVarOffset;
j++;
}

m_compHnd->setVars(m_methodInfo->ftn, totalVarCount, eeVars);
}

if (m_ILToNativeMapSize == 0 && m_pILToNativeMap != NULL)
Expand Down Expand Up @@ -2187,6 +2213,7 @@ InterpCompiler::InterpCompiler(COMP_HANDLE compHnd,
, m_initLocals(false)
, m_unmanagedCallersOnly(false)
, m_publishSecretStubParam(false)
, m_callReturnInfos(GetMemPoolAllocator(IMK_NativeToILMapping))
, m_globalVarsWithRefsStackTop(0)
, m_varIntervalMaps(GetMemPoolAllocator(IMK_IntervalMap))
#ifdef DEBUG
Expand Down Expand Up @@ -5645,6 +5672,8 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
m_pLastNewIns->SetSVar(CALL_ARGS_SVAR);

m_pLastNewIns->flags |= INTERP_INST_FLAG_CALL;
if (!tailcall && !newObj && !isCalli && callInfo.sig.retType != CORINFO_TYPE_VOID)
m_pLastNewIns->flags |= INTERP_INST_FLAG_DBG_CALL_INSTRUCTION;
m_pLastNewIns->info.pCallInfo = new (getAllocator(IMK_CallInfo)) InterpCallInfo();
m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;

Expand Down
13 changes: 12 additions & 1 deletion src/coreclr/interpreter/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,16 @@ enum InterpInstFlags
// Flag used internally by the var offset allocator
INTERP_INST_FLAG_ACTIVE_CALL = 0x02,
// The IL stack is empty at this instruction
INTERP_INST_FLAG_EMPTY_IL_STACK = 0x04
INTERP_INST_FLAG_EMPTY_IL_STACK = 0x04,
// Marks a value-returning managed call site whose return value is reportable to the debugger
INTERP_INST_FLAG_DBG_CALL_INSTRUCTION = 0x08
};

struct InterpCallReturnInfo
{
uint32_t ilOffset;
uint32_t postCallNativeOffset;
int32_t returnValueVarOffset;
};

struct InterpInst
Expand Down Expand Up @@ -861,6 +870,8 @@ class InterpCompiler
#endif
int32_t m_ILToNativeMapSize = 0;

TArray<InterpCallReturnInfo, MemPoolAllocator> m_callReturnInfos;

InterpBasicBlock* AllocBB(int32_t ilOffset);
InterpBasicBlock* GetBB(int32_t ilOffset);
void LinkBBs(InterpBasicBlock *from, InterpBasicBlock *to);
Expand Down
Loading