Exemple #1
0
        internal static void WriteConstStrings(
            CodeTextWriter twSource,
            TranslateContext translateContext)
        {
            IExtractContext extractContext = translateContext;

            var constStrings = extractContext.
                               ExtractConstStrings().
                               ToArray();

            if (constStrings.Length >= 1)
            {
                twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                twSource.WriteLine("// [9-1] Const strings:");
                twSource.SplitLine();

                foreach (var(symbolName, value) in extractContext.ExtractConstStrings())
                {
                    var expr = Utilities.GetCLanguageExpression(value);
                    twSource.WriteLine(
                        "IL2C_CONST_STRING({0}, {1});",
                        symbolName,
                        expr);
                }

                twSource.SplitLine();
            }
        }
Exemple #2
0
        public static string GetStaticFieldPrototypeString(
            FieldReference field,
            bool requireInitializerExpression,
            IExtractContext extractContext)
        {
            var initializer = String.Empty;

            if (requireInitializerExpression)
            {
                if (field.FieldType.IsNumericPrimitive())
                {
                    // TODO: numericPrimitive and (literal or readonly static) ?
                    var fieldDefinition = field.Resolve();
                    Debug.Assert(fieldDefinition.IsStatic);
                    var value = fieldDefinition.HasConstant ? fieldDefinition.Constant : 0;

                    Debug.Assert(value != null);

                    initializer = fieldDefinition.FieldType.IsInt64Type()
                        ? String.Format(" = {0}LL", value)
                        : String.Format(" = {0}", value);
                }
                else if (field.FieldType.IsValueType == false)
                {
                    initializer = " = NULL";
                }
            }

            return(string.Format(
                       "{0} {1}{2}",
                       extractContext.GetCLanguageTypeName(field.FieldType),
                       field.GetFullMemberName().ManglingSymbolName(),
                       initializer));
        }
Exemple #3
0
        internal static void WriteDeclaredValues(
            CodeTextWriter twSource,
            TranslateContext translateContext)
        {
            IExtractContext extractContext = translateContext;

            var declaredValues = extractContext.
                                 ExtractDeclaredValues().
                                 ToArray();

            if (declaredValues.Length >= 1)
            {
                twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                twSource.WriteLine("// [12-1] Declared values:");

                foreach (var information in extractContext.ExtractDeclaredValues())
                {
                    twSource.SplitLine();
                    foreach (var declaredFields in information.DeclaredFields)
                    {
                        twSource.WriteLine(
                            "// {0}",
                            declaredFields.FriendlyName);
                    }

                    var targetType = (information.HintTypes.Length == 1) ?
                                     information.HintTypes[0] :
                                     extractContext.MetadataContext.ByteType.MakeArray();
                    Debug.Assert(targetType.IsArray);

                    var elementType = targetType.ElementType.ResolveToRuntimeType();
                    var values      = Utilities.ResourceDataToSpecificArray(information.ResourceData, elementType);

                    var lhs  = targetType.GetCLanguageTypeName(information.SymbolName, true);
                    var expr = Utilities.GetCLanguageExpression(values);
                    twSource.WriteLine(
                        "static const {0} =",
                        lhs);
                    using (var _ = twSource.Shift())
                    {
                        twSource.WriteLine(
                            "{0};",
                            expr);
                    }
                }

                twSource.SplitLine();
            }
        }
Exemple #4
0
        public static string GetFunctionTypeString(
            TypeReference returnType,
            TypeReference[] parameterTypes,
            IExtractContext extractContext)
        {
            var parametersString = string.Join(
                ", ",
                parameterTypes.Select(parameterType =>
                                      extractContext.GetCLanguageTypeName(parameterType)));

            var returnTypeName =
                extractContext.GetCLanguageTypeName(returnType);

            return(string.Format(
                       "{0} (*)({1})",
                       returnTypeName,
                       (parametersString.Length >= 1) ? parametersString : "void"));
        }
Exemple #5
0
 private static void InternalWriteAssemblyReferences(
     CodeTextWriter tw,
     TranslateContext translateContext,
     IExtractContext extractContext,
     ITypeInformation declaringType)
 {
     foreach (var assembly in extractContext.EnumerateRegisteredTypesByDeclaringType(declaringType).
              Distinct().
              OrderByDependant(declaringType.DeclaringModule.DeclaringAssembly).
              Select(type => type.DeclaringModule.DeclaringAssembly).
              Where(assembly => !assembly.Equals(translateContext.Assembly)).
              Distinct().
              OrderBy(assembly => assembly.Name))
     {
         tw.WriteLine("#include <{0}.h>", assembly.Name);
     }
     tw.SplitLine();
 }
Exemple #6
0
        private static VirtualMethodInformation[] GetVirtualMethods(
            IExtractContext extractContext,
            TypeReference adjustorThunkTargetType,
            TypeReference delegationTargetType)
        {
            var typeName = extractContext
                           .GetCLanguageTypeName(adjustorThunkTargetType);
            var delegationTargetTypeName = delegationTargetType
                                           .GetFullMemberName()
                                           .ManglingSymbolName();

            return(new []
            {
                new VirtualMethodInformation(
                    delegationTargetTypeName,
                    "IL2C_RuntimeCast",
                    "void*",
                    new[]
                {
                    Utilities.KeyValue(typeName, "this__"),
                    Utilities.KeyValue("IL2C_RUNTIME_TYPE_DECL*", "type"),
                }),
            }
                   .Concat(adjustorThunkTargetType
                           .EnumerateOrderedOverridedMethods()
                           .Select(method => new VirtualMethodInformation(
                                       method.DeclaringType.MemberEquals(adjustorThunkTargetType)
                            ? delegationTargetTypeName
                            : method.DeclaringType
                                       .GetFullMemberName()
                                       .ManglingSymbolName(),
                                       method.GetOverloadedMethodName()
                                       .ManglingSymbolName(),
                                       extractContext.GetCLanguageTypeName(
                                           method.ReturnType),
                                       method.GetSafeParameters(adjustorThunkTargetType)
                                       .Select(parameter => Utilities.KeyValue(
                                                   extractContext.GetCLanguageTypeName(parameter.ParameterType),
                                                   parameter.Name))
                                       .ToArray())))
                   .ToArray());
        }
Exemple #7
0
 public static string GetGivenParameterDeclaration(
     RightExpressionGivenParameter[] parameters,
     IExtractContext extractContext,
     int offset)
 {
     return(string.Join(", ", parameters.Select(entry =>
     {
         var rightExpression = extractContext.GetRightExpression(
             entry.TargetType, entry.SymbolInformation);
         if (rightExpression == null)
         {
             throw new InvalidProgramSequenceException(
                 "Invalid parameter type: Offset={0}, StackType={1}, ParameterType={2}",
                 offset,
                 entry.SymbolInformation.TargetType.FullName,
                 entry.TargetType.FullName);
         }
         return rightExpression;
     })));
 }
Exemple #8
0
        public static string GetGivenParameterDeclaration(
            RightExpressionGivenParameter[] parameters,
            IExtractContext extractContext,
            ICodeInformation codeInformation)
        {
            return(string.Join(", ", parameters.Select(parameter =>
            {
                var rightExpression = (parameter.Expression != null) ?
                                      extractContext.GetRightExpression(parameter.TargetType, parameter.SymbolInformation.TargetType, parameter.Expression) :
                                      extractContext.GetRightExpression(parameter.TargetType, parameter.SymbolInformation);
                if (rightExpression == null)
                {
                    throw new InvalidProgramSequenceException(
                        "Invalid parameter type: Location={0}, StackType={1}, ParameterType={2}",
                        codeInformation.RawLocation,
                        parameter.SymbolInformation.TargetType.FriendlyName,
                        parameter.TargetType.FriendlyName);
                }

                return rightExpression;
            })));
        }
