Beispiel #1
0
        internal static PreparedFunctions Prepare(
            TranslateContext translateContext,
            Func <MethodDefinition, bool> predict)
        {
            IPrepareContext prepareContext = translateContext;

            var allTypes = translateContext.Assembly.Modules
                           .SelectMany(module => module.Types)
                           .Where(type => type.IsValidDefinition())
                           .ToArray();
            var types = allTypes
                        .Where(type => !(type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly))
                        .ToArray();

            // Lookup type references.
            foreach (var type in types)
            {
                prepareContext.RegisterType(type);
            }

            // Lookup fields.
            foreach (var field in types.SelectMany(type => type.Fields))
            {
                prepareContext.RegisterType(field.FieldType);
            }

            // Construct result.
            return(new PreparedFunctions(allTypes
                                         .SelectMany(type => type.Methods)
                                         .Where(predict)
                                         .ToDictionary(
                                             method => method,
                                             method => PrepareMethod(prepareContext, method),
                                             CecilHelper.MemberReferenceComparer <MethodDefinition> .Instance)));
        }
Beispiel #2
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);
            }
        }
Beispiel #3
0
        internal static void WriteConstStrings(
            CodeTextWriter twSource,
            TranslateContext translateContext)
        {
            IExtractContext extractContext = translateContext;

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

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

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

                twSource.SplitLine();
            }
        }
Beispiel #4
0
        public static void CallStaticMethodTest()
        {
            var mainMethod = testType.GetMethod("CallTestMethod");

            var translateContext = new TranslateContext(testTypeAssembly.Location);
            var tw = new StringWriter();

            var prepared = AssemblyPreparer.Prepare(
                translateContext, method => method.MemberEquals(mainMethod));

            AssemblyWriter.InternalConvertFromMethod(tw, translateContext, prepared, mainMethod, "  ");

            var sourceCode = tw.ToString();

            var expected = new StringWriter();

            expected.WriteLine(@"int32_t IL2C_TestTargetClass_CallTestMethod(void)");
            expected.WriteLine(@"{");
            expected.WriteLine(@"  int32_t local0;");
            expected.WriteLine(@"");
            expected.WriteLine(@"  int32_t __stack0_int32_t;");
            expected.WriteLine(@"  int32_t __stack1_int32_t;");
            expected.WriteLine(@"");
            expected.WriteLine(@"  __stack0_int32_t = 1;");
            expected.WriteLine(@"  __stack1_int32_t = 2;");
            expected.WriteLine(@"  __stack0_int32_t = IL2C_TestTargetClass_CallStaticMethodTestType_Test(__stack0_int32_t, (int16_t)__stack1_int32_t);");
            expected.WriteLine(@"  local0 = __stack0_int32_t;");
            expected.WriteLine(@"  goto L_0000;");
            expected.WriteLine(@"L_0000:");
            expected.WriteLine(@"  __stack0_int32_t = local0;");
            expected.WriteLine(@"  return __stack0_int32_t;");
            expected.WriteLine(@"}");

            Assert.AreEqual(expected.ToString(), sourceCode);
        }
Beispiel #5
0
 public static void WriteHeader(
     CodeTextWriter twHeader,
     TranslateContext translateContext,
     PreparedInformations prepared)
 {
     InternalWriteHeader(
         twHeader, translateContext, prepared, true);
 }
Beispiel #6
0
 public static PreparedInformations Prepare(TranslateContext translateContext)
 {
     return(Prepare(
                translateContext,
                // All types
                type => true,
                // The methods except type initializer.
                method => !(method.IsConstructor && method.IsStatic)));
 }
Beispiel #7
0
 public static void WriteSourceCode(
     CodeTextWriter twSource,
     TranslateContext translateContext,
     PreparedInformations prepared,
     DebugInformationOptions debugInformationOption = DebugInformationOptions.Full)
 {
     InternalWriteSourceCode(
         twSource, translateContext, prepared, debugInformationOption, true);
 }
