// note. pattern #1:
        // * ref = atom
        // * read(ref)
        // conditions:
        // 1) ref is read only once after it had been assigned
        // 2) atom isn't reassigned before read(ref) takes place
        // 3) if ref is CF$XXXX then atom can be of any node type (not only an atom)
        // transformed into:
        // * read(atom)
        private static bool TryMatchPattern1(DfaHelper dfa, Expression atom)
        {
            var p1_ref = atom as Ref;
            if (p1_ref == null) return false;

            var p1_lastass = dfa.Writes(p1_ref).LastOrDefault();
            if (p1_lastass == null) return false;

            var p1_ref_onlyread_afterass = dfa.Reads(p1_ref).SingleOrDefault2(
                r => dfa.ExecOrderOfStmt(r) >= dfa.ExecOrderOfStmt(p1_lastass));
            if (p1_ref_onlyread_afterass == null) return false;

            var p1_atom = p1_lastass.Rhs;
            if (!p1_ref.Sym.Name.StartsWith("CF$") &&
                !p1_ref.Sym.Name.StartsWith("CS$"))
            {
                if (!p1_atom.IsAtom()) return false;

                var p1_atom_reasses = dfa.Writes(p1_atom).Where(w =>
                    dfa.ExecOrderOfStmt(p1_lastass) <= dfa.ExecOrderOfStmt(w) &&
                    dfa.ExecOrderOfStmt(w) <= dfa.ExecOrderOfStmt(p1_ref_onlyread_afterass));
                if (p1_atom_reasses.IsNotEmpty()) return false;
            }

            dfa.Remove(p1_lastass);
            var p1_ref_onlyread_stmt = p1_ref_onlyread_afterass.Stmt();
            dfa.ReplaceRecursive(p1_ref_onlyread_stmt, p1_ref, p1_atom);
            return true;
        }
Esempio n. 2
0
 [DebuggerNonUserCode] private ExpressionExpander(Expression source, ExpansionContext ctx)
 {
     Source = source;
     Ctx = ctx;
     Stmts = new List<Node>();
     Result = Expand(Source);
 }
        // note. pattern #2: 
        // * atom = atom op any
        // transformed into: 
        // * atom [op=] any
        private static bool TryMatchPattern2(DfaHelper dfa, Expression atom)
        {
            var p2_atom = atom;
            foreach (var p2_ass in dfa.Writes(atom))
            {
                if (!(p2_ass.Rhs is BinaryOperator)) continue;
                var binary = p2_ass.Rhs as BinaryOperator;
                if (!p2_atom.Equiv(binary.Lhs)) continue;

                var p2_opeq = p2_atom.CreateOpPreAssign(binary.OperatorType, binary.Rhs);
                if (p2_opeq == null) return false;

                dfa.Replace(p2_ass, p2_opeq);
                return true;
            }

            return false;
        }
Esempio n. 4
0
 public static BinaryOperator LeftShift(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.LeftShift, lhs, rhs);
 }
Esempio n. 5
0
 public static BinaryOperator LessThanOrEqual(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.LessThanOrEqual, lhs, rhs);
 }
Esempio n. 6
0
 public static BinaryOperator AddAssign(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.AddAssign, lhs, rhs);
 }
Esempio n. 7
0
 protected Slot(NodeType nodeType, MemberInfo member, Expression target)
     : base(nodeType, target)
 {
     Member = member;
 }
