Exemple #1
0
 public Compiler(string name)
 {
     Assembly = new AssemblyDefinition(name, name + ".exe");
     Context  = new CompilerContext(this);
     Global   = new GlobalNamespace();
     AstRoot  = new AstProject(name + ".exe");
 }
Exemple #2
0
 public override StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) =>
 GenerateNullCheckIfNeeded(
     csElement,
     ExpressionStatement(
         InvocationExpression(
             MemberAccessExpression(
                 SyntaxKind.SimpleMemberAccessExpression,
                 GlobalNamespace.GetTypeNameSyntax(WellKnownName.MarshallingHelpers),
                 GenericName(Identifier("ConvertToPointerArray"))
                 .WithTypeArgumentList(
                     TypeArgumentList(
                         SingletonSeparatedList <TypeSyntax>(
                             IdentifierName(csElement.PublicType.QualifiedName)
                             )
                         )
                     )
                 ),
             ArgumentList(
                 SeparatedList(
                     new[]
 {
     // Span<IntPtr> pointers, ReadOnlySpan<TCallback> interfaces
     Argument(GetMarshalStorageLocation(csElement)),
     Argument(IdentifierName(csElement.Name))
 }
                     )
                 )
             )
         )
     );
Exemple #3
0
 public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) =>
 ExpressionStatement(
     AssignmentExpression(
         SyntaxKind.SimpleAssignmentExpression,
         GetMarshalStorageLocation(csElement),
         InvocationExpression(
             MemberAccessExpression(
                 SyntaxKind.SimpleMemberAccessExpression,
                 GlobalNamespace.GetTypeNameSyntax(WellKnownName.MarshallingHelpers),
                 GenericName(Identifier("ToCallbackPtr"))
                 .WithTypeArgumentList(
                     TypeArgumentList(
                         SingletonSeparatedList <TypeSyntax>(
                             IdentifierName(csElement.PublicType.QualifiedName)
                             )
                         )
                     )
                 ),
             ArgumentList(
                 SingletonSeparatedList(
                     Argument(IdentifierName(csElement.Name))
                     )
                 )
             )
         )
     );
        public override void SetUp()
        {
            base.SetUp();

            Context.References.Add(typeof(Boo.Lang.List).Assembly);
            Context.References.Add(typeof(Boo.Lang.Compiler.CompilerContext).Assembly);

            RunInCompilerContextEnvironment(() => _subject = My <GlobalNamespace> .Instance);
        }
Exemple #5
0
		public override void SetUp()
		{
			base.SetUp();

			Context.References.Add(typeof(Boo.Lang.List).Assembly);
			Context.References.Add(typeof(Boo.Lang.Compiler.CompilerContext).Assembly);

			RunInCompilerContextEnvironment(() => _subject = My<GlobalNamespace>.Instance);
		}
 private ExpressionSyntax GetMarshalFunctionPointerForDelegate(CsMethod method,
                                                               PlatformDetectionType platform) =>
 InvocationExpression(
     MemberAccessExpression(
         SyntaxKind.SimpleMemberAccessExpression,
         GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal),
         IdentifierName("GetFunctionPointerForDelegate")
         ),
     ArgumentList(SingletonSeparatedList(Argument(IdentifierName(GetMethodCacheName(method, platform)))))
     );
