Ejemplo n.º 1
0
        /// <summary>
        /// Determines if a method body can be inlined, that is, if invalid
        /// code will be generated by inlining it.
        /// </summary>
        /// <param name="calleeBody">
        /// A method body that is an inlining candidate.
        /// </param>
        /// <param name="caller">
        /// The caller that wants to inline <paramref name="calleeBody"/>.
        /// </param>
        /// <param name="callerBody">
        /// The method body for <paramref name="caller"/>.
        /// </param>
        /// <returns>
        /// <c>true</c> if inlining <paramref name="calleeBody"/> into <paramref name="caller"/> is
        /// safe; otherwise, <c>false</c>.
        /// </returns>
        protected virtual bool CanInline(MethodBody calleeBody, IMethod caller, FlowGraph callerBody)
        {
            // To determine if we can inline a method, we essentially just need to
            // consider all members that show up in the method body and see if the
            // caller is allowed to access them.

            var rules   = callerBody.GetAnalysisResult <AccessRules>();
            var members = calleeBody.Implementation
                          .NamedInstructions.Select(insn => insn.Instruction)
                          .Concat(calleeBody.Implementation.BasicBlocks.SelectMany(block => block.Flow.Instructions))
                          .SelectMany(insn => insn.Prototype.Members);

            foreach (var item in members)
            {
                if (item is IType && !rules.CanAccess(caller, (IType)item))
                {
                    return(false);
                }
                else if (item is ITypeMember && !rules.CanAccess(caller, (ITypeMember)item))
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public override FlowGraph Apply(FlowGraph graph)
        {
            // Compute the value numbering for the graph.
            var numbering = graph.GetAnalysisResult <ValueNumbering>();

            // Partition the set of all instructions into equivalence classes.
            var equivValues = new Dictionary <Instruction, HashSet <ValueTag> >(
                new ValueNumberingInstructionComparer(numbering));

            foreach (var insn in graph.NamedInstructions)
            {
                HashSet <ValueTag> valueSet;
                if (!equivValues.TryGetValue(insn.Instruction, out valueSet))
                {
                    equivValues[insn.Instruction] = valueSet = new HashSet <ValueTag>();
                }
                valueSet.Add(insn);
            }

            // Compute the dominator tree for the graph.
            var domTree = graph.GetAnalysisResult <DominatorTree>();

            // Replace instructions with copies to your heart's content.
            var builder = graph.ToBuilder();

            foreach (var insn in builder.Instructions)
            {
                // An instruction can be replaced with another instruction
                // if it is equivalent to that instruction and it is strictly
                // dominated by the other instruction.
                HashSet <ValueTag> valueSet;
                if (!equivValues.TryGetValue(insn.Instruction, out valueSet))
                {
                    continue;
                }

                foreach (var equivValue in valueSet)
                {
                    if (domTree.IsStrictlyDominatedBy(insn, equivValue))
                    {
                        insn.Instruction = Instruction.CreateCopy(insn.Instruction.ResultType, equivValue);
                        break;
                    }
                }
            }
            return(builder.ToImmutable());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Computes a mapping from basic block tags to their immediate
        /// dominators. The entry point block is mapped to <c>null</c>.
        /// </summary>
        private static IReadOnlyDictionary <BasicBlockTag, BasicBlockTag> GetImmediateDominators(
            FlowGraph graph)
        {
            var preds = graph.GetAnalysisResult <BasicBlockPredecessors>();

            return(GetImmediateDominators(
                       graph.BasicBlockTags,
                       graph.EntryPointTag,
                       tag => graph.GetBasicBlock(tag).Flow.BranchTargets,
                       preds.GetPredecessorsOf));
        }
Ejemplo n.º 4
0
        /// <inheritdoc/>
        public ValueLiveness Analyze(FlowGraph graph)
        {
            var liveness = new Dictionary <BasicBlockTag, BlockLiveness>();

            // First create liveness data for blocks in isolation.
            foreach (var block in graph.BasicBlocks)
            {
                liveness[block.Tag] = BlockLiveness.Create(block);
            }

            var preds = graph.GetAnalysisResult <BasicBlockPredecessors>();

            // Then propagate imports until a fixpoint is reached.
            // The idea is to create a worklist of basic blocks that
            // still need to be processed.
            var worklist = new Queue <BasicBlockTag>(graph.BasicBlockTags);
            var workset  = new HashSet <BasicBlockTag>(graph.BasicBlockTags);

            while (worklist.Count > 0)
            {
                // Dequeue a block from the worklist.
                var blockTag = worklist.Dequeue();
                workset.Remove(blockTag);

                var blockData = liveness[blockTag];

                // Propagate imports to predecessors.
                foreach (var predTag in preds.GetPredecessorsOf(blockTag))
                {
                    // Every predecessor must export each and every one of the
                    // block's imports.
                    var predData = liveness[predTag];
                    foreach (var import in blockData.Imports)
                    {
                        // Have the predecessor export the imported value.
                        if (predData.Export(import))
                        {
                            // The predecessor block doesn't define the imported value
                            // and hence also had to import the imported value. Add the
                            // predecessor block to the worklist.
                            if (workset.Add(predTag))
                            {
                                worklist.Enqueue(predTag);
                            }
                        }
                    }
                }
            }

            return(new ValueLiveness(liveness));
        }