Beispiel #8
0
        internal static PreparedInformations Prepare(
            TranslateContext translateContext,
            Func <ITypeInformation, bool> predictType,
            Func <IMethodInformation, bool> predictMethod)
        {
            IPrepareContext prepareContext = translateContext;

            var allTypes = translateContext.Assembly.Modules.
                           SelectMany(module => module.Types.Concat(module.Types.SelectMany(type => type.NestedTypes))).
                           Where(predictType).
                           Distinct().
                           ToArray();

            // Lookup type references.
            foreach (var type in allTypes)
            {
                // Register used type.
                prepareContext.RegisterType(type, type.CLanguageMemberScope);

                if (type.BaseType != null)
                {
                    prepareContext.RegisterType(type.BaseType, type.CLanguageMemberScope);
                }

                foreach (var interfaceType in type.InterfaceTypes)
                {
                    prepareContext.RegisterType(type.BaseType, type.CLanguageMemberScope);
                }
            }

            // Lookup fields.
            foreach (var field in allTypes.SelectMany(type => type.Fields))
            {
                // Register field type.
                prepareContext.RegisterType(field.FieldType, field.CLanguageMemberScope);

                // Register include file from the native value.
                if (field.NativeValue != null)
                {
                    prepareContext.RegisterImportIncludeFile(field.NativeValue.IncludeFileName);
                }
            }

            // Construct result.
            return(new PreparedInformations(
                       allTypes,
                       (from type in allTypes
                        from method in type.DeclaredMethods
                        where predictMethod(method)
                        let preparedMethod = PrepareMethod(prepareContext, method)
                                             where preparedMethod != null
                                             select preparedMethod).
                       ToDictionary(
                           preparedMethod => preparedMethod.Method,
                           preparedMethod => preparedMethod)));
        }
Beispiel #9
0
        internal static void WriteDeclaredValues(
            CodeTextWriter twSource,
            TranslateContext translateContext)
        {
            IExtractContext extractContext = translateContext;

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

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

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

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

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

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

                twSource.SplitLine();
            }
        }
Beispiel #10
0
        public static void ConditionalBranchTest()
        {
            var mainMethod = testType.GetMethod("ConditionalBranchMainBody");

            var translateContext = new TranslateContext(testTypeAssembly.Location);
            var tw = new StringWriter();

            var prepared = AssemblyPreparer.Prepare(
                translateContext, method => method.MemberEquals(mainMethod));

            AssemblyWriter.InternalConvertFromMethod(tw, translateContext, prepared, mainMethod, "  ");

            var sourceCode = tw.ToString();

            var expected = new StringWriter();

            expected.WriteLine(@"int32_t IL2C_TestTargetClass_ConditionalBranchMainBody(int32_t a)");
            expected.WriteLine(@"{");
            expected.WriteLine(@"  bool local0;");
            expected.WriteLine(@"  int32_t local1;");
            expected.WriteLine();
            expected.WriteLine(@"  int32_t __stack0_int32_t;");
            expected.WriteLine(@"  int32_t __stack1_int32_t;");
            expected.WriteLine();
            expected.WriteLine(@"  __stack0_int32_t = a;");
            expected.WriteLine(@"  __stack1_int32_t = 0;");
            expected.WriteLine(@"  __stack0_int32_t = (__stack0_int32_t > __stack1_int32_t) ? 1 : 0;");
            expected.WriteLine(@"  local0 = __stack0_int32_t ? true : false;");
            expected.WriteLine(@"  __stack0_int32_t = local0 ? 1 : 0;");
            expected.WriteLine(@"  if (__stack0_int32_t == 0) goto L_0000;");
            expected.WriteLine(@"  __stack0_int32_t = a;");
            expected.WriteLine(@"  __stack1_int32_t = 1;");
            expected.WriteLine(@"  __stack0_int32_t = __stack0_int32_t + __stack1_int32_t;");
            expected.WriteLine(@"  local1 = __stack0_int32_t;");
            expected.WriteLine(@"  goto L_0001;");
            expected.WriteLine(@"L_0000:");
            expected.WriteLine(@"  __stack0_int32_t = a;");
            expected.WriteLine(@"  __stack1_int32_t = 2;");
            expected.WriteLine(@"  __stack0_int32_t = __stack0_int32_t + __stack1_int32_t;");
            expected.WriteLine(@"  local1 = __stack0_int32_t;");
            expected.WriteLine(@"  goto L_0001;");
            expected.WriteLine(@"L_0001:");
            expected.WriteLine(@"  __stack0_int32_t = local1;");
            expected.WriteLine(@"  return __stack0_int32_t;");
            expected.WriteLine(@"}");

            Assert.AreEqual(expected.ToString(), sourceCode);
        }
Beispiel #11
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());
        }
