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

Error on multiple calling conventions in modopts #39809

Merged
merged 6 commits into from
Jul 28, 2020

Conversation

elinor-fung
Copy link
Member

@elinor-fung elinor-fung commented Jul 23, 2020

For Roslyn, the union of the calling conventions specified in modopts is used and the order doesn't matter. This means that the runtime should not try to choose one to respect based on the order in metadata. This change makes the runtime throw NotSupportedException when encountering an unmanaged calling convention and finding multiple calling conventions specified in modopts on the return type.

Resolves #39378

cc @AaronRobinsonMSFT @jkoritzinsky @davidwrighton

@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@elinor-fung elinor-fung added this to the 5.0.0 milestone Jul 23, 2020
Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

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

Runtime - LGTM.

src/coreclr/src/vm/dllimport.cpp Show resolved Hide resolved
@@ -524,25 +526,35 @@ private bool TryGetUnmanagedCallingConventionFromModOpt(MethodSignature signatur
if (defType.Namespace != "System.Runtime.CompilerServices")
continue;

// Take the first recognized calling convention in metadata.
void SetCallConv(CorInfoCallConv toSet)
Copy link
Member

Choose a reason for hiding this comment

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

This is very clever. I am personally not a fan, but defer to the crossgen2 owners.

Copy link
Member

Choose a reason for hiding this comment

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

The convention for functions like this is to put them after the return statement of the function wherever possible. When you embed them in the middle of the function its easy to think they are part of the natural program flow.

Also, its very unclear for a reader where callConvLocal gets set. I would make that a ref or out parameter to the helper function, if only to make it clear about how the data flows through the function.

Copy link
Member

@davidwrighton davidwrighton left a comment

Choose a reason for hiding this comment

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

Please adjust the inline function. I don't fundamentally dislike the idea of using local functions, but mutating outer function state is very hard to understand.

(I'm less concerned about the found variable as its only used in the local function.

@@ -524,25 +526,35 @@ private bool TryGetUnmanagedCallingConventionFromModOpt(MethodSignature signatur
if (defType.Namespace != "System.Runtime.CompilerServices")
continue;

// Take the first recognized calling convention in metadata.
void SetCallConv(CorInfoCallConv toSet)
Copy link
Member

Choose a reason for hiding this comment

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

The convention for functions like this is to put them after the return statement of the function wherever possible. When you embed them in the middle of the function its easy to think they are part of the natural program flow.

Also, its very unclear for a reader where callConvLocal gets set. I would make that a ref or out parameter to the helper function, if only to make it clear about how the data flows through the function.

src/coreclr/src/vm/siginfo.cpp Outdated Show resolved Hide resolved
src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs Outdated Show resolved Hide resolved
switch (defType.Name)
{
case "CallConvCdecl":
callConv = CorInfoCallConv.CORINFO_CALLCONV_C;
return true;
SetCallConvLocal(CorInfoCallConv.CORINFO_CALLCONV_C, ref callConvLocal);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Not a big fan of the local function. It creates a capture object with an unnecessary allocation and I'm not sure if this improves readability over something like:

CorInfoCallConv? callconvLocal = defType.Name switch
{
    "CallConvCdecl" => CorInfoCallConv.CORINFO_CALLCONV_C,
    // ...
    _ => null
};

if (callConvLocal.HasValue)
{
    if (found)
        throw...
    callConv = callConvLocal.Value;
    found = true;
}

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm honestly not a huge fan either. Happy to change it to what people think would be better.

Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

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

Crossgen2 side LTGM otherwise. Thanks!

@elinor-fung
Copy link
Member Author

The two 'in progress' checks show as completed and successful on Azure DevOps.

@davidwrighton I removed the local function and used @MichalStrehovsky's suggestion. Do you have any additional concerns with this change?

@elinor-fung elinor-fung merged commit 50a999d into dotnet:master Jul 28, 2020
@elinor-fung elinor-fung deleted the multipleCallConv-notSupported branch July 28, 2020 17:22
Jacksondr5 pushed a commit to Jacksondr5/runtime that referenced this pull request Aug 10, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Read all modopts for for unmanaged CallKind
5 participants