private IEnumerable <StatementSyntax> GenerateNativeByRefProlog(CsMarshalCallableBase publicElement, ExpressionSyntax nativeParameter)
        {
            var marshaller = generators.Marshalling.GetMarshaller(publicElement);
            var localByRef = publicElement.IsRef || publicElement.IsOut;
            ExpressionSyntax refToNativeExpression = InvocationExpression(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    globalNamespace.GetTypeNameSyntax(BuiltinType.Unsafe),
                    GenericName(Identifier("AsRef"))
                    .WithTypeArgumentList(
                        TypeArgumentList(
                            SingletonSeparatedList(
                                marshaller.GetMarshalTypeSyntax(publicElement))))))
                                                     .WithArgumentList(
                ArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            nativeParameter))));

            var publicType = ParseTypeName(publicElement.PublicType.QualifiedName);

            if (localByRef)
            {
                if (!marshaller.GeneratesMarshalVariable(publicElement))
                {
                    publicType = RefType(publicType);
                }

                refToNativeExpression = RefExpression(refToNativeExpression);
            }

            if (marshaller.GeneratesMarshalVariable(publicElement))
            {
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(
                                     RefType(marshaller.GetMarshalTypeSyntax(publicElement)))
                                 .WithVariables(
                                     SingletonSeparatedList(
                                         VariableDeclarator(
                                             generators.Marshalling.GetMarshalStorageLocationIdentifier(publicElement))
                                         .WithInitializer(
                                             EqualsValueClause(
                                                 refToNativeExpression))))));

                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(publicType)
                                 .WithVariables(
                                     SingletonSeparatedList(
                                         VariableDeclarator(
                                             Identifier(publicElement.Name))))));
            }
            else
            {
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(publicType)
                                 .AddVariables(
                                     VariableDeclarator(Identifier(publicElement.Name))
                                     .WithInitializer(EqualsValueClause(refToNativeExpression)))));
            }
        }
예제 #2
0
        private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider globalNamespace, PlatformDetectionType allPlatformBitmap, PlatformDetectionType platform, StatementSyntax statement)
        {
            if ((platform & allPlatformBitmap) == allPlatformBitmap)
            {
                return(statement);
            }

            ExpressionSyntax condition = null;

            foreach (PlatformDetectionType flag in platforms)
            {
                if ((platform & flag) == flag && flag != PlatformDetectionType.Any)
                {
                    var newCondition = MemberAccessExpression(
                        Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleMemberAccessExpression,
                        globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                        IdentifierName(flag.ToString()));
                    condition = condition is null ?
                                (ExpressionSyntax)newCondition
                        : BinaryExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.LogicalAndExpression,
                                           condition,
                                           newCondition);
                }
            }

            return(condition is null ?
                   statement
                : IfStatement(
                       condition,
                       statement));
        }
예제 #3
0
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var shadowClassName = csElement.ShadowName.Split('.').Last();

            return(ClassDeclaration(shadowClassName)
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null ?
                                   (NameSyntax)IdentifierName(csElement.Base.ShadowName)
                                : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow)))))
                   .WithMembers(
                       List(
                           new MemberDeclarationSyntax[] {
                generators.Vtbl.GenerateCode(csElement),
                PropertyDeclaration(
                    globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl),
                    Identifier("Vtbl"))
                .WithModifiers(
                    TokenList(
                        new [] {
                    Token(SyntaxKind.ProtectedKeyword),
                    Token(SyntaxKind.OverrideKeyword)
                }))
                .WithAccessorList(
                    AccessorList(
                        SingletonList(
                            AccessorDeclaration(
                                SyntaxKind.GetAccessorDeclaration)
                            .WithSemicolonToken(
                                Token(SyntaxKind.SemicolonToken)))))
                .WithInitializer(
                    EqualsValueClause(
                        ObjectCreationExpression(
                            IdentifierName(csElement.VtblName))
                        .WithArgumentList(
                            ArgumentList(
                                SingletonSeparatedList(
                                    Argument(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(0))))))))
                .WithSemicolonToken(
                    Token(SyntaxKind.SemicolonToken))
            })));
        }
예제 #4
0
 protected ExpressionStatementSyntax GenerateCopyMemoryInvocation(ExpressionSyntax numBytesExpression)
 {
     return(ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                           globalNamespace.GetTypeNameSyntax(WellKnownName.MemoryHelpers),
                                           IdentifierName("CopyMemory")),
                    ArgumentList(
                        SeparatedList(
                            new[]
     {
         Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__to"))),
         Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__from"))),
         Argument(numBytesExpression)
     }
                            )))));
 }
