예제 #1
0
        public static void PinMiddleware(ref IMarshalContext ctx, Action next)
        {
            for (var index = 0; index < ctx.ParameterVariables.Length; index++)
            {
                // in this loop, update all types & expressions

                var shouldPin = ctx.ShouldPinParameter[index];
                if (!shouldPin)
                {
                    continue;
                }

                var loadType = ctx.LoadTypes[index];
                loadType             = ctx.Compilation.CreatePointerTypeSymbol(loadType);
                ctx.LoadTypes[index] = loadType;

                var(id, name) = ctx.DeclareSpecialVariableNoInlining(loadType, false);
                ctx.SetParameterToVariable(index, id);
                var symbolName = ctx.MethodSymbol.Parameters[index].Name;
                var l          = ctx.LoadTypes[index].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
                ctx.BeginBlock((x, ctx) => FixedStatement
                               (
                                   VariableDeclaration
                                   (
                                       IdentifierName(l),
                                       SingletonSeparatedList
                                           (VariableDeclarator(Identifier(name), null, EqualsValueClause(PrefixUnaryExpression(SyntaxKind.AddressOfExpression, IdentifierName(FormatName(symbolName))))))
                                   ), x
                               ));
            }

            next();
        }
예제 #2
0
        public static void SpanMarshaller(ref IMarshalContext ctx, Action next)
        {
            bool[] b = new bool[ctx.ParameterVariables.Length];

            for (var index = 0; index < ctx.ParameterVariables.Length; index++)
            {
                if (!(ctx.LoadTypes[index] is INamedTypeSymbol named))
                {
                    continue;
                }

                if (!named.IsGenericType)
                {
                    continue;
                }

                if (!SymbolEqualityComparer.Default.Equals(named.OriginalDefinition, ctx.Compilation.GetTypeByMetadataName("System.Span`1")))
                {
                    continue;
                }

                b[index] = true;
            }

            var oldParameterIds = ctx.ParameterVariables.ToArray();

            for (var index = 0; index < ctx.ParameterVariables.Length; index++)
            {
                // in this loop, update all types & expressions

                var shouldPin = b[index];
                if (!shouldPin)
                {
                    continue;
                }

                var loadType = ctx.LoadTypes[index];
                loadType             = ctx.Compilation.CreatePointerTypeSymbol((loadType as INamedTypeSymbol) !.TypeArguments[0]);
                ctx.LoadTypes[index] = loadType;

                var(id, name) = ctx.DeclareSpecialVariableNoInlining(loadType, false);
                ctx.SetParameterToVariable(index, id);
                var l   = ctx.LoadTypes[index].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
                var old = ctx.ResolveVariable(oldParameterIds[index]);
                ctx.BeginBlock((x, ctx) => FixedStatement
                               (
                                   VariableDeclaration
                                   (
                                       IdentifierName(l),
                                       SingletonSeparatedList
                                           (VariableDeclarator(Identifier(name), null, EqualsValueClause(old.Value)))
                                   ), x
                               ));
            }

            next();
        }
예제 #3
0
        public static void ParameterInitMiddleware(ref IMarshalContext ctx, Action next)
        {
            for (int index = 0; index < ctx.MethodSymbol.Parameters.Length; index++)
            {
                var symbol = ctx.MethodSymbol.Parameters[index];
                var id     = ctx.DeclareVariable(symbol.Type);
                ctx.SetVariable(id, _ => IdentifierName(FormatName(symbol.Name)));
                ctx.SetParameterToVariable(index, id);
            }

            next();
        }
        public static void GenericPointerMarshaller(ref IMarshalContext ctx, Action next)
        {
            for (int i = 0; i < ctx.LoadTypes.Length - 1; i++)
            {
                var lt = ctx.LoadTypes[i];
                if (lt is IPointerTypeSymbol pts)
                {
                    if (pts.PointedAtType is ITypeParameterSymbol tps)
                    {
                        var id = ctx.DeclareVariable
                                 (
                            ctx.Compilation.CreatePointerTypeSymbol
                                (ctx.Compilation.GetSpecialType(SpecialType.System_Void))
                                 );
                        var baseId = ctx.ParameterVariables[i];
                        ctx.SetVariable(id, ctx => CastExpression(IdentifierName("void*"), ctx.ResolveVariable(baseId).Value));
                        ctx.SetParameterToVariable(i, id);
                    }
                }
            }

            next();
        }
