/// <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>
        /// Inject code coverage information into a function.
        /// </summary>
        /// <param name="unit">The function to instrument.</param>
        protected override void Execute(Phx.Unit unit)
        {
            // Only instrument MSIL functions
            if (!unit.IsFunctionUnit)
            {
                return;
            }
            Phx.FunctionUnit function = unit.AsFunctionUnit;
            if (!function.Architecture.NameString.Equals("Msil"))
            {
                return;
            }

            Phx.PEModuleUnit           module         = function.ParentUnit.AsPEModuleUnit;
            Phx.Symbols.FunctionSymbol functionSymbol = function.FunctionSymbol;
            Phx.Types.FunctionType     functionType   = functionSymbol.FunctionType;

            // Create the method signature
            List <string> parameterTypes = new List <string>();

            foreach (Phx.Types.Parameter parameter in functionType.UserDefinedParameters)
            {
                parameterTypes.Add(parameter.Type.ToString());
            }
            string methodName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}({1})",
                functionSymbol.NameString,
                string.Join(", ", parameterTypes.ToArray()));

            // Build the control flow graph for the current function
            function.BuildFlowGraph();
            Phx.Graphs.FlowGraph flow = function.FlowGraph;

            // Log method details
            string typeName = (functionSymbol.EnclosingAggregateType != null) ?
                              functionSymbol.EnclosingAggregateType.TypeSymbol.NameString :
                              "<Module>";

            Log.StartMethod(
                methodName,
                typeName,
                flow.StartBlock.FirstInstruction.GetFileName(),
                flow.StartBlock.FirstInstruction.GetLineNumber());

            // Create a mapping of the disassembled from instructions to the
            // basic block IDs so we can use them for coverage viewing.
            Dictionary <Phx.IR.Instruction, uint> dissassembly = new Dictionary <Phx.IR.Instruction, uint>();

            // Instrument and log the blocks for the current function.
            Log.StartBlocks();
            foreach (Phx.Graphs.BasicBlock block in flow.BasicBlocks)
            {
                // Find the first real instruction in the block
                Phx.IR.Instruction first = null;
                foreach (Phx.IR.Instruction instruction in block.Instructions)
                {
                    // Save the instructions to be dumped later
                    dissassembly.Add(instruction, BlockCounter);

                    // Ignore instructions that aren't actually "real"
                    if (first == null && instruction.IsReal)
                    {
                        Phx.Common.Opcode opcode = instruction.Opcode as Phx.Common.Opcode;
                        if (opcode == Phx.Common.Opcode.ReturnFinally ||
                            opcode == Phx.Common.Opcode.Leave ||
                            opcode == Phx.Common.Opcode.Unreached ||
                            opcode == Phx.Common.Opcode.ExitTypeFilter)
                        {
                            continue;
                        }

                        first = instruction;
                    }
                }

                // Inject a code coverage visitor call before the first
                // instruction of the basic block
                if (first != null)
                {
                    // Log the basic block
                    Phx.IR.Instruction last = block.LastInstruction;
                    Log.StartBlock(
                        BlockCounter,
                        first.GetMsilOffset(),
                        first.GetFileName(),
                        first.GetLineNumber(),
                        first.GetColumnNumber(),
                        last.GetLineNumberEnd(),
                        last.GetColumnNumberEnd());

                    Phx.Symbols.FunctionSymbol coverageVisit = GetFunctionSymbol(module, CoverageVisitAssembly, CoverageVisitType, CoverageVisitMethod);
                    InjectCoverageCall(function, coverageVisit, BlockCounter, first);

#if LogBlockDissassembly
                    // Dump the disassembly for the current block
                    Log.StartBlockDisassembly();
                    foreach (Phx.IR.Instruction instruction in block.Instructions)
                    {
                        Log.WriteBlockDisassembly(
                            instruction.GetMsilOffset(),
                            instruction.ToString(),
                            BlockCounter);
                    }
                    Log.EndBlockDisassembly();
#endif

                    Log.EndBlock();
                }

                // Increment the number of basic blocks
                BlockCounter++;
            }

            function.DeleteFlowGraph();
            Log.EndBlocks();

            // Dump the disassembly for the current method
            Log.StartMethodDisassembly();
            foreach (KeyValuePair <Phx.IR.Instruction, uint> pair in dissassembly)
            {
                Log.WriteBlockDisassembly(
                    pair.Key.GetMsilOffset(),
                    pair.Key.ToString(),
                    pair.Value);
            }
            Log.EndMethodDisassembly();

            Log.EndMethod();
        }