Exemple #1
0
        public static void TranslateAll(
            TextWriter logw,
            string outputPath,
            bool readSymbols,
            bool enableCpp,
            bool enableBundler,
            TargetPlatforms targetPlatform,
            DebugInformationOptions debugInformationOptions,
            IEnumerable <string> assemblyPaths)
        {
            var storage = new CodeTextStorage(
                logw,
                outputPath,
                enableCpp,
                "    ");

            foreach (var aseemblyPath in assemblyPaths)
            {
                Translate(
                    logw,
                    storage,
                    readSymbols,
                    enableBundler,
                    targetPlatform,
                    debugInformationOptions,
                    aseemblyPath);
            }
        }
        public static void Translate(
            CodeTextStorage storage,
            bool readSymbols,
            bool enableBundler,
            TargetPlatforms targetPlatform,
            DebugInformationOptions debugInformationOptions,
            string assemblyPath)
        {
            System.Console.WriteLine("IL2C: Preparing assembly: \"{0}\" ...", Path.GetFullPath(assemblyPath));

            var translateContext = new TranslateContext(assemblyPath, readSymbols);

            System.Console.WriteLine(" done.");
            using (var _ = storage.EnterScope("meta"))
            {
                MetadataSerializer metaSerializer = new MetadataSerializer(translateContext);
                metaSerializer.WriteResult(storage);
            }

            using (var _ = storage.EnterScope("include"))
            {
            }

            using (var _ = storage.EnterScope("src"))
            {
            }
        }
Exemple #3
0
        public static void Translate(
            TextWriter logw,
            CodeTextStorage storage,
            bool readSymbols,
            bool enableBundler,
            TargetPlatforms targetPlatform,
            DebugInformationOptions debugInformationOptions,
            string assemblyPath)
        {
            logw.Write("IL2C: Preparing assembly: \"{0}\" ...", Path.GetFullPath(assemblyPath));

            var translateContext  = new TranslateContext(assemblyPath, readSymbols, targetPlatform);
            var preparedFunctions = AssemblyPreparer.Prepare(translateContext);

            logw.WriteLine(" done.");

            using (var _ = storage.EnterScope("include"))
            {
                AssemblyWriter.WriteHeader(
                    storage,
                    translateContext,
                    preparedFunctions);
            }

            using (var _ = storage.EnterScope("src"))
            {
                AssemblyWriter.WriteSourceCode(
                    storage,
                    translateContext,
                    preparedFunctions,
                    enableBundler,
                    debugInformationOptions);
            }
        }
Exemple #4
0
 public static void WriteSourceCode(
     CodeTextWriter twSource,
     TranslateContext translateContext,
     PreparedInformations prepared,
     DebugInformationOptions debugInformationOption = DebugInformationOptions.Full)
 {
     InternalWriteSourceCode(
         twSource, translateContext, prepared, debugInformationOption, true);
 }
Exemple #5
0
        public static string[] WriteSourceCode(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            bool enableBundler,
            DebugInformationOptions debugInformationOption)
        {
            var sourceFilePaths = new List <string>();

            var assemblyName = translateContext.Assembly.Name;

            // Write assembly level common internal header.
            HeaderWriter.WriteCommonInternalHeader(
                storage,
                translateContext,
                prepared,
                assemblyName);

            // Write assembly level common internal source code.
            sourceFilePaths.Add(
                SourceCodeWriter.WriteCommonInternalSourceCode(
                    storage,
                    translateContext,
                    prepared,
                    assemblyName));

            // Write source code bundler.
            if (enableBundler)
            {
                SourceCodeWriter.WriteBundlerSourceCode(
                    storage,
                    prepared,
                    assemblyName);
            }

            using (var _ = storage.EnterScope(assemblyName, false))
            {
                // Write source codes.
                sourceFilePaths.AddRange(
                    SourceCodeWriter.WriteSourceCodes(
                        storage,
                        translateContext,
                        prepared,
                        debugInformationOption));
            }

            return(sourceFilePaths.ToArray());
        }
Exemple #6
0
 public static void TranslateAll(
     TextWriter logw,
     CodeTextStorage storage,
     bool readSymbols,
     bool enableBundler,
     DebugInformationOptions debugInformationOptions,
     params string[] assemblyPaths)
 {
     TranslateAll(
         logw,
         storage,
         readSymbols,
         enableBundler,
         debugInformationOptions,
         (IEnumerable <string>)assemblyPaths);
 }
 public static void TranslateAll(
     CodeTextStorage storage,
     bool readSymbols,
     bool enableBundler,
     TargetPlatforms targetPlatform,
     DebugInformationOptions debugInformationOptions,
     params string[] assemblyPaths)
 {
     TranslateAll(
         storage,
         readSymbols,
         enableBundler,
         targetPlatform,
         debugInformationOptions,
         (IEnumerable <string>)assemblyPaths);
 }
 public static void TranslateAll(
     TextWriter logw,
     string outputPath,
     bool readSymbols,
     bool enableBundler,
     TargetPlatforms targetPlatform,
     DebugInformationOptions debugInformationOptions,
     params string[] assemblyPaths)
 {
     TranslateAll(
         logw,
         outputPath,
         readSymbols,
         enableBundler,
         targetPlatform,
         debugInformationOptions,
         (IEnumerable <string>)assemblyPaths);
 }
