forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for GetPinnableReference for the new marshaller shapes (d…
…otnet#71412) * Add support for static and instance GetPinnableReference in codegen. * Add tests and collections support
- Loading branch information
1 parent
f28904a
commit 0112d5f
Showing
9 changed files
with
395 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
...en/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// 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.Collections.Generic; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||
|
||
namespace Microsoft.Interop | ||
{ | ||
public sealed class StaticPinnableManagedValueMarshaller : IMarshallingGenerator | ||
{ | ||
private readonly IMarshallingGenerator _innerMarshallingGenerator; | ||
private readonly TypeSyntax _getPinnableReferenceType; | ||
|
||
public StaticPinnableManagedValueMarshaller(IMarshallingGenerator innerMarshallingGenerator, TypeSyntax getPinnableReferenceType) | ||
{ | ||
_innerMarshallingGenerator = innerMarshallingGenerator; | ||
_getPinnableReferenceType = getPinnableReferenceType; | ||
} | ||
|
||
public bool IsSupported(TargetFramework target, Version version) | ||
=> _innerMarshallingGenerator.IsSupported(target, version); | ||
|
||
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) | ||
{ | ||
if (IsPinningPathSupported(info, context)) | ||
{ | ||
if (AsNativeType(info) is PointerTypeSyntax pointerType | ||
&& pointerType.ElementType is PredefinedTypeSyntax predefinedType | ||
&& predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword)) | ||
{ | ||
return ValueBoundaryBehavior.NativeIdentifier; | ||
} | ||
|
||
// Cast to native type if it is not void* | ||
return ValueBoundaryBehavior.CastNativeIdentifier; | ||
} | ||
|
||
return _innerMarshallingGenerator.GetValueBoundaryBehavior(info, context); | ||
} | ||
|
||
public TypeSyntax AsNativeType(TypePositionInfo info) | ||
{ | ||
return _innerMarshallingGenerator.AsNativeType(info); | ||
} | ||
|
||
public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) | ||
{ | ||
return _innerMarshallingGenerator.GetNativeSignatureBehavior(info); | ||
} | ||
|
||
public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) | ||
{ | ||
if (IsPinningPathSupported(info, context)) | ||
{ | ||
return GeneratePinningPath(info, context); | ||
} | ||
|
||
return _innerMarshallingGenerator.Generate(info, context); | ||
} | ||
|
||
public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) | ||
{ | ||
return _innerMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, context); | ||
} | ||
|
||
public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) | ||
{ | ||
if (IsPinningPathSupported(info, context)) | ||
{ | ||
return false; | ||
} | ||
|
||
return _innerMarshallingGenerator.UsesNativeIdentifier(info, context); | ||
} | ||
private static bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context) | ||
{ | ||
return context.SingleFrameSpansNativeContext && !info.IsByRef && !info.IsManagedReturnPosition; | ||
} | ||
|
||
private IEnumerable<StatementSyntax> GeneratePinningPath(TypePositionInfo info, StubCodeContext context) | ||
{ | ||
if (context.CurrentStage == StubCodeContext.Stage.Pin) | ||
{ | ||
(string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); | ||
|
||
// fixed (void* <nativeIdentifier> = &<getPinnableReferenceType>.GetPinnableReference(<managedIdentifier>)) | ||
yield return FixedStatement( | ||
VariableDeclaration( | ||
PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), | ||
SingletonSeparatedList( | ||
VariableDeclarator(Identifier(nativeIdentifier)) | ||
.WithInitializer(EqualsValueClause( | ||
PrefixUnaryExpression(SyntaxKind.AddressOfExpression, | ||
InvocationExpression( | ||
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, | ||
_getPinnableReferenceType, | ||
IdentifierName(ShapeMemberNames.GetPinnableReference)), | ||
ArgumentList(SingletonSeparatedList( | ||
Argument(IdentifierName(managedIdentifier)))))) | ||
)) | ||
) | ||
), | ||
EmptyStatement()); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.