Esempio n. 8
0
 public static UnaryOperator Not(Expression target)
 {
     return new UnaryOperator(OperatorType.Not, target);
 }
 private void Push(Expression expr)
 {
     var pp_expr = Filter(expr);
     _map.Add(pp_expr, _currentOp);
     var dbg = _currentOp.Source.DebugInfo;
     if (dbg != null) pp_expr.Family().Where(n => n != null).ForEach(n => n.Src = n.Src ?? dbg[_currentOp.Offset]);
     _stack.Push(pp_expr);
 }
        // note. pattern #4
        // <hoard> ref = atom
        // <op> atom = ref op any
        // <usage> read(ref)
        // conditions:
        // 1) exactly one read of ref
        // 2) <hoard> comes before <op> and <usage>
        // 3) <op> and <usage> may be ordered arbitrarily
        // 4) op is either an increment or a decrement
        // transformed into either:
        // * read(atom++), if op is an increment (use IsInc() method to test)
        // * read(atom--), if op is a decrement (use IsDec() method to test)
        private static bool TryMatchPattern4(DfaHelper dfa, Expression atom)
        {
            var p4_ref = atom as Ref;
            if (p4_ref == null) return false;
            var p4_usages = dfa.Usages(p4_ref);
            if (p4_usages.Count() != 3) return false;

            var p4_op = p4_usages.Select(u => u.Stmt()).OfType<Assign>().SingleOrDefault2(ass =>
            {
                var bo = ass.Rhs as BinaryOperator;
                if (bo == null) return false;
                return bo.Lhs.Equiv(p4_ref);
            });
            if (p4_op == null) return false;
            var p4_atom = p4_op.Lhs;
            if (!p4_atom.IsAtom()) return false;
            var p4_bop = p4_op.Rhs as BinaryOperator;
            if (p4_bop == null) return false;
            if (!p4_bop.Lhs.Equiv(p4_ref)) return false;
            var p4_optype = p4_bop.OperatorType;
            var p4_any = p4_bop.Rhs;

            var p4_hoard = p4_usages.First().Stmt();
            var p4_hoard_template = new Assign(p4_ref, p4_atom);
            if (!p4_hoard.Equiv(p4_hoard_template)) return false;
            var p4_usage = p4_usages.Select(u => u.Stmt()).Except(p4_op).Last();

            var p4_opeq = p4_atom.CreateOpPostAssign(p4_optype, p4_any);
            if (p4_opeq == null) return false;

            dfa.Remove(p4_hoard, p4_op);
            dfa.ReplaceRecursive(p4_usage, p4_ref, p4_opeq); 
            return true;
        }
Esempio n. 11
0
 public static BinaryOperator MultiplyAssign(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.MultiplyAssign, lhs, rhs);
 }
Esempio n. 12
0
 public UnaryOperator(OperatorType operatorType, Expression target)
     : base(operatorType, target)
 {
 }
        // note. pattern #3:
        // <op> ref = atom op any
        // <wb> atom = ref
        // <usage> read(ref)
        // conditions:
        // 1) exactly one read of ref
        // 2) <op> comes before <wb> and <usage>
        // 3) <wb> and <usage> may be ordered arbitrarily
        // transformed into either:
        // * read(++atom), if op is an increment (use IsInc() method to test)
        // * read(--atom), if op is a decrement (use IsDec() method to test)
        // * read(atom [op=] any), otherwise
        private static bool TryMatchPattern3(DfaHelper dfa, Expression atom)
        {
            var p3_ref = atom as Ref;
            if (p3_ref == null) return false;
            var p3_usages = dfa.Usages(p3_ref);
            if (p3_usages.Count() != 3) return false;

            var p3_op = p3_usages.First() as Assign;
            if (p3_op == null) return false;
            if (!p3_op.Lhs.Equiv(p3_ref)) return false;
            var p3_bop = p3_op.Rhs as BinaryOperator;
            if (p3_bop == null) return false;
            var p3_atom = p3_bop.Lhs;
            var p3_optype = p3_bop.OperatorType;
            var p3_any = p3_bop.Rhs;
            if (!p3_atom.IsAtom()) return false;

            var p3_usage2_stmt = p3_usages.Second().Stmt();
            var p3_usage3_stmt = p3_usages.Third().Stmt();
            Expression p3_wb, p3_usage;
            var p3_wb_template = new Assign(p3_atom, p3_ref);
            if (p3_usage2_stmt.Equiv(p3_wb_template)) { p3_wb = (Expression)p3_usage2_stmt; p3_usage = (Expression)p3_usage3_stmt; }
            else if (p3_usage3_stmt.Equiv(p3_wb_template)) { p3_wb = (Expression)p3_usage3_stmt; p3_usage = (Expression)p3_usage2_stmt; }
            else return false;

            var p3_opeq = p3_atom.CreateOpPreAssign(p3_optype, p3_any);
            if (p3_opeq == null) return false;

            dfa.Remove(p3_op, p3_wb);
            dfa.ReplaceRecursive(p3_usage, p3_ref, p3_opeq);
            return true;
        }
