Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6207af4
Initial P/Invokes on WASM
AaronRobinsonMSFT Aug 30, 2025
d815079
Apply feedback.
AaronRobinsonMSFT Sep 1, 2025
187ff1b
Narrow use of printing interpreter stack on assert to WASM.
AaronRobinsonMSFT Sep 1, 2025
58c9ee4
Remvove white space edit.
AaronRobinsonMSFT Sep 1, 2025
9f6858a
Handle native helpers with portable entry points
AaronRobinsonMSFT Sep 1, 2025
f385dac
Switch to high order bits for native entry points
AaronRobinsonMSFT Sep 1, 2025
f931b09
Rework WASM thunk look-up
AaronRobinsonMSFT Sep 1, 2025
998c61d
Fix Release build.
AaronRobinsonMSFT Sep 1, 2025
0aa701f
Feedback.
AaronRobinsonMSFT Sep 1, 2025
ed82888
Use Volatile<void*>.
AaronRobinsonMSFT Sep 1, 2025
e7755ad
Use nullptr when possible.
AaronRobinsonMSFT Sep 1, 2025
03cf908
Protect against null thread.
AaronRobinsonMSFT Sep 2, 2025
a86e411
Feedback on alignment define values.
AaronRobinsonMSFT Sep 2, 2025
6a7858f
Fix up assert for marshalling checks on stack slot size.
AaronRobinsonMSFT Sep 2, 2025
9f1e376
Remove bit marking for native implemented helpers.
AaronRobinsonMSFT Sep 2, 2025
fc8660e
Add casts to avoid build breaks.
AaronRobinsonMSFT Sep 2, 2025
00e8b26
Add TADDR cast.
AaronRobinsonMSFT Sep 2, 2025
9dd7738
Add more casts
AaronRobinsonMSFT Sep 2, 2025
41d730c
Remove invalid cast.
AaronRobinsonMSFT Sep 2, 2025
eb72bba
Feedback
AaronRobinsonMSFT Sep 2, 2025
1ac6302
Feedback.
AaronRobinsonMSFT Sep 3, 2025
7317a7d
Fix getHelperFtn for portable entrypoints
jkotas Sep 3, 2025
8aea576
Nits
AaronRobinsonMSFT Sep 3, 2025
4d67d11
Make field more obvious.
AaronRobinsonMSFT Sep 3, 2025
c2edbb2
Fix bug in casting.
AaronRobinsonMSFT Sep 3, 2025
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
6 changes: 3 additions & 3 deletions src/coreclr/debug/daccess/daccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5635,7 +5635,7 @@ ClrDataAccess::GetJitHelperName(

for (int i = 0; i < CORINFO_HELP_COUNT; i++)
{
if (address == (TADDR)(pTable[i].pfnHelper))
if (address == pTable[i].pfnHelper)
return s_rgHelperNames[i];
}
}
Expand All @@ -5652,7 +5652,7 @@ ClrDataAccess::GetJitHelperName(
PTR_READ(dac_cast<TADDR>(&hlpDynamicFuncTable), DYNAMIC_CORINFO_HELP_COUNT * sizeof(VMHELPDEF)));
for (unsigned d = 0; d < DYNAMIC_CORINFO_HELP_COUNT; d++)
{
if (address == (TADDR)(pDynamicTable[d].pfnHelper))
if (address == pDynamicTable[d].pfnHelper)
{
return s_rgHelperNames[s_rgDynamicHCallIds[d]];
}
Expand Down Expand Up @@ -5991,7 +5991,7 @@ ClrDataAccess::GetMethodVarInfo(MethodDesc* methodDesc,
BOOL success = DebugInfoManager::GetBoundariesAndVars(
request,
DebugInfoStoreNew, NULL, // allocator
BoundsType::Instrumented,
BoundsType::Instrumented,
NULL, NULL,
&countNativeVarInfo, &nativeVars);

Expand Down
22 changes: 11 additions & 11 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ SharedPatchBypassBuffer* DebuggerControllerPatch::GetOrCreateSharedPatchBypassBu
//

BYTE* bufferBypassRW = pSharedPatchBypassBufferRW->BypassBuffer;

// Overwrite the *signed* displacement.
int dwOldDisp = *(int*)(&patchBypassRX[instrAttrib.m_dwOffsetToDisp]);
int dwNewDisp = offsetof(SharedPatchBypassBuffer, BypassBuffer) -
(offsetof(SharedPatchBypassBuffer, PatchBypass) + instrAttrib.m_cbInstr);
*(int*)(&patchBypassRW[instrAttrib.m_dwOffsetToDisp]) = dwNewDisp;

// This could be an LEA, which we'll just have to change into a MOV and copy the original address.
if (((patchBypassRX[0] == 0x4C) || (patchBypassRX[0] == 0x48)) && (patchBypassRX[1] == 0x8d))
{
Expand All @@ -229,7 +229,7 @@ SharedPatchBypassBuffer* DebuggerControllerPatch::GetOrCreateSharedPatchBypassBu
_ASSERTE(instrAttrib.m_cOperandSize <= SharedPatchBypassBuffer::cbBufferBypass);
// Copy the data into our buffer.
memcpy(bufferBypassRW, this->address + instrAttrib.m_cbInstr + dwOldDisp, instrAttrib.m_cOperandSize);

if (instrAttrib.m_fIsWrite)
{
// save the actual destination address and size so when we TriggerSingleStep() we can update the value
Expand All @@ -238,17 +238,17 @@ SharedPatchBypassBuffer* DebuggerControllerPatch::GetOrCreateSharedPatchBypassBu
}
}
}

#endif // TARGET_AMD64

m_pSharedPatchBypassBuffer->SetInstructionAttrib(instrAttrib);

// Since we just created a new buffer of code, but the CPU caches code and may
// not be aware of our changes. This should force the CPU to dump any cached
// instructions it has in this region and load the new ones from memory
FlushInstructionCache(GetCurrentProcess(), patchBypassRW + CORDbg_BREAK_INSTRUCTION_SIZE,
MAX_INSTRUCTION_LENGTH - CORDbg_BREAK_INSTRUCTION_SIZE);

return m_pSharedPatchBypassBuffer;
}
#endif // !FEATURE_EMULATE_SINGLESTEP
Expand Down Expand Up @@ -2405,29 +2405,29 @@ static bool _AddrIsJITHelper(PCODE addr)
{
for (int i = 0; i < CORINFO_HELP_COUNT; i++)
{
if (hlpFuncTable[i].pfnHelper == (void*)addr)
if (hlpFuncTable[i].pfnHelper == addr)
{
LOG((LF_CORDB, LL_INFO10000,
"_ANIM: address of helper function found: 0x%08x\n",
"_ANIM: address of helper function found: 0x%zx\n",
addr));
return true;
}
}

for (unsigned d = 0; d < DYNAMIC_CORINFO_HELP_COUNT; d++)
{
if (hlpDynamicFuncTable[d].pfnHelper == (void*)addr)
if (hlpDynamicFuncTable[d].pfnHelper == addr)
{
LOG((LF_CORDB, LL_INFO10000,
"_ANIM: address of helper function found: 0x%08x\n",
"_ANIM: address of helper function found: 0x%zx\n",
addr));
return true;
}
}

LOG((LF_CORDB, LL_INFO10000,
"_ANIM: address within runtime dll, but not a helper function "
"0x%08x\n", addr));
"0x%zx\n", addr));
}
#else // !defined(HOST_64BIT) && !defined(TARGET_UNIX)
// TODO: Figure out what we want to do here
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/inc/regdisp.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ inline void FillContextPointers(PT_KNONVOLATILE_CONTEXT_POINTERS pCtxPtrs, PT_CO
*(&pCtxPtrs->Tp) = &pCtx->Tp;
*(&pCtxPtrs->Fp) = &pCtx->Fp;
*(&pCtxPtrs->Ra) = &pCtx->Ra;
#else // TARGET_RISCV64
#elif defined(TARGET_WASM)
// Wasm doesn't have registers
#else // TARGET_WASM
PORTABILITY_ASSERT("FillContextPointers");
#endif // _TARGET_???_ (ELSE)
}
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/pal/src/arch/wasm/stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do