Exemple #9
0
        public static void WriteHeader(
            TextWriter twHeader,
            TranslateContext translateContext,
            PreparedFunctions preparedFunctions,
            string indent)
        {
            IExtractContext extractContext = translateContext;

            var assemblyName   = extractContext.Assembly.Name.Name;
            var safeSymbolName = assemblyName.Replace('.', '_').Replace('-', '_');

            twHeader.WriteLine("#ifndef __MODULE_{0}__", safeSymbolName);
            twHeader.WriteLine("#define __MODULE_{0}__", safeSymbolName);
            twHeader.WriteLine();

            foreach (var fileName in extractContext.EnumerateRequiredIncludeFileNames())
            {
                twHeader.WriteLine("#include <{0}>", fileName);
            }

            var types = extractContext.Assembly.Modules
                        .SelectMany(module => module.Types)
                        .SelectMany(type => new[] { type }.Concat(type.NestedTypes))
                        // All types exclude privates
                        .Where(type => type.IsValidDefinition() &&
                               (type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly))
                        .ToArray();

            InternalConvertToPrototypes(
                twHeader,
                types,
                extractContext,
                preparedFunctions,
                method => method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly,
                indent);

            twHeader.WriteLine();
            twHeader.WriteLine("#endif");
        }
Exemple #10
0
        internal static void InternalWriteHeader(
            CodeTextWriter twHeader,
            TranslateContext translateContext,
            PreparedInformations prepared,
            bool includeAssemblyHeader)
        {
            IExtractContext extractContext = translateContext;

            var assemblyName = Utilities.GetMangledName(extractContext.Assembly.FriendlyName);

            twHeader.WriteLine("#ifndef __{0}_H__", assemblyName);
            twHeader.WriteLine("#define __{0}_H__", assemblyName);
            twHeader.SplitLine();
            twHeader.WriteLine("#pragma once");
            twHeader.SplitLine();
            twHeader.WriteLine("#include <il2c.h>");

            if (includeAssemblyHeader)
            {
                twHeader.SplitLine();
                foreach (var fileName in extractContext.EnumerateRequiredIncludeFileNames())
                {
                    twHeader.WriteLine("#include <{0}>", fileName);
                }
            }

            // All types exclude privates
            PrototypeWriter.InternalConvertToPrototypes(
                twHeader,
                prepared.Types,
                type => type.IsCLanguagePublicScope,
                field => field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly,
                method => (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly) &&
                prepared.Functions.ContainsKey(method));

            twHeader.SplitLine();
            twHeader.WriteLine("#endif");
            twHeader.SplitLine();
        }
Exemple #11
0
        public static string GetFunctionTypeString(
            string methodName,
            TypeReference returnType,
            Parameter[] parameters,
            IExtractContext extractContext)
        {
            var parametersString = string.Join(
                ", ",
                parameters.Select(parameter => string.Format(
                                      "{0} {1}",
                                      extractContext.GetCLanguageTypeName(parameter.ParameterType),
                                      parameter.Name)));

            var returnTypeName =
                extractContext.GetCLanguageTypeName(returnType);

            return(string.Format(
                       "{0} (*{1})({2})",
                       returnTypeName,
                       methodName.ManglingSymbolName(),
                       (parametersString.Length >= 1) ? parametersString : "void"));
        }
Exemple #12
0
        private static void InternalConvertFromAbstractFunction(
            TextWriter tw,
            IExtractContext extractContext,
            PreparedFunction preparedFunction,
            string indent)
        {
            var functionPrototype = Utilities.GetFunctionPrototypeString(
                GetFunctionNameByFunctionType(preparedFunction),
                preparedFunction.ReturnType,
                preparedFunction.Parameters,
                extractContext);

            tw.WriteLine();
            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine("// Abstract: {0}", preparedFunction.RawMethodName);
            tw.WriteLine();

            tw.WriteLine(functionPrototype);
            tw.WriteLine("{");

            tw.WriteLine(
                "{0}// WARNING: Pure virtual function called.",
                indent);
            tw.WriteLine(
                "{0}//TODO: throw : assert(0);",
                indent);

            if (preparedFunction.ReturnType.IsVoidType() == false)
            {
                tw.WriteLine(
                    "{0}return ({1}){2};",
                    indent,
                    extractContext.GetCLanguageTypeName(preparedFunction.ReturnType),
                    preparedFunction.ReturnType.IsNumericPrimitive() ? "0" : "NULL");
            }

            tw.WriteLine("}");
        }
Exemple #13
0
        private static void InternalConvertFromPInvokeFunction(
            TextWriter tw,
            IExtractContext extractContext,
            PreparedFunction preparedFunction,
            PInvokeInfo pinvokeInfo,
            string indent)
        {
            var functionPrototype = Utilities.GetFunctionPrototypeString(
                GetFunctionNameByFunctionType(preparedFunction),
                preparedFunction.ReturnType,
                preparedFunction.Parameters,
                extractContext);

            tw.WriteLine();
            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine("// P/Invoke: {0}", preparedFunction.RawMethodName);
            tw.WriteLine();

            tw.WriteLine(functionPrototype);
            tw.WriteLine("{");

            var arguments = string.Join(
                ", ",
                preparedFunction.Parameters
                .Select(parameter => parameter.GetMarshaledInExpression()));

            if (preparedFunction.ReturnType.IsVoidType())
            {
                tw.WriteLine("{0}{1}({2});", indent, pinvokeInfo.EntryPoint, arguments);
            }
            else
            {
                tw.WriteLine("{0}return {1}({2});", indent, pinvokeInfo.EntryPoint, arguments);
            }

            tw.WriteLine("}");
        }
Exemple #14
0
        internal static void InternalConvertFromMethod(
            TextWriter tw,
            IExtractContext extractContext,
            PreparedFunctions preparedFunctions,
            MethodDefinition method,
            string indent,
            DebugInformationOptions debugInformationOption = DebugInformationOptions.None)
        {
            var methodName       = method.GetFullMemberName();
            var preparedFunction = preparedFunctions.Functions[method];

            // Write method body
            switch (preparedFunction.FunctionType)
            {
            case FunctionTypes.Standard:
                Debug.Assert(preparedFunction.PreparedILBodies != null);

                InternalConvertFromFunction(
                    tw,
                    extractContext,
                    preparedFunction,
                    indent,
                    debugInformationOption);
                break;

            case FunctionTypes.Virtual:
                if (preparedFunction.PreparedILBodies != null)
                {
                    InternalConvertFromFunction(
                        tw,
                        extractContext,
                        preparedFunction,
                        indent,
                        debugInformationOption);
                }
                else
                {
                    InternalConvertFromAbstractFunction(
                        tw,
                        extractContext,
                        preparedFunction,
                        indent);
                }
                break;

            case FunctionTypes.InterfaceVirtual:
                // Nothing to do
                break;

            case FunctionTypes.PInvoke:
                var pinvokeInfo = method.PInvokeInfo;
                if (pinvokeInfo == null)
                {
                    throw new InvalidProgramSequenceException(
                              "Missing DllImport attribute at P/Invoke entry: Method={0}",
                              methodName);
                }

                InternalConvertFromPInvokeFunction(
                    tw,
                    extractContext,
                    preparedFunction,
                    pinvokeInfo,
                    indent);
                break;
            }
        }
