Beispiel #1
0
    private IEnumerable <StatementSyntax> GenerateNativeByRefProlog(CsMarshalCallableBase publicElement,
                                                                    ExpressionSyntax nativeParameter,
                                                                    TypeSyntax nativeParameterType)
    {
        var marshaller               = GetMarshaller(publicElement);
        var marshalTypeSyntax        = marshaller.GetMarshalTypeSyntax(publicElement);
        var publicType               = ParseTypeName(publicElement.PublicType.QualifiedName);
        var generatesMarshalVariable = marshaller.GeneratesMarshalVariable(publicElement);

        ExpressionSyntax publicDefaultValue = publicElement.UsedAsReturn ? default : DefaultLiteral;

                                              var refToNativeClause = GenerateAsRefInitializer(publicElement, nativeParameter, marshalTypeSyntax);

                                              TypeSyntax       publicVariableType, marshalVariableType;
                                              ExpressionSyntax publicVariableInitializer, marshalVariableInitializer;

                                              if (publicElement is CsParameter {
            IsOptional: true, IsLocalManagedReference : true
        } parameter)
                                              {
                                                  Debug.Assert(marshaller is RefWrapperMarshaller);

                                                  var refVariableDeclaration = LocalDeclarationStatement(
                                                      VariableDeclaration(
                                                          RefType(marshalTypeSyntax),
                                                          SingletonSeparatedList(
                                                              VariableDeclarator(
                                                                  MarshallerBase.GetRefLocationIdentifier(publicElement),
Beispiel #2
0
    private IEnumerable <StatementSyntax> GenerateProlog(CsMarshalCallableBase publicElement,
                                                         ExpressionSyntax nativeParameter,
                                                         TypeSyntax nativeParameterType)
    {
        ExpressionSyntax CastToPublicType(TypeSyntax targetType, ExpressionSyntax expression) =>
        targetType.IsEquivalentTo(nativeParameterType)
                ? expression
                : GeneratorHelpers.CastExpression(targetType, expression);

        var marshaller = GetMarshaller(publicElement);
        var publicType = GetPublicType(publicElement);

        var generatesMarshalVariable = marshaller.GeneratesMarshalVariable(publicElement);

        var publicTypeVariableValue = nativeParameter != null && !generatesMarshalVariable
                                          ? CastToPublicType(publicType, nativeParameter)
                                          : DefaultLiteral;

        yield return(LocalDeclarationStatement(
                         VariableDeclaration(
                             publicType,
                             SingletonSeparatedList(
                                 VariableDeclarator(Identifier(publicElement.Name))
                                 .WithInitializer(EqualsValueClause(publicTypeVariableValue))
                                 )
                             )
                         ));

        if (generatesMarshalVariable)
        {
            var marshalTypeSyntax = marshaller.GetMarshalTypeSyntax(publicElement);

            var initializerExpression = nativeParameter != null
                                            ? CastToPublicType(marshalTypeSyntax, nativeParameter)
                                            : DefaultLiteral;

            yield return(LocalDeclarationStatement(
                             VariableDeclaration(
                                 marshalTypeSyntax,
                                 SingletonSeparatedList(
                                     VariableDeclarator(
                                         MarshallerBase.GetMarshalStorageLocationIdentifier(publicElement),
                                         null,
                                         EqualsValueClause(initializerExpression)
                                         )
                                     )
                                 )
                             ));
        }
    }
Beispiel #3
0
 public SyntaxToken GetMarshalStorageLocationIdentifier(CsMarshalBase csElement)
 {
     return(MarshallerBase.GetMarshalStorageLocationIdentifier(csElement));
 }
Beispiel #4
0
    protected override ExpressionSyntax Generate(CsCallable callable, PlatformDetectionType platform)
    {
        var interopSig        = callable.InteropSignatures[platform];
        var interopReturnType = interopSig.ReturnTypeSyntax;
        var arguments         = IterateNativeArguments(callable is CsMethod, interopSig).ToArray();

        var vtblAccess = callable switch
        {
            CsMethod method => ElementAccessExpression(
                ThisExpression(),
                BracketedArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            method.CustomVtbl
                                ? MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                ThisExpression(),
                                IdentifierName($"{callable.Name}__vtbl_index")
                                )
                                : method.VTableOffsetExpression(platform)
                            )
                        )
                    )
                ),
            _ => null
        };

        ExpressionSyntax FnPtrCall()
        {
            var fnptrParameters = arguments
                                  .Select(x => x.Type)
                                  .Append(interopReturnType)
                                  .Select(FunctionPointerParameter);

            return(GeneratorHelpers.CastExpression(
                       FunctionPointerType(
                           FunctionPointerCallingConvention(
                               Token(SyntaxKind.UnmanagedKeyword),
                               FunctionPointerUnmanagedCallingConventionList(
                                   SingletonSeparatedList(
                                       FunctionPointerUnmanagedCallingConvention(
                                           Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                           )
                                       )
                                   )
                               ),
                           FunctionPointerParameterList(SeparatedList(fnptrParameters))
                           ),
                       vtblAccess
                       ));
        }

        var what = callable switch
        {
            CsFunction => IdentifierName(
                callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                ),
            CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
            _ => throw new ArgumentOutOfRangeException()
        };

        ExpressionSyntax call = InvocationExpression(
            what,
            ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
            );

        if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
        {
            return(call);
        }

        var generatesMarshalVariable = GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue);
        var publicTypeSyntax         = ReverseCallablePrologCodeGenerator.GetPublicType(callable.ReturnValue);

        if (callable.HasReturnTypeValue && !generatesMarshalVariable && !publicTypeSyntax.IsEquivalentTo(interopSig.ReturnTypeSyntax))
        {
            call = CastExpression(publicTypeSyntax, call);
        }

        return(AssignmentExpression(
                   SyntaxKind.SimpleAssignmentExpression,
                   generatesMarshalVariable
                ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                : IdentifierName(callable.ReturnValue.Name),
                   call
                   ));
    }
Beispiel #5
0
        public ExpressionSyntax GenerateCall(CsCallable callable, PlatformDetectionType platform,
                                             InteropMethodSignature interopSig)
        {
            var arguments = IterateNativeArguments(callable, interopSig).ToArray();

            ElementAccessExpressionSyntax vtblAccess = null;

            if (callable is CsMethod method)
            {
                var windowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.WindowsOffset));
                var nonWindowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Offset));

                ExpressionSyntax vtableOffsetExpression;
                if ((platform & PlatformDetectionType.Any) == PlatformDetectionType.Any &&
                    method.Offset != method.WindowsOffset)
                {
                    vtableOffsetExpression = ConditionalExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                            IdentifierName("Is" + nameof(PlatformDetectionType.Windows))),
                        windowsOffsetExpression,
                        nonWindowsOffsetExpression);
                }
                else if ((platform & PlatformDetectionType.Windows) != 0)
                {
                    vtableOffsetExpression = windowsOffsetExpression;
                }
                else
                {
                    vtableOffsetExpression = nonWindowsOffsetExpression;
                }

                vtblAccess = ElementAccessExpression(
                    ThisExpression(),
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                method.CustomVtbl
                                    ? MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName($"{callable.Name}__vtbl_index")
                                    )
                                    : vtableOffsetExpression
                                )
                            )
                        )
                    );
            }

            ExpressionSyntax FnPtrCall()
            {
                var fnptrParameters = arguments
                                      .Select(x => x.Type)
                                      .Append(ParseTypeName(interopSig.ReturnType.TypeName))
                                      .Select(FunctionPointerParameter);

                return(GeneratorHelpers.CastExpression(
                           FunctionPointerType(
                               FunctionPointerCallingConvention(
                                   Token(SyntaxKind.UnmanagedKeyword),
                                   FunctionPointerUnmanagedCallingConventionList(
                                       SingletonSeparatedList(
                                           FunctionPointerUnmanagedCallingConvention(
                                               Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                               )
                                           )
                                       )
                                   ),
                               FunctionPointerParameterList(SeparatedList(fnptrParameters))
                               ),
                           vtblAccess
                           ));
            }

            var what = callable switch
            {
                CsFunction => IdentifierName(
                    callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                    ),
                CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
                _ => throw new ArgumentOutOfRangeException()
            };

            ExpressionSyntax call = InvocationExpression(
                what,
                ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
                );

            if (interopSig.CastToNativeLong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeLong), call);
            }

            if (interopSig.CastToNativeULong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeULong), call);
            }

            if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
            {
                return(call);
            }

            return(AssignmentExpression(
                       SyntaxKind.SimpleAssignmentExpression,
                       GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue)
                    ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                    : IdentifierName(callable.ReturnValue.Name),
                       call
                       ));
        }