Exemple #1
0
 /// <summary>
 /// Appends a new instruction to the end of this basic block.
 /// Returns a new basic block in a new control-flow graph.
 /// </summary>
 /// <param name="instruction">The instruction to append.</param>
 /// <param name="tag">The tag for the instruction.</param>
 /// <returns>The appended instruction.</returns>
 public NamedInstruction AppendInstruction(Instruction instruction, ValueTag tag)
 {
     return(Graph.InsertInstructionInBasicBlock(Tag, instruction, tag, InstructionTags.Count));
 }
Exemple #2
0
 /// <summary>
 /// Checks if this control-flow graph contains an instruction
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">The instruction's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains an instruction
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsInstruction(ValueTag tag)
 {
     return(instructions.ContainsKey(tag));
 }
 /// <summary>
 /// Creates a dynamic cast instruction that converts
 /// from one pointer type to another.
 /// </summary>
 /// <param name="targetType">
 /// A type to convert operands to.
 /// </param>
 /// <param name="operand">
 /// An operand to convert to the target type.
 /// </param>
 /// <returns>
 /// A dynamic cast instruction.
 /// </returns>
 public static Instruction CreateDynamicCast(
     PointerType targetType, ValueTag operand)
 {
     return(DynamicCastPrototype.Create(targetType).Instantiate(operand));
 }
 /// <summary>
 /// Creates an instruction that boxes a value type,
 /// turning it into a reference type (aka box pointer).
 /// </summary>
 /// <param name="elementType">
 /// The type of value to box.
 /// </param>
 /// <param name="element">
 /// The value to box.
 /// </param>
 /// <returns>
 /// A box instruction.
 /// </returns>
 public static Instruction CreateBox(IType elementType, ValueTag element)
 {
     return(BoxPrototype.Create(elementType).Instantiate(element));
 }
        /// <summary>
        /// Replaces this instruction with a control-flow graph that implements
        /// this instruction.
        /// </summary>
        /// <param name="implementation">
        /// A control-flow graph that implements the instruction.
        /// </param>
        /// <param name="arguments">
        /// A list of arguments to pass to <paramref name="implementation"/>'s
        /// entry point block.
        /// </param>
        public override void ReplaceInstruction(FlowGraph implementation, IReadOnlyList <ValueTag> arguments)
        {
            if (!IsValid)
            {
                throw new InvalidOperationException("Cannot replace an invalid instruction builder.");
            }

            if (implementation.EntryPoint.Flow is ReturnFlow)
            {
                // In the likely case where the implementation consists of a
                // basic block that immediately returns a value, we will insert
                // the block's instructions just before this instruction and set
                // this instruction to the return value.
                var returnFlow = (ReturnFlow)Block.CopyInstructionsFrom(
                    InstructionIndex,
                    implementation.EntryPoint,
                    arguments);

                // Copy the return value.
                Instruction = returnFlow.ReturnValue;
            }
            else
            {
                // Otherwise, we will just copy the entire control-flow graph
                // into this control-flow graph and cut the current basic block
                // in two.

                // Create a continuation block, which represents the remainder
                // of this basic block, after `implementation` has run.
                var continuationBlock = Graph.AddBasicBlock();
                var resultParam       = new BlockParameter(ResultType);
                continuationBlock.AppendParameter(resultParam);

                // Split the parent basic block in two, copying all instructions
                // after this one to the continuation block. Include this instruction
                // as well because we'll turn it into a copy that runs in the continuation.
                var parentBlock = Graph.GetValueParent(this);
                int index       = InstructionIndex;
                MoveTo(continuationBlock);
                foreach (var insn in parentBlock.NamedInstructions.Skip(index).ToArray())
                {
                    insn.MoveTo(continuationBlock);
                }

                // Include `implementation` in this graph.
                var entryTag = Graph.Include(
                    implementation,
                    (retFlow, block) =>
                {
                    ValueTag resultTag = block.AppendInstruction(retFlow.ReturnValue);
                    return(new JumpFlow(continuationBlock, new[] { resultTag }));
                });

                // Copy the parent basic block's flow to the continuation block.
                continuationBlock.Flow = parentBlock.Flow;

                // Set the parent basic block's flow to a jump to `implementation`'s
                // entry point.
                parentBlock.Flow = new JumpFlow(entryTag, arguments);

                // Replace this instruction with a copy of the result parameter.
                Instruction = Instruction.CreateCopy(ResultType, resultParam.Tag);
            }
        }
 /// <summary>
 /// Creates an instruction that allocates storage on the stack
 /// for a variable number of elements of a particular type.
 /// </summary>
 /// <param name="elementType">
 /// The type of value to allocate storage for.
 /// </param>
 /// <param name="elementCount">
 /// The number of elements to allocate storage for.
 /// </param>
 /// <returns>
 /// An alloca-array instruction.
 /// </returns>
 public static Instruction CreateAllocaArray(
     IType elementType, ValueTag elementCount)
 {
     return(AllocaArrayPrototype.Create(elementType).Instantiate(elementCount));
 }
