public Offspring(IScope neighborScope, ControlFlowBlock root, ControlFlowBlock head)
        {
            Scope = neighborScope;
            Root  = root;
            Head  = head;

            CalculateBodyAndPivots();
            InitializeControlFlowGraph();
        }
Beispiel #2
0
        public ViewOfControlFlowGraph InferBranch(ControlFlowBlock headOfBranch, out ReadOnlyCollection <Offspring> offsprings_out)
        {
            var cfg = LocalCfg;

            var cflow    = cfg.Cflow(headOfBranch, _conv).Except(_conv);
            var wannabes = cfg.Cflow(headOfBranch).Except(cfg.Cflow(_conv));
            var closure  = cflow.Closure(wannabes, (vin, vout) => vout != _head && cfg.Vedge(vout, vin) != null);
            var vertices = closure.Except(_conv).OrderBy(v => cfg.Cflow().IndexOf(v)).ToReadOnly();

            if (vertices.IsEmpty())
            {
                var branch = cfg.CreateView(vertices).CreateEigenStartAndFinish();
                branch.AddEigenEdge(new ControlFlowEdge(branch.Start, branch.Finish));

                offsprings_out = Seq.Empty <Offspring>().ToReadOnly();
                return(branch);
            }
            else
            {
                var offsprings = new List <Offspring>();
                var branch     = cfg.CreateView(vertices, (e, vcfg) =>
                {
                    if (vertices.Contains(e.Target))
                    {
                        (e.Source == _head && e.Target == headOfBranch && e.IsConditional).AssertTrue();
                        vcfg.AddEigenEdge(new ControlFlowEdge(vcfg.Start, e.Target));
                    }
                    else
                    {
                        if (e.Target == _conv)
                        {
                            vcfg.AddEigenEdge(new ControlFlowEdge(e.Source, vcfg.Finish, e.Tag));
                        }
                        else
                        {
                            (cfg.Vedges(e.Source, null).Count() == 2).AssertTrue();
                            offsprings.Add(new Offspring(this, e.Source, e.Target));
                        }
                    }
                });
                (branch.Start != null && branch.Finish != null).AssertTrue();

                offsprings_out = offsprings.ToReadOnly();
                return(branch);
            }
        }
Beispiel #3
0
        static void InsertEmptyStateUpdate(CFGContext ctx, ControlFlowBlock block)
        {
            var body = ctx.Graph.Body;
            var key  = ctx.Keys[block.Id];

            if (key.EntryState == key.ExitState)
            {
                return;
            }

            // Cannot use graph.IndexOf because instructions has been modified.
            int targetIndex = body.Instructions.IndexOf(block.Header);

            Instruction first;

            if (key.Type == BlockKeyType.Incremental)
            {
                body.Instructions.Insert(targetIndex + 0, first = Instruction.Create(OpCodes.Ldloc, ctx.StateVariable));
                switch (ctx.Random.NextInt32(3))
                {
                case 0:
                    body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.EntryState ^ key.ExitState)));
                    body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Xor));
                    break;

                case 1:
                    body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.ExitState - key.EntryState)));
                    body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Add));
                    break;

                case 2:
                    body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.EntryState - key.ExitState)));
                    body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Sub));
                    break;
                }
                body.Instructions.Insert(targetIndex + 3, Instruction.Create(OpCodes.Stloc, ctx.StateVariable));
            }
            else
            {
                body.Instructions.Insert(targetIndex + 0, first = Instruction.Create(OpCodes.Ldc_I4, (int)key.ExitState));
                body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Stloc, ctx.StateVariable));
            }

            ctx.Graph.Body.ReplaceReference(block.Header, first);
        }
