protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { _hardcodedVertices = vertices != null ? vertices.ToHashSet() : (edges != null ? edges.SelectMany(e => new []{e.Source, e.Target}).ToHashSet() : null); var vertexFilter = _hardcodedVertices == null ? (cfb => true) : (Func<ControlFlowBlock, bool>)(cfb => _hardcodedVertices.Contains(cfb)); _hardcodedEdges = edges == null ? null : edges.ToHashSet(); var edgeFilter = edges == null ? (e => true) : ((Func<ControlFlowEdge, bool>)(e => _hardcodedEdges.Contains(e))); InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge); }
public ControlFlowGraph(BaseControlFlowGraph proto, bool deep) : base(proto, deep) { _start = proto.Start; _finish = proto.Finish; _allTimeVertexCounter = __vertices.Count(); if (_start == null) _allTimeVertexCounter++; if (_finish == null) _allTimeVertexCounter++; HookUpVertexPostprocessors(); }
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; }
private ComplexScope(IScope parent, BaseControlFlowGraph cfg) { _parent = parent.AssertNotNull(); _localCfg = cfg; var offsprings = new List <Offspring>(); var adjacentToFinish = cfg.Vedges(null, cfg.Finish).Select(e => e.Source).ToReadOnly(); var lastInFlow = cfg.Cflow()[adjacentToFinish.Max(v => cfg.Cflow().IndexOf(v))]; if (lastInFlow != cfg.Start) { var flow = lastInFlow.MkArray().Closure(cfg.Vertices, (vin, vout) => vout != cfg.Start && cfg.Vedge(vout, vin) != null); _localCfg = cfg.CreateView(flow, (e, vcfg) => { if (e.Source == cfg.Start) { vcfg.InheritStart(cfg.Start); vcfg.AddEigenEdge(e.ShallowClone()); } else if (e.Target == cfg.Finish) { if (e.Source == lastInFlow) { vcfg.InheritFinish(cfg.Finish); } vcfg.AddEigenEdge(e.ShallowClone()); } else { (cfg.Vedges(e.Source, null).Count() == 2).AssertTrue(); offsprings.Add(new Offspring(this, e.Source, e.Target)); } }); } Offsprings = offsprings.ToReadOnly(); _block = BlockScope.Decompile(this, _localCfg).Hir; }
public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, vertices, edges, onAlienEdge); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { vertexFilter = vertexFilter ?? (cfb => true); edgeFilter = edgeFilter ?? (e => true); InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertexFilter, edgeFilter, (e, _) => { throw AssertionHelper.Fail(); }); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, (IEnumerable<ControlFlowBlock>)null, edgeFilter, onAlienEdge); }
private void InitializeCore( BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Source = source.AssertNotNull(); HookUpVertexPostprocessors(); _vertexFilter = vertexFilter.AssertNotNull(); _edgeFilter = edgeFilter.AssertNotNull(); _cachedVertices = _hardcodedVertices != null ? null : source.Vertices.Where(_vertexFilter).ToList(); (_cachedVertices ?? _hardcodedVertices.AsEnumerable()).ForEach(OnVertexAdded); ReadOnlyCollection<ControlFlowEdge> alienEdges = null; if (_hardcodedEdges != null) { var edgeVertices = _hardcodedEdges.SelectMany(e => new []{e.Source, e.Target}).ToHashSet(); edgeVertices.ExceptWith(_cachedVertices ?? _hardcodedVertices.AsEnumerable()); edgeVertices.AssertEmpty(); } else { _edgeFilter = e => edgeFilter(e) && _vertexFilter(e.Source) && _vertexFilter(e.Target); var relatedEdges = source.Edges(_vertexFilter, null).Concat(source.Edges(null, _vertexFilter)).Distinct(); var parts = relatedEdges.GroupBy(e => _edgeFilter(e)).ToDictionary(g => g.Key, g => g.AsEnumerable()); _cachedEdges = (parts.GetOrDefault(true, Seq.Empty<ControlFlowEdge>)).ToList(); alienEdges = parts.GetOrDefault(false, Seq.Empty<ControlFlowEdge>).ToReadOnly(); } (_cachedEdges ?? _hardcodedEdges.AsEnumerable()).ForEach(OnEdgeAdded); Action<ControlFlowBlock> cacheVertex = v => { if (_cachedVertices != null) _cachedVertices.Add(v); else throw AssertionHelper.Fail(); }; Action<ControlFlowBlock> uncacheVertex = v => { if (_cachedVertices != null) _cachedVertices.Remove(v); else _hardcodedVertices.Remove(v); }; source.VertexAdded += v => { if (_vertexFilter(v)) { cacheVertex(v); OnVertexAdded(v); } }; source.VertexRemoved += v => { if (_vertexFilter(v)) { uncacheVertex(v); OnVertexRemoved(v); } }; Action<ControlFlowEdge> cacheEdge = e => { if (_cachedEdges != null) _cachedEdges.Add(e); else throw AssertionHelper.Fail(); }; Action<ControlFlowEdge> uncacheEdge = e => { if (_cachedEdges != null) _cachedEdges.Remove(e); else _hardcodedEdges.Remove(e); }; source.EdgeAdded += e => { if (_edgeFilter(e)) { cacheEdge(e); OnEdgeAdded(e); } }; source.EdgeRemoved += e => { if (_edgeFilter(e)) { uncacheEdge(e); OnEdgeRemoved(e); } }; __vertices = new VirtualList<ControlFlowBlock>( () => (_hardcodedVertices ?? (IEnumerable<ControlFlowBlock>)_cachedVertices).Concat(_eigenVertices), (i, v) => { if (_eigenVertices.Contains(v)) { // do nothing - the vertex has just been created by AddEigenVertex } else { _vertexFilter(v).AssertTrue(); (_cachedVertices != null && i == _cachedVertices.Count()).AssertTrue(); Source.AddVertex(v); } }, (i, v) => { _vertexFilter(v).AssertTrue(); throw AssertionHelper.Fail(); }, i => { if (i < _cachedEdges.Count()) { var v = _cachedVertices[i]; Source.RemoveVertex(v); } else { throw AssertionHelper.Fail(); } }); __edges = new VirtualList<ControlFlowEdge>( () => (_hardcodedEdges ?? (IEnumerable<ControlFlowEdge>)_cachedEdges).Concat(_eigenEdges), (i, e) => { if (_eigenEdges.Contains(e)) { // do nothing - the edge has just been created by AddEigenEdge } else { _edgeFilter(e).AssertTrue(); (_cachedEdges != null && i == _cachedEdges.Count()).AssertTrue(); Source.AddEdge(e); } }, (i, e) => { _edgeFilter(e).AssertTrue(); throw AssertionHelper.Fail(); }, i => { if (i < _cachedEdges.Count()) { var e = _cachedEdges[i]; Source.RemoveEdge(e); } else { var e = _eigenEdges[i - _cachedEdges.Count()]; _eigenEdges.Remove(e); } }); try { _allowAutoCreateStartAndFinish = true; alienEdges.ForEach(e => onAlienEdge(e, this)); } finally { _allowAutoCreateStartAndFinish = false; } }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { _hardcodedVertices = vertices == null ? null : vertices.ToHashSet(); var vertexFilter = _hardcodedVertices == null ? (cfb => true) : (Func<ControlFlowBlock, bool>)(cfb => _hardcodedVertices.Contains(cfb)); InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge); }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertices, edgeFilter, (v, _) => { throw AssertionHelper.Fail(); }); }
public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertices, edgeFilter); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { _hardcodedEdges = edges == null ? null : edges.ToHashSet(); var edgeFilter = edges == null ? (e => true) : ((Func<ControlFlowEdge, bool>)(e => _hardcodedEdges.Contains(e))); InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge); }
// hybrids public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, IEnumerable<ControlFlowEdge> edges) { Initialize(source, vertexFilter, edges); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter) { Initialize(source, vertexFilter, (IEnumerable<ControlFlowEdge>)null); }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices) { Initialize(source, vertices, (IEnumerable<ControlFlowEdge>)null); }
protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, (IEnumerable<ControlFlowBlock>)null, edgeFilter); }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, vertices, (IEnumerable<ControlFlowEdge>)null, onAlienEdge); }
public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertexFilter, edgeFilter); }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowEdge> edges) { Initialize(source, (IEnumerable<ControlFlowBlock>)null, edges); }
public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, vertexFilter, edgeFilter, onAlienEdge); }
public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges) { Initialize(source, vertices, edges); }
public static ComplexScope Decompile(IScope parent, BaseControlFlowGraph cfg) { return(new ComplexScope(parent, cfg)); }
protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges) { Initialize(source, vertices, edges, (e, _) => { throw AssertionHelper.Fail(); }); }
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; }
private BlockScope(IScope parent, BaseControlFlowGraph cfg) { _parent = parent.AssertNotNull(); _localCfg = cfg; var offspringsRecursive = new Dictionary <ControlFlowBlock, Offspring>(); this.Hierarchy().ForEach(s => s.Offsprings.ForEach(off => offspringsRecursive.Add(off.Root, off))); var pivotsRecursive = new Dictionary <ControlFlowBlock, IScope>(); this.Parents().Reverse().ForEach(p => p.Pivots.ForEach(cfb => pivotsRecursive[cfb] = p)); var cflow = _localCfg.Cflow().Except(cfg.Start).ToReadOnly(); var todo = cflow.ToList(); var expected = todo.First(); while (todo.IsNotEmpty()) { var curr = todo.First(); (expected == curr).AssertTrue(); todo.Remove(curr); var offspring = offspringsRecursive.GetOrDefault(curr); if (offspring != null) { var parentCfg = offspring.Scope.Parent.LocalCfg; (parentCfg.Vedges(curr, null).Count() == 2).AssertTrue(); (parentCfg.BackVedges(null, curr).Count() == 0).AssertTrue(); var localEdge = cfg.Vedges(curr, null).AssertSingle(); localEdge.IsConditional.AssertTrue(); expected = localEdge.Target; _block.AddElements(curr.BalancedCode); var test = curr.Residue.AssertSingle(); test = localEdge.Condition == PredicateType.IsTrue ? Operator.Not(test) : localEdge.Condition == PredicateType.IsFalse ? test : ((Func <Expression>)(() => { throw AssertionHelper.Fail(); }))(); _block.AddElements(new If(test, ComplexScope.Decompile(this, offspring).Hir)); } else { if (_localCfg.BackVedges(null, curr).IsNotEmpty()) { var loop = LoopScope.Decompile(this, curr); todo.RemoveElements(loop.Test, loop.Continue); todo.RemoveElements(loop.Body.Vertices); todo.RemoveElements(loop.Offsprings.SelectMany(off => off.Body)); _block.AddElements(loop.Hir); expected = loop.Conv; } else if (_localCfg.Vedges(curr, null).Count() >= 2) { (_localCfg.TreeVedges(curr, null).Count() == 2).AssertTrue(); (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue(); var @if = IfScope.Decompile(this, curr); todo.RemoveElements(@if.Test); todo.RemoveElements(@if.IfTrue.Vertices); todo.RemoveElements(@if.IfFalse.Vertices); todo.RemoveElements(@if.Offsprings.SelectMany(off => off.Body)); _block.AddElements(@if.Hir); expected = @if.Conv; } else { (_localCfg.TreeVedges(curr, null).Count() <= 1).AssertTrue(); (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue(); var e_next = _localCfg.TreeVedges(curr, null).SingleOrDefault(); (e_next == null).AssertEquiv(todo.IsEmpty()); expected = e_next == null ? null : e_next.Target; var isPivot = pivotsRecursive.ContainsKey(curr); isPivot.AssertImplies(e_next == null); if (!isPivot) { _block.AddElements(curr.BalancedCode); if (curr.Residue.IsNotEmpty()) { var nextIsRetOf = pivotsRecursive.GetOrDefault(expected) as LambdaScope; (nextIsRetOf != null && nextIsRetOf.Return == expected).AssertTrue(); _block.Add(curr.Residue.AssertSingle()); } } else { var scope = pivotsRecursive[curr]; if (scope is LambdaScope) { var lambda = scope.AssertCast <LambdaScope>(); if (curr == lambda.Return) { var i_curr = cflow.IndexOf(curr).AssertThat(i => i != -1); var prev = cflow.NthOrDefault(i_curr - 1); var prevWasExpression = _block.LastOrDefault() is Expression; var prevHasResidue = prev != null && prev.Residue.IsNotEmpty(); if (prevWasExpression && prevHasResidue) { var valueToRet = _block.Last().AssertCast <Expression>(); _block.RemoveLast(); _block.Add(new Return(valueToRet.DeepClone())); } else { var complex = parent as ComplexScope; var global = complex == null ? null : complex.Parent as LambdaScope; var canOmitReturn = global != null && global.Return == curr; if (!canOmitReturn) { _block.Add(new Return()); } } } else { throw AssertionHelper.Fail(); } } else if (scope is LoopScope) { var loop = scope.AssertCast <LoopScope>(); (loop == this.Parents().OfType <LoopScope>().First()).AssertTrue(); if (curr == loop.Continue) { _block.Add(new Continue()); } else if (curr == loop.Conv) { _block.Add(new Break()); } else { throw AssertionHelper.Fail(); } } else { throw AssertionHelper.Fail(); } } } } } }