Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support generic arguments for calli in CoreCLR #97079

Merged
merged 47 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f10af6b
Add generic support for calli
hez2010 Jan 17, 2024
345ef56
Consider classInst as well
hez2010 Jan 17, 2024
6e429cf
Merge branch 'main' into feature/generic-calli
hez2010 Jan 17, 2024
42debae
oops
hez2010 Jan 17, 2024
ab8839b
guarded by !DACCESS_COMPILE
hez2010 Jan 17, 2024
0327254
Block runtime marshaling for calli
hez2010 Jan 21, 2024
21c6202
Fix the error mode
hez2010 Jan 22, 2024
a10142c
Adding tests
hez2010 Jan 23, 2024
6f7eb0e
Minor fixes to tests
hez2010 Jan 23, 2024
68d5a09
Compare instantiations as well when lookup
hez2010 Jan 23, 2024
2ea3dac
Adding more test cases
hez2010 Jan 23, 2024
5ecc888
Avoid getting export multiple times
hez2010 Jan 23, 2024
21d9862
Improve tests
hez2010 Jan 24, 2024
8939e32
Use standard boolean
hez2010 Jan 24, 2024
ab165f1
Avoid casting to prevent ABI mismatch
hez2010 Jan 24, 2024
e0e7478
Handle collectible assemblies
hez2010 Jan 25, 2024
97a8bf6
Reverse the branch
hez2010 Jan 25, 2024
fd43493
Handle inlined P/Invoke transitions
hez2010 Jan 26, 2024
fad2701
Reimplement unloadability handling
hez2010 Jan 26, 2024
4f67d66
Fix native library resolving in tests
hez2010 Jan 27, 2024
b050468
Use AllocMemTracker properly
hez2010 Jan 27, 2024
549c746
Skip tests on windows x86
hez2010 Jan 27, 2024
4fcbbf8
Skip negative tests on Windows x86 and NativeAOT
hez2010 Jan 27, 2024
883f531
Merge branch 'main' into feature/generic-calli
hez2010 Jan 27, 2024
fec111f
Use better exception message
hez2010 Feb 12, 2024
83d9919
Enable Windows x86 tests again
hez2010 Feb 12, 2024
1390455
Exclude tests for mono
hez2010 Feb 13, 2024
e37a0d9
Use correct loader elsewhere
hez2010 Feb 13, 2024
7721626
Put VASigCookieBlock on loader module
hez2010 Feb 14, 2024
d05b1cb
Move VASigCookie creation to a new method
hez2010 Feb 14, 2024
909e7fa
Move more things
hez2010 Feb 14, 2024
f6833b9
oops
hez2010 Feb 14, 2024
35edb8d
Update issues.targets
hez2010 Feb 14, 2024
40d5c35
Allocate StubMD on loader module
hez2010 Feb 14, 2024
0282d1a
Fixes for vararg cases
hez2010 Feb 14, 2024
8fa2fd6
Handle varargs in error mode as well
hez2010 Feb 14, 2024
c2cfc1b
Add an error mode for generic varargs
hez2010 Feb 14, 2024
3c1c25d
Remove useless comments
hez2010 Feb 14, 2024
e503dfa
FB
hez2010 Feb 15, 2024
fc79d98
Update tests
hez2010 Feb 15, 2024
22ecfb2
Fix tests
hez2010 Feb 15, 2024
9518dd9
Apply suggestions from code review
hez2010 Feb 15, 2024
c9c0881
Make xUnit happy
hez2010 Feb 16, 2024
3974945
test mono ci
hez2010 Feb 16, 2024
a8d38b0
Tweak the tests
hez2010 Feb 21, 2024
f1a0fd3
Merge branch 'main' into feature/generic-calli
hez2010 Feb 21, 2024
151982a
Add link to an GH issue
hez2010 Feb 22, 2024
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
14 changes: 6 additions & 8 deletions src/coreclr/vm/ceeload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4696,7 +4696,7 @@ PTR_VOID ReflectionModule::GetRvaField(RVA field) // virtual
//==========================================================================
// Enregisters a VASig.
//==========================================================================
VASigCookie *Module::GetVASigCookie(Signature vaSignature)
VASigCookie *Module::GetVASigCookie(Signature vaSignature, const SigTypeContext* typeContext)
{
CONTRACT(VASigCookie*)
{
Expand Down Expand Up @@ -4734,13 +4734,7 @@ VASigCookie *Module::GetVASigCookie(Signature vaSignature)

// Compute the size of args first, outside of the lock.

// @TODO GENERICS: We may be calling a varargs method from a
// generic type/method. Using an empty context will make such a
// case cause an unexpected exception. To make this work,
// we need to create a specialized signature for every instantiation
SigTypeContext typeContext;

MetaSig metasig(vaSignature, this, &typeContext);
MetaSig metasig(vaSignature, this, typeContext);
ArgIterator argit(&metasig);

// Upper estimate of the vararg size
Expand Down Expand Up @@ -4778,6 +4772,10 @@ VASigCookie *Module::GetVASigCookie(Signature vaSignature)
pCookie->pNDirectILStub = NULL;
pCookie->sizeOfArgs = sizeOfArgs;
pCookie->signature = vaSignature;
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
pCookie->classInst = typeContext->m_classInst.GetRawArgs();
pCookie->classInstCount = typeContext->m_classInst.GetNumArgs();
pCookie->methInst = typeContext->m_methodInst.GetRawArgs();
pCookie->methInstCount = typeContext->m_methodInst.GetNumArgs();

// Finally, now that it's safe for asynchronous readers to see it,
// update the count.
Expand Down
6 changes: 5 additions & 1 deletion src/coreclr/vm/ceeload.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ struct VASigCookie
Volatile<PCODE> pNDirectILStub; // will be use if target is NDirect (tag == 0)
PTR_Module pModule;
Signature signature;
TypeHandle* classInst;
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
DWORD classInstCount;
TypeHandle* methInst;
DWORD methInstCount;
};

//
Expand Down Expand Up @@ -1361,7 +1365,7 @@ class Module : public ModuleBase
void NotifyEtwLoadFinished(HRESULT hr);

// Enregisters a VASig.
VASigCookie *GetVASigCookie(Signature vaSignature);
VASigCookie *GetVASigCookie(Signature vaSignature, const SigTypeContext* typeContext);

public:
#ifndef DACCESS_COMPILE
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4186,6 +4186,7 @@ namespace
pHashParams,
pParams->m_dwStubFlags,
pParams->m_pModule,
pParams->m_pTypeContext,
pParams->m_sig.GetRawSig(),
pParams->m_sig.GetRawSigLen(),
pamTracker,
Expand Down Expand Up @@ -5034,6 +5035,12 @@ namespace
}
else
{
// For generic calli, we only support blittable types
if (!pSigDesc->m_typeContext.IsEmpty() && SF_IsCALLIStub(dwStubFlags) && NDirect::MarshalingRequired(pStubMD))
{
COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_UNSUPPORTED_SIG);
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
}

