Beispiel #1
0
        private static void InternalConvertSetupExecutionFrame(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedMethodInformation preparedMethod,
            ILocalVariableInformation[] objRefEntries,
            ILocalVariableInformation[] valueEntries,
            DebugInformationWriteController debugInformationController)
        {
            tw.WriteLine("//-------------------");
            tw.WriteLine("// [3-5] Setup execution frame:");
            tw.SplitLine();

            // 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.
            debugInformationController.WriteInformationBeforeCode(tw);
            tw.WriteLine(
                "{0}_EXECUTION_FRAME__ frame__ =",
                preparedMethod.Method.CLanguageFunctionName);
            using (var __ = tw.Shift())
            {
                if (valueEntries.Length >= 1)
                {
                    tw.WriteLine(
                        "{{ NULL, {0}, {1}, {2} }};",
                        objRefEntries.Length,
                        valueEntries.Length,
                        string.Join(
                            ", ",
                            objRefEntries.Select(___ => "NULL").
                            Concat(valueEntries.
                                   Select(valueEntry =>
                                          string.Format(
                                              "il2c_typeof({0}), NULL",
                                              valueEntry.TargetType.MangledUniqueName)))));
                }
                else
                {
                    // Make short initializer expression if value type not included,
                    // maybe C compiler makes better code.
                    tw.WriteLine(
                        "{{ NULL, {0} }};",
                        objRefEntries.Length);
                }
            }

            foreach (var valueEntry in valueEntries)
            {
                debugInformationController.WriteInformationBeforeCode(tw);
                tw.WriteLine(
                    "frame__.{0}_value_ptr__ = &{0};",
                    extractContext.GetSymbolName(valueEntry));
            }

            debugInformationController.WriteInformationBeforeCode(tw);
            tw.WriteLine("il2c_link_execution_frame(&frame__);");
            tw.SplitLine();
        }
Beispiel #2
0
        private static void InternalConvertExecutionFrame(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedMethodInformation preparedMethod,
            ILocalVariableInformation[] objRefEntries,
            ILocalVariableInformation[] valueEntries)
        {
            tw.WriteLine("//-------------------");
            tw.WriteLine("// [3-7] Declare execution frame:");
            tw.SplitLine();

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

            using (var _ = tw.Shift())
            {
                tw.WriteLine("const IL2C_EXECUTION_FRAME* pNext__;");
                tw.WriteLine("const uint16_t objRefCount__;");
                tw.WriteLine("const uint16_t valueCount__;");

                if (objRefEntries.Length >= 1)
                {
                    tw.WriteLine("//-------------------- objref");
                    foreach (var objRefEntry in objRefEntries)
                    {
                        tw.WriteLine(
                            "{0} {1};",
                            objRefEntry.TargetType.CLanguageTypeName,
                            extractContext.GetSymbolName(objRefEntry));
                    }
                }

                if (valueEntries.Length >= 1)
                {
                    tw.WriteLine("//-------------------- value type");
                    foreach (var valueEntry in valueEntries)
                    {
                        var name = extractContext.GetSymbolName(valueEntry);
                        tw.WriteLine(
                            "const IL2C_RUNTIME_TYPE {0}_type__;",
                            name);
                        tw.WriteLine(
                            "const {0}* {1}_value_ptr__;",
                            valueEntry.TargetType.CLanguageTypeName,
                            name);
                    }
                }
            }

            tw.WriteLine(
                "}} {0}_EXECUTION_FRAME__;",
                preparedMethod.Method.CLanguageFunctionName);
            tw.SplitLine();
        }
Beispiel #3
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());
        }
Beispiel #4
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();
                }
            }
        }
Beispiel #5
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);
        }
Beispiel #6
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();
        }
Beispiel #7
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();
        }
Beispiel #8
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());
        }
Beispiel #9
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);
        }
Beispiel #10
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();
        }
Beispiel #11
0
        private static void InternalConvertExceptionFilter(
            CodeTextWriter tw,
            IExtractContextHost extractContext,
            PreparedMethodInformation preparedMethod,
            ICodeStream codeStream)
        {
            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_unlikely__(il2c_isinst__(ex, il2c_typeof({0})))) return {1};",
                                catchHandler.CatchType.MangledUniqueName,
                                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("}");
                tw.SplitLine();
            }
        }