Exemple #15
0
        public static void WriteHeaders(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared)
        {
            IExtractContext extractContext      = translateContext;
            var             assemblyName        = translateContext.Assembly.Name;
            var             assemblyMangledName = translateContext.Assembly.MangledName;

            var typesByDeclaring = prepared.Types.
                                   GroupBy(type => type.DeclaringType ?? type).
                                   ToDictionary(
                g => g.Key,
                g => g.OrderByDependant(translateContext.Assembly).ToArray());

            foreach (var g in prepared.Types.
                     Where(type => type.DeclaringType == null).
                     GroupBy(type => type.ScopeName))
            {
                using (var _ = storage.EnterScope(g.Key))
                {
                    foreach (var type in g)
                    {
                        using (var twHeader = storage.CreateHeaderWriter(type.Name))
                        {
                            var scopeName = Utilities.GetMangledName(type.ScopeName);

                            twHeader.WriteLine(
                                "// [14-1] This is {0} native code translated by IL2C, do not edit.",
                                assemblyName);
                            twHeader.SplitLine();

                            twHeader.WriteLine(
                                "#include <{0}.h>",
                                assemblyName);
                            twHeader.SplitLine();

                            twHeader.WriteLine("#ifdef __cplusplus");
                            twHeader.WriteLine("extern \"C\" {");
                            twHeader.WriteLine("#endif");
                            twHeader.SplitLine();

                            twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                            twHeader.WriteLine("// [14-2] Type pre definitions:");
                            twHeader.SplitLine();

                            // All types exclude privates
                            WriteTypePreDefinitions(
                                twHeader,
                                type,
                                typesByDeclaring);

                            twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                            twHeader.WriteLine("// [14-3] Type body definitions:");
                            twHeader.SplitLine();

                            twHeader.WriteLine(
                                "#ifdef {0}_DECL_TYPE_BODY__",
                                assemblyMangledName);
                            twHeader.SplitLine();

                            InternalWriteHeader(
                                twHeader,
                                prepared,
                                type,
                                MemberScopes.Public,
                                typesByDeclaring);

                            twHeader.WriteLine("#endif");
                            twHeader.SplitLine();

                            twHeader.WriteLine("#ifdef __cplusplus");
                            twHeader.WriteLine("}");
                            twHeader.WriteLine("#endif");
                            twHeader.SplitLine();

                            twHeader.Flush();
                        }
                    }
                }
            }
        }
Exemple #16
0
        public static void WriteCommonInternalHeader(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            string assemblyName)
        {
            IExtractContext extractContext               = translateContext;
            var             annotatedAssemblyName        = assemblyName + "_internal";
            var             annotatedAssemblyMangledName = Utilities.GetMangledName(annotatedAssemblyName);

            using (var twHeader = storage.CreateHeaderWriter(annotatedAssemblyName))
            {
                twHeader.WriteLine(
                    "// [13-1] This is {0} native code translated by IL2C, do not edit.",
                    assemblyName);
                twHeader.SplitLine();

                twHeader.WriteLine(
                    "#ifndef __{0}_H__",
                    annotatedAssemblyMangledName);
                twHeader.WriteLine(
                    "#define __{0}_H__",
                    annotatedAssemblyMangledName);
                twHeader.SplitLine();
                twHeader.WriteLine("#pragma once");
                twHeader.SplitLine();

                twHeader.WriteLine("#include <{0}.h>", assemblyName);
                twHeader.SplitLine();

                var constStrings = extractContext.
                                   ExtractConstStrings().
                                   ToArray();
                if (constStrings.Length >= 1)
                {
                    twHeader.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [9-1-1] Const strings:");
                    twHeader.SplitLine();

                    foreach (var(symbolName, _) in constStrings)
                    {
                        twHeader.WriteLine(
                            "extern System_String* const {0};",
                            symbolName);
                    }
                    twHeader.SplitLine();
                }

                var declaredValues = extractContext.
                                     ExtractDeclaredValues().
                                     ToArray();
                if (declaredValues.Length >= 1)
                {
                    twHeader.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [12-1-1] Declared values:");
                    twHeader.SplitLine();

                    foreach (var information in declaredValues)
                    {
                        foreach (var declaredFields in information.DeclaredFields)
                        {
                            twHeader.WriteLine(
                                "// {0}",
                                declaredFields.FriendlyName);
                        }

                        var targetType = (information.HintTypes.Length == 1) ?
                                         information.HintTypes[0] :
                                         extractContext.MetadataContext.ByteType.MakeArray();
                        Debug.Assert(targetType.IsArray);

                        var elementType = targetType.ElementType.ResolveToRuntimeType();
                        var values      = Utilities.ResourceDataToSpecificArray(information.ResourceData, elementType);

                        var lhs = targetType.GetCLanguageTypeName(information.SymbolName, true);
                        twHeader.WriteLine(
                            "extern const {0};",
                            lhs);
                    }
                    twHeader.SplitLine();
                }

                twHeader.WriteLine("#endif");
                twHeader.Flush();
            }
        }
Exemple #17
0
        public static void WriteCommonHeader(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            string assemblyName)
        {
            IExtractContext extractContext      = translateContext;
            var             assemblyMangledName = Utilities.GetMangledName(assemblyName);

            using (var twHeader = storage.CreateHeaderWriter(assemblyName))
            {
                twHeader.WriteLine(
                    "// [13-1] This is {0} native code translated by IL2C, do not edit.",
                    assemblyName);
                twHeader.SplitLine();

                twHeader.WriteLine(
                    "#ifndef __{0}_H__",
                    assemblyMangledName);
                twHeader.WriteLine(
                    "#define __{0}_H__",
                    assemblyMangledName);
                twHeader.SplitLine();
                twHeader.WriteLine("#pragma once");
                twHeader.SplitLine();

                // Write assembly references.
                var assemblies = extractContext.EnumerateRegisteredTypes().
                                 SelectMany(entry => entry.Value).
                                 Distinct().
                                 OrderByDependant(translateContext.Assembly).
                                 Select(type => type.DeclaringModule.DeclaringAssembly).
                                 Where(assembly => !assembly.Equals(translateContext.Assembly)).
                                 Distinct().
                                 ToArray();
                if (assemblies.Length >= 1)
                {
                    twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [13-2] Assembly references:");
                    twHeader.SplitLine();

                    foreach (var assembly in assemblies)
                    {
                        twHeader.WriteLine("#include <{0}.h>", assembly.Name);
                    }
                    twHeader.SplitLine();
                }

                // Write native headers from the NativeType/NativeMethod/NativeValue attributes.
                var importFileNames = extractContext.EnumerateRequiredImportIncludeFileNames().ToArray();
                if (importFileNames.Length >= 1)
                {
                    twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [13-3] Import native headers:");
                    twHeader.SplitLine();

                    foreach (var fileName in importFileNames)
                    {
                        twHeader.WriteLine("#include <{0}>", fileName);
                    }
                    twHeader.SplitLine();
                }

                var types = prepared.Types.
                            Where(type => type.DeclaringType == null).
                            OrderByDependant(translateContext.Assembly).
                            ToArray();
                if (types.Length >= 1)
                {
                    // Write pre definitions of type.
                    twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [13-4] Type pre definitions:");
                    twHeader.SplitLine();

                    foreach (var type in types)
                    {
                        twHeader.WriteLine(
                            "#include \"{0}/{1}/{2}.h\"",
                            assemblyName,
                            Utilities.GetCLanguageScopedPath(type.ScopeName),
                            type.Name);
                    }
                    twHeader.SplitLine();

                    // Write body definitions of type.
                    twHeader.WriteLine("///////////////////////////////////////////////////////////////////////////");
                    twHeader.WriteLine("// [13-5] Type body definitions:");
                    twHeader.SplitLine();

                    twHeader.WriteLine(
                        "#define {0}_DECL_TYPE_BODY__ 1",
                        assemblyMangledName);
                    twHeader.SplitLine();

                    foreach (var type in types)
                    {
                        twHeader.WriteLine(
                            "#include \"{0}/{1}/{2}.h\"",
                            assemblyName,
                            Utilities.GetCLanguageScopedPath(type.ScopeName),
                            type.Name);
                    }
                    twHeader.SplitLine();
                }

                twHeader.WriteLine("#endif");
                twHeader.Flush();
            }
        }
