Пример #1
0
        internal static void WriteConstStrings(
            CodeTextWriter twSource,
            TranslateContext translateContext)
        {
            IExtractContext extractContext = translateContext;

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

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

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

                twSource.SplitLine();
            }
        }
Пример #2
0
 public static void WriteHeader(
     CodeTextWriter twHeader,
     TranslateContext translateContext,
     PreparedInformations prepared)
 {
     InternalWriteHeader(
         twHeader, translateContext, prepared, true);
 }
Пример #3
0
 public void Dispose()
 {
     if (parent != null)
     {
         parent.UpdateIndent(shiftCount);
         parent     = null;
         shiftCount = 0;
     }
 }
Пример #4
0
 public static void WriteSourceCode(
     CodeTextWriter twSource,
     TranslateContext translateContext,
     PreparedInformations prepared,
     DebugInformationOptions debugInformationOption = DebugInformationOptions.Full)
 {
     InternalWriteSourceCode(
         twSource, translateContext, prepared, debugInformationOption, true);
 }
Пример #5
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();
            }
        }
Пример #6
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();
        }
Пример #7
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);
        }
Пример #8
0
 public Unshifter(CodeTextWriter parent, int shiftCount)
 {
     this.parent     = parent;
     this.shiftCount = shiftCount;
 }
Пример #9
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();
        }
Пример #10
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.");
        }