Exemple #7
0
 /// <summary>
 /// Asserts that this control-flow graph must not contain an instruction
 /// or basic block parameter with a particular tag.
 /// </summary>
 /// <param name="tag">
 /// The tag of the value that must not be in the graph.
 /// </param>
 public void AssertNotContainsValue(ValueTag tag)
 {
     AssertNotContainsValue(tag, "The graph already contains a value with the given tag.");
 }
        /// <inheritdoc/>
        public override NamedInstructionBuilder InsertBefore(Instruction instruction, ValueTag tag)
        {
            var selInsn = ImmutableInstruction.InsertBefore(instruction, tag);

            Graph.ImmutableGraph = selInsn.Block.Graph;
            return(Graph.GetInstruction(selInsn.Tag));
        }
Exemple #9
0
 /// <summary>
 /// Asserts that this control-flow graph must not contain an instruction
 /// or basic block parameter with a particular tag.
 /// </summary>
 /// <param name="tag">
 /// The tag of the value that must not be in the graph.
 /// </param>
 /// <param name="message">
 /// The error message for when a value in this control-flow graph
 /// has the tag.
 /// </param>
 public void AssertNotContainsValue(ValueTag tag, string message)
 {
     ContractHelpers.Assert(!ContainsValue(tag), message);
 }
Exemple #10
0
 /// <summary>
 /// Asserts that this control-flow graph must contain an instruction
 /// or basic block parameter with a particular tag.
 /// </summary>
 /// <param name="tag">
 /// The tag of the value that must be in the graph.
 /// </param>
 public void AssertContainsValue(ValueTag tag)
 {
     AssertContainsValue(tag, "The graph does not contain the given value.");
 }
Exemple #11
0
 /// <summary>
 /// Gets basic block that defines a value with a
 /// particular tag.
 /// </summary>
 /// <param name="tag">The tag of the value to look for.</param>
 /// <returns>The basic block that defines the value.</returns>
 public BasicBlock GetValueParent(ValueTag tag)
 {
     AssertContainsValue(tag);
     return(GetBasicBlock(valueParents[tag]));
 }
Exemple #12
0
 /// <summary>
 /// Checks if this control-flow graph contains an instruction
 /// or basic block parameter with a particular tag.
 /// </summary>
 /// <param name="tag">The value's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains a value
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsValue(ValueTag tag)
 {
     return(ContainsInstruction(tag) ||
            ContainsBlockParameter(tag));
 }
Exemple #13
0
 /// <summary>
 /// Checks if this control-flow graph contains a basic block parameter
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">The parameter's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains a basic block parameter
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsBlockParameter(ValueTag tag)
 {
     return(blockParamTypes.ContainsKey(tag));
 }
 /// <summary>
 /// Gets basic block that defines a value with a
 /// particular tag.
 /// </summary>
 /// <param name="tag">The tag of the value to look for.</param>
 /// <returns>The basic block that defines the value.</returns>
 public BasicBlockBuilder GetValueParent(ValueTag tag)
 {
     return(GetBasicBlock(ImmutableGraph.GetValueParent(tag).Tag));
 }