Exemple #18
0
        public static string WriteCommonInternalSourceCode(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            string assemblyName)
        {
            IExtractContext extractContext = translateContext;

            using (var twSource = storage.CreateSourceCodeWriter(assemblyName + "_internal"))
            {
                var assemblyMangledName = Utilities.GetMangledName(assemblyName);

                twSource.WriteLine(
                    "// [15-1] This is {0} native code translated by IL2C, do not edit.",
                    assemblyName);
                twSource.SplitLine();

                twSource.WriteLine(
                    "#include <{0}.h>",
                    assemblyName);
                twSource.WriteLine(
                    "#include <{0}_internal.h>",
                    assemblyName);
                twSource.SplitLine();

                var constStrings = extractContext.
                                   ExtractConstStrings().
                                   ToArray();
                if (constStrings.Length >= 1)
                {
                    twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                    twSource.WriteLine("// [9-1-2] Const strings:");
                    twSource.SplitLine();

                    foreach (var(symbolName, value) in constStrings)
                    {
                        twSource.WriteLine(
                            "IL2C_CONST_STRING({0}, {1});",
                            symbolName,
                            Utilities.GetCLanguageExpression(value));
                    }

                    twSource.SplitLine();
                }

                var declaredValues = extractContext.
                                     ExtractDeclaredValues().
                                     ToArray();
                if (declaredValues.Length >= 1)
                {
                    twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
                    twSource.WriteLine("// [12-1-2] Declared values:");
                    twSource.SplitLine();

                    foreach (var information in declaredValues)
                    {
                        foreach (var declaredFields in information.DeclaredFields)
                        {
                            twSource.WriteLine(
                                "// {0}",
                                declaredFields.FriendlyName);
                        }

                        var targetType = (information.HintTypes.Length == 1) ?
                                         information.HintTypes[0] :
                                         extractContext.MetadataContext.ByteType.MakeArray();
                        Debug.Assert(targetType.IsArray);

                        var elementType = targetType.ElementType.ResolveToRuntimeType();
                        var values      = Utilities.ResourceDataToSpecificArray(information.ResourceData, elementType);

                        var lhs = targetType.GetCLanguageTypeName(information.SymbolName, true);
                        twSource.WriteLine(
                            "const {0} =",
                            lhs);
                        using (var _ = twSource.Shift())
                        {
                            twSource.WriteLine(
                                "{0};",
                                Utilities.GetCLanguageExpression(values));
                        }
                    }

                    twSource.SplitLine();
                }

                twSource.Flush();

                return(twSource.RelatedPath);
            }
        }
Exemple #19
0
        public static void WriteSourceCode(
            TextWriter twSource,
            TranslateContext translateContext,
            PreparedFunctions preparedFunctions,
            string indent,
            DebugInformationOptions debugInformationOption = DebugInformationOptions.Full)
        {
            IExtractContext extractContext = translateContext;

            foreach (var fileName in extractContext.EnumerateRequiredPrivateIncludeFileNames())
            {
                twSource.WriteLine("#include \"{0}\"", fileName);
            }

            var assemblyName = extractContext.Assembly.Name.Name;

            twSource.WriteLine("#include \"{0}.h\"", assemblyName);

            twSource.WriteLine();
            twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            twSource.WriteLine("// Const strings:");
            twSource.WriteLine();

            foreach (var kv in extractContext.ExtractConstStrings())
            {
                var escaped = Utilities.GetEscapedCString(kv.Value);
                twSource.WriteLine(
                    "IL2C_CONST_STRING({0}, L\"{1}\");",
                    kv.Key,
                    escaped);
            }

            var allTypes = extractContext.Assembly.Modules
                           .SelectMany(module => module.Types)
                           .SelectMany(type => new[] { type }.Concat(type.NestedTypes))
                           .Where(type => type.IsValidDefinition())
                           .ToArray();

            // All types exclude publics and internals (for file scope prototypes)
            var types = allTypes
                        .Where(type => !(type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly))
                        .ToArray();

            InternalConvertToPrototypes(
                twSource,
                types,
                extractContext,
                preparedFunctions,
                method => !(method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly),
                indent);

            twSource.WriteLine();
            twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            twSource.WriteLine("// Static fields:");

            foreach (var type in allTypes.Where(type => !type.IsEnum))
            {
                twSource.WriteLine();

                // All static fields
                foreach (var field in type.Fields
                         .Where(field => field.IsStatic))
                {
                    twSource.WriteLine(
                        "{0};",
                        Utilities.GetStaticFieldPrototypeString(field, true, extractContext));
                }
            }

            twSource.WriteLine();
            twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            twSource.WriteLine("// Methods:");

            foreach (var type in allTypes.Where(type => !type.IsEnum))
            {
                twSource.WriteLine();
                twSource.WriteLine("////////////////////////////////////////////////////////////");
                twSource.WriteLine("// Type: {0}", type.GetFullMemberName());

                // All methods and constructor exclude type initializer
                foreach (var method in type.Methods
                         .Where(method => !method.IsConstructor || !method.IsStatic))
                {
                    InternalConvertFromMethod(
                        twSource,
                        extractContext,
                        preparedFunctions,
                        method,
                        indent,
                        debugInformationOption);
                }

                if (type.IsClass || type.IsValueType)
                {
                    InternalConvertTypeHelper(
                        twSource,
                        extractContext,
                        type,
                        indent);
                }
                else if (type.IsInterface)
                {
                    InternalConvertTypeHelperForInterface(
                        twSource,
                        type,
                        indent);
                }
            }
        }