예제 #5
0
        public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace,
                                                                    GeneratorConfig config,
                                                                    IEnumerable <PlatformDetectionType> types,
                                                                    Func <PlatformDetectionType, StatementSyntax> syntaxBuilder)
        {
            List <IfStatementSyntax> ifStatements = new();

            var allPlatformBitmap = config.Platforms;

            foreach (var platform in types)
            {
                var platformStatement = syntaxBuilder(platform);

                if ((platform & allPlatformBitmap) == allPlatformBitmap)
                {
                    return(platformStatement);
                }

                ExpressionSyntax condition = null;

                foreach (var flag in PlatformsNoAny)
                {
                    if ((platform & flag) != flag)
                    {
                        continue;
                    }

                    var newCondition = MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                        IdentifierName("Is" + flag)
                        );

                    condition = condition is null
                                    ? newCondition
                                    : BinaryExpression(SyntaxKind.LogicalAndExpression, condition, newCondition);
                }

                ifStatements.Add(
                    condition is null
                        ? (IfStatementSyntax)platformStatement
                        : IfStatement(condition, platformStatement)
                    );
            }

            IfStatementSyntax platformDetectionIfStatement = null;

            for (var i = ifStatements.Count - 1; i >= 0; i--)
            {
                platformDetectionIfStatement = ifStatements[i].WithElse(
                    platformDetectionIfStatement is null
                        ? ElseClause(ThrowPlatformNotSupportedStatement)
                        : ElseClause(platformDetectionIfStatement)
                    );
            }

            return(platformDetectionIfStatement);
        }
 public StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame)
 {
     if (!csElement.IsWideChar || !singleStackFrame)
     {
         return(ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal),
                            IdentifierName("FreeHGlobal")),
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(GetMarshalStorageLocation(csElement)))))));
     }
     return(null);
 }
예제 #7
0
        public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame)
        {
            if (csElement.IsArray) // Fixed-length character array
            {
                if (!csElement.IsWideChar)
                {
                    return(GenerateAnsiStringToArray(csElement));
                }

                if (!singleStackFrame)
                {
                    return(GenerateStringToArray(csElement));
                }

                return(null);
            }

            // Variable-length string represented as a pointer.

            if (!csElement.IsWideChar || !singleStackFrame)
            {
                return(ExpressionStatement(
                           AssignmentExpression(
                               SyntaxKind.SimpleAssignmentExpression,
                               GetMarshalStorageLocation(csElement),
                               InvocationExpression(
                                   MemberAccessExpression(
                                       SyntaxKind.SimpleMemberAccessExpression,
                                       GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal),
                                       IdentifierName(
                                           csElement.IsWideChar
                                        ? nameof(Marshal.StringToHGlobalUni)
                                        : nameof(Marshal.StringToHGlobalAnsi)
                                           )
                                       ),
                                   ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name))))
                                   )
                               )
                           ));
            }

            return(null);
        }
예제 #8
0
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var shadowClassName = csElement.ShadowName.Split('.').Last();

            var vtblName        = IdentifierName(csElement.VtblName);
            var vtblConstructor = ArgumentList(
                SingletonSeparatedList(
                    Argument(
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(0)
                            )
                        )
                    )
                );

            var vtblProperty = PropertyDeclaration(
                globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl),
                Identifier("Vtbl")
                )
                               .WithModifiers(
                TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))
                )
                               .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));

            List <MemberDeclarationSyntax> members = new();

            if (csElement.AutoGenerateVtbl)
            {
                members.Add(generators.Vtbl.GenerateCode(csElement));
            }

            if (csElement.StaticShadowVtbl)
            {
                var vtblInstanceName = Identifier("VtblInstance");

                members.Add(
                    FieldDeclaration(
                        VariableDeclaration(vtblName)
                        .WithVariables(
                            SingletonSeparatedList(
                                VariableDeclarator(vtblInstanceName)
                                .WithInitializer(
                                    EqualsValueClause(
                                        ImplicitObjectCreationExpression()
                                        .WithArgumentList(
                                            vtblConstructor
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    .WithModifiers(
                        TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword),
                                  Token(SyntaxKind.ReadOnlyKeyword))
                        )
                    );

                vtblProperty = vtblProperty
                               .WithExpressionBody(
                    ArrowExpressionClause(IdentifierName(vtblInstanceName))
                    );
            }
            else
            {
                vtblProperty = vtblProperty
                               .WithAccessorList(
                    AccessorList(
                        SingletonList(
                            AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                            .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
                            )
                        )
                    )
                               .WithInitializer(
                    EqualsValueClause(
                        ObjectCreationExpression(vtblName)
                        .WithArgumentList(
                            vtblConstructor
                            )
                        )
                    );
            }

            members.Add(vtblProperty);

            return(ClassDeclaration(shadowClassName)
                   .WithModifiers(
                       ModelUtilities.VisibilityToTokenList(csElement.ShadowVisibility, SyntaxKind.PartialKeyword)
                       )
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null
                                       ? IdentifierName(csElement.Base.ShadowName)
                                       : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow)
                                   )
                               )
                           )
                       )
                   .WithMembers(new SyntaxList <MemberDeclarationSyntax>(members)));
        }
