Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit dbb5135

Browse files
committed
Teach ILStubLinker to use the managed signature for the target stack delta when the stub is a reverse stub.
Make ILStubLinker understand changing calling conventions from instance to non-instance calling conventions.
1 parent 4e5a542 commit dbb5135

File tree

4 files changed

+40
-98
lines changed

4 files changed

+40
-98
lines changed

src/vm/dllimport.cpp

Lines changed: 1 addition & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -270,13 +270,6 @@ class ILStubState : public StubState
270270
STANDARD_VM_CONTRACT;
271271

272272
pInfo->MarshalHiddenLengthArgument(&m_slIL, SF_IsForwardStub(m_dwStubFlags), isForReturnArray);
273-
274-
if (SF_IsReverseStub(m_dwStubFlags))
275-
{
276-
// Hidden length arguments appear explicitly in the native signature
277-
// however, they are not in the managed signature.
278-
m_slIL.AdjustTargetStackDeltaForExtraParam();
279-
}
280273
}
281274

282275
void MarshalFactoryReturn()
@@ -515,15 +508,6 @@ class ILStubState : public StubState
515508
// add the extra arg to the unmanaged signature
516509
LocalDesc locDescNative(ELEMENT_TYPE_I4);
517510
pcs->SetStubTargetArgType(&locDescNative, false);
518-
519-
if (SF_IsReverseStub(m_dwStubFlags))
520-
{
521-
// reverse the effect of SetStubTargetArgType on the stack delta
522-
// (the LCID argument is explicitly passed from unmanaged but does not
523-
// show up in the managed signature in any way)
524-
m_slIL.AdjustTargetStackDeltaForExtraParam();
525-
}
526-
527511
}
528512

529513
void SwapStubSignatures(MethodDesc* pStubMD)
@@ -774,17 +758,6 @@ class ILStubState : public StubState
774758
}
775759
#endif // FEATURE_COMINTEROP
776760

777-
if (SF_IsHRESULTSwapping(m_dwStubFlags) && SF_IsReverseStub(m_dwStubFlags))
778-
{
779-
m_slIL.AdjustTargetStackDeltaForReverseInteropHRESULTSwapping();
780-
}
781-
782-
if (SF_IsForwardCOMStub(m_dwStubFlags))
783-
{
784-
// Compensate for the 'this' parameter.
785-
m_slIL.AdjustTargetStackDeltaForExtraParam();
786-
}
787-
788761
// Don't touch target signatures from this point on otherwise it messes up the
789762
// cache in ILStubState::GetStubTargetMethodSig.
790763

@@ -1624,13 +1597,9 @@ class COMToCLR_ILStubState : public ILStubState
16241597

16251598
ILStubState::BeginEmit(dwStubFlags);
16261599

1627-
if (SF_IsWinRTStaticStub(dwStubFlags))
1600+
if (!SF_IsWinRTStaticStub(dwStubFlags))
16281601
{
16291602
// we are not loading 'this' because the target is static
1630-
m_slIL.AdjustTargetStackDeltaForExtraParam();
1631-
}
1632-
else
1633-
{
16341603
// load this
16351604
m_slIL.GetDispatchCodeStream()->EmitLoadThis();
16361605
}
@@ -1659,7 +1628,6 @@ class COMToCLR_ILStubState : public ILStubState
16591628

16601629
// expect one additional argument - pointer to a location that receives the created instance
16611630
DWORD dwRetValArgNum = pcsDispatch->SetStubTargetArgType(&locDescFactoryRetVal, false);
1662-
m_slIL.AdjustTargetStackDeltaForExtraParam();
16631631

16641632
// convert 'this' to an interface pointer corresponding to the default interface of this class
16651633
pcsUnmarshal->EmitLoadThis();
@@ -1932,50 +1900,6 @@ ILCodeStream* NDirectStubLinker::GetExceptionCleanupCodeStream()
19321900
return m_pcsExceptionCleanup;
19331901
}
19341902

