Example #1
0
        /// <summary>
        /// This callback is called from the SccFinder, which passes it a list
        /// of Procedures that form a SCC.
        /// </summary>
        /// <param name="procs"></param>
        private void UntangleProcedureScc(IList <Procedure> procs)
        {
            if (eventListener.IsCanceled())
            {
                return;
            }
            Debug.Print("== SCC: {0} ===", string.Join(",", procs));
            this.sccProcs = procs.ToHashSet();
            flow.CreateFlowsFor(procs);

            // Convert all procedures in the SCC to SSA form and perform
            // value propagation.
            DumpWatchedProcedure("scc", "Before SSA", procs);
            var ssts = procs.Select(ConvertToSsa).ToArray();

            this.ssts !.AddRange(ssts);
            DumpWatchedProcedure("esv", "After extra stack vars", ssts);
            if (eventListener.IsCanceled())
            {
                return;
            }

            // At this point, the computation of ProcedureFlow is possible.
            var trf = new TrashedRegisterFinder(program, flow, ssts, this.eventListener);

            trf.Compute();
            if (eventListener.IsCanceled())
            {
                return;
            }

            // New stack based variables may be available now.
            foreach (var sst in ssts)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                var vp = new ValuePropagator(program.SegmentMap, sst.SsaState, program.CallGraph, dynamicLinker, this.eventListener);
                vp.Transform();
                sst.RenameFrameAccesses = true;
                sst.Transform();
                DumpWatchedProcedure("esv2", "After extra stack vars 2", sst.SsaState.Procedure);
            }

            foreach (var sst in ssts)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                var ssa = sst.SsaState;
                RemoveImplicitRegistersFromHellNodes(ssa);
                var sac = new SegmentedAccessClassifier(ssa);
                sac.Classify();
                var prj = new ProjectionPropagator(ssa, sac);
                prj.Transform();
                DumpWatchedProcedure("prpr", "After projection propagation", ssa.Procedure);
                //var stfu = new StoreFuser(ssa);
                //DumpWatchedProcedure("stfu", "After store fusion", ssa.Procedure);
            }

            var uid = new UsedRegisterFinder(flow, procs, this.eventListener);

            foreach (var sst in ssts)
            {
                if (eventListener.IsCanceled())
                {
                    return;
                }
                var ssa = sst.SsaState;
                RemovePreservedUseInstructions(ssa);
                DeadCode.Eliminate(ssa);
                uid.ComputeLiveIn(ssa, true);
                var procFlow = flow[ssa.Procedure];
                RemoveDeadArgumentsFromCalls(ssa.Procedure, procFlow, ssts);
                DumpWatchedProcedure("dcar", "After dead call argument removal", ssa.Procedure);
            }
            eventListener.Advance(procs.Count);
        }