CreateNDirectStubWorker(pss,
pSigDesc,
nlType,
Expand Down Expand Up @@ -6059,6 +6066,7 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD)
}

StubSigDesc sigDesc(pMD, signature, pVASigCookie->pModule);
sigDesc.InitTypeContext(pVASigCookie->classInst, pVASigCookie->classInstCount, pVASigCookie->methInst, pVASigCookie->methInstCount);

MethodDesc* pStubMD = NDirect::CreateCLRToNativeILStub(&sigDesc,
nlType,
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/vm/dllimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ struct StubSigDesc
}
}
#endif // _DEBUG

#ifndef DACCESS_COMPILE
void InitTypeContext(TypeHandle* classInst, DWORD classInstCount, TypeHandle* methInst, DWORD methInstCount)
{
LIMITED_METHOD_CONTRACT;

m_typeContext = SigTypeContext(Instantiation(classInst, classInstCount), Instantiation(methInst, methInstCount));
}
#endif
};

//=======================================================================
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/ilstubcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ MethodDesc* ILStubCache::GetStubMethodDesc(
ILStubHashBlob* pHashBlob,
DWORD dwStubFlags,
Module* pSigModule,
SigTypeContext* pTypeContext,
PCCOR_SIGNATURE pSig,
DWORD cbSig,
AllocMemTracker* pamTracker,
Expand Down Expand Up @@ -552,6 +553,10 @@ MethodDesc* ILStubCache::GetStubMethodDesc(
{
SigTypeContext::InitTypeContext(pTargetMD, &typeContext);
}
else if (pTypeContext != NULL)
{
typeContext = *pTypeContext;
}

pMD = ILStubCache::CreateNewMethodDesc(m_pAllocator->GetHighFrequencyHeap(), pStubMT, dwStubFlags, pSigModule, pSig, cbSig, &typeContext, pamTracker);

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/ilstubcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ILStubCache final
ILStubHashBlob* pHashBlob,
DWORD dwStubFlags, // bitmask of NDirectStubFlags
Module* pSigModule,
SigTypeContext* pTypeContext,
PCCOR_SIGNATURE pSig,
DWORD cbSig,
AllocMemTracker* pamTracker,
Expand Down
9 changes: 7 additions & 2 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6306,7 +6306,11 @@ CORINFO_VARARGS_HANDLE CEEInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig,

Module* module = GetModule(sig->scope);

result = CORINFO_VARARGS_HANDLE(module->GetVASigCookie(Signature(sig->pSig, sig->cbSig)));
Instantiation classInst = Instantiation((TypeHandle*) sig->sigInst.classInst, sig->sigInst.classInstCount);
Instantiation methodInst = Instantiation((TypeHandle*) sig->sigInst.methInst, sig->sigInst.methInstCount);
SigTypeContext typeContext = SigTypeContext(classInst, methodInst);

result = CORINFO_VARARGS_HANDLE(module->GetVASigCookie(Signature(sig->pSig, sig->cbSig), &typeContext));

EE_TO_JIT_TRANSITION();

Expand Down Expand Up @@ -13425,7 +13429,8 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
}
{
VarArgs:
result = (size_t) CORINFO_VARARGS_HANDLE(currentModule->GetVASigCookie(Signature(pSig, cSig)));
SigTypeContext typeContext = SigTypeContext();
result = (size_t) CORINFO_VARARGS_HANDLE(currentModule->GetVASigCookie(Signature(pSig, cSig), &typeContext));
}
break;

Expand Down
50 changes: 50 additions & 0 deletions src/tests/Interop/MarshalAPI/FunctionPointer/FunctionPointer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Xunit;

Expand Down Expand Up @@ -111,4 +112,53 @@ public static void RunGetDelForOutIntTest()
}
Assert.Equal(expectedValue, outVar);
}

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
static int UnmanagedExportedFunction(float arg)
{
return Convert.ToInt32(arg);
}

