private static void InternalWriteHeader( CodeTextWriter twHeader, PreparedInformations prepared, ITypeInformation targetType, MemberScopes memberScope, IReadOnlyDictionary <ITypeInformation, ITypeInformation[]> typesByDeclaring) { if (typesByDeclaring.TryGetValue(targetType, out var types)) { foreach (var type in types) { // The nested types have to declare before outer types. if (!type.Equals(targetType)) { InternalWriteHeader( twHeader, prepared, type, memberScope, typesByDeclaring); } // Write value type and object reference type. TypeWriter.WriteTypeDefinitions( twHeader, type); // Write type members. TypeWriter.WriteMemberDefinitions( twHeader, type, field => true, method => // Except type initializer !(method.IsConstructor && method.IsStatic) && prepared.Functions.ContainsKey(method)); // TODO: The internal or private members can separate into the internal headers. //field => field.CLanguageMemberScope == memberScope, //method => (method.CLanguageMemberScope == memberScope) && prepared.Functions.ContainsKey(method)); } } }
public static void InternalConvertToPrototypes( CodeTextWriter tw, ITypeInformation[] types, Func <ITypeInformation, bool> predictType, Func <IFieldInformation, bool> predictField, Func <IMethodInformation, bool> predictMethod) { tw.WriteLine("#ifdef __cplusplus"); tw.WriteLine("extern \"C\" {"); tw.WriteLine("#endif"); tw.SplitLine(); tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// [2-1] Types:"); tw.SplitLine(); // Output prototypes. foreach (var type in types. Where(type => predictType(type))) { // Unfortunately the enum type at C language has not the underlying type. // IL2C emits the enum types using not C language syntax. if (type.IsEnum) { tw.WriteLine( "typedef {0} {1};", type.ElementType.CLanguageTypeName, type.MangledName); } // The delegate derived types are same as System.MulticastDelegate. else if (type.IsDelegate) { tw.WriteLine( "typedef System_MulticastDelegate {0};", type.MangledName); } else { tw.WriteLine( "typedef struct {0} {0};", type.MangledName); } } tw.SplitLine(); // Output value type and object reference type. foreach (var type in types. Where(predictType)) { TypeWriter.InternalConvertType( tw, type); } tw.SplitLine(); tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// [2-2] Public static fields:"); tw.SplitLine(); foreach (var type in types. Where(type => !type.IsEnum)) { foreach (var field in type.Fields .Where(field => field.IsPublic && field.IsStatic && predictField(field))) { tw.WriteLine( "extern {0};", field.GetCLanguageStaticPrototype(false)); } tw.SplitLine(); } tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); tw.WriteLine("// [2-3] Methods:"); tw.SplitLine(); foreach (var type in types. Where(type => !type.IsEnum)) { var methods = type.DeclaredMethods. Where(predictMethod). ToArray(); if (methods.Length >= 1) { tw.WriteLine( "// [2-4] Member methods: {0}", type.FriendlyName); tw.SplitLine(); foreach (var method in type.DeclaredMethods. Where(predictMethod)) { tw.WriteLine( "extern {0}{1};", method.IsStatic ? "/* static */ " : method.IsVirtual ? (method.IsReuseSlot ? "/* override */ " : "/* virtual */ ") : string.Empty, method.CLanguageFunctionPrototype); } tw.SplitLine(); } } tw.WriteLine("#ifdef __cplusplus"); tw.WriteLine("}"); tw.WriteLine("#endif"); tw.SplitLine(); }
private static void InternalWriteSourceCode( CodeTextWriter twSource, IExtractContextHost extractContext, PreparedInformations prepared, ITypeInformation targetType, DebugInformationOptions debugInformationOption, IReadOnlyDictionary <ITypeInformation, ITypeInformation[]> typesByDeclaring) { // TODO: invalid sequence for multiple nested types. if (typesByDeclaring.TryGetValue(targetType, out var types)) { foreach (var type in types) { // The nested types have to declare before outer types. if (!type.Equals(targetType)) { InternalWriteSourceCode( twSource, extractContext, prepared, type, debugInformationOption, typesByDeclaring); } twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine( "// [9-1] Type: {0}", targetType.FriendlyName); twSource.SplitLine(); twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// [9-2] File scope prototypes:"); twSource.SplitLine(); // Write type members. TypeWriter.WriteMemberDefinitions( twSource, type, field => field.CLanguageMemberScope == MemberScopes.File, method => (method.CLanguageMemberScope == MemberScopes.File) && prepared.Functions.ContainsKey(method)); // All static fields except enum and native value. if (!type.IsEnum) { var staticFields = type.Fields. Where(field => field.IsStatic && (field.NativeValue == null)). ToArray(); if (staticFields.Length >= 1) { twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// [9-3] Static field handlers:"); twSource.SplitLine(); var staticFieldsName = type.MangledUniqueName + "_STATIC_FIELDS"; twSource.WriteLine( "static volatile uintptr_t {0}_initializerCount__ = 0;", staticFieldsName); twSource.SplitLine(); twSource.WriteLine( "static struct {0}_DECL__ /* IL2C_STATIC_FIELDS */", staticFieldsName); twSource.WriteLine("{"); var objrefStaticFields = staticFields. Where(field => field.FieldType.IsReferenceType). ToArray(); var valueTypeStaticFields = staticFields. Where(field => field.FieldType.IsValueType && field.FieldType.IsRequiredTraverse). ToArray(); var otherStaticFields = new HashSet <IFieldInformation>(staticFields. Except(objrefStaticFields). Except(valueTypeStaticFields)); using (var _ = twSource.Shift()) { twSource.WriteLine("IL2C_STATIC_FIELDS* pNext__;"); twSource.WriteLine("const uint16_t objRefCount__;"); twSource.WriteLine("const uint16_t valueCount__;"); if (objrefStaticFields.Length >= 1) { twSource.WriteLine("//-------------------- objref"); foreach (var field in objrefStaticFields) { twSource.WriteLine( "{0} {1};", field.FieldType.CLanguageTypeName, field.MangledName); } } if (valueTypeStaticFields.Length >= 1) { twSource.WriteLine("//-------------------- value type"); foreach (var field in valueTypeStaticFields) { twSource.WriteLine( "{0} {1};", field.FieldType.CLanguageTypeName, field.MangledName); } } } twSource.WriteLine( "}} {0}__ = {{ NULL, {1}, {2} }};", staticFieldsName, objrefStaticFields.Length, valueTypeStaticFields.Length); twSource.SplitLine(); foreach (var field in otherStaticFields) { twSource.WriteLine( "static {0} {1};", field.FieldType.CLanguageTypeName, field.MangledUniqueName); } twSource.SplitLine(); foreach (var field in staticFields) { twSource.WriteLine( "{0}* {1}_HANDLER__(void)", field.FieldType.CLanguageTypeName, field.MangledUniqueName); twSource.WriteLine("{"); using (var _ = twSource.Shift()) { // TODO: Have to guard race condition for the multi threading feature. twSource.WriteLine( "if (il2c_unlikely__({0}_initializerCount__ != *il2c_initializer_count))", staticFieldsName); twSource.WriteLine("{"); using (var __ = twSource.Shift()) { twSource.WriteLine( "{0}_initializerCount__ = *il2c_initializer_count;", staticFieldsName); twSource.WriteLine( "il2c_register_static_fields(&{0}__);", staticFieldsName); var typeInitializer = type.DeclaredMethods. FirstOrDefault(method => method.IsConstructor && method.IsStatic); if (typeInitializer != null) { twSource.WriteLine( "{0}();", typeInitializer.CLanguageFunctionFullName); } } twSource.WriteLine("}"); if (otherStaticFields.Contains(field)) { twSource.WriteLine( "return &{0};", field.MangledUniqueName); } else { twSource.WriteLine( "return &{0}__.{1};", staticFieldsName, field.MangledName); } } twSource.WriteLine("}"); twSource.SplitLine(); } } } twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////"); twSource.WriteLine("// [9-4] Type: {0}", type.FriendlyName); twSource.SplitLine(); // All methods and constructor exclude type initializer foreach (var method in type.DeclaredMethods. Where(method => prepared.Functions.ContainsKey(method))) { FunctionWriter.InternalConvertFromMethod( twSource, extractContext, prepared, method, debugInformationOption); } if (type.IsClass || type.IsValueType) { TypeHelperWriter.InternalConvertTypeHelper( twSource, type); } else if (type.IsInterface) { TypeHelperWriter.InternalConvertTypeHelperForInterface( twSource, type); } twSource.SplitLine(); } } }