예제 #5
0
        public static void DelegateMarshaller(ref IMarshalContext ctx, Action next)
        {
            for (var index = 0; index < ctx.ParameterVariables.Length; index++)
            {
                var options = ctx.ParameterMarshalOptions[index];

                if (ctx.LoadTypes[index].TypeKind != TypeKind.Delegate)
                {
                    continue;
                }

                ctx.LoadTypes[index] = ctx.Compilation.GetSpecialType(SpecialType.System_IntPtr);
                var id = ctx.DeclareVariable(ctx.LoadTypes[index]);
                var parameterVariable = ctx.ResolveVariable(ctx.ParameterVariables[index]);
                ctx.SetVariable
                (
                    id, ctx => ConditionalExpression
                    (
                        BinaryExpression
                        (
                            SyntaxKind.EqualsExpression, parameterVariable.Value,
                            LiteralExpression(SyntaxKind.NullLiteralExpression)
                        ),
                        MemberAccessExpression
                        (
                            SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(IntPtr)),
                            IdentifierName(nameof(IntPtr.Zero))
                        ), InvocationExpression
                            ( // System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<T>(ResultName)
                            MemberAccessExpression
                            (
                                SyntaxKind.SimpleMemberAccessExpression,
                                MemberAccessExpression
                                (
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    MemberAccessExpression
                                    (
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        MemberAccessExpression
                                        (
                                            SyntaxKind.SimpleMemberAccessExpression, IdentifierName("System"),
                                            IdentifierName("Runtime")
                                        ), IdentifierName("InteropServices")
                                    ), IdentifierName("Marshal")
                                ), IdentifierName("GetFunctionPointerForDelegate")
                            ), ArgumentList(SingletonSeparatedList(Argument(parameterVariable.Value)))
                            )
                    )
                );
                ctx.SetParameterToVariable(index, id);
            }

            int resultLocalId     = default;
            var processReturn     = ctx.ReturnLoadType.TypeKind == TypeKind.Delegate;
            var oldReturnLoadType = ctx.ReturnLoadType;

            if (processReturn)
            {
                resultLocalId      = ctx.DeclareVariable(ctx.ReturnLoadType);
                ctx.ReturnLoadType = ctx.Compilation.GetSpecialType(SpecialType.System_IntPtr);
            }

            next();

            if (processReturn)
            {
                var resultVariable = ctx.ResolveVariable(ctx.ResultVariable.Value);
                ctx.SetVariable
                (
                    resultLocalId, ctx => ConditionalExpression
                    (
                        BinaryExpression
                        (
                            SyntaxKind.EqualsExpression, resultVariable.Value,
                            MemberAccessExpression
                            (
                                SyntaxKind.SimpleMemberAccessExpression, IdentifierName("IntPtr"),
                                IdentifierName("Zero")
                            )
                        ), LiteralExpression(SyntaxKind.NullLiteralExpression), InvocationExpression
                            ( // System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<T>(ResultName)
                            MemberAccessExpression
                            (
                                SyntaxKind.SimpleMemberAccessExpression,
                                MemberAccessExpression
                                (
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    MemberAccessExpression
                                    (
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        MemberAccessExpression
                                        (
                                            SyntaxKind.SimpleMemberAccessExpression, IdentifierName("System"),
                                            IdentifierName("Runtime")
                                        ), IdentifierName("InteropServices")
                                    ), IdentifierName("Marshal")
                                ),
                                GenericName
                                (
                                    Identifier("GetDelegateForFunctionPointer"),
                                    TypeArgumentList
                                    (
                                        SingletonSeparatedList
                                        (
                                            (TypeSyntax)IdentifierName
                                            (
                                                oldReturnLoadType.ToDisplayString
                                                    (SymbolDisplayFormat.FullyQualifiedFormat)
                                            )
                                        )
                                    )
                                )
                            ),
                            ArgumentList
                                (SingletonSeparatedList(Argument(resultVariable.Value)))
                            )
                    )
                );
                ctx.ResultVariable = resultLocalId;
            }
        }