/// <summary> /// New creates an instance of a pass. Following Phoenix guidelines, New is static. /// </summary> /// /// <param name="config">Pointer to a Passes::PassConfiguration that provides /// properties for retrieving the initial pass list.</param> /// <returns>A pointer to the new pass.</returns> static public GameTimePass New(Phx.Passes.PassConfiguration config) { GameTimePass pass = new GameTimePass(); Phx.Graphs.CallGraphProcessOrder order = Phx.Graphs.CallGraphProcessOrder.BottomUp; pass.Initialize(config, order, passName); /* Set its pass control. */ pass.PassControl = GameTimePass.gameTimeControl; /* Build the PhaseList with only 2 phases: C2::Phases::CxxILReaderPhase and Phase. * You can add more phases to the new pass here. */ Phx.Phases.PhaseConfiguration phaseConfiguration = Phx.Phases.PhaseConfiguration.New(pass.Configuration.Lifetime, "GameTime Phase"); Phx.Phases.PhaseList phaseList = C2.Phases.Builder.BuildPreCompilePhaseList(phaseConfiguration); phaseConfiguration.PhaseList.AppendPhase(phaseList); pass.PhaseConfigurationNative = phaseConfiguration; pass.PhaseConfiguration = phaseConfiguration; return(pass); }
/// <summary> /// Instrument the assembly. /// </summary> /// <returns>Termination mode of the processing.</returns> public static Phx.Term.Mode Process() { string currentAssembly = Application.Input.GetValue(null); // Create the log file with details about the basic blocks using (LogWriter log = new LogWriter(Path.ChangeExtension(currentAssembly, "Coverage.xml"))) { log.Start(); Phx.Output.WriteLine("Instrumenting code coverage for " + currentAssembly + " ..."); log.StartAssembly(currentAssembly); // Get the architecture and runtime from the existing assembly Phx.PEModuleUnit oldModule = Phx.PEModuleUnit.Open(currentAssembly); Phx.Targets.Architectures.Architecture architecture = oldModule.Architecture; Phx.Targets.Runtimes.Runtime runtime = oldModule.Runtime; #if VS2010 string clrVersion = oldModule.ClrVersionString; #endif oldModule.Close(); oldModule.Delete(); // Create an empty program to contain the instrumented code Phx.Lifetime lifetime = Phx.Lifetime.New(Phx.LifetimeKind.Global, null); Phx.ProgramUnit program = Phx.ProgramUnit.New( lifetime, null, Phx.GlobalData.TypeTable, architecture, runtime); Phx.PEModuleUnit module = Phx.PEModuleUnit.New( lifetime, Phx.Name.New(lifetime, Path.GetFullPath(currentAssembly)), program, Phx.GlobalData.TypeTable, architecture, runtime); // Set to metadata version 2 if none was copied #if VS2010 if (clrVersion == null) { clrVersion = PreferredClrVersion; module.ClrVersionString = clrVersion; } #endif // Dev10 Phoenix seems to require this fix #if VS2010 module.RaiseMsilOnly = true; #endif // Create the phase list: // 1. For each function // a. Raise the binary executable code to LIR // b. Instrument function with code coverage calls // c. Encode the instrumented code // 2. Emit the instrumented program as a binary Phx.Phases.PhaseConfiguration phases = Phx.Phases.PhaseConfiguration.New(lifetime, "CodeCoverage Phases"); phases.PhaseList.AppendPhase(Phx.PE.ReaderPhase.New(phases)); Phx.Phases.PhaseList functionPhases = Phx.PE.UnitListPhaseList.New(phases, Phx.PE.UnitListWalkOrder.PrePass); functionPhases.AppendPhase(Phx.PE.RaiseIRPhase.New(phases, Phx.FunctionUnit.LowLevelIRBeforeLayoutFunctionUnitState)); functionPhases.AppendPhase(InstrumentPhase.New(phases, log)); functionPhases.AppendPhase(EncodePhase.New(phases)); functionPhases.AppendPhase(Phx.PE.DiscardIRPhase.New(phases)); phases.PhaseList.AppendPhase(functionPhases); phases.PhaseList.AppendPhase(EmitPhase.New(phases)); Phx.GlobalData.BuildPlugInPhases(phases); // Run Phoenix using our phases phases.PhaseList.DoPhaseList(module); // Close the log file log.EndAssembly(); log.Close(); } return(Phx.Term.Mode.Normal); }