Пример #1
0
        public static IList <TreeStatement> BuildAST(this Subprogram src)
        {
            IList <BasicBlock> bblist = src.GetBasicBlocks();
            Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred = bblist.Select(bb =>
                                                                                    new KeyValuePair <BasicBlock, IEnumerable <BasicBlock> >(bb,
                                                                                                                                             bblist.Where(bbel => bbel.Successor == bb || bbel.Target == bb))).
                                                                      ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            // Determine dominators.

            Dictionary <BasicBlock, List <BasicBlock> > dom = bblist.Select(bb =>
                                                                            new KeyValuePair <BasicBlock, List <BasicBlock> >(bb,
                                                                                                                              bb == src.CFGRoot ? new List <BasicBlock> {
                src.CFGRoot
            } : bblist.ToList())).
                                                              ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            bool changes = true;

            while (changes)
            {
                changes = false;
                foreach (BasicBlock n in bblist)
                {
                    if (n != src.CFGRoot)
                    {
                        IEnumerable <BasicBlock> doms = null;
                        foreach (BasicBlock p in pred[n])
                        {
                            doms = (doms == null) ? dom[p] : doms.Intersect(dom[p]);
                        }
                        doms = doms.Union(new [] { n });

                        if (!doms.SequenceEqual(dom[n]))
                        {
                            changes = true;
                            dom[n]  = new List <BasicBlock>(doms);
                        }
                    }
                }
            }

            // Perform depth-first enumeration.

            Dictionary <BasicBlock, int> dfn = bblist.Select(bb =>
                                                             new KeyValuePair <BasicBlock, int>(bb, 0)).
                                               ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            int c = bblist.Count;

            NumDepth(src.CFGRoot, dfn, ref c, new List <BasicBlock>());

            // Test CFG reducibility: each retreating edge must be back edge.

            foreach (BasicBlock sbb in bblist)
            {
                foreach (BasicBlock tbb in new [] { sbb.Successor, sbb.Target })
                {
                    if (tbb != null && dfn[tbb] < dfn[sbb] && !dom[sbb].Contains(tbb))
                    {
                        throw new IrreducibleCFGException("There is non-back retreating edge");
                    }
                }
            }

            if (bblist.Where(bb => bb.Trailer.OpCode == IROpCodes.RET).Count() != 1)
            {
                throw new IrreducibleCFGException("Control flow graph must have single node with RET ending");
            }

            List <TreeStatement> code        = new List <TreeStatement>();
            BasicBlock           cur         = src.CFGRoot;
            GraphPathFinder      path_finder = new GraphPathFinder(bblist);

            while (cur != null)
            {
                cur = HandleStatement(cur, null, bblist, pred, dom, path_finder, code);
            }
            return(code.AsReadOnly());
        }