Beispiel #12
0
        public static void SimpleOverallByInt64SummationTest()
        {
            var mainMethod = testType.GetMethod("Int64MainBody");

            var translateContext = new TranslateContext(testTypeAssembly.Location);
            var tw = new StringWriter();

            var prepared = AssemblyPreparer.Prepare(
                translateContext, method => method.MemberEquals(mainMethod));

            AssemblyWriter.InternalConvertFromMethod(tw, translateContext, prepared, mainMethod, "  ");

            var sourceCode = tw.ToString();

            var expected = new StringWriter();

            expected.WriteLine(@"int64_t IL2C_TestTargetClass_Int64MainBody(void)");
            expected.WriteLine(@"{");
            expected.WriteLine(@"  int64_t local0;");
            expected.WriteLine(@"  int64_t local1;");
            expected.WriteLine(@"  int64_t local2;");
            expected.WriteLine(@"  int64_t local3;");
            expected.WriteLine();
            expected.WriteLine(@"  int32_t __stack0_int32_t;");
            expected.WriteLine(@"  int64_t __stack0_int64_t;");
            expected.WriteLine(@"  int64_t __stack1_int64_t;");
            expected.WriteLine();
            expected.WriteLine(@"  __stack0_int32_t = 1;");
            expected.WriteLine(@"  __stack0_int64_t = __stack0_int32_t;");
            expected.WriteLine(@"  local0 = __stack0_int64_t;");
            expected.WriteLine(@"  __stack0_int32_t = 2;");
            expected.WriteLine(@"  __stack0_int64_t = __stack0_int32_t;");
            expected.WriteLine(@"  local1 = __stack0_int64_t;");
            expected.WriteLine(@"  __stack0_int64_t = local0;");
            expected.WriteLine(@"  __stack1_int64_t = local1;");
            expected.WriteLine(@"  __stack0_int64_t = __stack0_int64_t + __stack1_int64_t;");
            expected.WriteLine(@"  local2 = __stack0_int64_t;");
            expected.WriteLine(@"  __stack0_int64_t = local2;");
            expected.WriteLine(@"  local3 = __stack0_int64_t;");
            expected.WriteLine(@"  goto L_0000;");
            expected.WriteLine(@"L_0000:");
            expected.WriteLine(@"  __stack0_int64_t = local3;");
            expected.WriteLine(@"  return __stack0_int64_t;");
            expected.WriteLine(@"}");

            Assert.AreEqual(expected.ToString(), sourceCode);
        }
Beispiel #13
0
        internal static void InternalWriteHeader(
            CodeTextWriter twHeader,
            TranslateContext translateContext,
            PreparedInformations prepared,
            bool includeAssemblyHeader)
        {
            IExtractContext extractContext = translateContext;

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

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

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

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

            twHeader.SplitLine();
            twHeader.WriteLine("#endif");
            twHeader.SplitLine();
        }
Beispiel #14
0
        public static void WriteHeader(
            TextWriter twHeader,
            TranslateContext translateContext,
            PreparedFunctions preparedFunctions,
            string indent)
        {
            IExtractContext extractContext = translateContext;

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

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

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

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

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

            twHeader.WriteLine();
            twHeader.WriteLine("#endif");
        }
Beispiel #15
0
        internal static PreparedInformations Prepare(
            TranslateContext translateContext,
            Func <ITypeInformation, bool> predictType,
            Func <IMethodInformation, bool> predictMethod)
        {
            IPrepareContext prepareContext = translateContext;

            var allTypes = translateContext.Assembly.Modules.
                           SelectMany(module => module.Types).
                           Where(predictType).
                           Distinct().
                           ToArray();

            // Lookup type references.
            foreach (var type in allTypes)
            {
                prepareContext.RegisterType(type);
            }

            // Lookup fields.
            foreach (var field in allTypes.SelectMany(type => type.Fields))
            {
                prepareContext.RegisterType(field.FieldType);
            }

            // Construct result.
            return(new PreparedInformations(
                       allTypes,
                       (from type in allTypes
                        from method in type.DeclaredMethods
                        where predictMethod(method)
                        let preparedMethod = PrepareMethod(prepareContext, method)
                                             where preparedMethod != null
                                             select preparedMethod).
                       ToDictionary(
                           preparedMethod => preparedMethod.Method,
                           preparedMethod => preparedMethod)));
        }
Beispiel #16
0
        public static void WriteHeader(
            CodeTextStorage storage,
            TranslateContext translateContext,
            PreparedInformations prepared)
        {
            var assemblyName = translateContext.Assembly.Name;

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

            using (var _ = storage.EnterScope(assemblyName, false))
            {
                // Write public headers.
                HeaderWriter.WriteHeaders(
                    storage,
                    translateContext,
                    prepared);
            }
        }
