SharpGen/Generator/Marshallers/ArrayMarshallerBase.cs (104 lines of code) (raw):

using System.Collections.Generic; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using SharpGen.Model; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace SharpGen.Generator.Marshallers { internal abstract class ArrayMarshallerBase : MarshallerBase, IMarshaller { public ArgumentSyntax GenerateManagedArgument(CsParameter csElement) => Argument(IdentifierName(csElement.Name)); public ParameterSyntax GenerateManagedParameter(CsParameter csElement) => GenerateManagedArrayParameter(csElement); public abstract StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame); public IEnumerable<StatementSyntax> GenerateManagedToNativeProlog(CsMarshalCallableBase csElement) { var identifier = GetMarshalStorageLocationIdentifier(csElement); var elementType = GetMarshalElementTypeSyntax(csElement); var spanTypeName = GlobalNamespace.GetGenericTypeNameSyntax( BuiltinType.Span, TypeArgumentList(SingletonSeparatedList(elementType)) ); ArrayTypeSyntax GetArrayType(ExpressionSyntax length) => ArrayType( elementType, SingletonList(ArrayRankSpecifier(SingletonSeparatedList(length))) ); yield return LocalDeclarationStatement( VariableDeclaration( spanTypeName, SingletonSeparatedList( VariableDeclarator( identifier, default, EqualsValueClause(StackAllocArrayCreationExpression(GetArrayType(ZeroLiteral))) ) ) ) ); var variable = IdentifierName(identifier); var length = GeneratorHelpers.LengthExpression(IdentifierName(csElement.Name)); var arrayType = GetArrayType(LengthIdentifierName); yield return GenerateNullCheckIfNeeded( csElement, Block( LocalDeclarationStatement( VariableDeclaration( TypeInt32, SingletonSeparatedList( VariableDeclarator(LengthIdentifier, default, EqualsValueClause(length)) ) ) ), ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, variable, ConditionalExpression( BinaryExpression( SyntaxKind.LessThanExpression, BinaryExpression( SyntaxKind.MultiplyExpression, GeneratorHelpers.CastExpression(TypeUInt32, LengthIdentifierName), SizeOf(elementType) ), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1024u)) ), StackAllocArrayCreationExpression(arrayType), ObjectCreationExpression(arrayType) ) ) ) ) ); } public IEnumerable<StatementSyntax> GenerateNativeToManagedExtendedProlog(CsMarshalCallableBase csElement) { yield return GenerateArrayNativeToManagedExtendedProlog(csElement); } public abstract StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame); public abstract StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame); public ArgumentSyntax GenerateNativeArgument(CsMarshalCallableBase csElement) => Argument(IdentifierName(csElement.IntermediateMarshalName)); public FixedStatementSyntax GeneratePin(CsParameter csElement) => FixedStatement( VariableDeclaration( VoidPtrType, SingletonSeparatedList( VariableDeclarator( Identifier(csElement.IntermediateMarshalName), null, EqualsValueClause(GetMarshalStorageLocation(csElement)) ) ) ), EmptyStatement() ); public abstract bool CanMarshal(CsMarshalBase csElement); public bool GeneratesMarshalVariable(CsMarshalCallableBase csElement) => true; protected abstract TypeSyntax GetMarshalElementTypeSyntax(CsMarshalBase csElement); public TypeSyntax GetMarshalTypeSyntax(CsMarshalBase csElement) => PointerType(GetMarshalElementTypeSyntax(csElement)); protected ArrayMarshallerBase(Ioc ioc) : base(ioc) { } } }