예제 #9
0
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var vtblClassName = csElement.VtblName.Split('.').Last();

            return(ClassDeclaration(vtblClassName)
                   .WithModifiers(
                       TokenList(
                           Token(SyntaxKind.ProtectedKeyword),
                           Token(SyntaxKind.UnsafeKeyword)))
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null ?
                                   (NameSyntax)IdentifierName(csElement.Base.VtblName)
                                    : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl)))))
                   .WithMembers(
                       List(
                           new MemberDeclarationSyntax[]
            {
                ConstructorDeclaration(
                    Identifier(vtblClassName))
                .WithModifiers(
                    TokenList(
                        Token(SyntaxKind.PublicKeyword)))
                .WithParameterList(
                    ParameterList(
                        SingletonSeparatedList(
                            Parameter(
                                Identifier("numberOfCallbackMethods"))
                            .WithType(
                                PredefinedType(
                                    Token(SyntaxKind.IntKeyword))))))
                .WithInitializer(
                    ConstructorInitializer(
                        SyntaxKind.BaseConstructorInitializer,
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    BinaryExpression(
                                        SyntaxKind.AddExpression,
                                        IdentifierName("numberOfCallbackMethods"),
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(csElement.Methods.Count()))))))))
                .WithBody(
                    Block(csElement.Methods
                          .OrderBy(method => method.Offset)
                          .Select(method => ExpressionStatement(
                                      InvocationExpression(
                                          IdentifierName("AddMethod"))
                                      .WithArgumentList(
                                          ArgumentList(
                                              SingletonSeparatedList(
                                                  Argument(
                                                      ObjectCreationExpression(
                                                          IdentifierName($"{method.Name}Delegate"))
                                                      .WithArgumentList(
                                                          ArgumentList(
                                                              SingletonSeparatedList(
                                                                  Argument(
                                                                      IdentifierName(method.Name)))))))))))))
            }
                           .Concat(csElement.Methods
                                   .SelectMany(method => generators.ShadowCallable.GenerateCode(method))))));
        }
예제 #10
0
        private StatementSyntax GenerateStringToArray(CsMarshalBase marshallable)
        {
            var lengthIdentifier = LengthIdentifier(marshallable);

            return(FixedStatement(
                       VariableDeclaration(
                           PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))),
                           SeparatedList(
                               new[]
            {
                VariableDeclarator(FromIdentifier)
                .WithInitializer(EqualsValueClause(IdentifierName(marshallable.Name))),
                VariableDeclarator(ToIdentifier)
                .WithInitializer(EqualsValueClause(
                                     PrefixUnaryExpression(SyntaxKind.AddressOfExpression,
                                                           GetMarshalStorageLocation(marshallable))))
            })
                           ),
                       Block(
                           LocalDeclarationStatement(
                               VariableDeclaration(
                                   PredefinedType(Token(SyntaxKind.IntKeyword)),
                                   SingletonSeparatedList(
                                       VariableDeclarator(Identifier(lengthIdentifier))
                                       .WithInitializer(EqualsValueClause(
                                                            InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                        GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Math),
                                                                                                        IdentifierName(nameof(Math.Min))),
                                                                                 ArgumentList(
                                                                                     SeparatedList(
                                                                                         new[]
            {
                Argument(
                    BinaryExpression(SyntaxKind.MultiplyExpression,
                                     ParenthesizedExpression(
                                         BinaryExpression(SyntaxKind.CoalesceExpression,
                                                          ConditionalAccessExpression(
                                                              IdentifierName(marshallable.Name),
                                                              MemberBindingExpression(IdentifierName("Length"))),
                                                          LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))),
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2))
                                     )),
                Argument(
                    BinaryExpression(SyntaxKind.MultiplyExpression,
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(marshallable.ArrayDimensionValue - 1)),
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2))))
            }
                                                                                         )
                                                                                     ))))))),
                           GenerateCopyMemoryInvocation(IdentifierName(lengthIdentifier)),
                           ExpressionStatement(
                               AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                    ElementAccessExpression(IdentifierName(ToIdentifier),
                                                                            BracketedArgumentList(
                                                                                SingletonSeparatedList(
                                                                                    Argument(IdentifierName(lengthIdentifier))))),
                                                    LiteralExpression(SyntaxKind.CharacterLiteralExpression, Literal('\0')))))));
        }