Exemple #9
0
 public static void TranslateAll(
     TextWriter logw,
     CodeTextStorage storage,
     bool readSymbols,
     bool enableBundler,
     DebugInformationOptions debugInformationOptions,
     IEnumerable <string> assemblyPaths)
 {
     foreach (var aseemblyPath in assemblyPaths)
     {
         Translate(
             logw,
             storage,
             readSymbols,
             enableBundler,
             debugInformationOptions,
             aseemblyPath);
     }
 }
Exemple #10
0
 public static void TranslateAll(
     CodeTextStorage storage,
     bool readSymbols,
     bool enableBundler,
     TargetPlatforms targetPlatform,
     DebugInformationOptions debugInformationOptions,
     IEnumerable <string> assemblyPaths)
 {
     foreach (var aseemblyPath in assemblyPaths)
     {
         Translate(
             storage,
             readSymbols,
             enableBundler,
             targetPlatform,
             debugInformationOptions,
             aseemblyPath);
     }
 }
Exemple #11
0
        public static string[] WriteSourceCodes(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            DebugInformationOptions debugInformationOption)
        {
            IExtractContextHost extractContext = translateContext;
            var assemblyName = extractContext.Assembly.Name;

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

            var sourceFiles = new List <string>();

            foreach (var targetType in prepared.Types.
                     Where(type => type.DeclaringType == null))
            {
                using (var _ = storage.EnterScope(targetType.ScopeName))
                {
                    using (var twSource = storage.CreateSourceCodeWriter(targetType.Name))
                    {
                        // HACK: Unreal Engine 4 needs include directive with same file name as header extension (ex: foo.c --> foo.h) at first line.
                        if (extractContext.TargetPlatform == TargetPlatforms.UE4)
                        {
                            twSource.WriteLine(
                                "#include \"{0}.h\"   // [16-1] Needs for Unreal Engine 4.",
                                targetType.Name);
                            twSource.SplitLine();
                        }

                        twSource.WriteLine(
                            "// [15-2] 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();

                        // Write assembly references at the file scope.
                        InternalWriteAssemblyReferences(
                            twSource,
                            translateContext,
                            extractContext,
                            targetType);

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

                        InternalWriteSourceCode(
                            twSource,
                            extractContext,
                            prepared,
                            targetType,
                            debugInformationOption,
                            typesByDeclaring);

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

                        twSource.Flush();

                        sourceFiles.Add(twSource.RelatedPath);
                    }

                    // HACK: Unreal Engine 4 needs include directive with same file name as header extension (ex: foo.c --> foo.h) at first line.
                    if (extractContext.TargetPlatform == TargetPlatforms.UE4)
                    {
                        using (var twUE4Header = storage.CreateHeaderWriter(targetType.Name))
                        {
                            twUE4Header.WriteLine(
                                "// [16-2] This is {0} native code translated by IL2C, do not edit.",
                                assemblyName);
                            twUE4Header.WriteLine(
                                "// It's a dummy header file for helping and using only Unreal Engine 4.",
                                assemblyName);

                            twUE4Header.Flush();
                        }
                    }
                }
            }

            return(sourceFiles.ToArray());
        }
Exemple #12
0
        public static string[] WriteSourceCodes(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared,
            DebugInformationOptions debugInformationOption)
        {
            IExtractContextHost extractContext = translateContext;
            var assemblyName = extractContext.Assembly.Name;

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

            var sourceFiles = new List <string>();

            foreach (var targetType in prepared.Types.
                     Where(type => type.DeclaringType == null))
            {
                using (var _ = storage.EnterScope(targetType.ScopeName))
                {
                    using (var twSource = storage.CreateSourceCodeWriter(targetType.Name))
                    {
                        twSource.WriteLine(
                            "// [15-2] 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();

                        // Write assembly references at the file scope.
                        InternalWriteAssemblyReferences(
                            twSource,
                            translateContext,
                            extractContext,
                            targetType);

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

                        InternalWriteSourceCode(
                            twSource,
                            extractContext,
                            prepared,
                            targetType,
                            debugInformationOption,
                            typesByDeclaring);

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

                        twSource.Flush();

                        sourceFiles.Add(twSource.RelatedPath);
                    }
                }
            }

            return(sourceFiles.ToArray());
        }
Exemple #13
0
        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();
                }
            }
        }
 public DebugInformationWriteController(IMethodInformation method, DebugInformationOptions mode)
 {
     this.mode  = mode;
     this.debug = method.CodeStream.First().Debug.FirstOrDefault();
 }
