Esempio n. 1
0
 public static void CopyTo([NotNull] this IBasicBlock a, [NotNull] IMutableBasicBlock b)
 {
     foreach (var stmt in a.Statements)
     {
         b.Add(stmt);
     }
 }
Esempio n. 2
0
        private void HandleGoto(IMutableControlFlowGraph cfg, Goto @goto, IMutableBasicBlock block, int lineNumber)
        {
            block.Add(@goto);

            if (@goto.Destination.IsConstant)
            {
                var dest = @goto.Destination.StaticEvaluate();
                if (dest.Type == Execution.Type.Number)
                {
                    // We know exactly where this is going, jump to that line
                    var line      = Math.Clamp((int)dest.Number, 1, _maxLines);
                    var destBlock = GetLineEntryBlock(cfg, line);
                    cfg.CreateEdge(block, destBlock, EdgeType.GotoConstNum);
                }
                else if (dest.Type == Execution.Type.String)
                {
                    // We tried to statically jump to a string (which is always an error), fallthrough to the next line
                    AddFallthrough(cfg, block, lineNumber, EdgeType.GotoConstStr);
                }
            }
            else
            {
                // We don't know where this is going, so goto every line
                for (var j = 1; j <= _maxLines; j++)
                {
                    cfg.CreateEdge(block, GetLineEntryBlock(cfg, j), EdgeType.GotoExpression);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Convert a statement list into basic blocks. Return the final block that was created if it needs to be connected to the next block
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="statements"></param>
        /// <param name="lineNumber"></param>
        /// <param name="entry"></param>
        /// <returns>(entry_block!, exit_block?)</returns>
        private (IMutableBasicBlock, IMutableBasicBlock) HandleStatementList(IMutableControlFlowGraph cfg, StatementList statements, int lineNumber, IMutableBasicBlock entry)
        {
            var block = cfg.CreateNewBlock(BasicBlockType.Basic, lineNumber);

            cfg.CreateEdge(entry, block, EdgeType.Continue);

            foreach (var stmt in statements.Statements)
            {
                if (stmt is Goto @goto)
                {
                    HandleGoto(cfg, @goto, block, lineNumber);

                    // Create a new block which is _not_ linked to the previous (because we just unconditionally jumped away)
                    block = cfg.CreateNewBlock(BasicBlockType.Basic, lineNumber);
                }
                else if (stmt is If @if)
                {
                    block.Add(new Conditional(@if.Condition));

                    // Convert true and false branches into blocks
                    var(enTrue, exTrue) = HandleStatementList(cfg, @if.TrueBranch, lineNumber, cfg.CreateNewBlock(BasicBlockType.Basic, lineNumber));
                    var(enFals, exFals) = HandleStatementList(cfg, @if.FalseBranch, lineNumber, cfg.CreateNewBlock(BasicBlockType.Basic, lineNumber));

                    // Create edges from conditional to two branches
                    cfg.CreateEdge(block, enTrue, EdgeType.ConditionalTrue);
                    cfg.CreateEdge(block, enFals, EdgeType.ConditionalFalse);

                    // Link the exit blocks (if they're not null) to the next block
                    block = cfg.CreateNewBlock(BasicBlockType.Basic, lineNumber);
                    if (exTrue != null)
                    {
                        cfg.CreateEdge(exTrue, block, EdgeType.Continue);
                    }
                    if (exFals != null)
                    {
                        cfg.CreateEdge(exFals, block, EdgeType.Continue);
                    }
                }
                else if (stmt is EmptyStatement)
                {
                    // ignore empty statements, they (obviously) don't do anything
                    // ReSharper disable once RedundantJumpStatement
                    continue;
                }
                else
                {
                    // Add to block with fallthrough to next line if it can error
                    block.Add(stmt);
                    if (stmt.CanRuntimeError)
                    {
                        AddFallthrough(cfg, block, lineNumber, EdgeType.RuntimeError);

                        var b2 = cfg.CreateNewBlock(BasicBlockType.Basic, block.LineNumber);
                        cfg.CreateEdge(block, b2, EdgeType.Continue);
                        block = b2;
                    }
                }
            }

            return(entry, block);
        }