Example #1
0
        /// <summary>
        /// Builds flowgraph. Prepares list of basic blocks to translate.
        /// </summary>
        public static ControlFlowGraph Build(IClrMethodBody body)
        {
#if DEBUG
            DebugHooks.LogInfo("CFG Builder started");
#endif

            var graph = body.ControlFlowGraph;
            if (graph != null)
            {
#if DEBUG
                body.VisualizeGraph(graph.Entry, false);
#endif
                return(graph);
            }

            var builder = new GraphBuilder(body, false)
            {
                IsVoidCallEnd = true
            };
            var entry = builder.Build();
            if (entry == null)
            {
                throw new ILTranslatorException("Unable to build flowgraph");
            }

#if DEBUG
            body.VisualizeGraph(entry, false);
#endif

            //Prepares list of basic blocks in the same order as they are located in code.
            var  blocks   = new NodeList();
            Node prevNode = null;
            foreach (var instruction in body.Code)
            {
                var bb = instruction.BasicBlock;
                //if (bb == null)
                //    throw new InvalidOperationException();
                if (bb == null)
                {
                    continue;
                }
                if (prevNode == bb)
                {
                    continue;
                }
                blocks.Add(bb);
                prevNode = bb;
            }

            graph = new ControlFlowGraph {
                Entry = entry, Blocks = blocks
            };

            body.ControlFlowGraph = graph;

            return(graph);
        }
Example #2
0
        /// <summary>
        /// Concatenates code of all basic blocks in order of basic blocks layout.
        /// Prepares output code (instruction list).
        /// </summary>
        public static TranslatorResult Emit(TranslationContext context, string debugFile)
        {
#if DEBUG
            DebugHooks.LogInfo("ConcatBlocks started");
#endif

            var begin = Begin(context, debugFile);

            var provider = context.Provider;
            var branches = new List <Branch>();
            var output   = context.Code.New();

            output.Emit(begin);

            foreach (var bb in context.Body.ControlFlowGraph.Blocks)
            {
                //UNCOMMENT TO CHECK STACK BALANCE
                //Checks.CheckStackBalance(bb);

                bb.TranslatedEntryIndex = output.Count;

                var il = bb.TranslatedCode;

                var last = il[il.Count - 1];
                if (last.IsBranchOrSwitch())
                {
                    branches.Add(new Branch(last, bb));
                }

                TranslatorExtensions.FixSelfCycle(context.New(bb));

                output.Emit(il);

                bb.TranslatedExitIndex = output.Count - 1;
            }

            var end = (provider.End() ?? Enumerable.Empty <IInstruction>()).ToArray();
            output.Emit(end);

#if DEBUG
            DebugHooks.LogInfo("ConcatBlocks succeeded. CodeSize = {0}", output.Count);
#endif
            return(new TranslatorResult
            {
                Begin = begin,
                End = end,
                Output = output,
                Branches = branches
            });
        }
Example #3
0
        /// <summary>
        /// Resolves branch instructions.
        /// </summary>
        public static void Resolve(IList <Branch> branches, ICodeProvider provider)
        {
#if DEBUG
            DebugHooks.LogInfo("ResolveBranches started");
#endif
            for (int i = 0; i < branches.Count; ++i)
            {
                var br = branches[i].Source;
                var bb = branches[i].TargetBlock;
                if (br.IsSwitch)
                {
                    var e         = bb.FirstOut;
                    int deftarget = e.To.TranslatedEntryIndex;
                    var targets   = new List <int>();
                    for (e = e.NextOut; e != null; e = e.NextOut)
                    {
                        targets.Add(e.To.TranslatedEntryIndex);
                    }
                    provider.SetCaseTargets(br, targets.ToArray(), deftarget);
                }
                else if (br.IsConditionalBranch)
                {
                    var e = bb.TrueEdge;
                    provider.SetBranchTarget(br, e.To.TranslatedEntryIndex);
                }
                else                 //unconditional branch
                {
#if DEBUG
                    if (!br.IsUnconditionalBranch)                     //sanity check
                    {
                        throw new ILTranslatorException("Invalid branch instruction");
                    }
#endif

                    var e = bb.FirstOut;
                    if (e.To != bb)                     //avoid cycle!
                    {
                        provider.SetBranchTarget(br, e.To.TranslatedEntryIndex);
                    }
                    else
                    {
                        provider.SetBranchTarget(br, bb.TranslatedExitIndex - 1);
                    }
                }
            }
#if DEBUG
            DebugHooks.LogInfo("ResolveBranches succeeded");
#endif
        }
Example #4
0
        private static void Analyze(Context context)
        {
#if DEBUG
            DebugHooks.LogInfo("Flowgraph analysis started");
#endif
            foreach (var bb in context.Body.ControlFlowGraph.Blocks)
            {
                AnalyzeBlock(bb, context);
            }

            foreach (var bb in context.Body.ControlFlowGraph.Blocks)
            {
                bb.Stack = null;
            }

#if DEBUG
            DebugHooks.LogInfo("Flowgraph analysis succeeded");
#endif
        }