예제 #11
0
        public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame)
        {
            MemberAccessExpressionSyntax PtrToString(NameSyntax implName) =>
            MemberAccessExpression(
                SyntaxKind.SimpleMemberAccessExpression,
                implName,
                IdentifierName(
                    csElement.IsWideChar ? nameof(Marshal.PtrToStringUni) : nameof(Marshal.PtrToStringAnsi)
                    )
                );

            if (csElement.IsArray) // Fixed-length character array
            {
                if (csElement.IsWideChar && singleStackFrame)
                {
                    return(null);
                }

                const string ptrName = "__ptr";

                return(FixedStatement(
                           VariableDeclaration(
                               VoidPtrType,
                               SingletonSeparatedList(
                                   VariableDeclarator(ptrName)
                                   .WithInitializer(
                                       EqualsValueClause(
                                           PrefixUnaryExpression(
                                               SyntaxKind.AddressOfExpression,
                                               GetMarshalStorageLocation(csElement)
                                               )
                                           )
                                       )
                                   )
                               ),
                           ExpressionStatement(
                               AssignmentExpression(
                                   SyntaxKind.SimpleAssignmentExpression,
                                   IdentifierName(csElement.Name),
                                   InvocationExpression(
                                       PtrToString(GlobalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers)),
                                       ArgumentList(
                                           SeparatedList(
                                               new[]
                {
                    Argument(CastExpression(IntPtrType, IdentifierName(ptrName))),
                    Argument(
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(csElement.ArrayDimensionValue - 1)
                            )
                        )
                }
                                               )
                                           )
                                       )
                                   )
                               )
                           ));
            }

            // Variable-length string represented as a pointer.
            return(ExpressionStatement(
                       AssignmentExpression(
                           SyntaxKind.SimpleAssignmentExpression,
                           IdentifierName(csElement.Name),
                           InvocationExpression(
                               PtrToString(GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal)),
                               ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement))))
                               )
                           )
                       ));
        }
예제 #12
0
 private StatementSyntax GenerateAnsiStringToArray(CsMarshalBase marshallable)
 {
     return(Block(
                LocalDeclarationStatement(
                    VariableDeclaration(
                        PredefinedType(Token(SyntaxKind.IntKeyword)),
                        SingletonSeparatedList(
                            VariableDeclarator(Identifier($"{marshallable.Name}_length"))
                            .WithInitializer(EqualsValueClause(
                                                 InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                             GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Math),
                                                                                             IdentifierName("Min")),
                                                                      ArgumentList(
                                                                          SeparatedList(
                                                                              new[]
     {
         Argument(
             BinaryExpression(SyntaxKind.CoalesceExpression,
                              ConditionalAccessExpression(
                                  IdentifierName(marshallable.Name),
                                  MemberBindingExpression(IdentifierName("Length"))),
                              LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))),
         Argument(
             LiteralExpression(SyntaxKind.NumericLiteralExpression,
                               Literal(marshallable.ArrayDimensionValue - 1)))
     }
                                                                              )
                                                                          ))))))),
                LocalDeclarationStatement(
                    VariableDeclaration(
                        ParseTypeName("System.IntPtr"),
                        SingletonSeparatedList(
                            VariableDeclarator(Identifier("__from"))
                            .WithInitializer(EqualsValueClause(
                                                 InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                             GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal),
                                                                                             IdentifierName("StringToHGlobalAnsi")))
                                                 .WithArgumentList(
                                                     ArgumentList(SingletonSeparatedList(Argument(IdentifierName(marshallable.Name)))))))))),
                FixedStatement(
                    VariableDeclaration(
                        PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))),
                        SingletonSeparatedList(
                            VariableDeclarator("__to")
                            .WithInitializer(EqualsValueClause(
                                                 PrefixUnaryExpression(SyntaxKind.AddressOfExpression,
                                                                       GetMarshalStorageLocation(marshallable)))))
                        ),
                    Block(
                        GenerateCopyMemoryInvocation(IdentifierName($"{marshallable.Name}_length")),
                        ExpressionStatement(
                            AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                 ElementAccessExpression(IdentifierName("__to"),
                                                                         BracketedArgumentList(
                                                                             SingletonSeparatedList(
                                                                                 Argument(IdentifierName($"{marshallable.Name}_length"))))),
                                                 LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))))),
                ExpressionStatement(InvocationExpression(
                                        MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                               GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal),
                                                               IdentifierName("FreeHGlobal")),
                                        ArgumentList(SingletonSeparatedList(
                                                         Argument(IdentifierName($"__from"))))))
                ));
 }