Exemple #20
0
        private static void InternalConvertFromDelegateInvoker(
            CodeTextWriter tw,
            IExtractContext extractContext,
            IMethodInformation method)
        {
            if (method.Parameters.Length == 0)
            {
                throw new InvalidProgramSequenceException(
                          "Invalid delegate invoker. Name={0}",
                          method.FriendlyName);
            }

            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine("// [11-2] Delegate invoker: {0}", method.FriendlyName);
            tw.SplitLine();

            // DIRTY:
            //   Cause undefined symbol error at C compilation if "System.Delegate" type on the mscorlib assembly
            //   contains the fields with different symbol name.

            var thisName = method.Parameters[0].ParameterName;

            tw.WriteLine(method.CLanguageFunctionPrototype);
            tw.WriteLine("{");

            using (var _ = tw.Shift())
            {
                tw.WriteLine(
                    "il2c_assert({0} != NULL);",
                    thisName);
                tw.WriteLine(
                    "il2c_assert({0}->vptr0__ == &System_Delegate_VTABLE__);",
                    thisName);
                tw.WriteLine(
                    "il2c_assert({0}->count__ >= 1);",
                    thisName);
                tw.SplitLine();

                if (!method.ReturnType.IsVoidType)
                {
                    if (method.ReturnType.IsReferenceType)
                    {
                        tw.WriteLine(
                            "struct {0}_EXECUTION_FRAME__",
                            method.CLanguageFunctionName);
                        tw.WriteLine("{");
                        using (var __ = tw.Shift())
                        {
                            tw.WriteLine("uint8_t objRefCount__;");
                            tw.WriteLine("uint8_t objRefRefCount__;");
                            tw.WriteLine("IL2C_EXECUTION_FRAME* pNext__;");
                            tw.WriteLine(
                                "{0} result;",
                                method.ReturnType.CLanguageTypeName);
                        }
                        tw.WriteLine("} frame__ = { 1, 0 };");
                        tw.WriteLine("il2c_link_execution_frame(&frame__);");
                    }
                    else
                    {
                        tw.WriteLine(
                            "{0} result;",
                            method.ReturnType.CLanguageTypeName);
                    }
                }

                tw.SplitLine();
                tw.WriteLine(
                    "uintptr_t index = 0;");
                tw.WriteLine(
                    "do",
                    thisName);
                tw.WriteLine(
                    "{");

                using (var __ = tw.Shift())
                {
                    tw.WriteLine(
                        "IL2C_METHOD_TABLE_DECL* pMethodtbl = &{0}->methodtbl__[index];",
                        thisName);

                    if (method.ReturnType.IsVoidType)
                    {
                        tw.WriteLine("if (pMethodtbl->target != NULL)");
                        using (var ___ = tw.Shift())
                        {
                            tw.WriteLine(
                                "((void (*)(System_Object*{0}))(pMethodtbl->methodPtr))(pMethodtbl->target{1});",
                                string.Join(string.Empty, method.Parameters.
                                            Skip(1).
                                            Select(p => string.Format(", {0}", p.TargetType.CLanguageTypeName))),
                                string.Join(string.Empty, method.Parameters.
                                            Skip(1).
                                            Select(p => string.Format(", {0}", p.ParameterName))));
                        }
                        tw.WriteLine("else");
                        using (var ___ = tw.Shift())
                        {
                            tw.WriteLine(
                                "((void (*)({0}))(pMethodtbl->methodPtr))({1});",
                                string.Join(", ", method.Parameters.
                                            Skip(1).
                                            Select(p => p.TargetType.CLanguageTypeName)),
                                string.Join(", ", method.Parameters.
                                            Skip(1).
                                            Select(p => p.ParameterName)));
                        }
                    }
                    else
                    {
                        tw.WriteLine("if (pMethodtbl->target != NULL)");
                        using (var ___ = tw.Shift())
                        {
                            tw.WriteLine(
                                "{0}result = (({1} (*)(System_Object*{2}))(pMethodtbl->methodPtr))(pMethodtbl->target{3});",
                                method.ReturnType.IsReferenceType ? "frame__." : string.Empty,
                                method.ReturnType.CLanguageTypeName,
                                string.Join(string.Empty, method.Parameters.
                                            Skip(1).
                                            Select(p => string.Format(", {0}", p.TargetType.CLanguageTypeName))),
                                string.Join(string.Empty, method.Parameters.
                                            Skip(1).
                                            Select(p => string.Format(", {0}", p.ParameterName))));
                        }
                        tw.WriteLine("else");
                        using (var ___ = tw.Shift())
                        {
                            tw.WriteLine(
                                "{0}result = (({1} (*)({2}))(pMethodtbl->methodPtr))({3});",
                                method.ReturnType.IsReferenceType ? "frame__." : string.Empty,
                                method.ReturnType.CLanguageTypeName,
                                string.Join(", ", method.Parameters.
                                            Skip(1).
                                            Select(p => p.TargetType.CLanguageTypeName)),
                                string.Join(", ", method.Parameters.
                                            Skip(1).
                                            Select(p => p.ParameterName)));
                        }
                    }

                    tw.WriteLine("index++;");
                }
                tw.WriteLine("}");
                tw.WriteLine("while (index < this__->count__);");
                tw.SplitLine();

                if (!method.ReturnType.IsVoidType)
                {
                    if (method.ReturnType.IsReferenceType)
                    {
                        tw.WriteLine("il2c_unlink_execution_frame(&frame__);");
                        tw.WriteLine("return frame__.result;");
                    }
                    else
                    {
                        tw.WriteLine("return result;");
                    }
                }
            }

            tw.WriteLine("}");
            tw.SplitLine();
        }