Esempio n. 14
0
 public BinaryOperator(OperatorType operatorType, Expression lhs, Expression rhs)
     : base(operatorType, lhs, rhs)
 {
 }
        private static bool NeedsParenthesesInCSharp(this Expression child, Expression parent)
        {
            if (parent is Eval) parent = ((Eval)parent).Parent as Expression;
            if (child == null || parent == null) return false;

            var p_app = parent as Apply;
            if (p_app != null)
            {
                if (p_app.Callee == child)
                {
                    return false;
                }
                else
                {
                    var m = p_app.InvokedMethod();
                    if (m != null)
                    {
                        var reallySpecial = m.IsSpecialName && !m.IsConstructor && m.EnclosingProperty() == null;
                        var childIsFirstArg = p_app.Args.FirstOrDefault() == child;
                        var explicitThis = m.IsInstance() || m.IsExtension();
                        if (!reallySpecial && (!childIsFirstArg || !explicitThis)) return false;
                    }
                    else
                    {
                        var p = p_app.InvokedProperty();
                        if (p != null)
                        {
                            return false;
                        }
                        else
                        {
                            (p_app.Callee == null).AssertTrue();
                            return false;
                        }
                    }
                }
            }

            if (child is Apply)
            {
                var m = child.InvokedMethod();
                if (m != null)
                {
                    if (m.IsUserDefinedOperator())
                    {
                        // todo. add support for op_UnaryPlus
                        var op_type = (OperatorType)Enum.Parse(typeof(OperatorType), m.UserDefinedOperatorType());
                        var equiv = Operator.Create(op_type, ((Apply)child).Args);
                        return equiv.NeedsParenthesesInCSharp(parent);
                    }
                    else if (m.IsUserDefinedCast())
                    {
                        (m.Paramc() == 1).AssertTrue();
                        var targetType = m.Ret();
                        var source = ((Apply)child).Args.Single();

                        // todo. think about cases when we can omit the cast
                        // and, thus, need other algorithm of determining
                        // whether we need parentheses or not
                        var equiv = new Convert(targetType, source);
                        return equiv.NeedsParenthesesInCSharp(parent);
                    }
                }
            }

            // heuristics: this makes prettyprints more readable
            // todo. some day think this over again
            // check out examples in Truesight.Playground\Decompiler\Reference
            // for more thinking material
            if (parent is Operator && child is Operator)
            {
                var p_op = ((Operator)parent).OperatorType;
                var c_op = ((Operator)child).OperatorType;

                if (c_op.IsRelational() && p_op.IsEquality()) return true;

                if (p_op == c_op) return false;

                if (c_op == OperatorType.PostDecrement ||
                    c_op == OperatorType.PostIncrement ||
                    c_op == OperatorType.PreDecrement ||
                    c_op == OperatorType.PreIncrement ||
                    c_op == OperatorType.Negate ||
                    c_op == OperatorType.Not)
                {
                    return false;
                }

                if (p_op == OperatorType.AndAlso ||
                    p_op == OperatorType.OrElse)
                {
                    return true;
                }
            }

            if (child is Operator)
            {
                if (child.CSharpPriority() == Operator.PreIncrement().CSharpPriority())
                {
                    return child.CSharpPriority() < parent.CSharpPriority();
                }
                else
                {
                    return child.CSharpPriority() <= parent.CSharpPriority();
                }
            }
            else if (child is Assign)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is Addr)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is CollectionInit)
            {
                return false;
            }
            else if (child is Conditional)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is Const)
            {
                return false;
            }
            else if (child is Convert)
            {
                return child.CSharpPriority() <= parent.CSharpPriority() && !(parent is Convert);
            }
            else if (child is Deref)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is Slot)
            {
                return false;
            }
            else if (child is Loophole)
            {
                return false;
            }
            else if (child is ObjectInit)
            {
                return false;
            }
            else if (child is Ref)
            {
                return false;
            }
            else if (child is SizeOf)
            {
                return false;
            }
            else if (child is TypeAs)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is TypeIs)
            {
                return child.CSharpPriority() <= parent.CSharpPriority();
            }
            else if (child is Default)
            {
                return false;
            }
            else if (child is Apply)
            {
                return false;
            }
            else if (child is Eval)
            {
                return false;
            }
            else if (child is Lambda)
            {
                return false;
            }
            else
            {
                throw AssertionHelper.Fail();
            }
        }
 // node postprocessors
 private Expression Filter(Expression expr) { return Filter((Node)expr).AssertCast<Expression>(); }
Esempio n. 17
0
 public static BinaryOperator NotEqual(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.NotEqual, lhs, rhs);
 }
Esempio n. 18
0
 private void TransformExpression(Expression e, Block xregion, bool insideThreadLoop)
 {
     var xe = TransformExpression(e, insideThreadLoop);
     if (xe != null) xregion.Add(xe);
 }
Esempio n. 19
0
 public static BinaryOperator Modulo(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.Modulo, lhs, rhs);
 }
Esempio n. 20
0
 public static UnaryOperator PostIncrement(Expression target)
 {
     return new UnaryOperator(OperatorType.PostIncrement, target);
 }
Esempio n. 21
0
 public static UnaryOperator Negate(Expression target)
 {
     return new UnaryOperator(OperatorType.Negate, target);
 }
