Esempio n. 1
0
        /// <summary>
        /// Rewrites the blocks in the given cdfg so that every assignment to a local or parameter is to a new local (and thus each local is just
        /// assigned to in exactly one place in the graph). The new names introduced by the writes are connected to the reads in successor blocks
        /// by means of join points (a.k.a. Phi nodes) that are found in the Reads property of an SSABasicBlock.
        /// </summary>
        /// <param name="cdfg">
        /// A set of basic blocks, each of which has a list of successor blocks and some other information.
        /// Each block consists of a list of instructions, each of which can point to previous instructions that compute the operands it consumes.
        /// </param>
        /// <param name="cfgQueries">
        /// Presents information derived from a simple control flow graph. For example, traversal orders, predecessors, dominators and dominance frontiers.
        /// </param>
        /// <param name="nameTable">
        /// An extensible collection of IName instances that represent names that are commonly used during compilation.
        /// </param>
        /// <param name="sourceLocationProvider"></param>
        public static void GetInSingleAssignmentForm(INameTable nameTable, ControlAndDataFlowGraph <BasicBlock, Instruction> cdfg,
                                                     ControlGraphQueries <BasicBlock, Instruction> cfgQueries, ISourceLocationProvider sourceLocationProvider)
        {
            Contract.Requires(nameTable != null);
            Contract.Requires(cdfg != null);
            Contract.Requires(cfgQueries != null);

            var singleAssigner = new SingleAssigner <BasicBlock, Instruction>(nameTable, cdfg, cfgQueries, sourceLocationProvider);

            singleAssigner.GetInSingleAssignmentForm();
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes an instance of SingleAssigner.
        /// </summary>
        /// <param name="cdfg">
        /// A set of basic blocks, each of which has a list of successor blocks and some other information.
        /// Each block consists of a list of instructions, each of which can point to previous instructions that compute the operands it consumes.
        /// </param>
        /// <param name="nameTable">
        /// An extensible collection of IName instances that represent names that are commonly used during compilation.
        /// </param>
        /// <param name="cfgQueries"></param>
        /// <param name="sourceLocationProvider">An object that can map some kinds of ILocation objects to IPrimarySourceLocation objects. May be null.</param>
        private SingleAssigner(INameTable nameTable, ControlAndDataFlowGraph <BasicBlock, Instruction> cdfg,
                               ControlGraphQueries <BasicBlock, Instruction> cfgQueries, ISourceLocationProvider sourceLocationProvider)
        {
            Contract.Requires(nameTable != null);
            Contract.Requires(cdfg != null);
            Contract.Requires(cfgQueries != null);

            this.nameTable              = nameTable;
            this.cdfg                   = cdfg;
            this.cfgQueries             = cfgQueries;
            this.sourceLocationProvider = sourceLocationProvider;
        }
Esempio n. 3
0
        private TypeInferencer(IMetadataHost host, ControlAndDataFlowGraph <BasicBlock, Instruction> cfg, Stack <Instruction> stack, Queue <BasicBlock> blocksToVisit, SetOfObjects blocksAlreadyVisited)
        {
            Contract.Requires(host != null);
            Contract.Requires(cfg != null);
            Contract.Requires(stack != null);
            Contract.Requires(blocksToVisit != null);
            Contract.Requires(blocksAlreadyVisited != null);

            this.platformType         = host.PlatformType;
            this.cfg                  = cfg;
            this.stack                = stack;
            this.blocksToVisit        = blocksToVisit;
            this.blocksAlreadyVisited = blocksAlreadyVisited;
            this.internFactory        = host.InternFactory;
        }
Esempio n. 4
0
        private DataFlowInferencer(IMetadataHost host, ControlAndDataFlowGraph <BasicBlock, Instruction> cdfg)
        {
            Contract.Requires(host != null);
            Contract.Requires(cdfg != null);

            var numberOfBlocks = cdfg.BlockFor.Count;

            this.platformType = host.PlatformType;
            this.cdfg         = cdfg;
            this.operandStackSetupInstructions = new List <Instruction>(cdfg.MethodBody.MaxStack);
            this.stack                = new Stack <Instruction>(cdfg.MethodBody.MaxStack);
            this.blocksToVisit        = new Queue <BasicBlock>((int)numberOfBlocks);
            this.blocksAlreadyVisited = new SetOfObjects(numberOfBlocks);;
            this.internFactory        = host.InternFactory;
        }
Esempio n. 5
0
        /// <summary>
        ///
        /// </summary>
        internal static void FillInTypes(IMetadataHost host, ControlAndDataFlowGraph <BasicBlock, Instruction> cfg)
        {
            Contract.Requires(host != null);
            Contract.Requires(cfg != null);

            //If this is a dummy body, do nothing.
            if (cfg.AllBlocks.Count == 1 && cfg.AllBlocks[0] != null && cfg.AllBlocks[0].Instructions.Count <= 1)
            {
                return;
            }

            var stack                = new Stack <Instruction>(cfg.MethodBody.MaxStack, new List <Instruction>(0));
            var numberOfBlocks       = cfg.BlockFor.Count;
            var blocksToVisit        = new Queue <BasicBlock>((int)numberOfBlocks);
            var blocksAlreadyVisited = new SetOfObjects(numberOfBlocks);
            var inferencer           = new TypeInferencer <BasicBlock, Instruction>(host, cfg, stack, blocksToVisit, blocksAlreadyVisited);

            foreach (var root in cfg.RootBlocks)
            {
                blocksToVisit.Enqueue(root);
                while (blocksToVisit.Count != 0)
                {
                    inferencer.DequeueBlockAndFillInItsTypes();
                }
            }
            //At this point, all reachable code blocks have had their types inferred. Now look for unreachable blocks.
            foreach (var block in cfg.AllBlocks)
            {
                if (blocksAlreadyVisited.Contains(block))
                {
                    continue;
                }
                blocksToVisit.Enqueue(block);
                while (blocksToVisit.Count != 0)
                {
                    inferencer.DequeueBlockAndFillInItsTypes();
                }
            }
        }
Esempio n. 6
0
        internal static void FillInHandlers(IMetadataHost host, ControlAndDataFlowGraph <BasicBlock, Instruction> cdfg)
        {
            var method = cdfg.MethodBody;

            var handlers = new List <IOperationExceptionInformation>(method.OperationExceptionInformation).ToArray();

            #region Compute enclosing handlers for each block
            FList <IOperationExceptionInformation> currentHandlers    = null;
            FList <IOperationExceptionInformation> containingHandlers = null;

            foreach (var current in cdfg.AllBlocks)
            {
                //traceFile.WriteLine("Block at: {0:x3}", current.Offset);
                currentHandlers = PopPushHandlers(current, currentHandlers, handlers, ref containingHandlers);
            }
            #endregion

            // now compute extra block information:
            //  - local def maps
            //  - parameter def maps

            ComputeDataFlowThroughLocals(cdfg);
        }
Esempio n. 7
0
        /// <summary>
        /// Presents information derived from a simple control flow graph. For example, traversal orders, predecessors, dominators and dominance frontiers.
        /// </summary>
        /// <param name="controlFlowGraph">The simple control flow graph from which to derive the information.</param>
        public ControlGraphQueries(ControlAndDataFlowGraph <BasicBlock, Instruction> controlFlowGraph)
        {
            Contract.Requires(controlFlowGraph != null);

            this.cfg = controlFlowGraph;
        }
Esempio n. 8
0
        private static void ComputeDataFlowThroughLocals(ControlAndDataFlowGraph <BasicBlock, Instruction> cdg)
        {
            FMap <ILocalDefinition, Microsoft.Cci.Analysis.Instruction> currentLocals;

            var todo       = new Queue <BlockPC>();
            var seen       = new HashSet <BlockPC>();
            var startBlock = cdg.RootBlocks[0];

            FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction> currentParameters = new FMap <IParameterDefinition, Microsoft.Cci.Analysis.Instruction>(k => k.Index);

            var initialLocation = GetStartLocation(startBlock);

            // push parameters onto start block
            foreach (var arg in cdg.MethodBody.MethodDefinition.Parameters)
            {
                var initialOp  = new InitialParameterAssignment(arg, initialLocation);
                var initialDef = new Instruction()
                {
                    Operation = initialOp
                };
                currentParameters = currentParameters.Insert(arg, initialDef);
            }
            startBlock.ParamDefs = currentParameters;
            todo.Enqueue(new BlockPC(startBlock.Offset.Singleton()));

            while (todo.Count > 0)
            {
                var currentPC = todo.Dequeue();
                if (seen.Contains(currentPC))
                {
                    continue;
                }
                seen.Add(currentPC);

                var block = cdg.CurrentBlock(currentPC);
                Contract.Assume(block != null);

                currentLocals     = block.LocalDefs;
                currentParameters = block.ParamDefs;

                foreach (var instr in block.Instructions)
                {
                    if (instr.IsMergeNode)
                    {
                        continue;
                    }
                    switch (instr.Operation.OperationCode)
                    {
                    case OperationCode.Starg:
                    case OperationCode.Starg_S:
                        // without pdb we seem to have no parameter info.
                        var pdef = (IParameterDefinition)instr.Operation.Value;
                        if (pdef != null)
                        {
                            currentParameters = currentParameters.Insert(pdef, instr.Operand1);
                        }
                        break;

                    case OperationCode.Stloc:
                    case OperationCode.Stloc_0:
                    case OperationCode.Stloc_1:
                    case OperationCode.Stloc_2:
                    case OperationCode.Stloc_3:
                    case OperationCode.Stloc_S:
                        var ldef = (ILocalDefinition)instr.Operation.Value;
                        currentLocals = currentLocals.Insert(ldef, instr.Operand1);
                        break;

                    case OperationCode.Ldloc:
                    case OperationCode.Ldloc_0:
                    case OperationCode.Ldloc_1:
                    case OperationCode.Ldloc_2:
                    case OperationCode.Ldloc_3:
                    case OperationCode.Ldloc_S:
                        // save the source in Aux
                    {
                        currentLocals.TryGetValue((ILocalDefinition)instr.Operation.Value, out instr.Aux);
                        break;
                    }

                    case OperationCode.Ldarg:
                    case OperationCode.Ldarg_0:
                    case OperationCode.Ldarg_1:
                    case OperationCode.Ldarg_2:
                    case OperationCode.Ldarg_3:
                    case OperationCode.Ldarg_S:
                        // save the source in Aux
                        var pdef2 = (IParameterDefinition)instr.Operation.Value;
                        if (pdef2 == null)
                        {
                            // this parameter. Assume it's never overwritten
                        }
                        else
                        {
                            currentParameters.TryGetValue(pdef2, out instr.Aux);
                        }
                        break;

                    case OperationCode.Stind_I:
                    case OperationCode.Stind_I1:
                    case OperationCode.Stind_I2:
                    case OperationCode.Stind_I4:
                    case OperationCode.Stind_I8:
                    case OperationCode.Stind_R4:
                    case OperationCode.Stind_R8:
                    case OperationCode.Stind_Ref:
                    {
                        var location = cdg.LocalOrParameter(instr.Operand1);
                        UpdateLocation(ref currentLocals, ref currentParameters, location, (Analysis.Instruction)instr.Operand2);

                        break;
                    }

                    case OperationCode.Ldind_I:
                    case OperationCode.Ldind_I1:
                    case OperationCode.Ldind_I2:
                    case OperationCode.Ldind_I4:
                    case OperationCode.Ldind_I8:
                    case OperationCode.Ldind_R4:
                    case OperationCode.Ldind_R8:
                    case OperationCode.Ldind_Ref:
                    case OperationCode.Ldind_U1:
                    case OperationCode.Ldind_U2:
                    case OperationCode.Ldind_U4:
                    {
                        // save the read value in Aux
                        var location = cdg.LocalOrParameter(instr.Operand1);
                        instr.Aux = ReadLocation(currentLocals, currentParameters, location);
                        break;
                    }

                    case OperationCode.Call:
                    case OperationCode.Callvirt:
                    {
                        // update byref / out parameters
                        var methodRef = instr.Operation.Value as IMethodReference;
                        var args      = instr.Operand2 as Instruction[];
                        if (args != null && methodRef != null)
                        {
                            foreach (var p in methodRef.Parameters)
                            {
                                if (p.IsByReference && p.Index < args.Length)
                                {
                                    var arg = args[p.Index];
                                    if (arg != null)
                                    {
                                        var loc         = cdg.LocalOrParameter(arg);
                                        var syntheticOp = new CallByRefAssignment(instr, p);
                                        UpdateLocation(ref currentLocals, ref currentParameters, loc, new Instruction()
                                            {
                                                Operation = syntheticOp, Type = p.Type
                                            });
                                    }
                                }
                            }
                        }
                        break;
                    }
                    }
                    instr.PostLocalDefs = currentLocals;
                    instr.PostParamDefs = currentParameters;
                }
                foreach (var succ in cdg.Successors(currentPC))
                {
                    MergeLocalsAndParameters(cdg.CurrentBlock(succ), currentLocals, currentParameters);
                    todo.Enqueue(succ);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        ///
        /// </summary>
        internal static void SetupDataFlow(IMetadataHost host, IMethodBody methodBody, ControlAndDataFlowGraph <BasicBlock, Instruction> cdfg)
        {
            Contract.Requires(host != null);
            Contract.Requires(methodBody != null);
            Contract.Requires(cdfg != null);

            var dataFlowInferencer = new DataFlowInferencer <BasicBlock, Instruction>(host, cdfg);

            dataFlowInferencer.SetupDataFlowFor(methodBody);
        }