Пример #1
0
        /// <summary>
        /// Collects the storages that are live-out by looking at all known
        /// call sites and forming the union of all live storages at the call
        /// site.
        /// </summary>
        /// <param name="procCallee">Procedure that was called</param>
        /// <returns></returns>
        private Dictionary <Storage, BitRange> CollectLiveOutStorages(Procedure procCallee)
        {
            trace.Verbose("== Collecting live out storages of {0}", procCallee.Name);
            var liveOutStorages = new Dictionary <Storage, BitRange>();

            var sig = procCallee.Signature;

            if (sig.ParametersValid)
            {
                // Already have a signature, use that to define the
                // set of live storages.

                if (!sig.HasVoidReturn)
                {
                    liveOutStorages.Add(
                        sig.ReturnValue.Storage,
                        new BitRange(0, sig.ReturnValue.DataType.BitSize));
                }
            }
            else
            {
                var urf = new UsedRegisterFinder(dataFlow, new Procedure[0], eventListener);
                foreach (Statement stm in program.CallGraph.CallerStatements(procCallee))
                {
                    if (!(stm.Instruction is CallInstruction ci))
                    {
                        continue;
                    }
                    trace.Verbose("  {0}", ci);
                    var ssaCaller = this.procToSsa[stm.Block.Procedure];
                    foreach (var def in ci.Definitions)
                    {
                        if (!(def.Expression is Identifier id))
                        {
                            continue;
                        }
                        var sid = ssaCaller.Identifiers[id];
                        if (sid.Uses.Count > 0)
                        {
                            var br = urf.Classify(ssaCaller, sid, def.Storage, true);
                            trace.Verbose("  {0}: {1}", sid.Identifier.Name, br);
                            if (liveOutStorages.TryGetValue(def.Storage, out BitRange brOld))
                            {
                                br |= brOld;
                                liveOutStorages[def.Storage] = br;
                            }
                            else if (!br.IsEmpty)
                            {
                                liveOutStorages[def.Storage] = br;
                            }
                        }
                    }
                }
            }
            return(liveOutStorages);
        }
Пример #2
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)
        {
            this.sccProcs = procs.ToHashSet();
            flow.CreateFlowsFor(procs);

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

            this.ssts.AddRange(ssts);
            DumpWatchedProcedure("After extra stack vars", ssts);

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

            trf.Compute();

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

            foreach (var ssa in ssts.Select(sst => sst.SsaState))
            {
                RemoveImplicitRegistersFromHellNodes(ssa);
                var sac = new SegmentedAccessClassifier(ssa);
                sac.Classify();
                var prj = new ProjectionPropagator(ssa, sac);
                prj.Transform();
                DumpWatchedProcedure("After projection propagation", ssa.Procedure);
            }

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

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