Exemple #7
0
        GlobalNamespace GetGlobalNamespace()
        {
            INamespace      ns      = _global;
            GlobalNamespace globals = ns as GlobalNamespace;

            while (globals == null && ns != null)
            {
                ns      = ns.ParentNamespace;
                globals = ns as GlobalNamespace;
            }
            return(globals);
        }
        public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame)
        {
            var marshalStorage = GetMarshalStorageLocation(csElement);

            // TODO: Reverse-callback support?
            if (singleStackFrame)
            {
                return(GenerateNullCheckIfNeeded(
                           csElement, EmitConvertToIntArray(marshalStorage)
                           ));
            }
            else
            {
                return(GenerateNullCheckIfNeeded(csElement,
                                                 FixedStatement(
                                                     VariableDeclaration(GetMarshalTypeSyntax(csElement))
                                                     .WithVariables(
                                                         SingletonSeparatedList(
                                                             VariableDeclarator(
                                                                 Identifier("__ptr"))
                                                             .WithInitializer(
                                                                 EqualsValueClause(
                                                                     PrefixUnaryExpression(
                                                                         SyntaxKind.AddressOfExpression,
                                                                         marshalStorage))))),
                                                     EmitConvertToIntArray(IdentifierName("__ptr"))
                                                     )));
            }

            ExpressionStatementSyntax EmitConvertToIntArray(ExpressionSyntax destination) => ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        GlobalNamespace.GetTypeNameSyntax(WellKnownName.BooleanHelpers),
                        IdentifierName("ConvertToIntArray")
                        ),
                    ArgumentList(
                        SeparatedList(
                            new[]
            {
                Argument(IdentifierName(csElement.Name)),
                Argument(destination)
            }
                            )
                        )
                    )
                );
        }
Exemple #9
0
 public StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame)
 {
     if (!csElement.IsWideChar || !singleStackFrame)
     {
         return(ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal),
                            IdentifierName(nameof(Marshal.FreeHGlobal))
                            ),
                        ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement))))
                        )
                    ));
     }
     return(null);
 }
    public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame)
    {
        if (csElement.IsArray) // Fixed-length character array
        {
            if (!csElement.IsWideChar)
            {
                return(GenerateAnsiStringToArray(csElement));
            }

            if (!singleStackFrame)
            {
                return(GenerateStringToArray(csElement));
            }

            return(null);
        }

        // Variable-length string represented as a pointer.

        if (!csElement.IsWideChar || !singleStackFrame)
        {
            var argumentList       = ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name))));
            ExpressionSyntax value = csElement.StringMarshal switch
            {
                StringMarshalType.WindowsRuntimeString => ObjectCreationExpression(
                    GlobalNamespace.GetTypeNameSyntax(WellKnownName.WinRTString),
                    argumentList,
                    default
                    ),
                var type => InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal),
                        IdentifierName(
                            type switch
                {
                    StringMarshalType.GlobalHeap when csElement.IsWideChar =>
                    nameof(Marshal.StringToHGlobalUni),
                    StringMarshalType.GlobalHeap => nameof(Marshal.StringToHGlobalAnsi),
                    StringMarshalType.ComTaskAllocator when csElement.IsWideChar =>
                    nameof(Marshal.StringToCoTaskMemUni),
                    StringMarshalType.ComTaskAllocator => nameof(Marshal.StringToCoTaskMemAnsi),
                    StringMarshalType.BinaryString => nameof(Marshal.StringToBSTR),
                    _ => throw new ArgumentOutOfRangeException()
                }
 public override MemberDeclarationSyntax GenerateCode(CsResultConstant csElement) => AddDocumentationTrivia(
     FieldDeclaration(
         VariableDeclaration(
             GlobalNamespace.GetTypeNameSyntax(WellKnownName.Result),
             SingletonSeparatedList(
                 VariableDeclarator(Identifier(csElement.Name))
                 .WithInitializer(
                     EqualsValueClause(
                         ImplicitObjectCreationExpression()
                         .AddArgumentListArguments(Argument(ParseExpression(csElement.Value)))
                         )
                     )
                 )
             )
         )
     .WithModifiers(csElement.VisibilityTokenList),
     csElement
     );
Exemple #12
0
        public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame)
        {
            if (csElement.IsArray) // Fixed-length character array
            {
                if (!csElement.IsWideChar)
                {
                    return(GenerateAnsiStringToArray(csElement));
                }

                if (!singleStackFrame)
                {
                    return(GenerateStringToArray(csElement));
                }

                return(null);
            }

            // Variable-length string represented as a pointer.

            if (!csElement.IsWideChar || !singleStackFrame)
            {
                return(ExpressionStatement(
                           AssignmentExpression(
                               SyntaxKind.SimpleAssignmentExpression,
                               GetMarshalStorageLocation(csElement),
                               InvocationExpression(
                                   MemberAccessExpression(
                                       SyntaxKind.SimpleMemberAccessExpression,
                                       GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal),
                                       IdentifierName(
                                           csElement.IsWideChar
                                        ? nameof(Marshal.StringToHGlobalUni)
                                        : nameof(Marshal.StringToHGlobalAnsi)
                                           )
                                       ),
                                   ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name))))
                                   )
                               )
                           ));
            }

            return(null);
        }
 protected override ExpressionSyntax Generate(CsResultConstant csElement)
 {
     return(InvocationExpression(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    GlobalNamespace.GetTypeNameSyntax(WellKnownName.Result),
                    IdentifierName("Register")
                    ),
                ArgumentList(
                    SeparatedList(
                        new[]
     {
         Argument(ParseExpression(csElement.Value)),
         LiteralArgument(csElement.Module),
         LiteralArgument(csElement.CppElementName),
         LiteralArgument(csElement.Name)
     }
                        )
                    )
                ));
    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,