예제 #13
0
        public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame)
        {
            if (csElement.IsArray) // Fixed-length character array
            {
                if (!csElement.IsWideChar || !singleStackFrame)
                {
                    return(FixedStatement(
                               VariableDeclaration(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))),
                                                   SingletonSeparatedList(
                                                       VariableDeclarator("__ptr")
                                                       .WithInitializer(EqualsValueClause(
                                                                            PrefixUnaryExpression(SyntaxKind.AddressOfExpression,
                                                                                                  GetMarshalStorageLocation(csElement))
                                                                            )))),
                               ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                        IdentifierName(csElement.Name),
                                                                        InvocationExpression(
                                                                            MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                   globalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers),
                                                                                                   IdentifierName("PtrToString" + (csElement.IsWideChar ? "Uni" : "Ansi"))),
                                                                            ArgumentList(SeparatedList(
                                                                                             new[]
                    {
                        Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__ptr"))),
                        Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(csElement.ArrayDimensionValue - 1)))
                    }
                                                                                             )))))));
                }
                return(null);
            }

            if (!csElement.IsWideChar || !singleStackFrame) // Variable-length string represented as a pointer.
            {
                return(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                IdentifierName(csElement.Name),
                                                                InvocationExpression(
                                                                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                           GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal),
                                                                                           IdentifierName("PtrToString" + (csElement.IsWideChar ? "Uni" : "Ansi"))),
                                                                    ArgumentList(SingletonSeparatedList(
                                                                                     Argument(
                                                                                         GetMarshalStorageLocation(csElement))))))));
            }
            return(null);
        }
        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(
                    ParenthesizedExpression(
                        PrefixUnaryExpression(
                            SyntaxKind.PointerIndirectionExpression,
                            CastExpression(
                                TripleVoidPtr,
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName("_nativePointer")
                                    )
                                )
                            )
                        ),
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                method.CustomVtbl
                                    ? MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName($"{callable.Name}__vtbl_index")
                                    )
                                    : vtableOffsetExpression
                                )
                            )
                        )
                    );
            }

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

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

            ExpressionSyntax what = callable switch
            {
                CsFunction => IdentifierName(
                    callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                    ),
                CsMethod => ParenthesizedExpression(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);
            }

            var generatesMarshalVariable = generators.Marshalling
                                           .GetMarshaller(callable.ReturnValue)
                                           .GeneratesMarshalVariable(callable.ReturnValue);

            return(AssignmentExpression(
                       SyntaxKind.SimpleAssignmentExpression,
                       generatesMarshalVariable
                    ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                    : IdentifierName(callable.ReturnValue.Name),
                       call
                       ));
        }
    }