Beispiel #4
0
        private IfScope(BlockScope parent, ControlFlowBlock head)
        {
            _parent = parent.AssertNotNull();
            _head   = head.AssertNotNull();

            parent.Hir.AddElements(head.BalancedCode);
            _if.Test = head.Residue.AssertSingle();

            var v_true = LocalCfg.TreeVedges(head, null).AssertSingle(e => e.Tag == PredicateType.IsTrue).Target;

            _ifTrue = this.InferBranch(v_true, out _trueOffsprings);
            var v_false = LocalCfg.TreeVedges(head, null).AssertSingle(e => e.Tag == PredicateType.IsFalse).Target;

            _ifFalse = this.InferBranch(v_false, out _falseOffsprings);

            _if.IfTrue  = BlockScope.Decompile(this, _ifTrue).Hir;
            _if.IfFalse = BlockScope.Decompile(this, _ifFalse).Hir;
        }
        public static void DoSplitBlocksIntoAssignmentsAndPredicates(ControlFlowGraph cfg)
        {
            cfg.Vertices.ForEach(v =>
            {
                if (v.BalancedCode.IsEmpty() || v.Residue.IsEmpty())
                {
                    return;
                }

                var ass  = (v.BalancedCode.Last() is Assign) ? v.BalancedCode.Last().AssertCast <Assign>() : null;
                var lhs  = ass == null ? null : ass.Lhs.AssertCast <Ref>().Sym;
                var @ref = v.Residue.AssertSingle() is Ref ? v.Residue.AssertSingle().AssertCast <Ref>().Sym : null;
                if (lhs != null && @ref != null && lhs.ProtoId == @ref.ProtoId)
                {
                    // todo. this introduces a nasty bug if assigned variable is reused later
                    v.BalancedCode.RemoveLast();
                    v.Residue.SetElements(ass.Rhs);
                }

                if (v.BalancedCode.IsEmpty() || v.Residue.IsEmpty())
                {
                    return;
                }

                var v_test = new ControlFlowBlock();
                v_test.Residue.Add(v.Residue.AssertSingle());
                v.Residue.RemoveElements();

                var outEdges = cfg.Vedges(v, null);
                cfg.RemoveEdges(outEdges);

                cfg.AddVertex(v_test);
                cfg.AddEdge(new ControlFlowEdge(v, v_test));
                outEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(v_test, e.Target, e.Tag)));
            });
        }
        static void InsertEmptyStateUpdate(CFGContext ctx, ControlFlowBlock block)
        {
            var body = ctx.Graph.Body;
            var key = ctx.Keys[block.Id];
            if (key.EntryState == key.ExitState)
                return;

            // Cannot use graph.IndexOf because instructions has been modified.
            int targetIndex = body.Instructions.IndexOf(block.Header);

            Instruction first;
            if (key.Type == BlockKeyType.Incremental) {
                body.Instructions.Insert(targetIndex + 0, first = Instruction.Create(OpCodes.Ldloc, ctx.StateVariable));
                switch (ctx.Random.NextInt32(3)) {
                    case 0:
                        body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.EntryState ^ key.ExitState)));
                        body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Xor));
                        break;
                    case 1:
                        body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.ExitState - key.EntryState)));
                        body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Add));
                        break;
                    case 2:
                        body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Ldc_I4, (int)(key.EntryState - key.ExitState)));
                        body.Instructions.Insert(targetIndex + 2, Instruction.Create(OpCodes.Sub));
                        break;
                }
                body.Instructions.Insert(targetIndex + 3, Instruction.Create(OpCodes.Stloc, ctx.StateVariable));
            }
            else {
                body.Instructions.Insert(targetIndex + 0, first = Instruction.Create(OpCodes.Ldc_I4, (int)key.ExitState));
                body.Instructions.Insert(targetIndex + 1, Instruction.Create(OpCodes.Stloc, ctx.StateVariable));
            }

            ctx.Graph.Body.ReplaceReference(block.Header, first);
        }
        static void InsertEmptyStateUpdate(CFGContext ctx, ControlFlowBlock block)
        {
            var body = ctx.Graph.Body;
            var key  = ctx.Keys[block.Id];

            if (key.EntryState == key.ExitState)
            {
                return;
            }

            Instruction first = null;
            // Cannot use graph.IndexOf because instructions has been modified.
            int targetIndex = body.Instructions.IndexOf(block.Header);

            CFGState entry;

            if (!ctx.StatesMap.TryGetValue(key.EntryState, out entry))
            {
                key.Type = BlockKeyType.Explicit;
            }


            if (key.Type == BlockKeyType.Incremental)
            {
                // Incremental

                CFGState exit;
                if (!ctx.StatesMap.TryGetValue(key.ExitState, out exit))
                {
                    // Create new exit state
                    // Update one of the entry states to be exit state
                    exit = entry;
                    int  updateId    = ctx.Random.NextInt32(3);
                    uint targetValue = ctx.Random.NextUInt32();
                    exit.UpdateExplicit(updateId, targetValue);

                    int getId = ctx.Random.NextInt32(3);
                    var fl    = CFGState.EncodeFlag(false, updateId, getId);
                    var incr  = entry.GetIncrementalUpdate(updateId, targetValue);

                    body.Instructions.Insert(targetIndex++, first = Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)incr));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));

                    ctx.StatesMap[key.ExitState] = exit;
                }
                else
                {
                    // Scan for updated state
                    var headerIndex = targetIndex;
                    for (int stateId = 0; stateId < 4; stateId++)
                    {
                        if (entry.Get(stateId) == exit.Get(stateId))
                        {
                            continue;
                        }

                        uint targetValue = exit.Get(stateId);
                        int  getId       = ctx.Random.NextInt32(3);
                        var  fl          = CFGState.EncodeFlag(false, stateId, getId);
                        var  incr        = entry.GetIncrementalUpdate(stateId, targetValue);

                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)incr));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));
                    }
                    first = body.Instructions[headerIndex];
                }
            }
            else
            {
                // Explicit

                CFGState exit;
                if (!ctx.StatesMap.TryGetValue(key.ExitState, out exit))
                {
                    // Create new exit state from random seed
                    var seed = ctx.Random.NextUInt32();
                    exit = new CFGState(seed);
                    body.Instructions.Insert(targetIndex++, first = Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)seed));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxCtor));

                    ctx.StatesMap[key.ExitState] = exit;
                }
                else
                {
                    // Scan for updated state
                    var headerIndex = targetIndex;
                    for (int stateId = 0; stateId < 4; stateId++)
                    {
                        uint targetValue = exit.Get(stateId);
                        int  getId       = ctx.Random.NextInt32(3);
                        var  fl          = CFGState.EncodeFlag(true, stateId, getId);

                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)targetValue));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));
                    }
                    first = body.Instructions[headerIndex];
                }
            }

            ctx.Graph.Body.ReplaceReference(block.Header, first);
        }