1935-
void NDirectStubLinker::AdjustTargetStackDeltaForExtraParam()
1936-
{
1937-
LIMITED_METHOD_CONTRACT;
1938-
//
1939-
// Compensate for the extra parameter.
1940-
//
1941-
m_iTargetStackDelta++;
1942-
}
1943-
1944-
void NDirectStubLinker::AdjustTargetStackDeltaForReverseInteropHRESULTSwapping()
1945-
{
1946-
WRAPPER_NO_CONTRACT;
1947-
//
1948-
// In the case of reverse pinvoke, we build up the 'target'
1949-
// signature as if it were normal forward pinvoke and then
1950-
// switch that signature (representing the native sig) with
1951-
// the stub's sig (representing the managed sig). However,
1952-
// as a side-effect, our calcualted target stack delta is
1953-
// wrong.
1954-
//
1955-
// The only way that we support a different stack delta is
1956-
// through hresult swapping. So this code "undoes" the
1957-
// deltas that would have been applied in that case.
1958-
//
1959-
1960-
if (StubHasVoidReturnType())
1961-
{
1962-
//
1963-
// If the managed return type is void, undo the HRESULT
1964-
// return type added to our target sig for HRESULT swapping.
1965-
// No extra argument will have been added because it makes
1966-
// no sense to add an extry byref void argument.
1967-
//
1968-
m_iTargetStackDelta--;
1969-
}
1970-
else
1971-
{
1972-
//
1973-
// no longer pop the extra byref argument from the stack
1974-
//
1975-
m_iTargetStackDelta++;
1976-
}
1977-
}
1978-
19791903
void NDirectStubLinker::SetInteropParamExceptionInfo(UINT resID, UINT paramIdx)
19801904
{
19811905
LIMITED_METHOD_CONTRACT;

src/vm/dllimport.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,6 @@ class NDirectStubLinker : public ILStubLinker
489489
void SetExceptionCleanupNeeded();
490490
BOOL IsCleanupWorkListSetup();
491491
void GetCleanupFinallyOffsets(ILStubEHClause * pClause);
492-
void AdjustTargetStackDeltaForReverseInteropHRESULTSwapping();
493-
void AdjustTargetStackDeltaForExtraParam();
494492

495493
void SetInteropParamExceptionInfo(UINT resID, UINT paramIdx);
496494
bool HasInteropParamExceptionInfo();

src/vm/ilmarshalers.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -641,17 +641,6 @@ class ILMarshaler
641641
extraParamType.MakeByRef();
642642

643643
m_pcsMarshal->SetStubTargetArgType(&extraParamType, false);
644-
if (byrefNativeReturn && !IsCLRToNative(m_dwMarshalFlags))
645-
{
646-
// If doing a native->managed call and returning a structure by-ref,
647-
// the native signature has an extra param for the struct return
648-
// than the managed signature. Adjust the target stack delta to account this extra
649-
// parameter.
650-
m_pslNDirect->AdjustTargetStackDeltaForExtraParam();
651-
// We also need to account for the lack of a return value in the native signature.
652-
// To do this, we adjust the stack delta again for the return parameter.
653-
m_pslNDirect->AdjustTargetStackDeltaForExtraParam();
654-
}
655644

656645
if (IsHresultSwap(dwMarshalFlags))
657646
{

src/vm/stubgen.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,7 +2242,7 @@ ILStubLinker::ILStubLinker(Module* pStubSigModule, const Signature &signature, S
22422242
uNativeCallingConv |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
22432243
}
22442244

2245-
if (fTargetHasThis)
2245+
if (fTargetHasThis && !fIsReverseStub)
22462246
{
22472247
m_iTargetStackDelta--;
22482248
}
@@ -2252,7 +2252,22 @@ ILStubLinker::ILStubLinker(Module* pStubSigModule, const Signature &signature, S
22522252
if (uStubCallingConvInfo & IMAGE_CEE_CS_CALLCONV_GENERIC)
22532253
IfFailThrow(m_managedSigPtr.GetData(NULL)); // skip number of type parameters
22542254

2255-
IfFailThrow(m_managedSigPtr.GetData(NULL)); // skip number of parameters
2255+
if (fIsReverseStub)
2256+
{
2257+
ULONG numParams = 0;
2258+
IfFailThrow(m_managedSigPtr.GetData(&numParams));
2259+
// As per ECMA 335, the max number of parameters is 0x1FFFFFFF (see section 11.23.2), which fits in a 32-bit signed integer
2260+
// So this cast is safe.
2261+
m_iTargetStackDelta -= (INT)numParams;
2262+
if (!m_StubHasVoidReturnType)
2263+
{
2264+
m_iTargetStackDelta++;
2265+
}
2266+
}
2267+
else
2268+
{
2269+
IfFailThrow(m_managedSigPtr.GetData(NULL)); // skip number of parameters
2270+
}
22562271
IfFailThrow(m_managedSigPtr.SkipExactlyOne()); // skip return type
22572272
}
22582273
}
@@ -2475,13 +2490,15 @@ void ILStubLinker::SetStubTargetReturnType(LocalDesc* pLoc)
24752490

24762491
m_nativeFnSigBuilder.SetReturnType(pLoc);
24772492

2478-
// Update check for if a stub has a void return type based on the provided return type.
2479-
m_StubTargetHasVoidReturnType = ((1 == pLoc->cbType) && (ELEMENT_TYPE_VOID == pLoc->ElementType[0])) ? TRUE : FALSE;
2480-
if (!m_StubTargetHasVoidReturnType)
2493+
if (!m_fIsReverseStub)
24812494
{
2482-
m_iTargetStackDelta++;
2495+
// Update check for if a stub has a void return type based on the provided return type.
2496+
m_StubTargetHasVoidReturnType = ((1 == pLoc->cbType) && (ELEMENT_TYPE_VOID == pLoc->ElementType[0])) ? TRUE : FALSE;
2497+
if (!m_StubTargetHasVoidReturnType)
2498+
{
2499+
m_iTargetStackDelta++;
2500+
}
24832501
}
2484-
24852502
}
24862503