Exemple #15
0
        public static void InternalConvertFromMethod(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedInformations preparedFunctions,
            IMethodInformation method,
            DebugInformationOptions debugInformationOption = DebugInformationOptions.None)
        {
            if (method.IsVirtual)
            {
                if (method.IsAbstract)
                {
                    if (!method.DeclaringType.IsInterface)
                    {
                        InternalConvertFromAbstractFunction(
                            tw,
                            method);
                    }
                    return;
                }
            }

            // internalcall or DllImport
            if (method.IsExtern)
            {
                // DllImport
                var pinvokeInfo = method.PInvokeInfo;
                if (pinvokeInfo != null)
                {
                    InternalConvertFromPInvokeFunction(
                        tw,
                        method,
                        pinvokeInfo);
                    return;
                }

                // Specialize delegate type methods:
                if (method.DeclaringType.IsDelegate && !method.DeclaringType.IsAbstract)
                {
                    // Delegate constructor
                    if (method.IsConstructor)
                    {
                        // Ignore. We have to use the "il2c_new_delegate()" instead this constructor translated body.
                        return;
                    }

                    // Delegate "Invoke"
                    if (method.Name == "Invoke")
                    {
                        InternalConvertFromDelegateInvoker(
                            tw,
                            extractContext,
                            method);
                        return;
                    }
                }

                throw new InvalidProgramSequenceException(
                          "Unknown internallcall method declaration. Name={0}",
                          method.FriendlyName);
            }

            if (!preparedFunctions.Functions.TryGetValue(method, out var preparedMethod))
            {
                return;
            }

            InternalConvertFromFunction(
                tw,
                extractContext,
                preparedMethod,
                debugInformationOption);
        }