Beispiel #8
0
        private LoopScope(BlockScope parent, ControlFlowBlock head)
        {
            _parent = parent.AssertNotNull();
            _head   = head.AssertNotNull();

            var cfg         = LocalCfg;
            var jumpsToHead = cfg.BackVedges(null, _head).Select(e => e.Source).ToReadOnly();

            jumpsToHead.AssertNotEmpty();
            _bot = jumpsToHead.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();
            var cflow = cfg.Cflow(_head, _bot);

            // todo. check this
            //
            // all loops can be divided into four categories:
            // 1) while-do (head is test, either bot or head is continue label),
            // 2) while-true (neither head, nor bot are tests; actually, head is hardcoded to "CS$... = 1"
            //    also either bot or head serve as continue label),
            // 3) do-while (bot is test, it is also the only option for continue
            //    (since here we don't need to separate iteration block from other body instructions,
            //     and because of (nota bene - never knew it) the fact that continue in do-while
            //     first tests exit condition and only then proceeds with the next iteration),
            // 4) some loop with offspring embedded into either head or bot
            //
            // in the first two cases before proceeding to detect subscopes and offsprings
            // we need to find out what's the continue label. that's done as follows.
            // todo. we don't process case #4, since that's just too much for me
            //
            // if cflow features multiple jumps to head, then head is a continue label
            // else (if there's only one jump, i.e. from bot), then bot is a continue label
            //
            // now how we distinguish an offspring from loop's body?
            // answer: using regular closure algorithm, i.e.
            // 1) we pick a bot2 vertex (see below for options),
            // 2) we init the closure with cflow(head, bot2) + bot2
            // 3) we expand the closure using universum of parent's local cfg
            // 4) ... and relation of being reachable w/o touching _test and _iter
            //
            // so, bot2 is a logical bottom of the loop's body (while iter exists on its own!)
            // 1) if bot ain't a continue label, then bot2 = bot
            // 2) if bot is a continue label, then check number of jumps to bot
            // 3) if the latter is one, then bot2 = bot
            // 4) else bot2 = the last one that jumps to bot
            //
            // ah, the last point... how do we find convergence?
            // for cases 1 and 3 conv is the node that receives a jump from either head or bot
            // for case 2 conv is the node that receives a jump from the loop's body
            // todo. here we use a hack, assuming that there's exactly 1 jump from the loop's body
            // if there're two or more jumps we will just work incorrectly
            // if there're zero jumps, then it's fail anyways, since we've just entered an infinite loop

            // todo. also verify that test has supported type
            // also don't forget that IL allows using almost everything as a condition of a test
            // cf. brzero === brnull === brfalse, brtrue === brinst

            var hcond = _head.Residue.IsNotEmpty();
            var bcond = _bot.Residue.IsNotEmpty();

            (hcond && bcond).AssertFalse();

            // case #1. while-do
            if (hcond && !bcond)
            {
                _loop.IsWhileDo = true;
                _test           = _head;

                _loop.Test = _test.Residue.AssertSingle();
                parent.Hir.AddElements(_test.BalancedCode);

                var next1 = cfg.Vedges(_test, null).First().Target;
                var next2 = cfg.Vedges(_test, null).Second().Target;
                (cflow.Contains(next1) || cflow.Contains(next2)).AssertTrue();
                _conv     = cflow.Contains(next1) ? next2 : next1;
                _bodyHead = cflow.Contains(next1) ? next1 : next2;

                var botIsContinue = jumpsToHead.Count() == 1;
                if (botIsContinue)
                {
                    var jumpsToBot    = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                    var lastJumpToBot = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();

                    _continue = jumpsToBot.Count() > 1 ? _bot : null;
                    _bodyBot  = jumpsToBot.Count() > 1 ? lastJumpToBot : _bot;
                }
                else
                {
                    _continue = _head;
                    _bodyBot  = _bot;
                }
            }
            // case #2. while-true
            else if (!hcond && !bcond)
            {
                _head.Residue.AssertEmpty();
                var es  = _head.BalancedCode.AssertSingle();
                var ass = es.AssertCast <Assign>();
                (ass.Rhs.AssertCast <Const>().Value.AssertCast <int>() == 1).AssertTrue();

                _loop.IsWhileDo = true;
                _loop.Test      = new Const(true);
                _test           = _head;

                // todo. here we use a hack, assuming that there's exactly 1 jump from the loop's body
                var alienEdges = cfg.AlienEdges(cflow);
                var breaks     = alienEdges.Except(cfg.Vedges(null, _head), cfg.Vedges(null, _bot));
                _conv     = breaks.Select(e => e.Target).Distinct().AssertSingle();
                _bodyHead = cfg.Vedges(_head, null).AssertSingle().Target;

                var botIsContinue = jumpsToHead.Count() == 1;
                if (botIsContinue)
                {
                    var jumpsToBot    = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                    var lastJumpToBot = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();

                    _continue = (botIsContinue && jumpsToBot.Count() > 1) ? _bot : null;
                    _bodyBot  = (botIsContinue && jumpsToBot.Count() > 1) ? lastJumpToBot : _bot;
                }
                else
                {
                    _continue = _head;
                    _bodyBot  = _bot;
                }
            }
            // case #3: do-while
            else if (!hcond && bcond)
            {
                _loop.IsDoWhile = true;
                _test           = _bot;

                _loop.Test = _test.Residue.AssertSingle();
                parent.Hir.AddElements(_test.BalancedCode);

                var next1 = cfg.Vedges(_test, null).First().Target;
                var next2 = cfg.Vedges(_test, null).Second().Target;
                (cflow.Contains(next1) || cflow.Contains(next2)).AssertTrue();
                _conv     = cflow.Contains(next1) ? next2 : next1;
                _bodyHead = cflow.Contains(next1) ? next1 : next2;

                var jumpsToBot = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                _continue = jumpsToBot.Count() == 1 ? null : _bot;
                _bodyBot  = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();
            }
            // case #4: mysterious loop
            else
            {
                // todo. we don't process case #4, since that's just too much for me now
                throw AssertionHelper.Fail();
            }

            // here we need to pass a hint to DoDecompileScopesForLoopLocals
            if (_continue != null)
            {
                if (_continue == _test)
                {
                    _loop.Iter.Add(null);
                }
                else
                {
                    _loop.Iter.SetElements(_continue.AssertThat(cfb => cfb.Residue.IsEmpty()).BalancedCode);
                }
            }

            _body      = this.InferBody(out _offsprings);
            _loop.Body = BlockScope.Decompile(this, _body).Hir;
        }