Beispiel #17
0
        public static void AccessValueTypeFieldTest()
        {
            Assert.Fail("TODO:");

            var mainMethod = testType.GetMethod("AccessValueTypeFieldMethod");

            var translateContext = new TranslateContext(testTypeAssembly.Location);
            var tw = new StringWriter();

            var targetType = typeof(TestTargetClass.AccessValueTypeFieldTestType);

            var prepared = AssemblyPreparer.Prepare(
                translateContext, method => method.MemberEquals(mainMethod));

            AssemblyWriter.InternalConvertFromMethod(tw, translateContext, prepared, mainMethod, "  ");

            var sourceCode = tw.ToString();

            var expected = new StringWriter();

            expected.WriteLine(@"");

            Assert.AreEqual(expected.ToString(), sourceCode);
        }
Beispiel #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);
                }
            }
        }
Beispiel #19
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 #20
0
        public static async Task ExecuteTestAsync(TestCaseInformation caseInfo)
        {
            Assert.IsTrue(caseInfo.Method.IsPublic && caseInfo.Method.IsStatic);

            // Split current thread context.
            await Task.Yield();

            ///////////////////////////////////////////////

            // Step 1-1: Create translation context.
            var translateContext = new TranslateContext(caseInfo.Method.DeclaringType.Assembly.Location, false);

            // Step 1-2: Prepare target methods.
            var targetTypes = new HashSet <string>(
                new[] { caseInfo.Method }.
                Concat(caseInfo.AdditionalMethods).
                Select(method => method.DeclaringType).
                Concat(caseInfo.AdditionalTypes).
                Select(type => type.FullName).
                Distinct());
            var targetMethods = new[] { caseInfo.Method }.
                Concat(caseInfo.AdditionalMethods).
            GroupBy(method => method.Name).
            ToDictionary(g => g.Key, g => g.ToArray());

            var prepared = AssemblyPreparer.Prepare(
                translateContext,
                t => targetTypes.Contains(t.FriendlyName),
                m => targetMethods.ContainsKey(m.Name));

            // Step 1-3: Extract prepared target type/caseInfo.Method informations.
            var targetType =
                translateContext.Assembly.Modules
                .First().Types
                .First(t => t.FriendlyName == caseInfo.Method.DeclaringType.FullName);
            var targetMethod =
                targetType.DeclaredMethods
                .First(m => m.Name == caseInfo.Method.Name);
            var targetAdditionalMethods =
                targetType.DeclaredMethods
                .Where(m => (caseInfo.AdditionalMethods.FirstOrDefault(am => m.Name == am.Name) != null))
                .ToArray();

            // Step 1-4: Translate caseInfo.Method bodies.
            var header = CodeTextWriter.Create(new StringWriter(), "    ");

            AssemblyWriter.InternalWriteHeader(
                header, translateContext, prepared, false);
            header.Flush();

            var body = CodeTextWriter.Create(new StringWriter(), "    ");

            AssemblyWriter.InternalWriteSourceCode(
                body, translateContext, prepared, DebugInformationOptions.Full, false);
            body.Flush();

            // Step 1-5: Write Visual C++ project file and Visual Studio Code launch config from template.
            //     Note: It's only debugging purpose. The test doesn't use.
            var translatedPath = Path.GetFullPath(
                Path.Combine(
                    Path.GetDirectoryName(caseInfo.Method.DeclaringType.Assembly.Location),
                    caseInfo.CategoryName,
                    caseInfo.Id,
                    caseInfo.Name));

            var vcxprojTemplatePath = Path.Combine(translatedPath, "test.vcxproj");
            await TestUtilities.CopyResourceToTextFileAsync(vcxprojTemplatePath, "test.vcxproj");

            var launchTemplatePath = Path.Combine(translatedPath, ".vscode", "launch.json");
            await TestUtilities.CopyResourceToTextFileAsync(launchTemplatePath, "launch.json");

            // Step 1-6: Write source code into a file from template.
            var expectedType = targetMethod.ReturnType;

            var sourceCodeStream = new MemoryStream();
            await TestUtilities.CopyResourceToStreamAsync(
                sourceCodeStream,
                // If the target caseInfo.Method result is void-type, we have to use void-type tolerant template.
                (expectedType.IsVoidType || (caseInfo.Assert == TestCaseAsserts.CauseBreak))? "test_void.c" : "test.c");

            sourceCodeStream.Position = 0;
            var sourceCode = new StreamReader(sourceCodeStream);

            var constants = caseInfo.Arguments.
                            Zip(targetMethod.Parameters, (arg, p) => new Constant(
                                    p.ParameterName,
                                    p.TargetType,
                                    arg?.GetType(),
                                    Utilities.GetCLanguageExpression(arg))
                                ).
                            ToArray();
            var argumentList = constants.
                               Select(constant => new Constant(
                                          "_" + constant.SymbolName,
                                          constant.TargetType,
                                          null,
                                          GetCLangaugeSafeConversionExpression(constant.TargetType, constant.ExpressionType, constant.SymbolName))).
                               ToArray();

            var arguments = argumentList;
            var locals    = argumentList.
                            Select(argument =>
                                   new Constant(
                                       argument.SymbolName,
                                       argument.TargetType,
                                       argument.ExpressionType,
                                       Utilities.GetCLanguageExpression(expectedType.InternalStaticEmptyValue))).
                            ToArray();

            if (!(expectedType.IsVoidType || (caseInfo.Assert == TestCaseAsserts.CauseBreak)))
            {
                // VERY DIRTY:
                constants = constants.Concat(new Constant[]
                {
                    new Constant(
                        "expected",
                        expectedType,
                        caseInfo.Expected?.GetType(),
                        Utilities.GetCLanguageExpression(caseInfo.Expected)),
                }).
                            ToArray();
                arguments = constants.
                            Select(constant => new Constant(
                                       "_" + constant.SymbolName,
                                       constant.TargetType,
                                       null,
                                       GetCLangaugeSafeConversionExpression(constant.TargetType, constant.ExpressionType, constant.SymbolName))).
                            ToArray();
                locals = arguments.
                         Select(argument =>
                                new Constant(
                                    argument.SymbolName,
                                    argument.TargetType,
                                    argument.ExpressionType,
                                    Utilities.GetCLanguageExpression(argument.TargetType.InternalStaticEmptyValue))).
                         Concat(new Constant[]
                {
                    new Constant(
                        "_actual",
                        expectedType,
                        caseInfo.Expected?.GetType(),
                        Utilities.GetCLanguageExpression(expectedType.InternalStaticEmptyValue)),
                }).
                         ToArray();
            }

            // Construct test definitions.
            var expectedSymbolName = locals.
                                     Any(entry => (entry.SymbolName == "_expected") && entry.TargetType.IsReferenceType) ?
                                     "frame__._expected" :
                                     "_expected";
            var actualSymbolName = locals.
                                   Any(entry => (entry.SymbolName == "_actual") && entry.TargetType.IsReferenceType) ?
                                   "frame__._actual" :
                                   "_actual";
            var replaceValues = new Dictionary <string, object>
            {
                { "testName", targetMethod.FriendlyName },
                { "type", targetMethod.ReturnType.CLanguageTypeName },
                { "body", body.Parent.ToString() },
                { "constants", string.Join(" ", constants.
                                           Select(entry => string.Format("{0} {1} = {2};",
                                                                         (entry.ExpressionType != null) ? Utilities.GetCLanguageTypeName(entry.ExpressionType) : entry.TargetType.CLanguageTypeName,
                                                                         entry.SymbolName,
                                                                         entry.Expression))) },
                { "locals", string.Join(" ", locals.
                                        Where(entry => !entry.TargetType.IsReferenceType).
                                        Select(entry => string.Format("{0} {1} = {2};",
                                                                      entry.TargetType.CLanguageTypeName,
                                                                      entry.SymbolName,
                                                                      entry.Expression))) },
                { "frames", string.Join(" ", locals.
                                        Where(entry => entry.TargetType.IsReferenceType).
                                        Select(entry => string.Format("{0} {1};",
                                                                      entry.TargetType.CLanguageTypeName,
                                                                      entry.SymbolName))) },
                { "frameCount", locals.
                  Where(entry => entry.TargetType.IsClass).Count() },
                { "arguments", string.Join(" ", arguments.
                                           Select(entry => string.Format("{0}{1} = {2};",
                                                                         entry.TargetType.IsReferenceType ? "frame__." : string.Empty,
                                                                         entry.SymbolName,
                                                                         entry.Expression))) },
                { "actual", actualSymbolName },
                { "function", targetMethod.CLanguageFunctionName },
                { "argumentList", string.Join(", ", argumentList.
                                              Select(arg => string.Format(
                                                         "{0}{1}",
                                                         arg.TargetType.IsReferenceType ? "frame__." : string.Empty,
                                                         arg.SymbolName))) },
                { "equality", GetCLanguageCompareExpression(expectedType, expectedSymbolName, actualSymbolName) },
                { "format", GetCLanguagePrintFormatFromType(targetMethod.ReturnType) },
                { "expectedExpression", GetCLanguagePrintArgumentExpression(expectedType, expectedSymbolName) },
                { "actualExpression", GetCLanguagePrintArgumentExpression(expectedType, actualSymbolName) },
            };

            var sourcePath = Path.Combine(translatedPath, "test.c");
            var headerPath = Path.Combine(translatedPath, "test.h");

            await Task.WhenAll(
                TestUtilities.WriteTextFileAsync(sourcePath, sourceCode, replaceValues),
                TestUtilities.WriteTextFileAsync(headerPath, header.Parent.ToString()));

            ///////////////////////////////////////////////
            // Step 2: Test and verify result by real IL code at this runtime.

            object rawResult;

            switch (caseInfo.Assert)
            {
            case TestCaseAsserts.IgnoreValidateInvokeResult:
                try
                {
                    rawResult = caseInfo.Method.Invoke(null, caseInfo.Arguments);
                }
                catch
                {
                    // ignore.
                    rawResult = null;
                }
                break;

            case TestCaseAsserts.CauseBreak:
                rawResult = null;
                break;

            default:
                rawResult = caseInfo.Method.Invoke(null, caseInfo.Arguments);
                Assert.AreEqual(caseInfo.Expected, rawResult);
                break;
            }

            ///////////////////////////////////////////////
            // Step 3: Test compiled C source code and execute.

            string sanitized = null;

            try
            {
                var il2cRuntimeSourcePaths = new[] {
                    // Use combined runtime source. 5 times faster!
                    Path.Combine(il2cRuntimePath, "il2c_combined.c")
                };

#if DEBUG
                var executedResult = await GccDriver.CompileAndRunAsync(false, sourcePath, il2cRuntimePath);
#else
                var executedResult = await GccDriver.CompileAndRunAsync(true, sourcePath, il2cRuntimePath);
#endif

                sanitized = executedResult.Trim(' ', '\r', '\n');
            }
            catch (Exception ex)
            {
                if ((caseInfo.Assert == TestCaseAsserts.CauseBreak) && ex.Message.Contains("ExitCode=-2147483645"))
                {
                    return;
                }
                throw;
            }

            Assert.IsFalse(caseInfo.Assert == TestCaseAsserts.CauseBreak, "Code didn't break.");

            ///////////////////////////////////////////////
            // Step 4: Verify result.

            Assert.AreEqual("Success", sanitized);
        }