Exemple #16
0
        private static void InternalConvertFromFunction(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedMethodInformation preparedMethod,
            DebugInformationOptions debugInformationOption)
        {
            var locals = preparedMethod.Method.LocalVariables;

            tw.SplitLine();
            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine(
                "// [3] {0}{1}",
                preparedMethod.Method.IsVirtual ? "Virtual: " : string.Empty,
                preparedMethod.Method.FriendlyName);

            var codeStream = preparedMethod.Method.CodeStream;

            // Write exception filters:
            if (codeStream.ExceptionHandlers.Length >= 1)
            {
                tw.SplitLine();
                tw.WriteLine("//-------------------");
                tw.WriteLine("// [3-1] Exception filters:");
                tw.SplitLine();

                for (var handlerIndex = 0;
                     handlerIndex < codeStream.ExceptionHandlers.Length;
                     handlerIndex++)
                {
                    var handler = codeStream.ExceptionHandlers[handlerIndex];

                    var filterName = string.Format(
                        "{0}_ExceptionFilter{1}__",
                        preparedMethod.Method.CLanguageFunctionName,
                        handlerIndex);
                    tw.WriteLine(
                        "static int16_t {0}(System_Exception* ex)",
                        filterName);
                    tw.WriteLine("{");

                    using (var _ = tw.Shift())
                    {
                        tw.WriteLine("il2c_assert(ex != NULL);");

                        for (var catchHandlerIndex = 0;
                             catchHandlerIndex < handler.CatchHandlers.Length;
                             catchHandlerIndex++)
                        {
                            var catchHandler = handler.CatchHandlers[catchHandlerIndex];
                            if (catchHandler.CatchHandlerType == ExceptionCatchHandlerTypes.Catch)
                            {
                                tw.WriteLine(
                                    "if (il2c_isinst__(ex, il2c_typeof({0}))) return {1};",
                                    catchHandler.CatchType.MangledName,
                                    catchHandlerIndex + 1);
                            }
                        }

                        // Write finally block index if contains.
                        var finallyHandler = handler.CatchHandlers.
                                             Select((catchHandler, index) => new { catchHandler, index }).
                                             FirstOrDefault(entry => entry.catchHandler.CatchHandlerType == ExceptionCatchHandlerTypes.Finally);
                        if (finallyHandler != null)
                        {
                            tw.WriteLine("return IL2C_FILTER_FINALLY;  // Not matched (will go to finally)");
                        }
                        else
                        {
                            tw.WriteLine("return IL2C_FILTER_NOMATCH;  // Not matched");
                        }
                    }

                    tw.WriteLine("}");
                }
            }

            // Start function:
            tw.SplitLine();
            tw.WriteLine("//-------------------");
            tw.WriteLine("// [3-2] Function body:");
            tw.SplitLine();
            tw.WriteLine(preparedMethod.Method.CLanguageFunctionPrototype);
            tw.WriteLine("{");

            using (var _ = tw.Shift())
            {
                if (!preparedMethod.Method.IsStatic)
                {
                    tw.WriteLine("il2c_assert(this__ != NULL);");
                    tw.SplitLine();
                }

                var localDefinitions = preparedMethod.Method.LocalVariables.
                                       Where(local => !local.TargetType.IsReferenceType).
                                       ToArray();
                if (localDefinitions.Length >= 1)
                {
                    tw.WriteLine("//-------------------");
                    tw.WriteLine("// [3-3] Local variables (not objref):");
                    tw.SplitLine();

                    foreach (var local in localDefinitions)
                    {
                        // HACK: The local variables mark to "volatile."
                        //   Because the gcc misread these variables calculated statically (or maybe assigned to the registers)
                        //   at compile time with optimization.
                        //   It will cause the strange results for exception handling (with sjlj.)
                        tw.WriteLine(
                            "{0}{1} {2};",
                            (codeStream.ExceptionHandlers.Length >= 1) ? "volatile " : string.Empty,
                            local.TargetType.CLanguageTypeName,
                            extractContext.GetSymbolName(local));
                    }

                    tw.SplitLine();
                }

                var stackDefinitions = preparedMethod.Stacks.
                                       Where(stack => !stack.TargetType.IsReferenceType).
                                       ToArray();
                if (stackDefinitions.Length >= 1)
                {
                    tw.WriteLine("//-------------------");
                    tw.WriteLine("// [3-4] Evaluation stacks (not objref):");
                    tw.SplitLine();

                    foreach (var stack in stackDefinitions)
                    {
                        tw.WriteLine(
                            "{0} {1};",
                            stack.TargetType.CLanguageTypeName,
                            extractContext.GetSymbolName(stack));
                    }

                    tw.SplitLine();
                }

                var objRefEntries = locals.
                                    Concat(preparedMethod.Stacks).
                                    Where(v => v.TargetType.IsReferenceType). // Only objref
                                    ToArray();
                if (objRefEntries.Length >= 1)
                {
                    tw.WriteLine("//-------------------");
                    tw.WriteLine("// [3-5] Setup execution frame:");
                    tw.SplitLine();

                    tw.WriteLine(
                        "struct {0}_EXECUTION_FRAME__",
                        preparedMethod.Method.CLanguageFunctionName);
                    tw.WriteLine("{");

                    using (var __ = tw.Shift())
                    {
                        tw.WriteLine("uint8_t objRefCount__;");
                        tw.WriteLine("uint8_t objRefRefCount__;");
                        tw.WriteLine("IL2C_EXECUTION_FRAME* pNext__;");

                        foreach (var objRefEntry in objRefEntries)
                        {
                            tw.WriteLine(
                                "{0} {1};",
                                objRefEntry.TargetType.CLanguageTypeName,
                                extractContext.GetSymbolName(objRefEntry));
                        }
                    }

                    // Important NULL assigner (p = NULL):
                    //   Because these variables are pointer (of object reference 'O' type).
                    //   So GC will traverse these variables just setup the stack frame.
                    // TODO: https://github.com/kekyo/IL2C/issues/12
                    tw.WriteLine("}} frame__ = {{ {0}, 0 }};", objRefEntries.Length);
                    tw.WriteLine("il2c_link_execution_frame(&frame__);");
                    tw.SplitLine();
                }

                tw.WriteLine("//-------------------");
                tw.WriteLine("// [3-6] IL body:");
                tw.SplitLine();

                // Set symbol prefix to make valid access variables.
                using (var __ = extractContext.BeginLocalVariablePrefix(
                           local => local.TargetType.IsReferenceType ? "frame__." : null))
                {
                    // Construct exception handler controller.
                    var exceptionHandlerController = new ExceptionHandlerController(
                        codeStream.ExceptionHandlers,
                        (handler, handlerIndex, nestedIndex) =>
                    {
                        var nestedIndexName = string.Format("nest{0}", nestedIndex);
                        extractContext.SetNestedExceptionFrameIndexName(nestedIndexName);

                        // Reached try block:
                        var filterName = string.Format(
                            "{0}_ExceptionFilter{1}__",
                            preparedMethod.Method.CLanguageFunctionName,
                            handlerIndex);
                        tw.WriteLine("il2c_try({0}, {1})", nestedIndexName, filterName);
                        tw.WriteLine("{");
                        tw.Shift();
                    },
                        (handler, handlerIndex, nestedIndex) =>
                    {
                        // Reached try end block:
                        tw.Shift(-1);
                        tw.WriteLine("}");
                    },
                        (handler, handlerIndex, nestedIndex, catchHandler, catchHandlerIndex) =>
                    {
                        var nestedIndexName = extractContext.GetExceptionNestedFrameIndexName();
                        switch (catchHandler.CatchHandlerType)
                        {
                        case ExceptionCatchHandlerTypes.Catch:
                            // Reached catch block:
                            tw.WriteLine(
                                "il2c_catch({0}, {1}, {2})  // catch ({3})",
                                nestedIndexName,
                                catchHandlerIndex + 1,
                                extractContext.GetSymbolName(preparedMethod.CatchVariables[catchHandler.CatchStart]),
                                catchHandler.CatchType.MangledName);
                            break;

                        case ExceptionCatchHandlerTypes.Finally:
                            // Reached finally block:
                            tw.WriteLine("il2c_finally({0})", nestedIndexName);
                            break;
                        }
                        tw.WriteLine("{");
                        tw.Shift();
                    },
                        (handler, handlerIndex, nestedIndex, catchHandler, catchHandlerIndex) =>
                    {
                        // Reached catch end block:
                        tw.Shift(-1);
                        tw.WriteLine("}");
                    },
                        (handler, handlerIndex, nestedIndex, parentHandler, parentHandlerIndex, parentNestedIndex) =>
                    {
                        var nestedIndexName       = extractContext.GetExceptionNestedFrameIndexName();
                        var parentNestedIndexName = (parentNestedIndex >= 0) ? string.Format("nest{0}", parentNestedIndex) : null;

                        // Write leave bind expressions if needed.
                        // Extract the continuation fromOffset inside at mostly inner exception handler.
                        var bindEntries =
                            preparedMethod.LeaveContinuations.
                            SelectMany(entry => codeStream.ExceptionHandlers.
                                       // nested exception handlers: inner --> outer
                                       Reverse().
                                       // Is this handler contains leave continuation target?
                                       Where(h => entry.Value.fromOffsets.Any(offset => h.ContainsOffset(offset))).
                                       // Found.
                                       Select(h => new { handler = h, continuationIndex = entry.Key, entry.Value.targetOffset })).
                            // ... is current handler?
                            Where(entry => entry.handler.Equals(handler)).
                            ToArray();
                        if (bindEntries.Length >= 1)
                        {
                            tw.WriteLine("il2c_leave_to({0})", nestedIndexName);
                            tw.WriteLine("{");
                            using (var ___ = tw.Shift())
                            {
                                foreach (var bind in bindEntries)
                                {
                                    if ((parentNestedIndex < 0) ||
                                        codeStream.ExceptionHandlers[parentNestedIndex].ContainsOffset(bind.targetOffset))
                                    {
                                        var labelName = preparedMethod.LabelNames[bind.targetOffset];
                                        tw.WriteLine(
                                            "il2c_leave_bind({0}, {1}, {2});",
                                            nestedIndexName,
                                            bind.continuationIndex,
                                            labelName);
                                    }
                                    else
                                    {
                                        tw.WriteLine(
                                            "il2c_leave_through({0}, {1}, {2});",
                                            nestedIndexName, bind.continuationIndex, parentNestedIndexName);
                                    }
                                }
                            }
                            tw.WriteLine("}");
                        }

                        // Reached end of entire try block.
                        tw.WriteLine("il2c_end_try({0});", nestedIndexName);

                        extractContext.SetNestedExceptionFrameIndexName(parentNestedIndexName);
                    });

                    // Traverse code fragments.
                    var canWriteSequencePoint = true;
                    foreach (var ci in codeStream)
                    {
                        // 1: Update the exception handler controller.
                        //    (Will write exception related sentences.)
                        exceptionHandlerController.Update(ci);

                        // 2: Write label if available and used.
                        if (preparedMethod.LabelNames.TryGetValue(ci.Offset, out var labelName))
                        {
                            using (var ___ = tw.Shift(-1))
                            {
                                tw.WriteLine("{0}:", labelName);
                            }
                        }

                        // 3: Write the line preprocessor directive if available.
                        if (canWriteSequencePoint && ci.Debug.Any())
                        {
                            var sp = ci.Debug.First();
                            switch (debugInformationOption)
                            {
                            case DebugInformationOptions.Full:
                                tw.Parent.WriteLine(
                                    "#line {0} \"{1}\"",
                                    sp.Line,
                                    sp.Path.Replace("\\", "\\\\"));
                                break;

                            case DebugInformationOptions.CommentOnly:
                                tw.Parent.WriteLine(
                                    "/* {0}({1}): */",
                                    sp.Path.Replace("\\", "\\\\"),
                                    sp.Line);
                                break;
                            }

                            canWriteSequencePoint = false;
                        }

                        // 4: Generate source code fragments and write.
                        if (debugInformationOption != DebugInformationOptions.None)
                        {
                            // Write debugging information.
                            tw.WriteLine(
                                "/* {0} */",
                                ci);
                        }

                        var sourceCodes = preparedMethod.Generators[ci.Offset](extractContext);
                        foreach (var sourceCode in sourceCodes)
                        {
                            // Dirty hack:
                            //   Write unlink execution frame code if cause exiting method.
                            if (sourceCode.StartsWith("return") &&
                                (objRefEntries.Length >= 1))
                            {
                                tw.WriteLine(
                                    "il2c_unlink_execution_frame(&frame__);");
                            }

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

                            canWriteSequencePoint = true;
                        }
                    }

                    if (!exceptionHandlerController.IsFinished)
                    {
                        throw new InvalidProgramSequenceException(
                                  "Invalid exception handler range. MethodName={0}, ExceptionHandlers=[{1}]",
                                  preparedMethod.Method.FriendlyName,
                                  string.Join(
                                      ",",
                                      codeStream.ExceptionHandlers.
                                      Select(handler => string.Format("[{0}]", handler))));
                    }
                }
            }

            tw.WriteLine("}");
            tw.SplitLine();
        }