Beispiel #9
0
 public static LoopScope Decompile(BlockScope parent, ControlFlowBlock head)
 {
     return(new LoopScope(parent, head));
 }
        static void InsertEmptyStateUpdate(CFGContext ctx, ControlFlowBlock block)
        {
            var body = ctx.Graph.Body;
            var key = ctx.Keys[block.Id];
            if (key.EntryState == key.ExitState)
                return;

            Instruction first = null;
            // Cannot use graph.IndexOf because instructions has been modified.
            int targetIndex = body.Instructions.IndexOf(block.Header);

            CFGState entry;
            if (!ctx.StatesMap.TryGetValue(key.EntryState, out entry)) {
                Debug.Assert(key.Type == BlockKeyType.Explicit);
                key.Type = BlockKeyType.Explicit;
            }

            if (key.Type == BlockKeyType.Incremental) {
                // Incremental

                CFGState exit;
                if (!ctx.StatesMap.TryGetValue(key.ExitState, out exit)) {
                    // Create new exit state
                    // Update one of the entry states to be exit state
                    exit = entry;
                    int updateId = ctx.Random.NextInt32(3);
                    uint targetValue = ctx.Random.NextUInt32();
                    exit.UpdateExplicit(updateId, targetValue);

                    int getId = ctx.Random.NextInt32(3);
                    var fl = CFGState.EncodeFlag(false, updateId, getId);
                    var incr = entry.GetIncrementalUpdate(updateId, targetValue);

                    body.Instructions.Insert(targetIndex++, first = Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)incr));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));

                    ctx.StatesMap[key.ExitState] = exit;
                }
                else {
                    // Scan for updated state
                    var headerIndex = targetIndex;
                    for (int stateId = 0; stateId < 4; stateId++) {
                        if (entry.Get(stateId) == exit.Get(stateId))
                            continue;

                        uint targetValue = exit.Get(stateId);
                        int getId = ctx.Random.NextInt32(3);
                        var fl = CFGState.EncodeFlag(false, stateId, getId);
                        var incr = entry.GetIncrementalUpdate(stateId, targetValue);

                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)incr));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));
                    }
                    first = body.Instructions[headerIndex];
                }
            }
            else {
                // Explicit

                CFGState exit;
                if (!ctx.StatesMap.TryGetValue(key.ExitState, out exit)) {
                    // Create new exit state from random seed
                    var seed = ctx.Random.NextUInt32();
                    exit = new CFGState(seed);
                    body.Instructions.Insert(targetIndex++, first = Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)seed));
                    body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxCtor));

                    ctx.StatesMap[key.ExitState] = exit;
                }
                else {
                    // Scan for updated state
                    var headerIndex = targetIndex;
                    for (int stateId = 0; stateId < 4; stateId++) {
                        uint targetValue = exit.Get(stateId);
                        int getId = ctx.Random.NextInt32(3);
                        var fl = CFGState.EncodeFlag(true, stateId, getId);

                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldloca, ctx.StateVariable));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)fl));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)targetValue));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxNext));
                        body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Pop));
                    }
                    first = body.Instructions[headerIndex];
                }
            }

            ctx.Graph.Body.ReplaceReference(block.Header, first);
        }
 private InitialDecompilation(ControlFlowBlock block, ReadOnlyCollection <IILOp> cil, Symbols symbols)
 {
     _block   = block;
     _cil     = cil;
     _symbols = symbols;
 }
 public static void DoPrimaryDecompilation(ControlFlowBlock block, ReadOnlyCollection <IILOp> cil, Symbols symbols)
 {
     new InitialDecompilation(block, cil, symbols).DoPrimaryDecompilation();
 }