private static bool TryReplaceUsesInFlow( BlockFlow flow, IReadOnlyDictionary <ValueTag, ValueTag> replacementMap, out BlockFlow newFlow) { bool replacedAny = false; var instructions = flow.Instructions; var newInstructions = new Instruction[instructions.Count]; for (int i = 0; i < newInstructions.Length; i++) { Instruction newInsn; if (TryReplaceUsesInInstruction(instructions[i], replacementMap, out newInsn)) { newInstructions[i] = newInsn; replacedAny = true; } else { newInstructions[i] = instructions[i]; } } var branches = flow.Branches; var newBranches = new Branch[branches.Count]; for (int i = 0; i < newBranches.Length; i++) { var branch = branches[i]; var newArgs = new BranchArgument[branch.Arguments.Count]; for (int j = 0; j < newArgs.Length; j++) { var arg = branch.Arguments[j]; ValueTag value; if (arg.IsValue && replacementMap.TryGetValue(arg.ValueOrNull, out value) && value != arg.ValueOrNull) { newArgs[j] = BranchArgument.FromValue(value); replacedAny = true; } else { newArgs[j] = arg; } } newBranches[i] = branch.WithArguments(newArgs); } if (replacedAny) { newFlow = flow.WithBranches(newBranches).WithInstructions(newInstructions); } else { newFlow = flow; } return(replacedAny); }
/// <summary> /// Creates a basic block from a list of parameters, /// a list of instructions and an end-of-block control /// flow instruction. /// </summary> /// <param name="parameters"> /// The list of parameters for the basic block. /// </param> /// <param name="instructions"> /// The list of instructions for the basic block. /// </param> /// <param name="flow"> /// The block's end-of-block control flow. /// </param> public BasicBlockData( ImmutableList <BlockParameter> parameters, ImmutableList <ValueTag> instructions, BlockFlow flow) { this.Parameters = parameters; this.InstructionTags = instructions; this.Flow = flow; }
private void ValidateBranch( Branch branch, BranchArgumentKind extraAllowedKind, BlockFlow flow, List <string> errors) { if (Implementation.ContainsBasicBlock(branch.Target)) { var blockParams = Implementation.GetBasicBlock(branch.Target).Parameters; int blockParamCount = blockParams.Count; if (blockParamCount != branch.Arguments.Count) { errors.Add( string.Format( "Branch argument count ('{0}') mismatches target " + "block parameter count ('{1}').", branch.Arguments.Count, blockParamCount)); } else { for (int i = 0; i < blockParamCount; i++) { var arg = branch.Arguments[i]; if (arg.IsValue) { var argType = Implementation.GetValueType(arg.ValueOrNull); if (!argType.Equals(blockParams[i].Type)) { errors.Add( string.Format( "Branch argument type '{0}' mismatches target " + "block parameter type '{1}'.", branch.Arguments.Count, blockParams[i].Type)); } } else if (arg.Kind != extraAllowedKind) { errors.Add( string.Format( "Branch argument kind '{0}' is not allowed in this " + "branch of '{1}' flow.", arg.Kind, flow)); } } } } else { errors.Add("Branch to block outside of graph."); } }
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 new basic block in a new control-flow graph that /// has a particular flow. /// </summary> /// <param name="flow">The new flow.</param> /// <returns>A new basic block in a new control-flow graph.</returns> public BasicBlock WithFlow(BlockFlow flow) { return(Graph.UpdateBasicBlockFlow(Tag, flow)); }