/// <summary> /// Removes the basic block with a particular tag from this /// control-flow graph. /// </summary> /// <param name="tag">The basic block's tag.</param> /// <returns> /// A new control-flow graph that does not contain the basic block. /// </returns> public FlowGraph RemoveBasicBlock(BasicBlockTag tag) { AssertContainsBasicBlock(tag); var newGraph = new FlowGraph(this, new RemoveBasicBlockUpdate(tag)); var oldData = blocks[tag]; var oldParams = oldData.Parameters; var oldInsns = oldData.InstructionTags; var paramTypeBuilder = newGraph.blockParamTypes.ToBuilder(); var valueParentBuilder = newGraph.valueParents.ToBuilder(); int oldParamCount = oldParams.Count; for (int i = 0; i < oldParamCount; i++) { paramTypeBuilder.Remove(oldParams[i].Tag); valueParentBuilder.Remove(oldParams[i].Tag); } valueParentBuilder.RemoveRange(oldInsns); newGraph.blockParamTypes = paramTypeBuilder.ToImmutable(); newGraph.valueParents = valueParentBuilder.ToImmutable(); newGraph.instructions = newGraph.instructions.RemoveRange(oldInsns); newGraph.blocks = newGraph.blocks.Remove(tag); return(newGraph); }
internal BasicBlock(FlowGraph graph, BasicBlockTag tag, BasicBlockData data) { this = default(BasicBlock); this.Graph = graph; this.Tag = tag; this.data = data; }
internal NamedInstruction InsertInstructionInBasicBlock( BasicBlockTag blockTag, Instruction instruction, ValueTag insnTag, int index) { AssertContainsBasicBlock(blockTag); AssertNotContainsValue(insnTag); var oldBlockData = blocks[blockTag]; var newBlockData = new BasicBlockData( oldBlockData.Parameters, oldBlockData.InstructionTags.Insert(index, insnTag), oldBlockData.Flow); var newGraph = new FlowGraph(this, new AddInstructionUpdate(insnTag, instruction)); newGraph.blocks = newGraph.blocks.SetItem(blockTag, newBlockData); newGraph.instructions = newGraph.instructions.Add(insnTag, instruction); newGraph.valueParents = newGraph.valueParents.Add(insnTag, blockTag); return(new NamedInstruction( new BasicBlock(newGraph, blockTag, newBlockData), insnTag, instruction, index)); }
/// <summary> /// Moves this instruction from its current location to a /// the end of a basic block. /// </summary> /// <param name="block"> /// The block to move this instruction to. /// </param> public void MoveTo(BasicBlockTag block) { var data = this.Instruction; var target = Graph.GetBasicBlock(block); Graph.RemoveInstruction(Tag); target.AppendInstruction(data, Tag); }
/// <summary> /// Creates a new control-flow graph that takes the basic block /// with a particular tag as entry point. /// </summary> /// <param name="tag">The tag of the new entry point block.</param> /// <returns>A control-flow graph.</returns> public FlowGraph WithEntryPoint(BasicBlockTag tag) { AssertContainsBasicBlock(tag); var newGraph = new FlowGraph(this, new SetEntryPointUpdate(tag)); newGraph.EntryPointTag = tag; return(newGraph); }
/// <summary> /// Moves this instruction from its current location to a /// particular position in a block. /// </summary> /// <param name="index"> /// The position in <paramref name="block"/> at which to insert /// this instruction. /// </param> /// <param name="block"> /// The block to move this instruction to. /// </param> public void MoveTo(int index, BasicBlockTag block) { var data = this.Instruction; var target = Graph.GetBasicBlock(block); Graph.RemoveInstruction(Tag); target.InsertInstruction(index, data, Tag); }
/// <summary> /// Creates a new basic block that includes all basic blocks in this /// graph plus an empty basic block. The latter basic block is returned. /// </summary> /// <param name="name">The (preferred) name of the basic block's tag.</param> /// <returns>An empty basic block in a new control-flow graph.</returns> public BasicBlock AddBasicBlock(string name) { var tag = new BasicBlockTag(name); var data = new BasicBlockData(); var newGraph = new FlowGraph(this, new AddBasicBlockUpdate(tag)); newGraph.blocks = newGraph.blocks.Add(tag, data); return(new BasicBlock(newGraph, tag, data)); }
internal BasicBlock UpdateBasicBlockParameters( BasicBlockTag tag, ImmutableList <BlockParameter> parameters) { AssertContainsBasicBlock(tag); var oldBlock = blocks[tag]; var newData = new BasicBlockData( parameters, oldBlock.InstructionTags, oldBlock.Flow); var oldData = blocks[tag]; var oldParams = oldData.Parameters; var newGraph = new FlowGraph(this, new BasicBlockParametersUpdate(tag)); var paramTypeBuilder = newGraph.blockParamTypes.ToBuilder(); var valueParentBuilder = newGraph.valueParents.ToBuilder(); // Remove the basic block's parameters from the value parent // and parameter type dictionaries. int oldParamCount = oldParams.Count; for (int i = 0; i < oldParamCount; i++) { paramTypeBuilder.Remove(oldParams[i].Tag); valueParentBuilder.Remove(oldParams[i].Tag); } // Add the new basic block parameters to the value parent and // parameter type dictionaries. int newParamCount = parameters.Count; for (int i = 0; i < newParamCount; i++) { var item = parameters[i]; ContractHelpers.Assert( !valueParentBuilder.ContainsKey(item.Tag), "Value tag '" + item.Tag.Name + "' cannot appear twice in the same control-flow graph."); paramTypeBuilder.Add(item.Tag, item.Type); valueParentBuilder.Add(item.Tag, tag); } newGraph.blockParamTypes = paramTypeBuilder.ToImmutable(); newGraph.valueParents = valueParentBuilder.ToImmutable(); newGraph.blocks = newGraph.blocks.SetItem(tag, newData); return(new BasicBlock(newGraph, tag, newData)); }
internal BasicBlock UpdateBasicBlockFlow(BasicBlockTag tag, BlockFlow flow) { AssertContainsBasicBlock(tag); var oldBlock = blocks[tag]; var newData = new BasicBlockData( oldBlock.Parameters, oldBlock.InstructionTags, flow); var newGraph = new FlowGraph(this, new BasicBlockFlowUpdate(tag)); newGraph.blocks = newGraph.blocks.SetItem(tag, newData); return(new BasicBlock(newGraph, tag, newData)); }
/// <summary> /// Creates a basic block builder from a graph and a tag. /// </summary> /// <param name="graph">The basic block builder's defining graph.</param> /// <param name="tag">The basic block's tag.</param> internal BasicBlockBuilder(FlowGraphBuilder graph, BasicBlockTag tag) { this.Graph = graph; this.Tag = tag; }
/// <summary> /// Checks if this control-flow graph contains a basic block /// with a particular tag. /// </summary> /// <param name="tag">The basic block's tag.</param> /// <returns> /// <c>true</c> if this control-flow graph contains a basic block /// with the given tag; otherwise, <c>false</c>. /// </returns> public bool ContainsBasicBlock(BasicBlockTag tag) { return(ImmutableGraph.ContainsBasicBlock(tag)); }
/// <summary> /// Gets the basic block with a particular tag. /// </summary> /// <param name="tag">The basic block's tag.</param> /// <returns>A basic block.</returns> public BasicBlockBuilder GetBasicBlock(BasicBlockTag tag) { return(new BasicBlockBuilder(this, tag)); }
/// <summary> /// Removes the basic block with a particular tag from this /// control-flow graph. /// </summary> /// <param name="tag">The basic block's tag.</param> public void RemoveBasicBlock(BasicBlockTag tag) { ImmutableGraph = ImmutableGraph.RemoveBasicBlock(tag); }
/// <summary> /// Replaces this branch's target with another block. /// </summary> /// <param name="target">The new target block.</param> /// <returns>A new branch.</returns> public Branch WithTarget(BasicBlockTag target) { return(new Branch(target, Arguments)); }
/// <summary> /// Creates a branch that targets a particular block and /// passes a list of arguments. /// </summary> /// <param name="target">The target block.</param> /// <param name="arguments"> /// A list of arguments to pass to the target block. /// </param> public Branch(BasicBlockTag target, IReadOnlyList <BranchArgument> arguments) { this.Target = target; this.Arguments = arguments; }
/// <summary> /// Creates a branch that targets a particular block and /// passes a list of arguments. /// </summary> /// <param name="target">The target block.</param> /// <param name="arguments"> /// A list of arguments to pass to the target block. /// </param> public Branch(BasicBlockTag target, IReadOnlyList <ValueTag> arguments) : this(target, arguments.EagerSelect(BranchArgument.FromValue)) { }
/// <summary> /// Creates a branch that targets a particular block and /// passes no arguments. /// </summary> /// <param name="target">The target block.</param> public Branch(BasicBlockTag target) : this(target, EmptyArray <BranchArgument> .Value) { }
/// <summary> /// Gets the basic block with a particular tag. /// </summary> /// <param name="tag">The basic block's tag.</param> /// <returns>A basic block.</returns> public BasicBlock GetBasicBlock(BasicBlockTag tag) { AssertContainsBasicBlock(tag); return(new BasicBlock(this, tag, blocks[tag])); }
/// <summary> /// Checks if this control-flow graph contains a basic block /// with a particular tag. /// </summary> /// <param name="tag">The basic block's tag.</param> /// <returns> /// <c>true</c> if this control-flow graph contains a basic block /// with the given tag; otherwise, <c>false</c>. /// </returns> public bool ContainsBasicBlock(BasicBlockTag tag) { return(blocks.ContainsKey(tag)); }
/// <summary> /// Asserts that this control-flow graph must contain a basic block /// with a particular tag. /// </summary> /// <param name="tag"> /// The tag of the basic block that must be in the graph. /// </param> /// <param name="message"> /// The error message for when no basic block in this control-flow graph /// has the tag. /// </param> public void AssertContainsBasicBlock(BasicBlockTag tag, string message) { ContractHelpers.Assert(ContainsBasicBlock(tag), message); }
/// <summary> /// Asserts that this control-flow graph must contain a basic block /// with a particular tag. /// </summary> /// <param name="tag"> /// The tag of the basic block that must be in the graph. /// </param> public void AssertContainsBasicBlock(BasicBlockTag tag) { AssertContainsBasicBlock(tag, "The graph does not contain the given basic block."); }