Exemple #15
0
 protected ExpressionStatementSyntax GenerateCopyMemoryInvocation(
     ExpressionSyntax destination, ExpressionSyntax source, ExpressionSyntax numBytesExpression
     ) => ExpressionStatement(
     InvocationExpression(
         MemberAccessExpression(
             SyntaxKind.SimpleMemberAccessExpression,
             GlobalNamespace.GetTypeNameSyntax(WellKnownName.MemoryHelpers),
             IdentifierName("CopyMemory")
             ),
         ArgumentList(
             SeparatedList(
                 new[]
 {
     Argument(destination),
     Argument(source),
     Argument(numBytesExpression)
 }
                 )
             )
         )
     );
        public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame)
        {
            MemberAccessExpressionSyntax PtrToString(NameSyntax implName) =>
            MemberAccessExpression(
                SyntaxKind.SimpleMemberAccessExpression,
                implName,
                IdentifierName(
                    csElement.IsWideChar ? nameof(Marshal.PtrToStringUni) : nameof(Marshal.PtrToStringAnsi)
                    )
                );

            if (csElement.IsArray) // Fixed-length character array
            {
                if (csElement.IsWideChar && singleStackFrame)
                {
                    return(null);
                }

                const string ptrName = "__ptr";

                return(FixedStatement(
                           VariableDeclaration(
                               VoidPtrType,
                               SingletonSeparatedList(
                                   VariableDeclarator(ptrName)
                                   .WithInitializer(
                                       EqualsValueClause(
                                           PrefixUnaryExpression(
                                               SyntaxKind.AddressOfExpression,
                                               GetMarshalStorageLocation(csElement)
                                               )
                                           )
                                       )
                                   )
                               ),
                           ExpressionStatement(
                               AssignmentExpression(
                                   SyntaxKind.SimpleAssignmentExpression,
                                   IdentifierName(csElement.Name),
                                   InvocationExpression(
                                       PtrToString(GlobalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers)),
                                       ArgumentList(
                                           SeparatedList(
                                               new[]
                {
                    Argument(CastExpression(IntPtrType, IdentifierName(ptrName))),
                    Argument(
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(csElement.ArrayDimensionValue - 1)
                            )
                        )
                }
                                               )
                                           )
                                       )
                                   )
                               )
                           ));
            }

            // Variable-length string represented as a pointer.
            return(ExpressionStatement(
                       AssignmentExpression(
                           SyntaxKind.SimpleAssignmentExpression,
                           IdentifierName(csElement.Name),
                           InvocationExpression(
                               PtrToString(GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal)),
                               ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement))))
                               )
                           )
                       ));
        }
Exemple #17
0
        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
                       ));
        }
