/// <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); }
/// <summary> /// Given a set of clusters, finds all the entries for each cluster /// and tries to partition each cluster into procedures with single /// entries and exits. /// </summary> /// <param name="sr"></param> /// <param name="clusters"></param> private List <RtlProcedure> BuildProcedures(IList <Cluster> clusters) { var procs = new List <RtlProcedure>(); if (clusters.Count == 0) { return(procs); } listener.ShowProgress("Building procedures", 0, clusters.Count); foreach (var cluster in clusters) { if (listener.IsCanceled()) { break; } FuseLinearBlocks(cluster); // cluster.Dump(sr.ICFG); if (FindClusterEntries(cluster)) { procs.AddRange(PostProcessCluster(cluster)); } listener.Advance(1); } return(procs); }