/* debugbreak */

#ifdef _DEBUG
extern void DBG_PrintInterpreterStack();
#endif // _DEBUG

extern "C" void
DBG_DebugBreak()
{
#ifdef _DEBUG
DBG_PrintInterpreterStack();
#endif // _DEBUG
asm volatile ("unreachable");
}

Expand Down
10 changes: 3 additions & 7 deletions src/coreclr/vm/callhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ void* DispatchCallSimple(
callDescrData.pTarget = pTargetAddress;

#ifdef TARGET_WASM
PORTABILITY_ASSERT("wasm need to fill call description data");
#endif
callDescrData.nArgsSize = numStackSlotsToCopy * sizeof(ARGHOLDER_TYPE);
#endif // TARGET_WASM

if ((dwDispatchCallSimpleFlags & DispatchCallSimple_CatchHandlerFoundNotification) != 0)
{
Expand Down Expand Up @@ -519,9 +519,6 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
CallDescrData callDescrData;

callDescrData.pSrc = pTransitionBlock + sizeof(TransitionBlock);
#ifdef TARGET_WASM
callDescrData.pTransitionBlock = (TransitionBlock*)pTransitionBlock;
#endif
_ASSERTE((nStackBytes % TARGET_POINTER_SIZE) == 0);
callDescrData.numStackSlots = nStackBytes / TARGET_POINTER_SIZE;
#ifdef CALLDESCR_ARGREGS
Expand All @@ -539,9 +536,8 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
callDescrData.fpReturnSize = fpReturnSize;
callDescrData.pTarget = m_pCallTarget;
#ifdef TARGET_WASM
callDescrData.pMD = m_pMD;
callDescrData.nArgsSize = m_argIt.GetArgSize();
#endif
#endif // TARGET_WASM

CallDescrWorkerWithHandler(&callDescrData);

Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/callhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ struct CallDescrData
UINT32 fpReturnSize;
PCODE pTarget;
#ifdef TARGET_WASM
// method description is used to compile the method with the interpreter
MethodDesc* pMD;
// size of the arguments and the transition block are used to execute the method with the interpreter
size_t nArgsSize;
TransitionBlock* pTransitionBlock;
#endif

#ifdef CALLDESCR_RETBUFFARGREG
Expand Down
34 changes: 19 additions & 15 deletions src/coreclr/vm/callingconvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#ifndef __CALLING_CONVENTION_INCLUDED
#define __CALLING_CONVENTION_INCLUDED

#ifdef FEATURE_INTERPRETER
#include "../../interpreter/interpretershared.h"
#endif // FEATURE_INTERPRETER

BOOL IsRetBuffPassedAsFirstArg();

// Describes how a single argument is laid out in registers and/or stack locations when given as an input to a
Expand Down Expand Up @@ -491,31 +495,31 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE

while (typ == ELEMENT_TYPE_VALUETYPE &&
pMT->GetNumInstanceFields() == 1 && (!pMT->HasLayout() ||
pMT->GetNumInstanceFieldBytes() == 4
)) // Don't do the optimization if we're getting specified anything but the trivial layout.
{
FieldDesc * pFD = pMT->GetApproxFieldDescListRaw();
pMT->GetNumInstanceFieldBytes() == 4
)) // Don't do the optimization if we're getting specified anything but the trivial layout.
{
FieldDesc * pFD = pMT->GetApproxFieldDescListRaw();
CorElementType type = pFD->GetFieldType();

bool exitLoop = false;
switch (type)
switch (type)
{
case ELEMENT_TYPE_VALUETYPE:
{
//@todo: Is it more apropos to call LookupApproxFieldTypeHandle() here?
TypeHandle fldHnd = pFD->GetApproxFieldTypeHandleThrowing();
//@todo: Is it more apropos to call LookupApproxFieldTypeHandle() here?
TypeHandle fldHnd = pFD->GetApproxFieldTypeHandleThrowing();
CONSISTENCY_CHECK(!fldHnd.IsNull());
pMT = fldHnd.GetMethodTable();
FALLTHROUGH;
}
}
case ELEMENT_TYPE_PTR:
case ELEMENT_TYPE_I:
case ELEMENT_TYPE_U:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
{
{
typ = type;
break;
break;
}
default:
exitLoop = true;
Expand Down Expand Up @@ -853,7 +857,7 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE
pLoc->m_idxFloatReg = floatRegOfsInBytes / FLOAT_REGISTER_SIZE;
pLoc->m_cFloatReg = 1;
}
else
else
#endif // UNIX_AMD64_ABI
if (!TransitionBlock::IsStackArgumentOffset(argOffset))
{
Expand Down Expand Up @@ -1874,11 +1878,11 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()

return argOfs;
#elif defined(TARGET_WASM)
int cbArg = ALIGN_UP(StackElemSize(argSize), TARGET_POINTER_SIZE);
int cbArg = ALIGN_UP(argSize, INTERP_STACK_SLOT_SIZE);
int argOfs = TransitionBlock::GetOffsetOfArgs() + m_ofsStack;

m_ofsStack += cbArg;

return argOfs;
#else
PORTABILITY_ASSERT("ArgIteratorTemplate::GetNextOffset");
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5654,6 +5654,9 @@ PCODE PInvoke::GetStubForILStub(PInvokeMethodDesc* pNMD, MethodDesc** ppStubMD,
// varargs goes through vararg PInvoke stub
//
pStub = TheVarargPInvokeStub(pNMD->HasRetBuffArg());

// Only vararg P/Invoke use shared stubs, they need a precode to push the hidden argument.
(void)pNMD->GetOrCreatePrecode();
}

if (pNMD->IsEarlyBound())
Expand Down
Loading