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(); }
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(); }
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(); }
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; } }