Skip to content
Draft
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
5 changes: 4 additions & 1 deletion src/coreclr/inc/cordebuginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,9 @@ class ICorDebugInfo

UNKNOWN_ILNUM = -4, // Unknown variable

MAX_ILNUM = -4 // Sentinel value. This should be set to the largest magnitude value in th enum
CALL_RETURN_ILNUM = -5, // The return value of a call

MAX_ILNUM = -5 // Sentinel value. This should be set to the largest magnitude value in th enum
// so that the compression routines know the enum's range.
};

Expand All @@ -403,6 +405,7 @@ class ICorDebugInfo
{
uint32_t startOffset;
uint32_t endOffset;
uint32_t callReturnValueILOffset;
uint32_t varNumber;
VarLoc loc;
};
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* 5635ae9d-ffa5-4336-b027-a383971e3918 */
0x5635ae9d,
0xffa5,
0x4336,
{0xb0, 0x27, 0xa3, 0x83, 0x97, 0x1e, 0x39, 0x18}
constexpr GUID JITEEVersionIdentifier = { /* 59df85b8-c0fd-4e40-aea1-68cb2cd916cc */
0x59df85b8,
0xc0fd,
0x4e40,
{0xae, 0xa1, 0x68, 0xcb, 0x2c, 0xd9, 0x16, 0xcc}
};

#endif // JIT_EE_VERSIONING_GUID_H
12 changes: 1 addition & 11 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3255,17 +3255,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call)

params.isJump = call->IsFastTailCall();
params.hasAsyncRet = call->IsAsync();

// We need to propagate the debug information to the call instruction, so we can emit
// an IL to native mapping record for the call, to support managed return value debugging.
// We don't want tail call helper calls that were converted from normal calls to get a record,
// so we skip this hash table lookup logic in that case.
if (m_compiler->opts.compDbgInfo && m_compiler->genCallSite2DebugInfoMap != nullptr && !call->IsTailCall())
{
DebugInfo di;
(void)m_compiler->genCallSite2DebugInfoMap->Lookup(call, &di);
params.debugInfo = di;
}
params.returnValueCall = call;

#ifdef DEBUG
// Pass the call signature information down into the emitter so the emitter can associate
Expand Down
92 changes: 92 additions & 0 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,98 @@ void CodeGen::genEmitCallWithCurrentGC(EmitCallParams& params)
params.gcrefRegs = gcInfo.gcRegGCrefSetCur;
params.byrefRegs = gcInfo.gcRegByrefSetCur;
GetEmitter()->emitIns_Call(params);

// Emit an entry for managed return value reporting, if needed.
GenTreeCall* call = params.returnValueCall;
JITDUMP("Emit ret val for [%06u]\n", call == nullptr ? 0 : Compiler::dspTreeID(call));
if ((call == nullptr) || !m_compiler->opts.compDbgInfo || (m_compiler->genCallSite2DebugInfoMap == nullptr) || params.isJump)
{
return;
}
Comment on lines +1763 to +1769

if (call->gtReturnType == TYP_VOID)
{
return;
}

DebugInfo di;
if (!m_compiler->genCallSite2DebugInfoMap->Lookup(call, &di))
{
return;
}

emitLocation retLoc;
retLoc.CaptureLocation(GetEmitter());

CodeGenInterface::EmittedCallReturnInfo info;
info.callILOffset = di.GetRoot().GetLocation().GetOffset();
info.returnLocation = retLoc;

CallArg* retBuf = call->gtArgs.GetRetBufferArg();
if (retBuf != nullptr)
{
GenTree* node = retBuf->GetNode();
assert(node->OperIsPutArg());

node = node->gtGetOp1()->gtSkipReloadOrCopy();
if (!node->OperIs(GT_LCL_ADDR))
{
return;
}

unsigned lclNum = node->AsLclVarCommon()->GetLclNum();
unsigned lclOffs = node->AsLclVarCommon()->GetLclOffs();
int stackLevelBias = 0;
#ifdef TARGET_X86
stackLevelBias = getCurrentStackLevel();
if (params.argSize > 0)
{
// Call popped these but stack level hasn't been adjusted yet, account for it here
stackLevelBias -= params.argSize;
}
#endif

info.returnValueLoc = getSiVarLoc(m_compiler->lvaGetDesc(lclNum), lclOffs, stackLevelBias);
}
Comment on lines +1801 to +1814
else if (call->HasMultiRegRetVal())
{
const ReturnTypeDesc* retDesc = call->GetReturnTypeDesc();
unsigned numRegs = retDesc->GetReturnRegCount();
if (numRegs > 2)
{
// Cannot encode more than 2 registers.
return;
}

assert(numRegs == 2);
info.returnValueLoc.storeVariableInRegisters(
retDesc->GetABIReturnReg(0, call->GetUnmanagedCallConv()),
retDesc->GetABIReturnReg(1, call->GetUnmanagedCallConv()));
}
else if (varTypeIsFloating(call))
{
#ifdef TARGET_X86
info.returnValueLoc.vlType = VLT_FPSTK;
info.returnValueLoc.vlFPstk.vlfReg = 0;
#else
info.returnValueLoc.storeVariableInRegisters(REG_FLOATRET, REG_NA);
#endif
}
else if (varTypeUsesFloatReg(call))
{
info.returnValueLoc.storeVariableInRegisters(REG_FLOATRET, REG_NA);
}
else
{
info.returnValueLoc.storeVariableInRegisters(REG_INTRET, REG_NA);
}

