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),
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) ) ) ) )); } }
public SyntaxToken GetMarshalStorageLocationIdentifier(CsMarshalBase csElement) { return(MarshallerBase.GetMarshalStorageLocationIdentifier(csElement)); }
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 )); }
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 )); }