Exemple #17
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 #18
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 #19
0
        public static void InternalConvertFromMethod(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedInformations preparedFunctions,
            IMethodInformation method,
            DebugInformationOptions debugInformationOption = DebugInformationOptions.None)
        {
            if (method.IsVirtual)
            {
                if (method.IsAbstract)
                {
                    if (!method.DeclaringType.IsInterface)
                    {
                        InternalConvertFromAbstractFunction(
                            tw,
                            method);
                    }
                    return;
                }
            }

            // internalcall or DllImport
            if (method.IsExtern)
            {
                // Specialize delegate type methods:
                if (method.DeclaringType.IsDelegate && !method.DeclaringType.IsAbstract)
                {
                    // Delegate constructor
                    if (method.IsConstructor)
                    {
                        // Ignore. We have to use the "il2c_new_delegate()" instead this constructor translated body.
                        return;
                    }

                    // Delegate "Invoke"
                    if (method.Name == "Invoke")
                    {
                        InternalConvertFromDelegateInvoker(
                            tw,
                            extractContext,
                            method);
                        return;
                    }
                }

                // InternalCall or DllImport
                InternalConvertFromInternalCallFunction(
                    tw,
                    method);
                return;
            }

            if (!preparedFunctions.Functions.TryGetValue(method, out var preparedMethod))
            {
                return;
            }

            InternalConvertFromFunction(
                tw,
                extractContext,
                preparedMethod,
                debugInformationOption);
        }