Exemple #18
0
 /// <summary>
 /// Iterate through all namespace data from top to bottom
 /// </summary>
 public IEnumerable <NamespaceData> GetAllNamespaceDatas(Func <NamespaceData, bool> predicate = null)
 {
     return(GlobalNamespace.GetSelfAndDescendantsNamespaceData(predicate));
 }
Exemple #19
0
        private StatementSyntax GenerateStringToArray(CsMarshalBase marshallable)
        {
            var lengthIdentifier = LengthVariableName(marshallable);

            return(FixedStatement(
                       VariableDeclaration(
                           PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))),
                           SeparatedList(
                               new[]
            {
                VariableDeclarator(FromIdentifier)
                .WithInitializer(EqualsValueClause(IdentifierName(marshallable.Name))),
                VariableDeclarator(ToIdentifier)
                .WithInitializer(EqualsValueClause(
                                     PrefixUnaryExpression(SyntaxKind.AddressOfExpression,
                                                           GetMarshalStorageLocation(marshallable))))
            })
                           ),
                       Block(
                           LocalDeclarationStatement(
                               VariableDeclaration(
                                   TypeInt32,
                                   SingletonSeparatedList(
                                       VariableDeclarator(lengthIdentifier)
                                       .WithInitializer(EqualsValueClause(
                                                            InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                        GlobalNamespace.GetTypeNameSyntax(BuiltinType.Math),
                                                                                                        IdentifierName(nameof(Math.Min))),
                                                                                 ArgumentList(
                                                                                     SeparatedList(
                                                                                         new[]
            {
                Argument(
                    BinaryExpression(
                        SyntaxKind.MultiplyExpression,
                        ParenthesizedExpression(
                            GeneratorHelpers.OptionalLengthExpression(IdentifierName(marshallable.Name))
                            ),
                        LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2))
                        )),
                Argument(
                    BinaryExpression(SyntaxKind.MultiplyExpression,
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(marshallable.ArrayDimensionValue - 1)),
                                     LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2))))
            }
                                                                                         )
                                                                                     ))))))),
                           GenerateCopyMemoryInvocation(IdentifierName(lengthIdentifier), castTo: false, castFrom: false),
                           ExpressionStatement(
                               AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                    ElementAccessExpression(IdentifierName(ToIdentifier),
                                                                            BracketedArgumentList(
                                                                                SingletonSeparatedList(
                                                                                    Argument(IdentifierName(lengthIdentifier))))),
                                                    LiteralExpression(SyntaxKind.CharacterLiteralExpression, Literal('\0')))))));
        }
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var vtblClassName = csElement.VtblName.Split('.').Last();

            // Default: at least protected to enable inheritance.
            var vtblVisibility = csElement.VtblVisibility ?? Visibility.ProtectedInternal;

            StatementSyntax VtblMethodSelector(CsMethod method)
            {
                StatementSyntax MethodBuilder(PlatformDetectionType platform)
                {
                    var arguments = new[]
                    {
                        Argument(
                            ObjectCreationExpression(IdentifierName(GetMethodDelegateName(method, platform)))
                            .WithArgumentList(
                                ArgumentList(
                                    SingletonSeparatedList(
                                        Argument(
                                            IdentifierName(
                                                $"{method.Name}{GeneratorHelpers.GetPlatformSpecificSuffix(platform)}"
                                                )
                                            )
                                        )
                                    )
                                )
                            ),
                        Argument(
                            LiteralExpression(
                                SyntaxKind.NumericLiteralExpression,
                                Literal((platform & PlatformDetectionType.Windows) != 0
                                            ? method.WindowsOffset
                                            : method.Offset)
                                )
                            )
                    };

                    return(ExpressionStatement(
                               InvocationExpression(IdentifierName("AddMethod"))
                               .WithArgumentList(ArgumentList(SeparatedList(arguments)))
                               ));
                }

                return(GeneratorHelpers.GetPlatformSpecificStatements(GlobalNamespace, Generators.Config,
                                                                      method.InteropSignatures.Keys, MethodBuilder));
            }

            List <MemberDeclarationSyntax> members = new()
            {
                ConstructorDeclaration(Identifier(vtblClassName))
                .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                .WithParameterList(
                    ParameterList(
                        SingletonSeparatedList(
                            Parameter(Identifier("numberOfCallbackMethods"))
                            .WithType(PredefinedType(Token(SyntaxKind.IntKeyword)))
                            )
                        )
                    )
                .WithInitializer(
                    ConstructorInitializer(
                        SyntaxKind.BaseConstructorInitializer,
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    BinaryExpression(
                                        SyntaxKind.AddExpression,
                                        IdentifierName("numberOfCallbackMethods"),
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(csElement.MethodList.Count)
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
                .WithBody(
                    Block(
                        csElement.Methods
                        .OrderBy(method => method.Offset)
                        .Select(VtblMethodSelector)
                        )
                    )
            };

            members.AddRange(csElement.Methods.SelectMany(method => Generators.ShadowCallable.GenerateCode(method)));

            return(ClassDeclaration(vtblClassName)
                   .WithModifiers(
                       ModelUtilities.VisibilityToTokenList(vtblVisibility, SyntaxKind.UnsafeKeyword,
                                                            SyntaxKind.PartialKeyword)
                       )
                   .WithAttributeLists(DebuggerTypeProxyAttribute)
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null
                                       ? IdentifierName(csElement.Base.VtblName)
                                       : GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl)
                                   )
                               )
                           )
                       )
                   .WithMembers(List(members)));
        }
        public MemberDeclarationSyntax GenerateCode(CsInterface csElement)
        {
            var shadowClassName = csElement.ShadowName.Split('.').Last();

            var vtblName        = IdentifierName(csElement.VtblName);
            var vtblConstructor = ArgumentList(
                SingletonSeparatedList(
                    Argument(
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(0)
                            )
                        )
                    )
                );

            var vtblProperty = PropertyDeclaration(
                GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl),
                Identifier("Vtbl")
                )
                               .WithModifiers(
                TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword))
                )
                               .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));

            List <MemberDeclarationSyntax> members = new();

            if (csElement.AutoGenerateVtbl)
            {
                members.Add(Generators.Vtbl.GenerateCode(csElement));
            }

            if (csElement.StaticShadowVtbl)
            {
                var vtblInstanceName = Identifier("VtblInstance");

                members.Add(
                    FieldDeclaration(
                        VariableDeclaration(vtblName)
                        .WithVariables(
                            SingletonSeparatedList(
                                VariableDeclarator(vtblInstanceName)
                                .WithInitializer(
                                    EqualsValueClause(
                                        ImplicitObjectCreationExpression()
                                        .WithArgumentList(
                                            vtblConstructor
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    .WithModifiers(
                        TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword),
                                  Token(SyntaxKind.ReadOnlyKeyword))
                        )
                    );

                vtblProperty = vtblProperty
                               .WithExpressionBody(
                    ArrowExpressionClause(IdentifierName(vtblInstanceName))
                    );
            }
            else
            {
                vtblProperty = vtblProperty
                               .WithAccessorList(
                    AccessorList(
                        SingletonList(
                            AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                            .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
                            )
                        )
                    )
                               .WithInitializer(
                    EqualsValueClause(
                        ObjectCreationExpression(vtblName)
                        .WithArgumentList(
                            vtblConstructor
                            )
                        )
                    );
            }

            members.Add(vtblProperty);

            return(ClassDeclaration(shadowClassName)
                   .WithModifiers(
                       ModelUtilities.VisibilityToTokenList(csElement.ShadowVisibility, SyntaxKind.PartialKeyword)
                       )
                   .WithBaseList(
                       BaseList(
                           SingletonSeparatedList <BaseTypeSyntax>(
                               SimpleBaseType(
                                   csElement.Base != null
                                       ? IdentifierName(csElement.Base.ShadowName)
                                       : GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow)
                                   )
                               )
                           )
                       )
                   .WithMembers(new SyntaxList <MemberDeclarationSyntax>(members)));
        }