private static void ProcessMethod ( GeneratorExecutionContext sourceContext, MarshalBuilder rootMarshalBuilder, CallingConvention callingConvention, Dictionary <int, string> entryPoints, string entryPoint, bool classIsSealed, bool generateSeal, bool generateVTable, int slot, Compilation compilation, IMethodSymbol symbol, MethodDeclarationSyntax declaration, List <MemberDeclarationSyntax> newMembers, ref int gcCount, List <EntryPoint> processedEntrypoints, string generatedVTableName ) { void BuildLoadInvoke(ref IMarshalContext ctx, Action next) { ctx.TransitionTo(SilkTouchStage.PreLoad); // this is terminal, we never call next var parameters = ctx.ResolveAllLoadParameters(); var fPtrType = FunctionPointerType ( FunctionPointerCallingConvention ( Token(SyntaxKind.UnmanagedKeyword), FunctionPointerUnmanagedCallingConventionList ( SingletonSeparatedList ( FunctionPointerUnmanagedCallingConvention (Identifier(GetCallingConvention(callingConvention))) ) ) ), FunctionPointerParameterList ( SeparatedList ( ctx.LoadTypes.Select ( x => FunctionPointerParameter (IdentifierName(x.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat))) ) ) ) ); entryPoints[ctx.Slot] = entryPoint; processedEntrypoints.Add ( new EntryPoint ( entryPoint, ctx.Slot, callingConvention, ctx.LoadTypes.Select ( x => (TypeSyntax)IdentifierName (x.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)) ) .ToArray(), symbol ) ); ExpressionSyntax loadCallTarget; if ((classIsSealed || generateSeal) && generateVTable) { loadCallTarget = MemberAccessExpression ( SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression ( BinaryExpression ( SyntaxKind.AsExpression, IdentifierName("CurrentVTable"), IdentifierName(generatedVTableName) ) ), IdentifierName("Load") ); } else { loadCallTarget = IdentifierName("Load"); } // build load + invocation Func <IMarshalContext, ExpressionSyntax> expression = ctx => InvocationExpression ( ParenthesizedExpression ( CastExpression ( fPtrType, InvocationExpression ( loadCallTarget, ArgumentList ( SeparatedList ( new[] { Argument (LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(ctx.Slot))), Argument (LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(entryPoint))) } ) ) ) ) ), ArgumentList(SeparatedList(parameters.Select(x => Argument(x.Value)))) ); if (ctx.ReturnsVoid) { var exp = expression(ctx); // this forces evaluation of everything until this point. ctx.AddSideEffect(ctx => ExpressionStatement(exp)); ctx.ResultVariable = null; } else { var id = ctx.DeclareVariable(ctx.ReturnLoadType, false); ctx.ResultVariable = id; ctx.SetVariable(id, expression); _ = ctx.ResolveVariable(id).Value; // force evaluation of ret } ctx.CurrentResultType = ctx.ReturnLoadType; ctx.TransitionTo(SilkTouchStage.PostLoad); } try { var marshalBuilder = rootMarshalBuilder.Clone(); marshalBuilder.Use(BuildLoadInvoke); var context = new MarshalContext(compilation, symbol, slot); marshalBuilder.Run(context); var block = context.BuildFinalBlock(); gcCount += context.GCCount; if (declaration.Modifiers.All(x => x.Text != "unsafe")) { // this is not done as a middleware to allow middleware to prepend any variable declaration, even if it's unsafe block = Block(UnsafeStatement(Token(SyntaxKind.UnsafeKeyword), block)); } var method = declaration.WithBody (block) .WithAttributeLists(default)