/// <summary> /// Inject a call to the coverage function with the id of a basic block /// before its first instruction. /// </summary> /// <param name="function">Function being instrumented.</param> /// <param name="coverageVisit"> /// Coverage function to call before each block. /// </param> /// <param name="block"> /// The id of the block to pass to the coverage function. /// </param> /// <param name="blockStartInstruction"> /// First instruction of the basic block. /// </param> private static void InjectCoverageCall(Phx.FunctionUnit function, Phx.Symbols.FunctionSymbol coverageVisit, uint block, Phx.IR.Instruction blockStartInstruction) { Phx.Types.Table typeTable = function.ParentUnit.TypeTable; if (function.FlowGraph == null) { function.BuildFlowGraph(); } // Create the instructions Phx.IR.Operand blockOperand = Phx.IR.ImmediateOperand.New(function, typeTable.UInt32Type, (uint)block); Phx.IR.Instruction loadBlock = Phx.IR.ValueInstruction.NewUnaryExpression(function, Phx.Targets.Architectures.Msil.Opcode.ldc, typeTable.UInt32Type, blockOperand); loadBlock.DestinationOperand.Register = Phx.Targets.Architectures.Msil.Register.SR0; Phx.IR.Instruction callCoverage = Phx.IR.CallInstruction.New(function, Phx.Targets.Architectures.Msil.Opcode.call, coverageVisit); // Insert the instructions blockStartInstruction.InsertBefore(loadBlock); callCoverage.AppendSource(loadBlock.DestinationOperand); loadBlock.DestinationOperand.BreakExpressionTemporary(); loadBlock.DebugTag = blockStartInstruction.DebugTag; blockStartInstruction.InsertBefore(callCoverage); }
/// <summary> /// Splits the BasicBlock in <paramref name="functionUnit"/> that contains a user-defined /// label with the name <paramref name="name"/>, and returns the new BasicBlock as a /// result of the split. /// </summary> /// /// <param name="functionUnit">Function unit that contains the label.</param> /// <param name="name">Name of the user-defined label to find.</param> /// <returns>New BasicBlock in <paramref name="functionUnit"/> /// that results from a split at the user-defined label with the name /// <paramref name="name"/>; null otherwise.</returns> /// <remarks>Precondition: There is only one user-defined label with /// the name <paramref name="name"/>.</remarks> public static Phx.Graphs.BasicBlock SplitAtUserLabel(Phx.FunctionUnit functionUnit, string name) { Phx.Graphs.FlowGraph flowGraph = functionUnit.FlowGraph; Phx.Graphs.BasicBlock result = null; foreach (Phx.IR.Instruction instruction in functionUnit.Instructions) { if (instruction.Opcode == Phx.Common.Opcode.UserLabel) { Phx.IR.Operand userLabelOperand = instruction.SourceOperand; string operandName = userLabelOperand.ToString(); /* Fix the label name, if needed. */ if (operandName.StartsWith("$")) { operandName = operandName.Substring(1); } if (operandName == name) { Phx.Graphs.BasicBlock block = instruction.BasicBlock; result = flowGraph.SplitBlock(block, instruction); break; } } } if (result == null) { Console.Out.WriteLine("PHOENIX: Cannot find user-defined label: " + name); Console.Out.WriteLine("Exiting GameTime."); Environment.Exit(1); } return(result); }