Exemple #21
0
        private static void InternalConvertType(
            TextWriter tw,
            IExtractContext extractContext,
            TypeDefinition declaredType,
            string indent)
        {
            if (declaredType.IsPrimitive ||
                !(declaredType.IsValueType || declaredType.IsClass || declaredType.IsInterface))
            {
                return;
            }

            var typeName = extractContext.GetCLanguageTypeName(
                declaredType,
                TypeNameFlags.Dereferenced)
                           .ManglingSymbolName();

            var rawTypeName = declaredType
                              .GetFullMemberName()
                              .ManglingSymbolName();
            var typeString =
                declaredType.IsEnum
                ? "Enum"
                : declaredType.IsValueType
                    ? "Struct"
                    : declaredType.IsInterface
                        ? "Interface"
                        : "Class";

            tw.WriteLine("////////////////////////////////////////////////////////////");
            tw.WriteLine(
                "// {0}: {1}",
                typeString,
                declaredType.GetFullMemberName());

            if (declaredType.IsEnum)
            {
                tw.WriteLine();
                tw.WriteLine(
                    "// {0} layout",
                    typeString);
                tw.WriteLine(
                    "typedef enum {0}",
                    typeName);
                tw.WriteLine("{");

                // Emit enum values
                foreach (var field in declaredType.Fields.Where(field => field.IsLiteral))
                {
                    tw.WriteLine(
                        "{0}{1}_{2} = {3},",
                        indent,
                        typeName,
                        field.Name,
                        field.Constant);
                }

                tw.WriteLine(
                    "}} {0};",
                    typeName);
                tw.WriteLine();
            }
            else
            {
                // IL2C vtable model case [1]:
                //
                // public class A : IB {
                //   public int F1;
                //   public string F2;
                //   public virtual int Calc(int a, int b);
                // }
                // public interface IB {
                //   int Calc(int a, int b);
                // }
                //
                // +----------------------+
                // | IL2C_REF_HEADER      |
                // +----------------------+ <-- this__       __A_VTABLE__
                // | vptr0__              | -------------> +--------------------+
                // +----------------------+                | ILC2_RuntimeCast() |
                // | vptr_A_IB__          | ----------+    | ToString()         |
                // +----------------------+           |    | GetHashCode()      |
                // | int F1               |           |    | Finalize()         |
                // | string F2            |           |    | Equals()           |
                // +----------------------+           |    | Calc()             |
                //                                    |    +--------------------+
                //                                    |      __A_IB_VTABLE__
                //                                    +--> +------------------------------+
                //                                         | ILC2_RuntimeCast() [with AT] |
                //                                         | ToString() [with AT]         |
                //                                         | GetHashCode() [with AT]      |
                //                                         | Finalize() [with AT]         |
                //                                         | Equals() [with AT]           |
                //                                         | Calc() [with AT]             |
                //                                         +------------------------------+

                tw.WriteLine();
                tw.WriteLine(
                    "// {0} vtable layout",
                    typeString);
                tw.WriteLine("typedef const struct");
                tw.WriteLine("{");
                tw.WriteLine(
                    "{0}/* internalcall */ void* (*IL2C_RuntimeCast)({1}* this__, IL2C_RUNTIME_TYPE_DECL* type);",
                    indent,
                    rawTypeName);

                var virtualMethods = declaredType
                                     .EnumerateOrderedOverridedMethods()
                                     .ToArray();
                foreach (var method in virtualMethods)
                {
                    var functionPrototype = Utilities.GetFunctionTypeString(
                        method.GetOverloadedMethodName().ManglingSymbolName(),
                        method.ReturnType,
                        method.GetSafeParameters(declaredType),
                        extractContext);
                    tw.WriteLine(
                        "{0}{1};",
                        indent,
                        functionPrototype);
                }

                tw.WriteLine(
                    "}} __{0}_VTABLE_DECL__;",
                    rawTypeName);

                var fields = declaredType
                             .Traverse(type => type.BaseType?.Resolve())
                             .Reverse()
                             .SelectMany(type =>
                {
                    var vptrs = type.Interfaces
                                .Select(interfaceImpl => new
                    {
                        Name = string.Format(
                            "vptr_{0}__",
                            interfaceImpl.InterfaceType
                            .GetFullMemberName()
                            .ManglingSymbolName()),
                        TypeName = string.Format(
                            "__{0}_VTABLE_DECL__*",
                            interfaceImpl.InterfaceType
                            .GetFullMemberName()
                            .ManglingSymbolName())
                    });
                    var thisFields = type.Fields
                                     .Where(field => !field.IsStatic)
                                     .Select(field => new
                    {
                        field.Name,
                        TypeName = extractContext.GetCLanguageTypeName(field.FieldType)
                    });
                    return(vptrs.Concat(thisFields));
                })
                             .ToArray();

                if ((declaredType.IsValueType == false) ||
                    (fields.Length >= 1))
                {
                    tw.WriteLine();
                    tw.WriteLine(
                        "// {0} layout",
                        typeString);
                    tw.WriteLine(
                        "struct {0}",
                        typeName);
                    tw.WriteLine("{");

                    // Emit vptr:
                    if (declaredType.IsClass || declaredType.IsInterface)
                    {
                        tw.WriteLine(
                            "{0}__{1}_VTABLE_DECL__* vptr0__;",
                            indent,
                            rawTypeName);
                    }

                    foreach (var field in fields)
                    {
                        tw.WriteLine(
                            "{0}{1} {2};",
                            indent,
                            field.TypeName,
                            field.Name);
                    }

                    tw.WriteLine("};");
                    tw.WriteLine();
                }
            }

            var makrHandlerPrototype = string.Format(
                "extern IL2C_RUNTIME_TYPE_DECL __{0}_RUNTIME_TYPE__;",
                rawTypeName);

            tw.WriteLine();
            tw.WriteLine(
                "// {0} runtime type information",
                typeString);
            tw.WriteLine(makrHandlerPrototype);
        }
Exemple #22
0
        private static void InternalConvertToPrototypes(
            TextWriter tw,
            TypeDefinition[] types,
            IExtractContext extractContext,
            PreparedFunctions preparedFunctions,
            Func <MethodDefinition, bool> predictMethod,
            string indent)
        {
            tw.WriteLine();
            tw.WriteLine("#ifdef __cplusplus");
            tw.WriteLine("extern \"C\" {");
            tw.WriteLine("#endif");

            tw.WriteLine();
            tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            tw.WriteLine("// Types:");
            tw.WriteLine();

            // Output prototypes.
            foreach (var type in types.Where(type => !type.IsEnum))
            {
                var typeName = extractContext.GetCLanguageTypeName(type, TypeNameFlags.Dereferenced)
                               .ManglingSymbolName();
                tw.WriteLine(
                    "typedef struct {0} {0};",
                    typeName);
            }

            // Output value type and object reference type.
            foreach (var type in types)
            {
                tw.WriteLine();
                InternalConvertType(
                    tw,
                    extractContext,
                    type,
                    indent);
            }

            tw.WriteLine();
            tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            tw.WriteLine("// Public static fields:");

            foreach (var type in types.Where(type => !type.IsEnum))
            {
                tw.WriteLine();

                foreach (var field in type.Fields
                         .Where(field => field.IsPublic && field.IsStatic))
                {
                    tw.WriteLine(
                        "extern {0};",
                        Utilities.GetStaticFieldPrototypeString(field, false, extractContext));
                }
            }

            tw.WriteLine();
            tw.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            tw.WriteLine("// Methods:");

            foreach (var type in types.Where(type => !type.IsEnum))
            {
                var rawTypeName = type
                                  .GetFullMemberName()
                                  .ManglingSymbolName();
                var typeName = extractContext
                               .GetCLanguageTypeName(type, TypeNameFlags.Dereferenced)
                               .ManglingSymbolName();

                tw.WriteLine();
                tw.WriteLine(
                    "// {0}",
                    type.FullName);

                if (!type.IsInterface)
                {
                    tw.WriteLine(
                        "extern /* internalcall */ void __{0}_IL2C_MarkHandler__({1}* this__);",
                        rawTypeName,
                        typeName);
                }

                tw.WriteLine(
                    "extern /* internalcall */ void* __{0}_IL2C_RuntimeCast__({1}* this__, IL2C_RUNTIME_TYPE_DECL* type);",
                    rawTypeName,
                    typeName);

                // TODO: Support enum type methods
                foreach (var method in type.Methods
                         .Where(method =>
                                (!method.IsConstructor || !method.IsStatic) &&
                                predictMethod(method)))
                {
                    var preparedFunction = preparedFunctions.Functions[method];

                    var functionPrototype = Utilities.GetFunctionPrototypeString(
                        GetFunctionNameByFunctionType(preparedFunction),
                        preparedFunction.ReturnType,
                        preparedFunction.Parameters,
                        extractContext);

                    tw.WriteLine(
                        "extern {0}{1};",
                        method.IsVirtual ? "/* virtual */ " : string.Empty,
                        functionPrototype);
                }

                var virtualMethods = type
                                     .EnumerateOrderedOverridedMethods()
                                     .Where(predictMethod)
                                     .ToArray();
                foreach (var method in virtualMethods)
                {
                    var fullMethodName = type
                                         .GetFullMemberName(method, MethodNameTypes.Index)
                                         .ManglingSymbolName();
                    var functionParametersDeclaration = string.Join(
                        ", ",
                        method.GetSafeParameters()
                        .Select((parameter, index) => (index == 0)
                                ? string.Format(
                                    "/* {0} */ {1}",
                                    extractContext.GetCLanguageTypeName(type),
                                    parameter.Name)
                                : string.Format(
                                    "/* {0} */ {1}",
                                    extractContext.GetCLanguageTypeName(parameter.ParameterType),
                                    parameter.Name)));
                    tw.WriteLine(
                        "#define {0}({1}) \\",
                        fullMethodName,
                        functionParametersDeclaration);

                    var methodName = method
                                     .GetOverloadedMethodName()
                                     .ManglingSymbolName();
                    var functionParameters = string.Join(
                        ", ",
                        method.GetSafeParameters()
                        .Select(parameter => parameter.Name));

                    tw.WriteLine(
                        "{0}((this__)->vptr0__->{1}({2}))",
                        indent,
                        methodName,
                        functionParameters);
                }
            }

            tw.WriteLine();
            tw.WriteLine("#ifdef __cplusplus");
            tw.WriteLine("}");
            tw.WriteLine("#endif");
        }