Exemple #20
0
        private static void InternalConvertFromFunction(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedMethodInformation preparedMethod,
            DebugInformationOptions debugInformationOption)
        {
            var locals = preparedMethod.Method.LocalVariables;

            tw.WriteLine("///////////////////////////////////////");
            tw.WriteLine(
                "// [3] {0}{1}",
                preparedMethod.Method.IsVirtual ? "Virtual: " : string.Empty,
                preparedMethod.Method.FriendlyName);
            tw.SplitLine();

            var codeStream    = preparedMethod.Method.CodeStream;
            var objRefEntries = locals.
                                Concat(preparedMethod.Stacks).
                                Where(v => v.TargetType.IsReferenceType). // Only objref
                                ToArray();
            var valueEntries = locals.
                               Concat(preparedMethod.Stacks).
                               Where(v => v.TargetType.IsValueType && v.TargetType.IsRequiredTraverse).
                               ToArray();

            // Write declaring exception handlers
            if (codeStream.ExceptionHandlers.Length >= 1)
            {
                InternalConvertExceptionFilter(
                    tw,
                    extractContext,
                    preparedMethod,
                    codeStream);
            }

            // Write declaring execution frame
            if ((objRefEntries.Length >= 1) || (valueEntries.Length >= 1))
            {
                InternalConvertExecutionFrame(
                    tw,
                    extractContext,
                    preparedMethod,
                    objRefEntries,
                    valueEntries);
            }

            // Make readable debugging comment, it was splitting and reducing same informations.
            var debugInformationController =
                new DebugInformationWriteController(
                    preparedMethod.Method,
                    debugInformationOption);

            // Start function:
            tw.WriteLine("//-------------------");
            tw.WriteLine("// [3-2] Function body:");
            tw.SplitLine();
            tw.WriteLine(preparedMethod.Method.CLanguageFunctionPrototype);
            tw.WriteLine("{");

            using (var _ = tw.Shift())
            {
                if (!preparedMethod.Method.IsStatic)
                {
                    debugInformationController.WriteInformationBeforeCode(tw);
                    tw.WriteLine("il2c_assert(this__ != NULL);");
                    tw.SplitLine();
                }

                var localDefinitions = preparedMethod.Method.LocalVariables.
                                       Where(local => !local.TargetType.IsReferenceType).
                                       ToArray();
                if (localDefinitions.Length >= 1)
                {
                    tw.WriteLine("//-------------------");
                    tw.WriteLine("// [3-3] Local variables (!objref):");
                    tw.SplitLine();

                    foreach (var local in localDefinitions)
                    {
                        var name = extractContext.GetSymbolName(local);

                        // HACK: The local variables mark to "volatile."
                        //   Because the gcc misread these variables calculated statically (or maybe assigned to the registers)
                        //   at compile time with optimization.
                        //   It will cause the strange results for exception handling (with sjlj.)

                        // We have to initialize the local variables.
                        if (local.TargetType.IsPrimitive ||
                            local.TargetType.IsPointer ||
                            local.TargetType.IsByReference)
                        {
                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "{0}{1} {2} = {3};",
                                (codeStream.ExceptionHandlers.Length >= 1) ? "volatile " : string.Empty,
                                local.TargetType.CLanguageTypeName,
                                name,
                                Utilities.GetCLanguageExpression(local.TargetType.InternalStaticEmptyValue));
                        }
                        else
                        {
                            Debug.Assert(local.TargetType.IsValueType);

                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "{0}{1} {2};",
                                (codeStream.ExceptionHandlers.Length >= 1) ? "volatile " : string.Empty,
                                local.TargetType.CLanguageTypeName,
                                name);

                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "memset({0}&{1}, 0x00, sizeof {1});",
                                (codeStream.ExceptionHandlers.Length >= 1) ? "(void*)" : string.Empty,
                                name);
                        }
                    }

                    tw.SplitLine();
                }

                var stackDefinitions = preparedMethod.Stacks.
                                       Where(stack => !stack.TargetType.IsReferenceType).
                                       ToArray();
                if (stackDefinitions.Length >= 1)
                {
                    tw.WriteLine("//-------------------");
                    tw.WriteLine("// [3-4] Evaluation stacks (!objref):");
                    tw.SplitLine();

                    foreach (var stack in stackDefinitions)
                    {
                        var name = extractContext.GetSymbolName(stack);

                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.WriteLine(
                            "{0} {1};",
                            stack.TargetType.CLanguageTypeName,
                            name);

                        // Note: We often don't have to initalize the evaluation stack variables.
                        //   Because these variables push value at first usage.
                        //   But the value type may contains objref field,
                        //   so we have to initialize for value type.
                        if (stack.TargetType.IsRequiredTraverse)
                        {
                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "memset(&{0}, 0, sizeof {0});",
                                name);
                        }
                    }

                    tw.SplitLine();
                }

                // Write doing setup execution frame
                if ((objRefEntries.Length >= 1) || (valueEntries.Length >= 1))
                {
                    InternalConvertSetupExecutionFrame(
                        tw,
                        extractContext,
                        preparedMethod,
                        objRefEntries,
                        valueEntries,
                        debugInformationController);
                }

                tw.WriteLine("//-------------------");
                tw.WriteLine("// [3-6] IL body:");
                tw.SplitLine();

                // Set symbol prefix to make valid access variables.
                using (var __ = extractContext.BeginLocalVariablePrefix(
                           local => local.TargetType.IsReferenceType ? "frame__." : null))
                {
                    // Construct exception handler controller.
                    var exceptionHandlerController = new ExceptionHandlerController(
                        codeStream.ExceptionHandlers,
                        (handler, handlerIndex, nestedIndex) =>
                    {
                        var nestedIndexName = string.Format("nest{0}", nestedIndex);
                        extractContext.SetNestedExceptionFrameIndexName(nestedIndexName);

                        // Reached try block:
                        var filterName = string.Format(
                            "{0}_ExceptionFilter{1}__",
                            preparedMethod.Method.CLanguageFunctionName,
                            handlerIndex);

                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.WriteLine("il2c_try({0}, {1})", nestedIndexName, filterName);

                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.WriteLine("{");
                        tw.Shift();
                    },
                        (handler, handlerIndex, nestedIndex) =>
                    {
                        // Reached try end block:
                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.Shift(-1);
                        tw.WriteLine("}");
                    },
                        (handler, handlerIndex, nestedIndex, catchHandler, catchHandlerIndex) =>
                    {
                        var nestedIndexName = extractContext.GetExceptionNestedFrameIndexName();
                        switch (catchHandler.CatchHandlerType)
                        {
                        case ExceptionCatchHandlerTypes.Catch:
                            // Reached catch block:
                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "il2c_catch({0}, {1}, {2})  // catch ({3})",
                                nestedIndexName,
                                catchHandlerIndex + 1,
                                extractContext.GetSymbolName(preparedMethod.CatchVariables[catchHandler.CatchStart]),
                                catchHandler.CatchType.MangledUniqueName);
                            break;

                        case ExceptionCatchHandlerTypes.Finally:
                            // Reached finally block:
                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine("il2c_finally({0})", nestedIndexName);
                            break;
                        }
                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.WriteLine("{");
                        tw.Shift();
                    },
                        (handler, handlerIndex, nestedIndex, catchHandler, catchHandlerIndex) =>
                    {
                        // Reached catch end block:
                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.Shift(-1);
                        tw.WriteLine("}");
                    },
                        (handler, handlerIndex, nestedIndex, parentHandler, parentHandlerIndex, parentNestedIndex) =>
                    {
                        var nestedIndexName       = extractContext.GetExceptionNestedFrameIndexName();
                        var parentNestedIndexName = (parentNestedIndex >= 0) ? string.Format("nest{0}", parentNestedIndex) : null;

                        // Write leave bind expressions if needed.
                        // Extract the continuation fromOffset inside at mostly inner exception handler.
                        var bindEntries =
                            preparedMethod.LeaveContinuations.
                            SelectMany(entry => codeStream.ExceptionHandlers.
                                       // nested exception handlers: inner --> outer
                                       Reverse().
                                       // Is this handler contains leave continuation target?
                                       Where(h => entry.Value.fromOffsets.Any(offset => h.ContainsOffset(offset))).
                                       // Found.
                                       Select(h => new { handler = h, continuationIndex = entry.Key, entry.Value.targetOffset })).
                            // ... is current handler?
                            Where(entry => entry.handler.Equals(handler)).
                            ToArray();
                        if (bindEntries.Length >= 1)
                        {
                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine("il2c_leave_to({0})", nestedIndexName);

                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine("{");

                            using (var ___ = tw.Shift())
                            {
                                foreach (var bind in bindEntries)
                                {
                                    if ((parentNestedIndex < 0) ||
                                        codeStream.ExceptionHandlers[parentNestedIndex].ContainsOffset(bind.targetOffset))
                                    {
                                        var labelName = preparedMethod.LabelNames[bind.targetOffset];

                                        debugInformationController.WriteInformationBeforeCode(tw);
                                        tw.WriteLine(
                                            "il2c_leave_bind({0}, {1}, {2});",
                                            nestedIndexName,
                                            bind.continuationIndex,
                                            labelName);
                                    }
                                    else
                                    {
                                        debugInformationController.WriteInformationBeforeCode(tw);
                                        tw.WriteLine(
                                            "il2c_leave_through({0}, {1}, {2});",
                                            nestedIndexName, bind.continuationIndex, parentNestedIndexName);
                                    }
                                }
                            }

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

                        // Reached end of entire try block.
                        debugInformationController.WriteInformationBeforeCode(tw);
                        tw.WriteLine("il2c_end_try({0});", nestedIndexName);

                        extractContext.SetNestedExceptionFrameIndexName(parentNestedIndexName);
                    });

                    // Traverse code fragments.
                    foreach (var ci in codeStream)
                    {
                        debugInformationController.SetNextCode(ci);

                        // 1: Update the exception handler controller.
                        //    (Will write exception related sentences.)
                        exceptionHandlerController.Update(ci);

                        // 2: Write label if available and used.
                        if (preparedMethod.LabelNames.TryGetValue(ci.Offset, out var labelName))
                        {
                            using (var ___ = tw.Shift(-1))
                            {
                                tw.WriteLine("{0}:", labelName);
                            }
                        }

                        // 3: Write source code comment.
                        debugInformationController.WriteCodeComment(tw);

                        // 4: Generate source code fragments and write.
                        var sourceCodes = preparedMethod.Generators[ci.Offset](extractContext);
                        foreach (var sourceCode in sourceCodes)
                        {
                            // DIRTY HACK:
                            //   Write unlink execution frame code if cause exiting method.
                            if (sourceCode.StartsWith("return") &&
                                ((objRefEntries.Length >= 1) || (valueEntries.Length >= 1)))
                            {
                                debugInformationController.WriteInformationBeforeCode(tw);
                                tw.WriteLine(
                                    "il2c_unlink_execution_frame(&frame__);");
                            }

                            debugInformationController.WriteInformationBeforeCode(tw);
                            tw.WriteLine(
                                "{0};",
                                sourceCode);
                        }
                    }

                    // If last opcode is 'endfinally' and not emitted 'ret',
                    // can't finished for exceptionHandlerController.
                    // We can check and force update the TryFinish method for this situation.
                    exceptionHandlerController.TryFinish();

                    if (!exceptionHandlerController.IsFinished)
                    {
                        throw new InvalidProgramSequenceException(
                                  "Invalid exception handler range. MethodName={0}, ExceptionHandlers=[{1}]",
                                  preparedMethod.Method.FriendlyName,
                                  string.Join(
                                      ",",
                                      codeStream.ExceptionHandlers.
                                      Select(handler => string.Format("[{0}]", handler))));
                    }
                }
            }

            debugInformationController.WriteInformationBeforeCode(tw);
            tw.WriteLine("}");
            tw.SplitLine();
        }