Exemple #15
0
 /// <summary>
 /// Asserts that this control-flow graph must contain an instruction
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">
 /// The tag of the instruction that must be in the graph.
 /// </param>
 /// <param name="message">
 /// The error message for when no instruction in this control-flow graph
 /// has the tag.
 /// </param>
 public void AssertContainsInstruction(ValueTag tag, string message)
 {
     ContractHelpers.Assert(ContainsInstruction(tag), message);
 }
        /// <summary>
        /// Includes a control-flow graph in this control-flow graph.
        /// Any values and blocks defined by the graph to include are
        /// renamed in order to avoid conflicts with tags in this graph.
        /// Instructions that may throw an exception are wrapped in 'try'
        /// flow.
        /// </summary>
        /// <param name="graph">
        /// The graph to include in this graph.
        /// </param>
        /// <param name="rewriteReturnFlow">
        /// Rewrites 'return' flow.
        /// </param>
        /// <param name="exceptionBranch">
        /// The branch to take when an exception is thrown by an instruction
        /// in <paramref name="graph"/>. Instructions are not wrapped in
        /// 'try' flow if this parameter is set to <c>null</c>.
        /// </param>
        /// <returns>
        /// The tag of the imported graph's entry point.
        /// </returns>
        public BasicBlockTag Include(
            FlowGraph graph,
            Func <ReturnFlow, BasicBlockBuilder, BlockFlow> rewriteReturnFlow,
            Branch exceptionBranch)
        {
            // The first thing we want to do is compose a mapping of
            // value tags in `graph` to value tags in this
            // control-flow graph.
            var valueRenameMap = new Dictionary <ValueTag, ValueTag>();

            foreach (var insn in graph.NamedInstructions)
            {
                valueRenameMap[insn] = new ValueTag(insn.Tag.Name);
            }

            // Populate a basic block rename mapping.
            var blockMap       = new Dictionary <BasicBlockTag, BasicBlockBuilder>();
            var blockRenameMap = new Dictionary <BasicBlockTag, BasicBlockTag>();

            foreach (var block in graph.BasicBlocks)
            {
                // Add a basic block.
                var newBlock = AddBasicBlock(block.Tag.Name);
                blockMap[block]       = newBlock;
                blockRenameMap[block] = newBlock;

                // Also handle parameters here.
                foreach (var param in block.Parameters)
                {
                    var newParam = newBlock.AppendParameter(param.Type, param.Tag.Name);
                    valueRenameMap[param.Tag] = newParam.Tag;
                }
            }

            InstructionExceptionSpecs exceptionSpecs;

            if (exceptionBranch == null)
            {
                exceptionSpecs = null;
            }
            else
            {
                if (!graph.HasAnalysisFor <InstructionExceptionSpecs>())
                {
                    graph = graph.WithAnalysis(GetAnalysisFor <InstructionExceptionSpecs>());
                }
                exceptionSpecs = graph.GetAnalysisResult <InstructionExceptionSpecs>();
            }

            // Copy basic block instructions and flow.
            foreach (var block in graph.BasicBlocks)
            {
                var newBlock = blockMap[block];
                // Copy the block's instructions.
                foreach (var insn in block.NamedInstructions)
                {
                    if (exceptionBranch != null &&
                        exceptionSpecs.GetExceptionSpecification(insn.Instruction).CanThrowSomething)
                    {
                        // Create a new block for the success path.
                        var successBlock = AddBasicBlock();
                        var successParam = successBlock.AppendParameter(insn.ResultType, valueRenameMap[insn]);

                        // Wrap the instruction in 'try' flow.
                        newBlock.Flow = new TryFlow(
                            insn.Instruction.MapArguments(valueRenameMap),
                            new Branch(successBlock, new[] { BranchArgument.TryResult }),
                            exceptionBranch);

                        // Update the current block.
                        newBlock = successBlock;
                    }
                    else
                    {
                        newBlock.AppendInstruction(
                            insn.Instruction.MapArguments(valueRenameMap),
                            valueRenameMap[insn]);
                    }
                }

                // If the block ends in 'return' flow, then we want to
                // turn that return into a jump to the continuation.
                if (block.Flow is ReturnFlow)
                {
                    var returnFlow = (ReturnFlow)block.Flow;
                    newBlock.Flow = rewriteReturnFlow(
                        new ReturnFlow(
                            returnFlow.ReturnValue.MapArguments(valueRenameMap)),
                        newBlock);
                }
                else
                {
                    newBlock.Flow = block.Flow
                                    .MapValues(valueRenameMap)
                                    .MapBlocks(blockRenameMap);
                }
            }

            return(blockRenameMap[graph.EntryPointTag]);
        }