Beispiel #21
0
        public static async Task ExecuteTestAsync(TestCaseInformation caseInfo)
        {
            Assert.IsTrue(caseInfo.Method.IsPublic && caseInfo.Method.IsStatic);

            // Split current thread context.
            await Task.Delay(1);

#if DEBUG
            const string configuration = "Debug";
#else
            const string configuration = "Release";
#endif

            ///////////////////////////////////////////////

            // Step 1-1: Create translation context.
            var translateContext = new TranslateContext(
                caseInfo.Method.DeclaringType.Assembly.Location,
                true,
                TargetPlatforms.Generic);

            // Step 1-2: Prepare target methods.
            var targetTypes = new HashSet <string>(
                new[] { caseInfo.Method }.
                Concat(caseInfo.AdditionalMethods).
                Select(method => method.DeclaringType).
                Concat(caseInfo.AdditionalTypes).
                Select(type => type.FullName).
                Distinct());
            var targetMethods = new[] { caseInfo.Method }.
                Concat(caseInfo.AdditionalMethods).
            GroupBy(method => method.Name).
            ToDictionary(g => g.Key, g => g.ToArray());

            var prepared = AssemblyPreparer.Prepare(
                translateContext,
                t => targetTypes.Contains(t.FriendlyName),
                m => targetMethods.ContainsKey(m.Name));

            // Step 1-3: Extract prepared target type/caseInfo.Method informations.
            var targetType =
                translateContext.Assembly.Modules
                .First().Types
                .First(t => t.FriendlyName == caseInfo.Method.DeclaringType.FullName);
            var targetMethod =
                targetType.DeclaredMethods
                .First(m => m.Name == caseInfo.Method.Name);
            var targetAdditionalMethods =
                targetType.DeclaredMethods
                .Where(m => (caseInfo.AdditionalMethods.FirstOrDefault(am => m.Name == am.Name) != null))
                .ToArray();

            // Step 1-4: Create storing director for test artifacts
            //   HACK: It's reliability for Windows MAX_PATH limitation.
            var basePath =
                Path.GetFullPath(
                    Path.Combine(
                        Path.GetDirectoryName(caseInfo.Method.DeclaringType.Assembly.Location),
                        "..", "..", "..", "..", "..",
                        "test-artifacts", configuration));
            while (true)
            {
                try
                {
                    if (!Directory.Exists(basePath))
                    {
                        Directory.CreateDirectory(basePath);
                    }
                    break;
                }
                catch
                {
                }
            }

            // Step 1-4: Translate caseInfo.Method bodies.
            var translatedPath =
                Path.Combine(
                    basePath,
                    caseInfo.CategoryName,
                    caseInfo.Id,
                    caseInfo.UniqueName);

            var logw    = new StringWriter();
            var storage = new CodeTextStorage(logw, translatedPath, false, "    ");

            AssemblyWriter.WriteHeader(
                storage,
                translateContext,
                prepared);
            var sourceFiles = AssemblyWriter.WriteSourceCode(
                storage,
                translateContext,
                prepared,
                true,
                DebugInformationOptions.CommentOnly);

            // Step 1-5: Write source code into a file from template.
            var expectedType = targetMethod.ReturnType;

            var sourceCodeStream = new MemoryStream();
            await TestUtilities.CopyResourceToStreamAsync(
                sourceCodeStream,
                // If the target caseInfo.Method result is void-type, we have to use void-type tolerant template.
                (expectedType.IsVoidType || (caseInfo.Assert == TestCaseAsserts.CauseBreak))? "test_void.c" : "test.c");

            sourceCodeStream.Position = 0;
            var sourceCode = new StreamReader(sourceCodeStream);

            var constants = caseInfo.Arguments.
                            Zip(targetMethod.Parameters, (arg, p) => new Constant(
                                    p.ParameterName,
                                    p.TargetType,
                                    arg?.GetType(),
                                    Utilities.GetCLanguageExpression(arg))
                                ).
                            ToArray();
            var argumentList = constants.
                               Select(constant => new Constant(
                                          "_" + constant.SymbolName,
                                          constant.TargetType,
                                          null,
                                          GetCLangaugeSafeConversionExpression(constant.TargetType, constant.ExpressionType, constant.SymbolName))).
                               ToArray();

            var arguments = argumentList;
            var locals    = argumentList.
                            Select(argument =>
                                   new Constant(
                                       argument.SymbolName,
                                       argument.TargetType,
                                       argument.ExpressionType,
                                       Utilities.GetCLanguageExpression(expectedType.InternalStaticEmptyValue))).
                            ToArray();

            if (!(expectedType.IsVoidType || (caseInfo.Assert == TestCaseAsserts.CauseBreak)))
            {
                // VERY DIRTY:
                constants = constants.Concat(new Constant[]
                {
                    new Constant(
                        "expected",
                        expectedType,
                        caseInfo.Expected?.GetType(),
                        Utilities.GetCLanguageExpression(caseInfo.Expected)),
                }).
                            ToArray();
                arguments = constants.
                            Select(constant => new Constant(
                                       "_" + constant.SymbolName,
                                       constant.TargetType,
                                       null,
                                       GetCLangaugeSafeConversionExpression(constant.TargetType, constant.ExpressionType, constant.SymbolName))).
                            ToArray();
                locals = arguments.
                         Select(argument =>
                                new Constant(
                                    argument.SymbolName,
                                    argument.TargetType,
                                    argument.ExpressionType,
                                    Utilities.GetCLanguageExpression(argument.TargetType.InternalStaticEmptyValue))).
                         Concat(new Constant[]
                {
                    new Constant(
                        "_actual",
                        expectedType,
                        caseInfo.Expected?.GetType(),
                        Utilities.GetCLanguageExpression(expectedType.InternalStaticEmptyValue)),
                }).
                         ToArray();
            }

            // Construct test definitions.
            var expectedSymbolName = locals.
                                     Any(entry => (entry.SymbolName == "_expected") && entry.TargetType.IsReferenceType) ?
                                     "frame__._expected" :
                                     "_expected";
            var actualSymbolName = locals.
                                   Any(entry => (entry.SymbolName == "_actual") && entry.TargetType.IsReferenceType) ?
                                   "frame__._actual" :
                                   "_actual";
            var replaceValues = new Dictionary <string, object>
            {
                { "assemblyName", targetMethod.DeclaringType.DeclaringModule.DeclaringAssembly.Name },
                { "testName", targetMethod.FriendlyName },
                { "type", targetMethod.ReturnType.CLanguageTypeName },
                { "constants", string.Join(" ", constants.
                                           Select(entry => string.Format("{0} {1} = {2};",
                                                                         (entry.ExpressionType != null) ? Utilities.GetCLanguageTypeName(entry.ExpressionType) : entry.TargetType.CLanguageTypeName,
                                                                         entry.SymbolName,
                                                                         entry.Expression))) },
                { "locals", string.Join(" ", locals.
                                        Where(entry => !entry.TargetType.IsReferenceType).
                                        Select(entry => string.Format("{0} {1} = {2};",
                                                                      entry.TargetType.CLanguageTypeName,
                                                                      entry.SymbolName,
                                                                      entry.Expression))) },
                { "frames", string.Join(" ", locals.
                                        Where(entry => entry.TargetType.IsReferenceType).
                                        Select(entry => string.Format("{0} {1};",
                                                                      entry.TargetType.CLanguageTypeName,
                                                                      entry.SymbolName))) },
                { "frameCount", locals.
                  Where(entry => entry.TargetType.IsClass).Count() },
                { "arguments", string.Join(" ", arguments.
                                           Select(entry => string.Format("{0}{1} = {2};",
                                                                         entry.TargetType.IsReferenceType ? "frame__." : string.Empty,
                                                                         entry.SymbolName,
                                                                         entry.Expression))) },
                { "actual", actualSymbolName },
                { "function", targetMethod.CLanguageFunctionFullName },
                { "argumentList", string.Join(", ", argumentList.
                                              Select(arg => string.Format(
                                                         "{0}{1}",
                                                         arg.TargetType.IsReferenceType ? "frame__." : string.Empty,
                                                         arg.SymbolName))) },
                { "equality", GetCLanguageCompareExpression(expectedType, expectedSymbolName, actualSymbolName) },
                { "format", GetCLanguagePrintFormatFromType(targetMethod.ReturnType) },
                { "expectedExpression", GetCLanguagePrintArgumentExpression(expectedType, expectedSymbolName) },
                { "actualExpression", GetCLanguagePrintArgumentExpression(expectedType, actualSymbolName) },
                { "sourcePath", translateContext.Assembly.Name + "_bundle.c" }
            };

            // Step 1-6: Write Visual C++ project file and Visual Studio Code launch config from template.
            //     Note: It's only debugging purpose. The test doesn't use.
            var vcxprojTemplatePath = Path.Combine(translatedPath, "test.vcxproj");
            await TestUtilities.CopyResourceToTextFileAsync(vcxprojTemplatePath, "test.vcxproj", replaceValues);

            TestContext.AddTestAttachment(vcxprojTemplatePath, "Generated VC++ project");

            var launchTemplatePath = Path.Combine(translatedPath, ".vscode", "launch.json");
            await TestUtilities.CopyResourceToTextFileAsync(launchTemplatePath, "launch.json", replaceValues);

            var sourcePath = Path.Combine(translatedPath, "test.c");
            await TestUtilities.WriteTextFileAsync(sourcePath, sourceCode, replaceValues);

            ///////////////////////////////////////////////
            // Step 2: Test and verify result by real IL code at this runtime.

            object rawResult;
            switch (caseInfo.Assert)
            {
            case TestCaseAsserts.IgnoreValidateInvokeResult:
                break;

            case TestCaseAsserts.CauseBreak:
                rawResult = null;
                break;

            default:
                CultureInfo.CurrentCulture   = CultureInfo.InvariantCulture;
                CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
                rawResult = caseInfo.Method.Invoke(null, caseInfo.Arguments);
                Assert.AreEqual(caseInfo.Expected, rawResult);
                break;
            }

            ///////////////////////////////////////////////
            // Step 3: Test compiled C source code and execute.

            string sanitized = null;
            try
            {
                var executedResult = await CMakeDriver.BuildDirectlyAsync(
                    binPath,
                    configuration,
                    sourcePath,
                    il2cRuntimePath);

                sanitized = executedResult.Trim(' ', '\r', '\n');
            }
            catch (Exception ex)
            {
                if ((caseInfo.Assert == TestCaseAsserts.CauseBreak) && ex.Message.Contains("ExitCode=-2147483645"))
                {
                    return;
                }
                throw;
            }

            Assert.IsFalse(caseInfo.Assert == TestCaseAsserts.CauseBreak, "Code didn't break.");

            ///////////////////////////////////////////////
            // Step 4: Verify result.

            Assert.AreEqual("Success", sanitized);
        }
Beispiel #22
0
 public static PreparedFunctions Prepare(TranslateContext translateContext)
 {
     return(Prepare(
                translateContext,
                method => !method.IsConstructor || !method.IsStatic));
 }
Beispiel #23
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.");
        }