Skip to content

Use explicit secret arguments in IL stubs - #132534

Draft
jkoritzinsky wants to merge 5 commits into
dev/jkoritzinsky/varargs-windows-onlyfrom
dev/jkoritzinsky/secret-stub-arguments
Draft

Use explicit secret arguments in IL stubs#132534
jkoritzinsky wants to merge 5 commits into
dev/jkoritzinsky/varargs-windows-onlyfrom
dev/jkoritzinsky/secret-stub-arguments

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Summary

  • represent IL stub secret context as an explicit native int modreq(SecretStubArgument) parameter
  • remove StubHelpers.GetStubContext() and the obsolete publish-secret-parameter consumption paths
  • update JIT, interpreter, VM, and ABI documentation to use the explicit argument

Validation

  • checked CoreCLR build
  • reverse P/Invoke struct marshalling test
  • COM extension points test
  • calling-convention tests under JIT and interpreter mode
  • JIT formatting

Note

This pull request description was generated by GitHub Copilot.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 9 pipeline(s).
7 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Comment threadsrc/coreclr/inc/corjitflags.h Outdated
Comment threadsrc/coreclr/jit/lower.cpp
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 19, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI lite review requested due to automatic review settings August 19, 2026 22:26

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates CoreCLR IL stub plumbing so the “secret” stub context is represented and consumed via an explicit native int parameter annotated with the SecretStubArgument required modifier, removing the older StubHelpers.GetStubContext() / publish-secret-parameter paths. This aligns the VM, JIT, interpreter, SuperPMI tooling, and ABI docs around a single mechanism for identifying and binding the secret stub argument register.

Changes:

  • Adds explicit SecretStubArgument handling in stub generation and IL emission, and removes the StubHelpers.GetStubContext() intrinsic path.
  • Removes CORJIT_FLAG_PUBLISH_SECRET_PARAM, replaces it with a new method attribute flag (CORINFO_FLG_HAS_MD_CONTEXT_ARG) and updates JIT/interpreter consumption accordingly.
  • Updates SuperPMI dumps, JIT interface type definitions, and ABI documentation to reflect the new model.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/vm/stubgen.hAdds secret-arg placeholder constant, tracking index, and IL emission helper.
src/coreclr/vm/stubgen.cppPatches placeholder LDARG to the real index during linking; tracks secret-arg index.
src/coreclr/vm/jitinterface.cppExposes new method flag for stubs with an MD context argument; recognizes SecretStubArgument modreq.
src/coreclr/vm/dllimport.hReplaces stub-context load helper with signature augmentation helper for secret argument.
src/coreclr/vm/dllimport.cppAppends SecretStubArgument to signatures where needed and updates stub IL to load it via LDARG.
src/coreclr/vm/corelib.hRemoves binding for StubHelpers.GetStubContext.
src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cppAdds dump support for CORINFO_FLG_HAS_MD_CONTEXT_ARG; removes dump of publish-secret JIT flag.
src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cppRemoves CORJIT_FLAG_PUBLISH_SECRET_PARAM stringification.
src/coreclr/tools/Common/JitInterface/CorInfoTypes.csAdds CORINFO_FLG_HAS_MD_CONTEXT_ARG; removes CORJIT_FLAG_PUBLISH_SECRET_PARAM.
src/coreclr/System.Private.CoreLib/src/System/StubHelpers.csRemoves the GetStubContext intrinsic stub.
src/coreclr/jit/targetx86.hUpdates comment for REG_SECRET_STUB_PARAM to match explicit SecretStubArgument usage.
src/coreclr/jit/targetwasm.hSame comment update for wasm target.
src/coreclr/jit/targetriscv64.hSame comment update for riscv64 target.
src/coreclr/jit/targetloongarch64.hSame comment update for loongarch64 target.
src/coreclr/jit/targetarm64.hSame comment update for arm64 target.
src/coreclr/jit/targetarm.hSame comment update for arm target.
src/coreclr/jit/targetamd64.hSame comment update for amd64 target.
src/coreclr/jit/namedintrinsiclist.hRemoves named intrinsic entry for StubHelpers.GetStubContext.
src/coreclr/jit/morph.cppSwitches frame-pointer GC-info requirement to new “has MD context arg” signal.
src/coreclr/jit/lsrabuild.cppRemoves publish-secret-param live-in handling (now modeled via explicit parameter).
src/coreclr/jit/lower.cppUses MD-context-arg + explicit secret arg local to populate InlinedCallFrame secret field.
src/coreclr/jit/lclvars.cppTracks SecretStubArgument parameter as a well-known arg and adjusts stack-space logic.
src/coreclr/jit/jitee.hRemoves JIT_FLAG_PUBLISH_SECRET_PARAM mapping.
src/coreclr/jit/importercalls.cppRemoves import-time intrinsic expansion for GetStubContext; handles SecretStubArgument modifier on call args.
src/coreclr/jit/flowgraph.cppUses presence of explicit secret stub arg for reverse pinvoke tracking and uses MD-context-arg for frame sizing.
src/coreclr/jit/compiler.hppStops treating the old stub-arg temp as a special “never zero-init” var.
src/coreclr/jit/compiler.hAdds helpers to query presence of explicit secret stub arg and MD-context-arg flag; removes compPublishStubParam.
src/coreclr/jit/compiler.cppRemoves allocation/initialization of the old “published stub argument” temp.
src/coreclr/jit/codegenxarch.cppUpdates stack-probing path to preserve secret stub register based on explicit-secret-arg presence.
src/coreclr/jit/codegenloongarch64.cppUpdates assertions to key off explicit-secret-arg presence.
src/coreclr/jit/codegencommon.cppRemoves homing/spilling logic tied to the old publish-secret-param mechanism.
src/coreclr/jit/codegenarm64.cppUpdates assertions to key off explicit-secret-arg presence.
src/coreclr/jit/codegenarm.cppUpdates assertions to key off explicit-secret-arg presence.
src/coreclr/interpreter/intrinsics.cppRemoves interpreter named intrinsic lookup for GetStubContext.
src/coreclr/interpreter/compiler.cppDetects SecretStubArgument modifier on parameters and removes intrinsic-based expansion path.
src/coreclr/inc/jiteeversionguid.hBumps JIT/EE interface GUID for flag/contract changes.
src/coreclr/inc/corjitflags.hRemoves CORJIT_FLAG_PUBLISH_SECRET_PARAM.
src/coreclr/inc/corinfo.hAdds CORINFO_FLG_HAS_MD_CONTEXT_ARG and keeps SecretStubArgument modifier flag.
docs/design/coreclr/botr/clr-abi.mdUpdates ABI documentation to describe SecretStubArgument as an explicit parameter.

