예제 #1
0
        protected override void TraverseNode(Node node)
        {
            if (Stack.Count() == 1)
            {
                _retlabel = _ptx.def_label("ret");
                base.TraverseNode(node);
                _ptx.label(_retlabel);
                _ptx.emit(new exit{});
                _ptx._stk.AssertEmpty();
            }
            else
            {
                var stmt = !(node is Expression);
                var top_level_expr = node is Expression && !(node.Parent is Expression);
                top_level_expr &= (node.Parent != null); // rule out synthetic expressions (e.g. see TraverseOperator for AndAlso)
                if (stmt || top_level_expr)
                {
                    // note. we comment only top-level expressions
                    // since there's a discrepancy in visit time and emit time
                    // so that typically all comments for intermediate expressions
                    // get emitted much earlier than instructions they refer to

                    _ptx.comment(Environment.NewLine);
                    var i_indent = node.Parents().Count() - 1;
                    var s_indent = i_indent.Times("    ");
                    _ptx.comment(s_indent + node.ToDebugString_WithoutParentInfo());
                }

                base.TraverseNode(node);
            }
        }
예제 #2
0
        private void PutIntoCache(Node stmt)
        {
            double? index = null;
            _vertices.TakeWhile(_ => index == null).ForEach((cfb, i) =>
            {
                var united = cfb.BalancedCode.Concat(cfb.Residue.Cast<Node>()).ToReadOnly();
                var iof = united.IndexOf(stmt);
                if (iof == -1) return;

                Node before = null;
                if (iof > 0) before = united[iof - 1];
                else
                {
                    before = (i - 1).DownTo(0).Select(j => _vertices[j].Residue.LastOrDefault() ??
                        _vertices[j].BalancedCode.LastOrDefault()).Where(n => n != null).FirstOrDefault();
                }

                Node after = null;
                if (iof < united.Count() - 1) after = united[iof + 1];
                else
                {
                    after = (i + 1).UpTo(_vertices.Count() - 1).Select(j => _vertices[j].BalancedCode.FirstOrDefault() ?? 
                        _vertices[j].Residue.FirstOrDefault()).Where(n => n != null).FirstOrDefault();
                }

                var i_before = before == null ? _execOrders.Values.MinOrDefault() - 1 : _execOrders[before];
                var i_after = after == null ? _execOrders.Values.MaxOrDefault() + 1 : _execOrders[after];
                index = (i_before + i_after) / 2;
            });

            index.AssertNotNull();
            PutIntoCache(stmt, index.Value);
        }
예제 #3
0
 public ArrayLayout(Node node, space space, Address ptr, ReadOnlyCollection<Reg> dims)
 {
     Node = node;
     Space = space;
     Ptr = ptr;
     Dims = dims;
 }