24872504
DWORD ILStubLinker::SetStubTargetArgType(CorElementType typ, bool fConsumeStubArg /*= true*/)
@@ -2495,7 +2512,17 @@ DWORD ILStubLinker::SetStubTargetArgType(CorElementType typ, bool fConsumeStubAr
24952512
void ILStubLinker::SetStubTargetCallingConv(CorCallingConvention uNativeCallingConv)
24962513
{
24972514
LIMITED_METHOD_CONTRACT;
2515+
CorCallingConvention originalCallingConvention = m_nativeFnSigBuilder.GetCallingConv();
24982516
m_nativeFnSigBuilder.SetCallingConv(uNativeCallingConv);
2517+
if (!m_fIsReverseStub)
2518+
{
2519+
if ( (originalCallingConvention & CORINFO_CALLCONV_HASTHIS) && !(uNativeCallingConv & CORINFO_CALLCONV_HASTHIS))
2520+
{
2521+
// Our calling convention had an implied-this beforehand and now it doesnt.
2522+
// Account for this in the target stack delta.
2523+
m_iTargetStackDelta++;
2524+
}
2525+
}
24992526
}
25002527

25012528
static size_t GetManagedTypeForMDArray(LocalDesc* pLoc, Module* pModule, PCCOR_SIGNATURE psigManagedArg, SigTypeContext *pTypeContext)
@@ -2770,7 +2797,11 @@ ILStubLinker::SetStubTargetArgType(
27702797
TransformArgForJIT(pLoc);
27712798

27722799
DWORD dwArgNum = m_nativeFnSigBuilder.NewArg(pLoc);
2773-
m_iTargetStackDelta--;
2800+
2801+
if (!m_fIsReverseStub)
2802+
{
2803+
m_iTargetStackDelta--;
2804+
}
27742805

27752806
return dwArgNum;
27762807
} // ILStubLinker::SetStubTargetArgType

0 commit comments

Comments
 (0)