예제 #1
0
        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);
        }
예제 #2
0
 /// <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;
 }
예제 #3
0
        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.");
            }
        }
예제 #4
0
        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));
        }
예제 #5
0
 /// <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));
 }