class GenericCaller<T>
{
internal static unsafe T GenericCalli<U>(void* fnptr, U arg)
{
return ((delegate* unmanaged<U, T>)fnptr)(arg);
}
}

[Fact]
public static void RunGenericFunctionPointerTest()
{
Console.WriteLine($"Running {nameof(RunGenericFunctionPointerTest)}...");
int outVar = 0;
int expectedValue = 42;
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
unsafe
{
outVar = GenericCaller<int>.GenericCalli((delegate* unmanaged[Cdecl]<float, int>)&UnmanagedExportedFunction, 42.0f);
}
Assert.Equal(expectedValue, outVar);
}

hez2010 marked this conversation as resolved.
Show resolved Hide resolved
[Fact]
public static void RunInvalidGenericFunctionPointerTest()
{
Console.WriteLine($"Running {nameof(RunInvalidGenericFunctionPointerTest)}...");
unsafe
{
nint lib = nint.Zero;
try
{
lib = NativeLibrary.Load(nameof(FunctionPointerNative));
Assert.Throws<MarshalDirectiveException>(() => GenericCaller<string>.GenericCalli((delegate* unmanaged[Cdecl]<string, string>)NativeLibrary.GetExport(lib, "ReturnParameter"), "test"));
}
finally
{
if (lib != nint.Zero)
{
NativeLibrary.Free(lib);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ extern "C" DLL_EXPORT void FillOutIntParameter(intptr_t *p)
*p = 50;
}

extern "C" DLL_EXPORT intptr_t* ReturnParameter(intptr_t *p)
{
return p;
}
hez2010 marked this conversation as resolved.
Show resolved Hide resolved

Loading