Esempio n. 22
0
 public static BinaryOperator SubtractAssign(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.SubtractAssign, lhs, rhs);
 }
Esempio n. 23
0
 public static BinaryOperator OrElse(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.OrElse, lhs, rhs);
 }
Esempio n. 24
0
 private Expression TransformExpression(Expression e, bool insideThreadLoop)
 {
     var xe = e.Transform(
         (Eval eval) =>
         {
             var m = eval.InvokedMethod();
             var decl = m == null ? null : m.DeclaringType;
             while (decl != null && decl.DeclaringType != null) decl = decl.DeclaringType;
             return decl == typeof(Hints) ? null : eval.DefaultTransform();
         },
         (Fld fld) =>
         {
             var isXyz = fld.Field.Name == "X" || fld.Field.Name == "Y" || fld.Field.Name == "Z";
             if (isXyz)
             {
                 var parent = fld.This as Prop;
                 var p_api = (parent == null ? null : parent.Property).Api();
                 if (p_api != null && p_api.DeclaringType == typeof(IGridApi))
                 {
                     if (p_api.Name == "BlockIdx")
                     {
                         return new Fld(fld.Field, new Ref(_blockIdx));
                     }
                     else if (p_api.Name == "ThreadIdx")
                     {
                         return new Ref(_tids[fld.Field.Name.ToLower()]);
                     }
                     else
                     {
                         return fld.DefaultTransform();
                     }
                 }
                 else
                 {
                     return fld.DefaultTransform();
                 }
             }
             else
             {
                 return (Node)fld.DefaultTransform();
             }
         },
         (Prop prop) =>
         {
             var p_api = prop.Property.Api();
             if (p_api != null && p_api.DeclaringType == typeof(IGridApi))
             {
                 // todo. support raw queries for *Idx properties
                 return prop.DefaultTransform();
             }
             else
             {
                 return prop.DefaultTransform();
             }
         },
         (Assign ass) =>
         {
             var @ref = ass.Lhs as Ref;
             var local = @ref == null ? null : @ref.Sym as Local;
             if (local != null)
             {
                 if (Alloc(local) == allocPrivate &&
                     _needsReplication[local])
                 {
                     insideThreadLoop.AssertTrue();
                     var r_local = _replicatedLocals[local];
                     var replica = new Eval(new Apply(
                         new Lambda(r_local.Type.ArraySetter()),
                         new Ref(r_local), 
                         new Ref(_tids["z"]), 
                         new Ref(_tids["y"]), 
                         new Ref(_tids["x"]),
                         ass.Rhs.CurrentTransform()));
                     return (Node)replica;
                 }
                 else
                 {
                     return ass.DefaultTransform();
                 }
             }
             else
             {
                 return ass.DefaultTransform();
             }
         },
         (Ref @ref) =>
         {
             var sym = (Sym)@ref.Sym;
             if (sym == _params.Single())
             {
                 return new Ref(_this);
             }
             else
             {
                 var local = sym as Local;
                 if (local != null)
                 {
                     if (Alloc(local) == allocPrivate &&
                         _needsReplication[local])
                     {
                         insideThreadLoop.AssertTrue();
                         var r_local = _replicatedLocals[local];
                         var replica = new Eval(new Apply(
                             new Lambda(r_local.Type.ArrayGetter()),
                             new Ref(r_local),
                             new Ref(_tids["z"]),
                             new Ref(_tids["y"]),
                             new Ref(_tids["x"])));
                         return (Node)replica;
                     }
                     else
                     {
                         return @ref.DefaultTransform();
                     }
                 }
                 else
                 {
                     return @ref.DefaultTransform();
                 }
             }
         }).AssertCast<Expression>();
     return xe;
 }
Esempio n. 25
0
 public static BinaryOperator RightShiftAssign(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.RightShiftAssign, lhs, rhs);
 }
Esempio n. 26
0
 public static BinaryOperator Divide(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.Divide, lhs, rhs);
 }
Esempio n. 27
0
 public static BinaryOperator Xor(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.Xor, lhs, rhs);
 }
Esempio n. 28
0
 public static BinaryOperator Coalesce(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.Coalesce, lhs, rhs);
 }
Esempio n. 29
0
 public static BinaryOperator AndAlso(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.AndAlso, lhs, rhs);
 }
Esempio n. 30
0
 public static BinaryOperator GreaterThan(Expression lhs, Expression rhs)
 {
     return new BinaryOperator(OperatorType.GreaterThan, lhs, rhs);
 }