예제 #4
0
        public static Operator CreateOpPostAssign(this Node lhs, OperatorType op, Node rhs)
        {
            var e_lhs = lhs as Expression;
            var e_rhs = rhs as Expression;
            if (e_lhs == null || e_rhs == null) return null;

            OperatorType opAssign;
            if (EnumHelper.TryParse(op + "Assign", out opAssign))
            {
                if (op == OperatorType.Add && e_rhs.IsConstOne())
                {
                    return Operator.PostIncrement(e_lhs);
                }
                else if (op == OperatorType.Subtract && e_rhs.IsConstOne())
                {
                    return Operator.PostDecrement(e_lhs);
                }
                else
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }
예제 #5
0
 public static void Remove(this ControlFlowGraph cfg, Node toDelete)
 {
     var parent = cfg.Vertices.SingleOrDefault(cfb =>
         cfb.BalancedCode.Contains(toDelete) || cfb.Residue.Contains(toDelete as Expression));
     if (parent != null)
     {
         parent.BalancedCode.Remove(toDelete);
         parent.Residue.Remove(toDelete as Expression);
     }
 }
예제 #6
0
 public static void Replace(this ControlFlowGraph cfg, Node replacee, Node replacer)
 {
     var parent = cfg.Vertices.SingleOrDefault(cfb =>
         cfb.BalancedCode.Contains(replacee) || cfb.Residue.Contains(replacee as Expression));
     if (parent != null)
     {
         parent.BalancedCode.ReplaceElements(replacee, replacer);
         parent.Residue.ReplaceElements(replacee as Expression, replacer as Expression);
     }
 }
예제 #7
0
        public void ReplaceWith(Node node)
        {
            if (node == null) RemoveSelf();

            var blk = node as Block;
            if (blk != null && blk.IsEmpty()) RemoveSelf();
            else
            {
                Parent.AssertNotNull();
                Parent.Children[Index] = node;
            }
        }
예제 #8
0
 public NodeSnippet(Node node) { Node = node.AssertNotNull(); }
예제 #9
0
 public void ReplaceRecursive(Node root, Func<Node, bool> find, Func<Node, Node> replace)
 {
     EvictFromCache(root.Stmt());
     root.ReplaceRecursive(find, replace);
     PutIntoCache(root.Stmt());
 }
예제 #10
0
 private Node Filter(Node node) { return node; }
예제 #11
0
 public void Replace(Node replacee, Node replacer)
 {
     _cfg.Replace(replacee, replacer);
     EvictFromCache(replacee);
     PutIntoCache(replacer);
 }
예제 #12
0
 public static void ReplaceRecursive(this Node root, Node find, Func<Node, Node> replace)
 {
     root.ReplaceRecursive(n => ReferenceEquals(find, n), replace);
 }
예제 #13
0
 public ReadOnlyCollection<Expression> Reads(Node atom)
 {
     return _usages[atom.AssertCast<Expression>()].Where(u => !(u is Assign)).ToReadOnly();
 }
        private static void Traverse(Node n, List<Node> log)
        {
            // this is a child-first traversal
            if (n == null)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Addr)
            {
                var addr = (Addr)n;
                Traverse(addr.Target, log);
            }
            else if (n is Assign)
            {
                var ass = (Assign)n;
                Traverse(ass.Rhs, log);
                Traverse(ass.Lhs, log);
            }
            else if (n is Operator)
            {
                var op = (Operator)n;
                op.Args.ForEach(a => Traverse(a, log));
            }
            else if (n is Conditional)
            {
                var cond = (Conditional)n;
                Traverse(cond.Test, log);
                Traverse(cond.IfTrue, log);
                Traverse(cond.IfFalse, log);
            }
            else if (n is Const)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Convert)
            {
                var cvt = (Convert)n;
                Traverse(cvt.Source, log);
            }
            else if (n is Deref)
            {
                var deref = (Deref)n;
                Traverse(deref.Target, log);
            }
            else if (n is Slot)
            {
                var slot = (Slot)n;
                Traverse(slot.This, log);
            }
            else if (n is Loophole)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Ref)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is SizeOf)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is TypeAs)
            {
                var typeAs = (TypeAs)n;
                Traverse(typeAs.Target, log);
            }
            else if (n is TypeIs)
            {
                var typeIs = (TypeIs)n;
                Traverse(typeIs.Target, log);
            }
            else if (n is Default)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is CollectionInit)
            {
                var ci = (CollectionInit)n;
                ci.Elements.ForEach(el => Traverse(el, log));
                Traverse(ci.Ctor, log);
            }
            else if (n is ObjectInit)
            {
                var oi = (ObjectInit)n;
                oi.Members.ForEach(mi => Traverse(oi.MemberInits[mi], log));
                Traverse(oi.Ctor, log);
            }
            else if (n is Apply)
            {
                var app = (Apply)n;
                app.Args.ForEach(a => Traverse(a, log));
                Traverse(app.Callee, log);
            }
            else if (n is Eval)
            {
                var eval = (Eval)n;
                Traverse(eval.Callee, log);
            }
            else if (n is Lambda)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Catch)
            {
                var @catch = (Catch)n;
                Traverse(@catch.Filter, log);
                @catch.ForEach(c => Traverse(c, log));
            }
            else if (n is Block)
            {
                var block = (Block)n;
                block.ForEach(c => Traverse(c, log));
            }
            else if (n is If)
            {
                var @if = (If)n;
                Traverse(@if.Test, log);
                Traverse(@if.IfTrue, log);
                Traverse(@if.IfFalse, log);
            }
            else if (n is Loop)
            {
                var loop = (Loop)n;
                Traverse(loop.Init, log);
                if (loop.IsWhileDo) Traverse(loop.Test, log);
                Traverse(loop.Body, log);
                Traverse(loop.Iter, log);
                if (loop.IsDoWhile) Traverse(loop.Test, log);
            }
            else if (n is Break)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Continue)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Goto)
            {
                // todo. I don't really have time to implement this right now
                // neither I can think about the case in the near future when this will be useful
//                throw new NotImplementedException();
            }
            else if (n is Label)
            {
                // do nothing - nowhere to drill into
            }
            else if (n is Return)
            {
                var @return = (Return)n;
                Traverse(@return.Value, log);
            }
            else if (n is Throw)
            {
                var @throw = (Throw)n;
                Traverse(@throw.Exception, log);
            }
            else if (n is Try)
            {
                var @try = (Try)n;
                Traverse(@try.Body, log);
                @try.Clauses.ForEach(c => Traverse(c, log));
            }
            else if (n is Using)
            {
                var @using = (Using)n;
                Traverse(@using.Init, log);
                Traverse(@using.Body, log);
            }
            else if (n is Iter)
            {
                var iter = (Iter)n;
                Traverse(iter.Seq, log);
                Traverse(iter.Body, log);
            }
            else
            {
                throw AssertionHelper.Fail();
            }

            // this is a child-first traversal
            log.Add(n);
        }
