summaryrefslogtreecommitdiff
path: root/src/jit/codegencommon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/codegencommon.cpp')
-rw-r--r--src/jit/codegencommon.cpp577
1 files changed, 1 insertions, 576 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index 3c0d0b600b..4ac7fcbf40 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -6483,581 +6483,6 @@ void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed
#endif // !ARM64 !ARM
}
-#ifdef PROFILING_SUPPORTED
-
-//-----------------------------------------------------------------------------------
-// genProfilingEnterCallback: Generate the profiling function enter callback.
-//
-// Arguments:
-// initReg - register to use as scratch register
-// pInitRegZeroed - OUT parameter. *pInitRegZeroed set to 'false' if 'initReg' is
-// not zero after this call.
-//
-// Return Value:
-// None
-//
-// Notes:
-// The x86 profile enter helper has the following requirements (see ProfileEnterNaked in
-// VM\i386\asmhelpers.asm for details):
-// 1. The calling sequence for calling the helper is:
-// push FunctionIDOrClientID
-// call ProfileEnterHelper
-// 2. The calling function has an EBP frame.
-// 3. EBP points to the saved ESP which is the first thing saved in the function. Thus,
-// the following prolog is assumed:
-// push ESP
-// mov EBP, ESP
-// 4. All registers are preserved.
-// 5. The helper pops the FunctionIDOrClientID argument from the stack.
-//
-void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed)
-{
- assert(compiler->compGeneratingProlog);
-
- // Give profiler a chance to back out of hooking this method
- if (!compiler->compIsProfilerHookNeeded())
- {
- return;
- }
-
-#if defined(_TARGET_AMD64_)
-#if !defined(UNIX_AMD64_ABI)
-
- unsigned varNum;
- LclVarDsc* varDsc;
-
- // Since the method needs to make a profiler callback, it should have out-going arg space allocated.
- noway_assert(compiler->lvaOutgoingArgSpaceVar != BAD_VAR_NUM);
- noway_assert(compiler->lvaOutgoingArgSpaceSize >= (4 * REGSIZE_BYTES));
-
- // Home all arguments passed in arg registers (RCX, RDX, R8 and R9).
- // In case of vararg methods, arg regs are already homed.
- //
- // Note: Here we don't need to worry about updating gc'info since enter
- // callback is generated as part of prolog which is non-gc interruptible.
- // Moreover GC cannot kick while executing inside profiler callback which is a
- // profiler requirement so it can examine arguments which could be obj refs.
- if (!compiler->info.compIsVarArgs)
- {
- for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->info.compArgsCount; varNum++, varDsc++)
- {
- noway_assert(varDsc->lvIsParam);
-
- if (!varDsc->lvIsRegArg)
- {
- continue;
- }
-
- var_types storeType = varDsc->lvaArgType();
- regNumber argReg = varDsc->lvArgReg;
-
- instruction store_ins = ins_Store(storeType);
-
-#ifdef FEATURE_SIMD
- if ((storeType == TYP_SIMD8) && genIsValidIntReg(argReg))
- {
- store_ins = INS_mov;
- }
-#endif // FEATURE_SIMD
-
- getEmitter()->emitIns_S_R(store_ins, emitTypeSize(storeType), argReg, varNum, 0);
- }
- }
-
- // Emit profiler EnterCallback(ProfilerMethHnd, caller's SP)
- // RCX = ProfilerMethHnd
- if (compiler->compProfilerMethHndIndirected)
- {
- // Profiler hooks enabled during Ngen time.
- // Profiler handle needs to be accessed through an indirection of a pointer.
- getEmitter()->emitIns_R_AI(INS_mov, EA_PTR_DSP_RELOC, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- // No need to record relocations, if we are generating ELT hooks under the influence
- // of COMPlus_JitELTHookEnabled=1
- if (compiler->opts.compJitELTHookEnabled)
- {
- genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- }
-
- // RDX = caller's SP
- // Notes
- // 1) Here we can query caller's SP offset since prolog will be generated after final frame layout.
- // 2) caller's SP relative offset to FramePointer will be negative. We need to add absolute value
- // of that offset to FramePointer to obtain caller's SP value.
- assert(compiler->lvaOutgoingArgSpaceVar != BAD_VAR_NUM);
- int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
- getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_ARG_1, genFramePointerReg(), -callerSPOffset);
-
- // Can't have a call until we have enough padding for rejit
- genPrologPadForReJit();
-
- // This will emit either
- // "call ip-relative 32-bit offset" or
- // "mov rax, helper addr; call rax"
- genEmitHelperCall(CORINFO_HELP_PROF_FCN_ENTER, 0, EA_UNKNOWN);
-
- // TODO-AMD64-CQ: Rather than reloading, see if this could be optimized by combining with prolog
- // generation logic that moves args around as required by first BB entry point conditions
- // computed by LSRA. Code pointers for investigating this further: genFnPrologCalleeRegArgs()
- // and genEnregisterIncomingStackArgs().
- //
- // Now reload arg registers from home locations.
- // Vararg methods:
- // - we need to reload only known (i.e. fixed) reg args.
- // - if floating point type, also reload it into corresponding integer reg
- for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->info.compArgsCount; varNum++, varDsc++)
- {
- noway_assert(varDsc->lvIsParam);
-
- if (!varDsc->lvIsRegArg)
- {
- continue;
- }
-
- var_types loadType = varDsc->lvaArgType();
- regNumber argReg = varDsc->lvArgReg;
-
- instruction load_ins = ins_Load(loadType);
-
-#ifdef FEATURE_SIMD
- if ((loadType == TYP_SIMD8) && genIsValidIntReg(argReg))
- {
- load_ins = INS_mov;
- }
-#endif // FEATURE_SIMD
-
- getEmitter()->emitIns_R_S(load_ins, emitTypeSize(loadType), argReg, varNum, 0);
-
-#if FEATURE_VARARG
- if (compiler->info.compIsVarArgs && varTypeIsFloating(loadType))
- {
- regNumber intArgReg = compiler->getCallArgIntRegister(argReg);
- instruction ins = ins_CopyFloatToInt(loadType, TYP_LONG);
- inst_RV_RV(ins, argReg, intArgReg, loadType);
- }
-#endif // FEATURE_VARARG
- }
-
- // If initReg is one of RBM_CALLEE_TRASH, then it needs to be zero'ed before using.
- if ((RBM_CALLEE_TRASH & genRegMask(initReg)) != 0)
- {
- *pInitRegZeroed = false;
- }
-
-#else // !defined(UNIX_AMD64_ABI)
-
- // Emit profiler EnterCallback(ProfilerMethHnd, caller's SP)
- // R14 = ProfilerMethHnd
- if (compiler->compProfilerMethHndIndirected)
- {
- // Profiler hooks enabled during Ngen time.
- // Profiler handle needs to be accessed through an indirection of a pointer.
- getEmitter()->emitIns_R_AI(INS_mov, EA_PTR_DSP_RELOC, REG_PROFILER_ENTER_ARG_0,
- (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- // No need to record relocations, if we are generating ELT hooks under the influence
- // of COMPlus_JitELTHookEnabled=1
- if (compiler->opts.compJitELTHookEnabled)
- {
- genSetRegToIcon(REG_PROFILER_ENTER_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_8BYTE, REG_PROFILER_ENTER_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- }
-
- // R15 = caller's SP
- // Notes
- // 1) Here we can query caller's SP offset since prolog will be generated after final frame layout.
- // 2) caller's SP relative offset to FramePointer will be negative. We need to add absolute value
- // of that offset to FramePointer to obtain caller's SP value.
- assert(compiler->lvaOutgoingArgSpaceVar != BAD_VAR_NUM);
- int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
- getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_PROFILER_ENTER_ARG_1, genFramePointerReg(), -callerSPOffset);
-
- // Can't have a call until we have enough padding for rejit
- genPrologPadForReJit();
-
- // We can use any callee trash register (other than RAX, RDI, RSI) for call target.
- // We use R11 here. This will emit either
- // "call ip-relative 32-bit offset" or
- // "mov r11, helper addr; call r11"
- genEmitHelperCall(CORINFO_HELP_PROF_FCN_ENTER, 0, EA_UNKNOWN, REG_DEFAULT_PROFILER_CALL_TARGET);
-
- // If initReg is one of RBM_CALLEE_TRASH, then it needs to be zero'ed before using.
- if ((RBM_CALLEE_TRASH & genRegMask(initReg)) != 0)
- {
- *pInitRegZeroed = false;
- }
-
-#endif // !defined(UNIX_AMD64_ABI)
-
-#elif defined(_TARGET_X86_) || defined(_TARGET_ARM_)
-
- unsigned saveStackLvl2 = genStackLevel;
-
-#if defined(_TARGET_X86_)
-// Important note: when you change enter probe layout, you must also update SKIP_ENTER_PROF_CALLBACK()
-// for x86 stack unwinding
-
-#if defined(UNIX_X86_ABI)
- // Manually align the stack to be 16-byte aligned. This is similar to CodeGen::genAlignStackBeforeCall()
- getEmitter()->emitIns_R_I(INS_sub, EA_4BYTE, REG_SPBASE, 0xC);
-#endif // UNIX_X86_ABI
-
- // Push the profilerHandle
- if (compiler->compProfilerMethHndIndirected)
- {
- getEmitter()->emitIns_AR_R(INS_push, EA_PTR_DSP_RELOC, REG_NA, REG_NA, (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- inst_IV(INS_push, (size_t)compiler->compProfilerMethHnd);
- }
-
-#elif defined(_TARGET_ARM_)
- // On Arm arguments are prespilled on stack, which frees r0-r3.
- // For generating Enter callout we would need two registers and one of them has to be r0 to pass profiler handle.
- // The call target register could be any free register.
- regNumber argReg = REG_PROFILER_ENTER_ARG;
- regMaskTP argRegMask = genRegMask(argReg);
- assert((regSet.rsMaskPreSpillRegArg & argRegMask) != 0);
-
- if (compiler->compProfilerMethHndIndirected)
- {
- getEmitter()->emitIns_R_AI(INS_ldr, EA_PTR_DSP_RELOC, argReg, (ssize_t)compiler->compProfilerMethHnd);
- regSet.verifyRegUsed(argReg);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_4BYTE, argReg, (ssize_t)compiler->compProfilerMethHnd);
- }
-#else // _TARGET_*
- NYI("Pushing the profilerHandle & caller's sp for the profiler callout and locking registers");
-#endif // _TARGET_*
-
- //
- // Can't have a call until we have enough padding for rejit
- //
- genPrologPadForReJit();
-
- // This will emit either
- // "call ip-relative 32-bit offset" or
- // "mov rax, helper addr; call rax"
- genEmitHelperCall(CORINFO_HELP_PROF_FCN_ENTER,
- 0, // argSize. Again, we have to lie about it
- EA_UNKNOWN); // retSize
-
-#if defined(_TARGET_X86_)
- // Check that we have place for the push.
- assert(compiler->fgPtrArgCntMax >= 1);
-
-#if defined(UNIX_X86_ABI)
- // Restoring alignment manually. This is similar to CodeGen::genRemoveAlignmentAfterCall
- getEmitter()->emitIns_R_I(INS_add, EA_4BYTE, REG_SPBASE, 0x10);
-#endif // UNIX_X86_ABI
-
-#elif defined(_TARGET_ARM_)
- if (initReg == argReg)
- {
- *pInitRegZeroed = false;
- }
-#else // _TARGET_*
- NYI("Pushing the profilerHandle & caller's sp for the profiler callout and locking registers");
-#endif // _TARGET_*
-
- /* Restore the stack level */
-
- SetStackLevel(saveStackLvl2);
-
-#else // target
- NYI("Emit Profiler Enter callback");
-#endif // target
-}
-
-//-----------------------------------------------------------------------------------
-// genProfilingLeaveCallback: Generate the profiling function leave or tailcall callback.
-// Technically, this is not part of the epilog; it is called when we are generating code for a GT_RETURN node.
-//
-// Arguments:
-// helper - which helper to call. Either CORINFO_HELP_PROF_FCN_LEAVE or CORINFO_HELP_PROF_FCN_TAILCALL
-//
-// Return Value:
-// None
-//
-// Notes:
-// The x86 profile leave/tailcall helper has the following requirements (see ProfileLeaveNaked and
-// ProfileTailcallNaked in VM\i386\asmhelpers.asm for details):
-// 1. The calling sequence for calling the helper is:
-// push FunctionIDOrClientID
-// call ProfileLeaveHelper or ProfileTailcallHelper
-// 2. The calling function has an EBP frame.
-// 3. EBP points to the saved ESP which is the first thing saved in the function. Thus,
-// the following prolog is assumed:
-// push ESP
-// mov EBP, ESP
-// 4. helper == CORINFO_HELP_PROF_FCN_LEAVE: All registers are preserved.
-// helper == CORINFO_HELP_PROF_FCN_TAILCALL: Only argument registers are preserved.
-// 5. The helper pops the FunctionIDOrClientID argument from the stack.
-//
-void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FCN_LEAVE*/)
-{
- assert((helper == CORINFO_HELP_PROF_FCN_LEAVE) || (helper == CORINFO_HELP_PROF_FCN_TAILCALL));
-
- // Only hook if profiler says it's okay.
- if (!compiler->compIsProfilerHookNeeded())
- {
- return;
- }
-
- compiler->info.compProfilerCallback = true;
-
- // Need to save on to the stack level, since the helper call will pop the argument
- unsigned saveStackLvl2 = genStackLevel;
-
-#if defined(_TARGET_AMD64_)
-#if !defined(UNIX_AMD64_ABI)
-
- // Since the method needs to make a profiler callback, it should have out-going arg space allocated.
- noway_assert(compiler->lvaOutgoingArgSpaceVar != BAD_VAR_NUM);
- noway_assert(compiler->lvaOutgoingArgSpaceSize >= (4 * REGSIZE_BYTES));
-
- // If thisPtr needs to be kept alive and reported, it cannot be one of the callee trash
- // registers that profiler callback kills.
- if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaTable[compiler->info.compThisArg].lvIsInReg())
- {
- regMaskTP thisPtrMask = genRegMask(compiler->lvaTable[compiler->info.compThisArg].lvRegNum);
- noway_assert((RBM_PROFILER_LEAVE_TRASH & thisPtrMask) == 0);
- }
-
- // At this point return value is computed and stored in RAX or XMM0.
- // On Amd64, Leave callback preserves the return register. We keep
- // RAX alive by not reporting as trashed by helper call. Also note
- // that GC cannot kick-in while executing inside profiler callback,
- // which is a requirement of profiler as well since it needs to examine
- // return value which could be an obj ref.
-
- // RCX = ProfilerMethHnd
- if (compiler->compProfilerMethHndIndirected)
- {
- // Profiler hooks enabled during Ngen time.
- // Profiler handle needs to be accessed through an indirection of an address.
- getEmitter()->emitIns_R_AI(INS_mov, EA_PTR_DSP_RELOC, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- // Don't record relocations, if we are generating ELT hooks under the influence
- // of COMPlus_JitELTHookEnabled=1
- if (compiler->opts.compJitELTHookEnabled)
- {
- genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- }
-
- // RDX = caller's SP
- // TODO-AMD64-Cleanup: Once we start doing codegen after final frame layout, retain the "if" portion
- // of the stmnts to execute unconditionally and clean-up rest.
- if (compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT)
- {
- // Caller's SP relative offset to FramePointer will be negative. We need to add absolute
- // value of that offset to FramePointer to obtain caller's SP value.
- int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
- getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_ARG_1, genFramePointerReg(), -callerSPOffset);
- }
- else
- {
- // If we are here means that it is a tentative frame layout during which we
- // cannot use caller's SP offset since it is an estimate. For now we require the
- // method to have at least a single arg so that we can use it to obtain caller's
- // SP.
- LclVarDsc* varDsc = compiler->lvaTable;
- NYI_IF((varDsc == nullptr) || !varDsc->lvIsParam, "Profiler ELT callback for a method without any params");
-
- // lea rdx, [FramePointer + Arg0's offset]
- getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, REG_ARG_1, 0, 0);
- }
-
- // We can use any callee trash register (other than RAX, RCX, RDX) for call target.
- // We use R8 here. This will emit either
- // "call ip-relative 32-bit offset" or
- // "mov r8, helper addr; call r8"
- genEmitHelperCall(helper, 0, EA_UNKNOWN, REG_ARG_2);
-
-#else // !defined(UNIX_AMD64_ABI)
-
- // RDI = ProfilerMethHnd
- if (compiler->compProfilerMethHndIndirected)
- {
- getEmitter()->emitIns_R_AI(INS_mov, EA_PTR_DSP_RELOC, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- if (compiler->opts.compJitELTHookEnabled)
- {
- genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
- }
-
- // RSI = caller's SP
- if (compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT)
- {
- int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed());
- getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_ARG_1, genFramePointerReg(), -callerSPOffset);
- }
- else
- {
- LclVarDsc* varDsc = compiler->lvaTable;
- NYI_IF((varDsc == nullptr) || !varDsc->lvIsParam, "Profiler ELT callback for a method without any params");
-
- // lea rdx, [FramePointer + Arg0's offset]
- getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, REG_ARG_1, 0, 0);
- }
-
- // We can use any callee trash register (other than RAX, RDI, RSI) for call target.
- // We use R11 here. This will emit either
- // "call ip-relative 32-bit offset" or
- // "mov r11, helper addr; call r11"
- genEmitHelperCall(helper, 0, EA_UNKNOWN, REG_DEFAULT_PROFILER_CALL_TARGET);
-
-#endif // !defined(UNIX_AMD64_ABI)
-
-#elif defined(_TARGET_X86_)
-
-#if defined(UNIX_X86_ABI)
- // Manually align the stack to be 16-byte aligned. This is similar to CodeGen::genAlignStackBeforeCall()
- getEmitter()->emitIns_R_I(INS_sub, EA_4BYTE, REG_SPBASE, 0xC);
- AddStackLevel(0xC);
- AddNestedAlignment(0xC);
-#endif // UNIX_X86_ABI
-
- //
- // Push the profilerHandle
- //
-
- if (compiler->compProfilerMethHndIndirected)
- {
- getEmitter()->emitIns_AR_R(INS_push, EA_PTR_DSP_RELOC, REG_NA, REG_NA, (ssize_t)compiler->compProfilerMethHnd);
- }
- else
- {
- inst_IV(INS_push, (size_t)compiler->compProfilerMethHnd);
- }
- genSinglePush();
-
-#if defined(UNIX_X86_ABI)
- int argSize = -REGSIZE_BYTES; // negative means caller-pop (cdecl)
-#else
- int argSize = REGSIZE_BYTES;
-#endif
- genEmitHelperCall(helper, argSize, EA_UNKNOWN /* retSize */);
-
- // Check that we have place for the push.
- assert(compiler->fgPtrArgCntMax >= 1);
-
-#if defined(UNIX_X86_ABI)
- // Restoring alignment manually. This is similar to CodeGen::genRemoveAlignmentAfterCall
- getEmitter()->emitIns_R_I(INS_add, EA_4BYTE, REG_SPBASE, 0x10);
- SubtractStackLevel(0x10);
- SubtractNestedAlignment(0xC);
-#endif // UNIX_X86_ABI
-
-#elif defined(_TARGET_ARM_)
- //
- // Push the profilerHandle
- //
-
- // Contract between JIT and Profiler Leave callout on arm:
- // Return size <= 4 bytes: REG_PROFILER_RET_SCRATCH will contain return value
- // Return size > 4 and <= 8: <REG_PROFILER_RET_SCRATCH,r1> will contain return value.
- // Floating point or double or HFA return values will be in s0-s15 in case of non-vararg methods.
- // It is assumed that profiler Leave callback doesn't trash registers r1,REG_PROFILER_RET_SCRATCH and s0-s15.
- //
- // In the following cases r0 doesn't contain a return value and hence need not be preserved before emitting Leave
- // callback.
- bool r0Trashed;
- emitAttr attr = EA_UNKNOWN;
-
- if (compiler->info.compRetType == TYP_VOID || (!compiler->info.compIsVarArgs && !compiler->opts.compUseSoftFP &&
- (varTypeIsFloating(compiler->info.compRetType) ||
- compiler->IsHfa(compiler->info.compMethodInfo->args.retTypeClass))))
- {
- r0Trashed = false;
- }
- else
- {
- // Has a return value and r0 is in use. For emitting Leave profiler callout we would need r0 for passing
- // profiler handle. Therefore, r0 is moved to REG_PROFILER_RETURN_SCRATCH as per contract.
- if (RBM_ARG_0 & gcInfo.gcRegGCrefSetCur)
- {
- attr = EA_GCREF;
- gcInfo.gcMarkRegSetGCref(RBM_PROFILER_RET_SCRATCH);
- }
- else if (RBM_ARG_0 & gcInfo.gcRegByrefSetCur)
- {
- attr = EA_BYREF;
- gcInfo.gcMarkRegSetByref(RBM_PROFILER_RET_SCRATCH);
- }
- else
- {
- attr = EA_4BYTE;
- }
-
- getEmitter()->emitIns_R_R(INS_mov, attr, REG_PROFILER_RET_SCRATCH, REG_ARG_0);
- regSet.verifyRegUsed(REG_PROFILER_RET_SCRATCH);
- gcInfo.gcMarkRegSetNpt(RBM_ARG_0);
- r0Trashed = true;
- }
-
- if (compiler->compProfilerMethHndIndirected)
- {
- getEmitter()->emitIns_R_AI(INS_ldr, EA_PTR_DSP_RELOC, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- regSet.verifyRegUsed(REG_ARG_0);
- }
- else
- {
- instGen_Set_Reg_To_Imm(EA_4BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- }
-
- genEmitHelperCall(CORINFO_HELP_PROF_FCN_LEAVE,
- 0, // argSize
- EA_UNKNOWN); // retSize
-
- // Restore state that existed before profiler callback
- if (r0Trashed)
- {
- getEmitter()->emitIns_R_R(INS_mov, attr, REG_ARG_0, REG_PROFILER_RET_SCRATCH);
- regSet.verifyRegUsed(REG_ARG_0);
- gcInfo.gcMarkRegSetNpt(RBM_PROFILER_RET_SCRATCH);
- }
-
-#else // target
- NYI("Emit Profiler Leave callback");
-#endif // target
-
- /* Restore the stack level */
- SetStackLevel(saveStackLvl2);
-}
-
-#endif // PROFILING_SUPPORTED
-
/*****************************************************************************
Esp frames :
@@ -11628,7 +11053,7 @@ void CodeGen::genReturn(GenTree* treeNode)
}
}
- genProfilingLeaveCallback();
+ genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_LEAVE);
if (varTypeIsGC(compiler->info.compRetType))
{