Exemple #23
0
        private static void InternalConvertFromFunction(
            TextWriter tw,
            IExtractContext extractContext,
            PreparedFunction preparedFunction,
            string indent,
            DebugInformationOptions debugInformationOption)
        {
            var locals = preparedFunction.LocalVariables;

            var functionPrototype = Utilities.GetFunctionPrototypeString(
                GetFunctionNameByFunctionType(preparedFunction),
                preparedFunction.ReturnType,
                preparedFunction.Parameters,
                extractContext);

            tw.WriteLine();
            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine(
                "// {0}{1}",
                (preparedFunction.FunctionType == FunctionTypes.Virtual)
                    ? "Virtual: "
                    : string.Empty,
                preparedFunction.RawMethodName);
            tw.WriteLine();

            tw.WriteLine(functionPrototype);
            tw.WriteLine("{");

            tw.WriteLine("{0}//-------------------", indent);
            tw.WriteLine("{0}// Local variables:", indent);
            tw.WriteLine();

            // Important NULL assigner (p = NULL):
            //   Because these variables are pointer (of object reference).
            //   So GC will traverse these variables just setup the stack frame.

            foreach (var local in preparedFunction.LocalVariables)
            {
                tw.WriteLine(
                    "{0}{1} {2}{3};",
                    indent,
                    extractContext.GetCLanguageTypeName(local.TargetType),
                    local.SymbolName,
                    local.TargetType.IsValueType ? string.Empty : " = NULL");
            }

            tw.WriteLine();
            tw.WriteLine("{0}//-------------------", indent);
            tw.WriteLine("{0}// Evaluation stacks:", indent);
            tw.WriteLine();

            foreach (var si in preparedFunction.Stacks)
            {
                tw.WriteLine(
                    "{0}{1} {2}{3};",
                    indent,
                    extractContext.GetCLanguageTypeName(si.TargetType),
                    si.SymbolName,
                    si.TargetType.IsValueType ? string.Empty : " = NULL");
            }

            var frameEntries = locals
                               .Concat(preparedFunction.Stacks)
                               .Where(local => !local.TargetType.IsValueType && !local.TargetType.IsPointer)
                               .ToArray();

            if (frameEntries.Length >= 1)
            {
                tw.WriteLine();
                tw.WriteLine("{0}//-------------------", indent);
                tw.WriteLine("{0}// Setup stack frame:", indent);
                tw.WriteLine();

                tw.WriteLine("{0}struct /* IL2C_EXECUTION_FRAME */", indent);
                tw.WriteLine("{0}{{", indent);
                tw.WriteLine("{0}{0}IL2C_EXECUTION_FRAME* pNext;", indent);
                tw.WriteLine("{0}{0}uint8_t targetCount;", indent);

                foreach (var frameEntry in frameEntries)
                {
                    tw.WriteLine(
                        "{0}{0}{1}* p{2};",
                        indent,
                        extractContext.GetCLanguageTypeName(frameEntry.TargetType),
                        frameEntry.SymbolName);
                }

                tw.WriteLine("{0}}} __executionFrame__;", indent);
                tw.WriteLine();
                tw.WriteLine("{0}__executionFrame__.targetCount = {1};", indent, frameEntries.Length);

                foreach (var frameEntry in frameEntries)
                {
                    tw.WriteLine(
                        "{0}__executionFrame__.p{1} = &{1};",
                        indent,
                        frameEntry.SymbolName);
                }

                tw.WriteLine("{0}il2c_link_execution_frame(&__executionFrame__);", indent);
            }

            tw.WriteLine();
            tw.WriteLine("{0}//-------------------", indent);
            tw.WriteLine("{0}// IL body:", indent);
            tw.WriteLine();

            var canWriteSequencePoint = true;

            foreach (var ilBody in preparedFunction.PreparedILBodies)
            {
                // Write label if available and used.
                if (preparedFunction.TryGetLabelName(
                        ilBody.Label, out var labelName))
                {
                    tw.WriteLine("{0}:", labelName);
                }

                // Write the line preprocessor directive if available.
                if (canWriteSequencePoint && ilBody.SequencePoints.Any())
                {
                    var sp = ilBody.SequencePoints.First();
                    switch (debugInformationOption)
                    {
                    case DebugInformationOptions.Full:
                        tw.WriteLine(
                            "#line {0} \"{1}\"",
                            sp.StartLine,
                            sp.Document.Url.Replace("\\", "\\\\"));
                        break;

                    case DebugInformationOptions.CommentOnly:
                        tw.WriteLine(
                            "/* {0}({1}): */",
                            sp.Document.Url.Replace("\\", "\\\\"),
                            sp.StartLine);
                        break;
                    }

                    canWriteSequencePoint = false;
                }

                if (debugInformationOption != DebugInformationOptions.None)
                {
                    // Write debugging information.
                    tw.WriteLine(
                        "{0}/* {1} */",
                        indent,
                        ilBody);
                }

                // Generate source code fragments and write.
                var sourceCodes = ilBody.Generator(extractContext);
                foreach (var sourceCode in sourceCodes)
                {
                    // Dirty hack:
                    //   Write unlink execution frame code if cause exiting method.
                    if (sourceCode.StartsWith("return") &&
                        (frameEntries.Length >= 1))
                    {
                        tw.WriteLine(
                            "{0}il2c_unlink_execution_frame(&__executionFrame__);",
                            indent);
                    }

                    tw.WriteLine(
                        "{0}{1};",
                        indent,
                        sourceCode);

                    canWriteSequencePoint = true;
                }
            }

            tw.WriteLine("}");
        }