예제 #15
0
 public static void ReplaceRecursive(this Node root, Node find, Node replace)
 {
     root.ReplaceRecursive(n => find.Equiv(n), _ => replace);
 }
예제 #16
0
        private void PutIntoCache(Node stmt, double execOrder)
        {
            _execOrders.Add(stmt, execOrder);

            // todo. use Family instead of ChildrenRecursive and make this not crash
            var usages = stmt.ChildrenRecursive().Where(n => n.IsAtom()).ToReadOnly();
            foreach (Expression u in usages)
            {
                _atoms.Add(u);
                var cache = _usages.GetOrCreate(u, () => new List<Expression>());
                var ins = cache.TakeWhile((u2, i) => _execOrders[u2.Stmt()] <= execOrder).Count();

                var isAssignToAtom = u.Parent is Assign && ((Assign)u.Parent).Lhs == u;
                cache.Insert(ins, isAssignToAtom ? u.Parent.AssertCast<Assign>() : u);
            }
        }
예제 #17
0
 public double ExecOrderOfStmt(Node anyNode)
 {
     return _execOrders[anyNode.Stmt()];
 }
예제 #18
0
 public ReadOnlyCollection<Assign> Writes(Node atom)
 {
     return _usages[atom.AssertCast<Expression>()].OfType<Assign>().ToReadOnly();
 }
예제 #19
0
 public void ReplaceRecursive(Node root, Node find, Node replace)
 {
     EvictFromCache(root.Stmt());
     root.ReplaceRecursive(find, replace);
     PutIntoCache(root.Stmt());
 }
예제 #20
0
        // note. unlike most transformations in Truesight, this one works in-place
        private static void StripOffRedundanciesInPlace(Node root)
        {
            Action<Node> defaultTraverse = node => node.Children.ForEach(c =>
            {
                var deref = c as Deref;
                if (deref != null)
                {
                    var t = deref.Target.Type();
                    if (t != null && t.IsByRef) c.ReplaceWith(deref.Target);
                    c = deref.Target;
                }

                c.Traverse();
            });

            root.Traverse(defaultTraverse,
                (Assign ass) =>
                {
                    defaultTraverse(ass);

                    var ass_prop = ass.Lhs as Prop;
                    var ass_app = ass.Lhs as Apply;
                    if (ass_app != null) ass_prop = ass_app.Callee as Prop;
                    if (ass_prop != null)
                    {
                        var addr = ass_prop.This as Addr;
                        if (addr != null) ass_prop.This = addr.Target;
                    }

                    var ass_deref = ass.Lhs as Deref;
                    if (ass_deref != null)
                    {
                        var t = ass_deref.Target.Type();
                        if (t != null && t.IsByRef) ass.Lhs = ass_deref.Target;
                    }
                },
                (Fld fld) =>
                {
                    var addr = fld.This as Addr;
                    if (addr != null) fld.This = addr.Target;
                    defaultTraverse(fld);
                },
                (Prop prop) =>
                {
                    var addr = prop.This as Addr;
                    if (addr != null) prop.This = addr.Target;
                    defaultTraverse(prop);
                },
                (Deref deref) =>
                {
                    var t = deref.Target.Type();
                    if (t != null && t.IsByRef) throw AssertionHelper.Fail();
                    defaultTraverse(deref);
                },
                (Apply app) =>
                {
                    var callee_addr = app.Callee as Addr;
                    if (callee_addr != null) app.Callee = callee_addr.Target;
                    defaultTraverse(app);

                    app.ArgsInfo.Zip((arg, pi, i) =>
                    {
                        var addr = arg as Addr;
                        var arg_byref = addr != null;
                        var p_byref = pi != null && pi.Type.IsByRef;
                        if (arg_byref && p_byref) app.Args[i] = addr.Target;

                        var p_is_this = i == 0 && pi != null && pi.Name == "this";
                        if (arg_byref && p_is_this) app.Args[i] = addr.Target;
                    });
                }
            );
        }