Exemple #21
0
        public static void Translate(
            TextWriter tw,
            string assemblyPath,
            string outputPath,
            bool readSymbols,
            bool enableCpp,
            DebugInformationOptions debugInformationOptions)
        {
            tw.Write("IL2C: Preparing assembly: \"{0}\" ...", Path.GetFullPath(assemblyPath));

            if (Directory.Exists(outputPath) == false)
            {
                try
                {
                    Directory.CreateDirectory(outputPath);
                }
                catch
                {
                }
            }

            var translateContext  = new TranslateContext(assemblyPath, readSymbols);
            var preparedFunctions = AssemblyPreparer.Prepare(translateContext);

            tw.WriteLine(" done.");

            var assemblyName   = Path.GetFileNameWithoutExtension(assemblyPath);
            var filePath       = Path.Combine(outputPath, assemblyName);
            var sourceFilePath = filePath + (enableCpp ? ".cpp" : ".c");

            tw.Write("IL2C: Writing source code: \"{0}\" ...", Path.GetFullPath(sourceFilePath));

            using (var fsSource = new FileStream(
                       sourceFilePath,
                       FileMode.Create,
                       FileAccess.ReadWrite,
                       FileShare.None))
            {
                var twSource = CodeTextWriter.Create(fsSource, "    ");
                AssemblyWriter.WriteSourceCode(
                    twSource, translateContext, preparedFunctions, debugInformationOptions);
                twSource.Flush();
            }

            tw.WriteLine(" done.");

            var headerFilePath = filePath + ".h";

            tw.Write("IL2C: Writing header: \"{0}\" ...", Path.GetFullPath(headerFilePath));

            using (var fsHeader = new FileStream(
                       headerFilePath,
                       FileMode.Create,
                       FileAccess.ReadWrite,
                       FileShare.None))
            {
                var twHeader = CodeTextWriter.Create(fsHeader, "    ");
                AssemblyWriter.WriteHeader(twHeader, translateContext, preparedFunctions);
                twHeader.Flush();
            }

            tw.WriteLine(" done.");
        }