Exemple #24
0
        private static void InternalConvertTypeHelper(
            TextWriter tw,
            IExtractContext extractContext,
            TypeDefinition declaredType,
            string indent)
        {
            tw.WriteLine();
            tw.WriteLine("//////////////////////");
            tw.WriteLine("// Runtime helpers:");

            var rawTypeName = declaredType
                              .GetFullMemberName()
                              .ManglingSymbolName();
            var typeName = extractContext.GetCLanguageTypeName(
                declaredType,
                TypeNameFlags.Dereferenced);

            // Write RuntimeCast function:
            tw.WriteLine();
            tw.WriteLine("// Runtime cast");
            tw.WriteLine(
                "void* __{0}_IL2C_RuntimeCast__({1} this__, IL2C_RUNTIME_TYPE_DECL* type)",
                rawTypeName,
                extractContext.GetCLanguageTypeName(
                    declaredType,
                    TypeNameFlags.ForcePointer));
            tw.WriteLine("{");

            // RuntimeCast: this type.
            //   TODO: inlining all base type comparer are better than base invoker?
            tw.WriteLine(
                "{0}// This type",
                indent);
            tw.WriteLine(
                "{0}if (type == il2c_typeof({1})) return this__;",
                indent,
                rawTypeName);

            // RuntimeCast: implemented interfaces.
            if (declaredType.Interfaces.Count >= 1)
            {
                tw.WriteLine();
                tw.WriteLine(
                    "{0}// Interface types",
                    indent);

                foreach (var interfaceImpl in declaredType.Interfaces)
                {
                    var rawInterfaceTypeName = interfaceImpl.InterfaceType
                                               .GetFullMemberName()
                                               .ManglingSymbolName();

                    // NOTE:
                    //  The virtual function pointer added offset from between vptr_TYPE__ and vptr0__.
                    //  If will invoke interface's virtual function,
                    //  the function is delegated "Adjust thunk" function,
                    //  it will recalculate this pointer offset.
                    tw.WriteLine(
                        "{0}if (type == il2c_typeof({1})) return (void*)&(this__->vptr_{1}__);",
                        indent,
                        rawInterfaceTypeName);
                }
            }

            var rawBaseTypeName = declaredType.BaseType
                                  .GetFullMemberName()
                                  .ManglingSymbolName();

            // RuntimeCast: reflect base types.
            tw.WriteLine();
            tw.WriteLine(
                "{0}// Delegate checking base types",
                indent);
            tw.WriteLine(
                "{0}return __{1}_IL2C_RuntimeCast__(({2})this__, type);",
                indent,
                rawBaseTypeName,
                extractContext.GetCLanguageTypeName(
                    declaredType.BaseType,
                    TypeNameFlags.ForcePointer));
            tw.WriteLine("}");

            // Write mark handler:
            var makrHandlerPrototype = string.Format(
                "void __{0}_IL2C_MarkHandler__({1} this__)",
                rawTypeName,
                extractContext.GetCLanguageTypeName(declaredType, TypeNameFlags.ForcePointer));

            tw.WriteLine();
            tw.WriteLine("// GC's mark handler");
            tw.WriteLine(makrHandlerPrototype);
            tw.WriteLine("{");

            var fields = declaredType.Fields
                         .Where(field => !field.IsStatic && !field.FieldType.IsValueType)
                         .ToArray();

            if (fields.Length >= 1)
            {
                tw.WriteLine(
                    "{0}// Try marking each object reference fields",
                    indent);
                foreach (var field in fields)
                {
                    tw.WriteLine(
                        "{0}il2c_try_mark_from_handler(this__->{1});",
                        indent,
                        field.Name);
                }
            }

            // Invoke base class mark handler except System.Object and System.ValueType.
            var baseType = declaredType.BaseType;

            if (baseType != null)
            {
                if ((baseType.IsObjectType() || baseType.IsValueTypeType()) == false)
                {
                    tw.WriteLine();
                    tw.WriteLine(
                        "{0}// Delegate checking base types",
                        indent);
                    tw.WriteLine(
                        "{0}__{1}_IL2C_MarkHandler__(({2})this__);",
                        indent,
                        rawBaseTypeName,
                        extractContext.GetCLanguageTypeName(declaredType.BaseType));
                }
                else
                {
                    tw.WriteLine();
                    tw.WriteLine(
                        "{0}/* Suppressed invoke base mark handler */",
                        indent);
                }
            }

            tw.WriteLine("}");

            // Write runtime type information
            tw.WriteLine();
            tw.WriteLine("// Runtime type information");
            tw.WriteLine(
                "IL2C_RUNTIME_TYPE_DECL __{0}_RUNTIME_TYPE__ = {{",
                rawTypeName);
            tw.WriteLine(
                "{0}\"{1}\",",
                indent,
                declaredType.GetFullMemberName());
            tw.WriteLine(
                "{0}sizeof({1}),",
                indent,
                typeName);
            tw.WriteLine(
                "{0}/* internalcall */ (IL2C_MARK_HANDLER)__{1}_IL2C_MarkHandler__,",
                indent,
                rawTypeName);

            tw.WriteLine("};");

            tw.WriteLine();
            tw.WriteLine("//////////////////////");
            tw.WriteLine("// VTables:");

            // Write virtual methods
            tw.WriteLine();
            tw.WriteLine(
                "// Vtable of {0}",
                declaredType.FullName);
            tw.WriteLine(
                "__{0}_VTABLE_DECL__ __{0}_VTABLE__ = {{",
                rawTypeName);

            var virtualMethods = GetVirtualMethods(
                extractContext,
                declaredType,
                declaredType);

            foreach (var method in virtualMethods)
            {
                tw.WriteLine(
                    "{0}({1} (*)({2}))__{3}_{4}__,",
                    indent,
                    method.ReturnTypeName,
                    string.Join(", ", method.Parameters.Select(p => p.Key)),
                    method.TypeName,
                    method.Name);
            }

            tw.WriteLine("};");

            foreach (var interfaceType in declaredType.Interfaces
                     .Select(interfaceImpl => interfaceImpl.InterfaceType))
            {
                var rawInterfaceTypeName = interfaceType
                                           .GetFullMemberName()
                                           .ManglingSymbolName();

                var interfaceVirtualMethods = GetVirtualMethods(
                    extractContext,
                    interfaceType,
                    declaredType);

                foreach (var method in interfaceVirtualMethods)
                {
                    // Adjustor thunk will not invoke direct, so try to emit static function.
                    tw.WriteLine();
                    tw.WriteLine(
                        "// Adjustor thunk: {0}.{1}",
                        method.TypeName,
                        method.Name);
                    tw.WriteLine(
                        "static {0} __{1}_{2}_AT_{3}__(",
                        method.ReturnTypeName,
                        method.TypeName,
                        method.Name,
                        rawInterfaceTypeName);
                    tw.WriteLine(
                        "{0}{1})",
                        indent,
                        string.Join(
                            ", ",
                            method.Parameters.Select(parameter =>
                                                     string.Format(
                                                         "{0} {1}",
                                                         parameter.Key,
                                                         parameter.Value))));
                    tw.WriteLine(
                        "{");
                    tw.WriteLine(
                        "{0}{1}__{2}_{3}__({4});",
                        indent,
                        (method.ReturnTypeName != "void") ? "return " : string.Empty,
                        method.TypeName,
                        method.Name,
                        string.Join(
                            ", ",
                            method.Parameters.Select((parameter, index) =>
                                                     (index == 0)
                                                     // Adjust vptr offset with il2c_cast_from_interface() macro.
                                    ? string.Format(
                                                         "({0}*)il2c_cast_from_interface({1}, {2}, {3})",
                                                         method.TypeName,
                                                         rawTypeName,
                                                         rawInterfaceTypeName,
                                                         parameter.Value)
                                    : parameter.Value)));
                    tw.WriteLine(
                        "}");
                }

                tw.WriteLine();
                tw.WriteLine(
                    "// Vtable of {0} (with adjustor thunk)",
                    interfaceType.FullName);
                tw.WriteLine(
                    "__{0}_VTABLE_DECL__ __{1}_{0}_VTABLE__ = {{",
                    rawInterfaceTypeName,
                    rawTypeName);

                foreach (var method in interfaceVirtualMethods)
                {
                    tw.WriteLine(
                        "{0}__{1}_{2}_AT_{3}__,",
                        indent,
                        method.TypeName,
                        method.Name,
                        rawInterfaceTypeName);
                }

                tw.WriteLine("};");
            }
        }