/// <summary> /// Constructs a control and data flow graph for the given method body. /// </summary> public static ControlAndDataFlowGraph <BasicBlock, Instruction> GetControlAndDataFlowGraphFor(IMetadataHost host, IMethodBody methodBody, ILocalScopeProvider /*?*/ localScopeProvider = null) { Contract.Requires(host != null); Contract.Requires(methodBody != null); Contract.Ensures(Contract.Result <ControlAndDataFlowGraph <BasicBlock, Instruction> >() != null); var cdfg = ControlFlowInferencer <BasicBlock, Instruction> .SetupControlFlow(host, methodBody, localScopeProvider); DataFlowInferencer <BasicBlock, Instruction> .SetupDataFlow(host, methodBody, cdfg); TypeInferencer <BasicBlock, Instruction> .FillInTypes(host, cdfg); return(cdfg); }
/// <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(); } } }