예제 #21
0
 public NodeDebugView(Node node) : this(node, null) {}
예제 #22
0
 public ReadOnlyCollection<Expression> Usages(Node atom)
 {
     return _usages[atom.AssertCast<Expression>()].ToReadOnly();
 }
예제 #23
0
 public static void ReplaceRecursive(this Node root, Func<Node, bool> find, Node replace)
 {
     root.ReplaceRecursive(find, _ => replace);
 }
예제 #24
0
 public NodeDebugView_NoParent(Node node) : this(node, null) { }
예제 #25
0
        private void Expand(Node node)
        {
            if (node is Expression)
            {
                var expr = (Expression)node;
                var inlined = expr.Expand(Ctx);
                inlined.Stmts.ForEach(Stmts.Add);
                if (inlined.Result != null) Stmts.Add(inlined.Result);
            }
            else if (node is Block)
            {
                var block = (Block)node;
                Stmts.Add(block.Expand(Ctx.SpinOff()));
            }
            else if (node is Break)
            {
                Stmts.Add(node);
            }
            else if (node is Continue)
            {
                Stmts.Add(node);
            }
            else if (node is Goto)
            {
                Stmts.Add(node);
            }
            else if (node is Label)
            {
                Stmts.Add(node);
            }
            else if (node is If)
            {
                var @if = (If)node;

                var test = @if.Test.Expand(Ctx);
                test.Stmts.ForEach(Stmts.Add);
                test.Result.AssertNotNull();

                var if_true = @if.IfTrue.Expand(Ctx.SpinOff());
                var if_false = @if.IfFalse.Expand(Ctx.SpinOff());
                var expanded = new If(test.Result, if_true, if_false);
                Stmts.Add(expanded);
            }
            else if (node is Loop)
            {
                var loop = (Loop)node;

                var test = loop.Test.Expand(Ctx);
                test.Result.AssertNotNull();
                var init = loop.Init.Expand(Ctx.SpinOff());
                var iter = loop.Iter.Expand(Ctx.SpinOff());
                var body = loop.Body.Expand(Ctx.SpinOff());

                var prepend_test = loop.IsWhileDo && test.Stmts.IsNotEmpty();
                if (init.IsNotEmpty() && prepend_test) { Stmts.Add(init); init = new Block(); }
                if (prepend_test) test.Stmts.ForEach(Stmts.Add);
                test.Stmts.ForEach(iter.Add);

                var xloop = new Loop(test.Result, body, loop.IsWhileDo){Init = init, Iter = iter};
                var cloned_locals = loop.Locals.Select(l => l.DeepClone());
                cloned_locals.ForEach(local => xloop.Locals.Add(local));

                Stmts.Add(xloop);
            }
            else if (node is Return)
            {
                var ret = (Return)node;
                (ret.Value == null).AssertEquiv(Ret == null);
                if (ret.Value != null) Expand(new Assign(Ret, ret.Value));
                Stmts.Add(new Goto(RetLabel));
            }
            else if (node is Try || node is Clause || node is Throw ||
                node is Using || node is Iter)
            {
                // todo. implement support for non-linear control flow
                // this is only possible when we fully implement decompilation of tries
                // until now I leave this marked as "to be implemented"
                throw AssertionHelper.Fail();
            }
            else
            {
                throw AssertionHelper.Fail();
            }
        }
예제 #26
0
 public NodeDebugView_NoParent(Node node, Object parentProxy) : this(node, parentProxy, NodeDebuggabilityHelper.InferDebugProxyNameFromStackTrace()) {}
예제 #27
0
 public NodeDebugView_NoParent(Node node, Object parentProxy, String name) { _node = node; _parentProxy = parentProxy; _name = name; }
예제 #28
0
 private void Qualify(Node node)
 {
     var pp_node = Filter(node);
     _map.Add(pp_node, _currentOp);
     var dbg = _currentOp.Source.DebugInfo;
     if (dbg != null) pp_node.Family().Where(n => n != null).ForEach(n => n.Src = n.Src ?? dbg[_currentOp.Offset]);
     _qualified.Enqueue(pp_node);
 }
예제 #29
0
 public SlotLayout(Node node, Slot slot)
 {
     Node = node;
     Slot = slot;
 }
예제 #30
0
 public void Remove(Node toDelete)
 {
     _cfg.Remove(toDelete);
     EvictFromCache(toDelete);
 }