Exemple #17
0
 /// <summary>
 /// Asserts that this control-flow graph must contain an instruction
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">
 /// The tag of the instruction that must be in the graph.
 /// </param>
 public void AssertContainsInstruction(ValueTag tag)
 {
     AssertContainsInstruction(tag, "The graph does not contain the given instruction.");
 }
 /// <summary>
 /// Creates a named instruction builder from a graph and a tag.
 /// </summary>
 /// <param name="graph">The instruction builder's defining graph.</param>
 /// <param name="tag">The instruction's tag.</param>
 internal NamedInstructionBuilder(FlowGraphBuilder graph, ValueTag tag)
 {
     this.graph = graph;
     this.Tag   = tag;
 }
 /// <summary>
 /// Removes a particular instruction from this control-flow graph.
 /// Returns a new control-flow graph that does not contain the
 /// instruction.
 /// </summary>
 /// <param name="instructionTag">The tag of the instruction to remove.</param>
 /// <returns>
 /// A control-flow graph that no longer contains the instruction.
 /// </returns>
 public void RemoveInstruction(ValueTag instructionTag)
 {
     ImmutableGraph = ImmutableGraph.RemoveInstruction(instructionTag);
 }
 /// <summary>
 /// Creates a copy instruction, which creates an alias for
 /// an existing value.
 /// </summary>
 /// <param name="type">
 /// The type of value to copy.
 /// </param>
 /// <param name="value">
 /// The value to copy.
 /// </param>
 /// <returns>
 /// A copy instruction.
 /// </returns>
 public static Instruction CreateCopy(IType type, ValueTag value)
 {
     return(CopyPrototype.Create(type).Instantiate(value));
 }
 /// <summary>
 /// Checks if this control-flow graph contains an instruction
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">The instruction's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains an instruction
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsInstruction(ValueTag tag)
 {
     return(ImmutableGraph.ContainsInstruction(tag));
 }
 /// <summary>
 /// Creates a load instruction.
 /// </summary>
 /// <param name="pointeeType">The type of value to load.</param>
 /// <param name="pointer">A pointer to the value to load.</param>
 /// <returns>A load instruction.</returns>
 public static Instruction CreateLoad(
     IType pointeeType, ValueTag pointer)
 {
     return(LoadPrototype.Create(pointeeType).Instantiate(pointer));
 }
 /// <summary>
 /// Checks if this control-flow graph contains a basic block parameter
 /// with a particular tag.
 /// </summary>
 /// <param name="tag">The parameter's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains a basic block parameter
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsBlockParameter(ValueTag tag)
 {
     return(ImmutableGraph.ContainsBlockParameter(tag));
 }
 /// <summary>
 /// Creates a get-field-pointer instruction.
 /// </summary>
 /// <param name="field">
 /// The field to create a pointer to.
 /// </param>
 /// <param name="basePointer">
 /// A value that includes <paramref name="field"/>.
 /// </param>
 /// <returns>A get-field-pointer instruction.</returns>
 public static Instruction CreateGetFieldPointer(
     IField field,
     ValueTag basePointer)
 {
     return(GetFieldPointerPrototype.Create(field).Instantiate(basePointer));
 }
 /// <summary>
 /// Checks if this control-flow graph contains an instruction
 /// or basic block parameter with a particular tag.
 /// </summary>
 /// <param name="tag">The value's tag.</param>
 /// <returns>
 /// <c>true</c> if this control-flow graph contains a value
 /// with the given tag; otherwise, <c>false</c>.
 /// </returns>
 public bool ContainsValue(ValueTag tag)
 {
     return(ImmutableGraph.ContainsValue(tag));
 }
 /// <summary>
 /// Creates an instruction that unboxes a box pointer,
 /// turning it into a ref pointer to the box's contents.
 /// </summary>
 /// <param name="elementType">
 /// The type of value to unbox.
 /// </param>
 /// <param name="value">The value to unbox.</param>
 /// <returns>An unbox instruction.</returns>
 public static Instruction CreateUnbox(IType elementType, ValueTag value)
 {
     return(UnboxPrototype.Create(elementType).Instantiate(value));
 }
 /// <summary>
 /// Gets the type of a value in this graph.
 /// </summary>
 /// <param name="tag">The value's tag.</param>
 /// <returns>The value's type.</returns>
 public IType GetValueType(ValueTag tag)
 {
     return(ImmutableGraph.GetValueType(tag));
 }
Exemple #28
0
 /// <summary>
 /// Inserts a new instruction into this basic block's list of instructions.
 /// Returns a new basic block in a new control-flow graph.
 /// </summary>
 /// <param name="index">
 /// The index at which the instruction is to be inserted.
 /// </param>
 /// <param name="instruction">The instruction to insert.</param>
 /// <param name="tag">The tag for the instruction.</param>
 /// <returns>The inserted instruction.</returns>
 public NamedInstruction InsertInstruction(int index, Instruction instruction, ValueTag tag)
 {
     return(Graph.InsertInstructionInBasicBlock(Tag, instruction, tag, index));
 }
 /// <summary>
 /// Creates a block parameter from a type and a tag.
 /// </summary>
 /// <param name="type">The block parameter's type.</param>
 /// <param name="tag">The block parameter's tag.</param>
 public BlockParameter(IType type, ValueTag tag)
 {
     this      = default(BlockParameter);
     this.Type = type;
     this.Tag  = tag;
 }