예제 #15
0
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var vtblClassName = csElement.VtblName.Split('.').Last();

            // Default: at least protected to enable inheritance.
            var vtblVisibility = csElement.VtblVisibility ?? Visibility.ProtectedInternal;

            StatementSyntax VtblMethodSelector(CsMethod method)
            {
                StatementSyntax MethodBuilder(PlatformDetectionType platform)
                {
                    var arguments = new[]
                    {
                        Argument(
                            ObjectCreationExpression(IdentifierName(GetMethodDelegateName(method, platform)))
                            .WithArgumentList(
                                ArgumentList(
                                    SingletonSeparatedList(
                                        Argument(
                                            IdentifierName(
                                                $"{method.Name}{GeneratorHelpers.GetPlatformSpecificSuffix(platform)}"
                                                )
                                            )
                                        )
                                    )
                                )
                            ),
                        Argument(
                            LiteralExpression(
                                SyntaxKind.NumericLiteralExpression,
                                Literal((platform & PlatformDetectionType.Windows) != 0
                                            ? method.WindowsOffset
                                            : method.Offset)
                                )
                            )
                    };

                    return(ExpressionStatement(
                               InvocationExpression(IdentifierName("AddMethod"))
                               .WithArgumentList(ArgumentList(SeparatedList(arguments)))
                               ));
                }

                return(GeneratorHelpers.GetPlatformSpecificStatements(globalNamespace, generators.Config,
                                                                      method.InteropSignatures.Keys, MethodBuilder));
            }

            List <MemberDeclarationSyntax> members = new()
            {
                ConstructorDeclaration(Identifier(vtblClassName))
                .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                .WithParameterList(
                    ParameterList(
                        SingletonSeparatedList(
                            Parameter(Identifier("numberOfCallbackMethods"))
                            .WithType(PredefinedType(Token(SyntaxKind.IntKeyword)))
                            )
                        )
                    )
                .WithInitializer(
                    ConstructorInitializer(
                        SyntaxKind.BaseConstructorInitializer,
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    BinaryExpression(
                                        SyntaxKind.AddExpression,
                                        IdentifierName("numberOfCallbackMethods"),
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(csElement.MethodList.Count)
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
                .WithBody(
                    Block(
                        csElement.Methods
                        .OrderBy(method => method.Offset)
                        .Select(VtblMethodSelector)
                        )
                    )
            };

            members.AddRange(csElement.Methods.SelectMany(method => generators.ShadowCallable.GenerateCode(method)));

            return(ClassDeclaration(vtblClassName)
                   .WithModifiers(
                       ModelUtilities.VisibilityToTokenList(vtblVisibility, SyntaxKind.UnsafeKeyword,
                                                            SyntaxKind.PartialKeyword)
                       )
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null
                                       ? IdentifierName(csElement.Base.VtblName)
                                       : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl)
                                   )
                               )
                           )
                       )
                   .WithMembers(List(members)));
        }
        private StatementSyntax GenerateCopyBlock(CsMarshalBase parameter, CopyBlockDirection direction)
        {
            var arrayIdentifier   = IdentifierName(parameter.Name);
            var pointerIdentifier = GetMarshalStorageLocationIdentifier(parameter);
            var fixedName         = $"{pointerIdentifier}_";

            var fixedInitializer = VariableDeclarator(fixedName)
                                   .WithInitializer(EqualsValueClause(arrayIdentifier));

            var unsafeName = GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Unsafe);

            var destination = direction switch
            {
                CopyBlockDirection.UnmanagedToFixedArray => Identifier(fixedName),
                CopyBlockDirection.FixedArrayToUnmanaged => pointerIdentifier,
                _ => throw new ArgumentOutOfRangeException(nameof(direction))
            };

            var source = direction switch
            {
                CopyBlockDirection.UnmanagedToFixedArray => pointerIdentifier,
                CopyBlockDirection.FixedArrayToUnmanaged => Identifier(fixedName),
                _ => throw new ArgumentOutOfRangeException(nameof(direction))
            };

            var invokeArguments = ArgumentList(
                SeparatedList(
                    new[]
            {
                Argument(IdentifierName(destination)),
                Argument(IdentifierName(source)),
                Argument(
                    CastExpression(
                        PredefinedType(Token(SyntaxKind.UIntKeyword)),
                        ParenthesizedExpression(
                            BinaryExpression(
                                SyntaxKind.MultiplyExpression,
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    arrayIdentifier,
                                    IdentifierName("Length")
                                    ),
                                InvocationExpression(
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        unsafeName,
                                        GenericName(
                                            Identifier(nameof(Unsafe.SizeOf)),
                                            TypeArgumentList(
                                                SingletonSeparatedList <TypeSyntax>(
                                                    IdentifierName(parameter.PublicType.QualifiedName)
                                                    )
                                                )
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
            }
                    )
                );

            return(FixedStatement(
                       VariableDeclaration(
                           VoidPtrType,
                           SingletonSeparatedList(fixedInitializer)
                           ),
                       ExpressionStatement(
                           InvocationExpression(
                               MemberAccessExpression(
                                   SyntaxKind.SimpleMemberAccessExpression,
                                   unsafeName,
                                   IdentifierName(nameof(Unsafe.CopyBlockUnaligned))
                                   ),
                               invokeArguments
                               )
                           )
                       ));
        }
    }
}