Exemple #22
0
        internal static void InternalWriteSourceCode(
            CodeTextWriter twSource,
            TranslateContext translateContext,
            PreparedInformations prepared,
            DebugInformationOptions debugInformationOption,
            bool includeAssemblyHeader)
        {
            IExtractContextHost extractContext = translateContext;

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

                twSource.WriteLine("#include \"{0}.h\"", extractContext.Assembly.Name);
                twSource.SplitLine();
            }

            WriteConstStrings(twSource, translateContext);
            WriteDeclaredValues(twSource, translateContext);

            twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            twSource.WriteLine("// [9-2] File scope prototypes:");
            twSource.SplitLine();

            // All types exclude publics and internals (for file scope prototypes)
            PrototypeWriter.InternalConvertToPrototypes(
                twSource,
                prepared.Types,
                type => !type.IsCLanguagePublicScope,
                field => !(field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly),
                method => (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly) &&
                prepared.Functions.ContainsKey(method));

            twSource.WriteLine("//////////////////////////////////////////////////////////////////////////////////");
            twSource.WriteLine("// [9-3] Declare static fields:");
            twSource.SplitLine();

            foreach (var type in prepared.Types.
                     Where(type => !type.IsEnum))
            {
                // All static fields
                foreach (var field in type.Fields.
                         Where(field => field.IsStatic))
                {
                    twSource.WriteLine(
                        "{0};",
                        field.GetCLanguageStaticPrototype(true));
                }
                twSource.SplitLine();
            }

            foreach (var type in prepared.Types)
            {
                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)
                {
                    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();
        }
Exemple #23
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;
            }
        }