Comment on lines 149 to 152
*Stub dispatch* - when a virtual call uses a VSD stub, rather than back-patching the calling code (or disassembling it), the JIT must place the address of the stub used to load the call target, the "stub indirection cell", in (x86) `EAX` / (AMD64) `R11` / (ARM) `R12` / (ARM64) `R11`. In the JIT, this is encapsulated in the `VirtualStubParamInfo` class.

*Normal PInvoke* - The VM shares IL stubs based on signatures, but wants the right method to show up in call stack and exceptions, so the MethodDesc for the exact PInvoke is passed in the (x86) `EAX` / (AMD64) `R10` / (ARM, ARM64) `R12` (in the JIT: `REG_SECRET_STUB_PARAM`). Then in the IL stub, when the JIT gets `CORJIT_FLG_PUBLISH_SECRET_PARAM`, it must move the register into a compiler temp. The value is returned for the intrinsic `NI_System_StubHelpers_GetStubContext`.
*Normal PInvoke* - The VM shares IL stubs based on signatures, but wants the right method to show up in call stack and exceptions, so the MethodDesc for the exact PInvoke is passed in the (x86) `EAX` / (AMD64) `R10` / (ARM, ARM64) `R12` (in the JIT: `REG_SECRET_STUB_PARAM`). The IL stub represents this value as an explicit `native int` parameter with a required `System.Runtime.CompilerServices.SecretStubArgument` modifier, which tells the JIT to bind the parameter to the secret stub register.

Comment threadsrc/coreclr/vm/dllimport.cpp Outdated
{
WRAPPER_NO_CONTRACT;

if (SF_IsFieldGetterStub(dwStubFlags) || SF_IsFieldSetterStub(dwStubFlags))

@jkotasjkotasAug 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the logic positive and check for stubs that do need the hidden arg - it will make it easier to match the conditions with the emitter. I think it should be just:

if (SF_IsForwardStub(dwStubFlags))
{
if (SF_IsVarArgStub(dwStubFlags))
return true;
}
else
{
// All native-managed stub need the hidden arg currently
return true;
}

{
genSpillOrAddNonStandardRegisterParam(m_compiler->lvaStubArgumentVar, REG_SECRET_STUB_PARAM, &graph);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can delete genSpillOrAddNonStandardRegisterParam.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 39 out of 39 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/coreclr/jit/flowgraph.cpp:1862

  • The comment describing the Reverse P/Invoke helper’s third argument is misleading: the secret stub argument passed here is thunk data (e.g., UMEntryThunkData*) that the helper uses to recover the target MethodDesc, not the MethodDesc itself. Updating the comment would avoid future confusion while working on this code path.
 // If we have a secret param for a Reverse P/Invoke, that means that we are in an IL stub.
// In this case, the method handle we pass down to the Reverse P/Invoke helper should be
// the target method, which is passed in the secret parameter.

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated
Comment on lines +5731 to +5735
if (lclNum == lvaSecretStubArg)
{
// The secret stub argument is passed in a nonstandard register without caller-reserved stack space.
return true;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you instead switch the Windows ABI case to base the result on lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter?

@jkoritzinsky
jkoritzinskyforce-pushed the dev/jkoritzinsky/secret-stub-arguments branch from 21f3e07 to d378425CompareAugust 20, 2026 18:17
jkoritzinskyand others added 5 commits August 21, 2026 15:26
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jkoritzinsky
jkoritzinskyforce-pushed the dev/jkoritzinsky/secret-stub-arguments branch from d378425 to 4725c3aCompareAugust 21, 2026 22:26
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jkotas@jakobbotsch