Example #5
0
        public static void Write(IEnumerable <Node> graph, string path, bool subgraph, bool translatedCode)
        {
            if (NameService == null)
            {
                NameService = new NameService();
            }
            NameService.SetNames(graph);

            DebugHooks.LogInfo("WriteDotFile started");
            WriteDotFile(graph, path, translatedCode);
            DebugHooks.LogInfo("WriteDotFile succeeded");

            DebugHooks.LogInfo("dot.exe started");
            int start = Environment.TickCount;

            Dot.Render(path, null);
            int end = Environment.TickCount;

            DebugHooks.LogInfo("dot.exe succeeded. ellapsed time: {0}", (end - start) + "ms");
        }
Example #6
0
        internal static void VisualizeGraph(this IClrMethodBody body, NodeList list, bool translatedCode)
        {
            DebugHooks.LogInfo("Flow graph constructed");

            DotService.NameService = null;

            bool filter = DebugHooks.EvalFilter(body.Method);
            var  after  = translatedCode;
            var  before = !translatedCode;

            if (filter || (before && DebugHooks.VisualizeGraphBefore) || (after && DebugHooks.VisualizeGraphAfter))
            {
                DotService.Write(list, DotService.MakePath(body, before ? "before" : "after"), true, translatedCode);
            }

            if (filter || DebugHooks.DumpILCode)
            {
                DumpService.Dump(list, body, CommonLanguageInfrastructure.TestCaseDirectory);
                DebugHooks.LogInfo("IL code dumped");
            }
        }
Example #7
0
        private TranslatorResult TranslateCore(TranslationContext context)
        {
            if (context.Method.DeclaringType.IsGeneric())
            {
                throw new ILTranslatorException("Not supported");
            }

#if DEBUG
            DebugHooks.LogSeparator();
            DebugHooks.LogInfo("ILTranslator started for method: {0}", context.Method);
            if (DebugHooks.CanBreak(context.Method))
            {
                Debugger.Break();
            }
#endif

            try
            {
                var output = Process(context);
#if DEBUG
                DebugHooks.LogInfo("ILTranslator succeeded for method: {0}", context.Method);
                DebugHooks.LogSeparator();
#endif
                return(output);
            }
            catch (Exception e)
            {
#if DEBUG
                DebugHooks.SetLastError(context.Method);
#endif
                if (e is CompilerException)
                {
                    throw;
                }
                throw Errors.CILTranslator.UnableToTranslateMethod.CreateInnerException(e, context.FullMethodName);
            }
        }
Example #8
0
        /// <summary>
        /// Translates all basic blocks in flow graph.
        /// </summary>
        public void Translate(TranslationContext context)
        {
#if DEBUG
            DebugHooks.LogInfo("TranslateBlocks started for method: {0}", context.Method);
#endif

            //Note: CIL pops exception from stack for us if it is not used
            context.Provider.PopException = false;
            context.Provider.BeforeTranslation();

            foreach (var bb in context.Body.ControlFlowGraph.Blocks)
            {
#if DEBUG
                //if (DebugHooks.CanBreak(_method)) Debugger.Break();
#endif
                TranslateBlock(context.New(bb));
            }

            context.Provider.AfterTranslation();

#if DEBUG
            DebugHooks.LogInfo("TranslateBlocks succeeded for method: {0}", context.Method);
#endif
        }
Example #9
0
        public static void Dump(IClrMethodBody body, TranslatorResult result, string format, string filename)
        {
            if (!(DebugHooks.EvalFilter(body.Method) || DebugHooks.DumpILMap))
            {
                return;
            }

            DebugHooks.LogInfo("DumpILMap started. Format = {0}. FileName = {1}.", format, filename);

            string dir = body.GetTestDirectory();

            Directory.CreateDirectory(dir);
            using (var writer = new StreamWriter(Path.Combine(dir, filename)))
            {
                DumpService.DumpLocalVariables(writer, body);
                writer.WriteLine(Separator);

                if (result.Begin != null && result.Begin.Length > 0)
                {
                    writer.WriteLine("#BEGIN CODE");
                    writer.WriteLine(Separator);
                    for (int i = 0; i < result.Begin.Length; ++i)
                    {
                        writer.WriteLine(result.Output[i].ToString(format, null));
                    }
                    writer.WriteLine(Separator);
                }

                foreach (var bb in body.ControlFlowGraph.Blocks)
                {
                    writer.WriteLine("#BASIC BLOCK {0}", bb.Index);
                    DumpStackState(writer, bb);
                    writer.WriteLine(Separator);

                    writer.WriteLine("#ORIGINAL CODE");
                    foreach (var instruction in bb.Code)
                    {
                        writer.WriteLine(instruction.ToString(format, null));
                    }
                    writer.WriteLine();

                    var code = bb.TranslatedCode;
                    writer.WriteLine("#TRANSLATED CODE");
                    foreach (var instruction in code)
                    {
                        writer.WriteLine(instruction.ToString(format, null));
                    }
                    writer.WriteLine(Separator);
                }

                if (result.End != null && result.End.Length > 0)
                {
                    writer.WriteLine("#END CODE");
                    writer.WriteLine(Separator);
                    foreach (var instruction in result.End)
                    {
                        writer.WriteLine(instruction.ToString(format, null));
                    }
                }
            }

            DebugHooks.LogInfo("DumpILMap succeded");
        }