if (emittedCallReturnInfo == nullptr)
{
emittedCallReturnInfo = new (m_compiler, CMK_DebugInfo) jitstd::vector<EmittedCallReturnInfo>(m_compiler->getAllocator(CMK_DebugInfo));
}

emittedCallReturnInfo->push_back(info);
}

/*****************************************************************************
Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/jit/codegeninterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,15 @@ class CodeGenInterface
const LclVarDsc* varDsc, var_types type, regNumber baseReg, int offset, bool isFramePointerUsed);
};

struct EmittedCallReturnInfo
{
IL_OFFSET callILOffset;
emitLocation returnLocation;
siVarLoc returnValueLoc;
};

public:
siVarLoc getSiVarLoc(const LclVarDsc* varDsc, unsigned int stackLevel) const;
siVarLoc getSiVarLoc(const LclVarDsc* varDsc, unsigned offset, unsigned stackLevel) const;

#ifdef DEBUG
void dumpSiVarLoc(const siVarLoc* varLoc) const;
Expand Down Expand Up @@ -858,6 +865,8 @@ class CodeGenInterface
protected:
VariableLiveKeeper* varLiveKeeper; // Used to manage VariableLiveRanges of variables

jitstd::vector<EmittedCallReturnInfo>* emittedCallReturnInfo;

#ifdef LATE_DISASM
public:
virtual const char* siRegVarName(size_t offs, size_t size, unsigned reg) = 0;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ void CodeGen::genInitialize()
}

initializeVariableLiveKeeper();
emittedCallReturnInfo = new (m_compiler, CMK_DebugInfo) jitstd::vector<EmittedCallReturnInfo>(m_compiler->getAllocator(CMK_DebugInfo));

genPendingCallLabel = nullptr;

Expand Down
12 changes: 1 addition & 11 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2473,17 +2473,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
EmitCallParams params;
params.isJump = call->IsFastTailCall();
params.hasAsyncRet = call->IsAsync();

// We need to propagate the debug information to the call instruction, so we can emit
// an IL to native mapping record for the call, to support managed return value debugging.
// We don't want tail call helper calls that were converted from normal calls to get a record,
// so we skip this hash table lookup logic in that case.
if (m_compiler->opts.compDbgInfo && m_compiler->genCallSite2DebugInfoMap != nullptr && !call->IsTailCall())
{
DebugInfo di;
(void)m_compiler->genCallSite2DebugInfoMap->Lookup(call, &di);
params.debugInfo = di;
}
params.returnValueCall = call;

#ifdef DEBUG
// Pass the call signature information down into the emitter so the emitter can associate
Expand Down
13 changes: 1 addition & 12 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6196,18 +6196,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA

params.isJump = call->IsFastTailCall();
params.hasAsyncRet = call->IsAsync();

// We need to propagate the IL offset information to the call instruction, so we can emit
// an IL to native mapping record for the call, to support managed return value debugging.
// We don't want tail call helper calls that were converted from normal calls to get a record,
// so we skip this hash table lookup logic in that case.

if (m_compiler->opts.compDbgInfo && m_compiler->genCallSite2DebugInfoMap != nullptr && !call->IsTailCall())
{
DebugInfo di;
(void)m_compiler->genCallSite2DebugInfoMap->Lookup(call, &di);
params.debugInfo = di;
}
params.returnValueCall = call;

#ifdef DEBUG
// Pass the call signature information down into the emitter so the emitter can associate
Expand Down
7 changes: 5 additions & 2 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9516,19 +9516,22 @@ class Compiler

void eeGetVars();

unsigned eeVarsCount;
unsigned eeVarsCount = 0;
unsigned eeVarsCapacity = 0;

struct VarResultInfo
{
UNATIVE_OFFSET startOffset;
UNATIVE_OFFSET endOffset;
uint32_t callReturnValueILOffset;
DWORD varNumber;
CodeGenInterface::siVarLoc loc;
}* eeVars;
void eeSetLVcount(unsigned count);
void eeSetLVinfo(unsigned which,
UNATIVE_OFFSET startOffs,
UNATIVE_OFFSET length,
UNATIVE_OFFSET endOffs,
uint32_t callReturnValILOffs,
unsigned varNum,
const CodeGenInterface::siVarLoc& loc);
void eeSetLVdone();
Expand Down
24 changes: 15 additions & 9 deletions src/coreclr/jit/ee_il_dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,10 +670,10 @@ void Compiler::eeSetLVcount(unsigned count)

JITDUMP("VarLocInfo count is %d\n", count);

eeVarsCount = count;
if (eeVarsCount)
eeVarsCapacity = count;
if (count > 0)
{
eeVars = (VarResultInfo*)info.compCompHnd->allocateArray(eeVarsCount * sizeof(eeVars[0]));
eeVars = (VarResultInfo*)info.compCompHnd->allocateArray(count * sizeof(eeVars[0]));
}
else
{
Expand All @@ -683,21 +683,22 @@ void Compiler::eeSetLVcount(unsigned count)

void Compiler::eeSetLVinfo(unsigned which,
UNATIVE_OFFSET startOffs,
UNATIVE_OFFSET length,
UNATIVE_OFFSET endOffs,
uint32_t callReturnValueILOffset,
unsigned varNum,
const CodeGenInterface::siVarLoc& varLoc)
{
// ICorDebugInfo::VarLoc and CodeGenInterface::siVarLoc have to overlap
// This is checked in siInit()

assert(opts.compScopeInfo);
assert(eeVarsCount > 0);
assert(which < eeVarsCount);
assert(which < eeVarsCapacity);

if (eeVars != nullptr)
{
eeVars[which].startOffset = startOffs;
eeVars[which].endOffset = startOffs + length;
eeVars[which].endOffset = endOffs;
eeVars[which].callReturnValueILOffset = callReturnValueILOffset;
eeVars[which].varNumber = varNum;
eeVars[which].loc = varLoc;
}
Expand Down Expand Up @@ -870,15 +871,20 @@ void Compiler::eeDispVar(ICorDebugInfo::NativeVarInfo* var)
{
name = "typeCtx";
}
if (0 <= var->varNumber && var->varNumber < lvaCount)

if (var->varNumber == (DWORD)ICorDebugInfo::CALL_RETURN_ILNUM)
{
int printed = printf("(call %03u)", var->callReturnValueILOffset);
}
Comment on lines +875 to +878
else if (0 <= var->varNumber && var->varNumber < lvaCount)
{
printf("(");
gtDispLclVar(var->varNumber, false);
printf(")");
}
else
{
printf("(%10s)", (VarNameToStr(name) == nullptr) ? "UNKNOWN" : VarNameToStr(name));
printf("(%8s)", (VarNameToStr(name) == nullptr) ? "UNKNOWN" : VarNameToStr(name));
}
printf(" : From %08Xh to %08Xh, in ", var->startOffset, var->endOffset);

Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/emit.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,14 @@ struct EmitCallParams
BitVec ptrVars = BitVecOps::UninitVal();
regMaskTP gcrefRegs = RBM_NONE;
regMaskTP byrefRegs = RBM_NONE;
DebugInfo debugInfo;
regNumber ireg = REG_NA;
regNumber xreg = REG_NA;
unsigned xmul = 0;
ssize_t disp = 0;
bool isJump = false;
bool noSafePoint = false;
// If this call should have managed return value debug info associated with it, this is the call to associate it with.
GenTreeCall* returnValueCall = nullptr;
#ifdef TARGET_WASM
CORINFO_WASM_TYPE_SYMBOL_HANDLE wasmSignature = nullptr;
#endif
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/jit/emitarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4683,12 +4683,6 @@ void emitter::emitIns_Call(const EmitCallParams& params)
}
#endif

/* Managed RetVal: emit sequence point for the call */
if (m_compiler->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
{
codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
}

/*
We need to allocate the appropriate instruction descriptor based
on whether this is a direct/indirect call, and whether we need to
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9493,12 +9493,6 @@ void emitter::emitIns_Call(const EmitCallParams& params)
}
#endif

/* Managed RetVal: emit sequence point for the call */
if (m_compiler->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
{
codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
}

/*
We need to allocate the appropriate instruction descriptor based
on whether this is a direct/indirect call, and whether we need to
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/jit/emitloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2460,12 +2460,6 @@ void emitter::emitIns_Call(const EmitCallParams& params)
}
#endif

/* Managed RetVal: emit sequence point for the call */
if (m_compiler->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
{
codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
}

/*
We need to allocate the appropriate instruction descriptor based
on whether this is a direct/indirect call, and whether we need to
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,12 +1941,6 @@ void emitter::emitIns_Call(const EmitCallParams& params)
emitLoadImmediate<true>(EA_PTRSIZE, params.ireg, imm); // upper bits
}

/* Managed RetVal: emit sequence point for the call */
if (m_compiler->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
{
codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
}

/*
We need to allocate the appropriate instruction descriptor based
on whether this is a direct/indirect call, and whether we need to
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/jit/emitwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,6 @@ void emitter::emitIns_Call(const EmitCallParams& params)
assert(params.callType < EC_COUNT);
assert((params.callType == EC_FUNC_TOKEN) || (params.addr == nullptr));

/* Managed RetVal: emit sequence point for the call */
if (m_compiler->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
{
codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
}

assert(params.wasmSignature != nullptr);

/*
Expand Down
Loading
Loading