Наследование: AstRecursiveVisitor
        public static ICode V(ICode ast)
        {
            var v   = new VisitorIfSimplification(ast);
            var ret = v.Visit(ast);

            foreach (var replace in v.replaceVars)
            {
                ret = VisitorReplace.V(ret, replace.Item1, replace.Item2);
            }
            return(ret);
        }
Пример #2
0
        // Only have if, switch, cil, continuation, try - no other type of statement
        // Blocks will only start with cil or try
        // Will end with null, if, switch or continuation
        // If ending in 'if', 'then' and 'else' will both have continuations only
        // 'try' statements will have only 0 or 1 catch clauses

        public static ICode V(ICode ast)
        {
            var v = new VisitorConvertCilToSsa(ast);

            ast = v.Visit(ast);
            foreach (var instResult in v.instResults.Values)
            {
                var var = new ExprVarLocal(ast.Ctx, instResult.Type);
                ast = VisitorReplace.V(ast, instResult, var);
            }
            return(ast);
        }
Пример #3
0
        protected override ICode VisitIf(StmtIf s)
        {
            var ctx       = s.Ctx;
            var condition = (Expr)this.Visit(s.Condition);

            this.stack.Push(new List <ExprVar>());
            var then   = (Stmt)this.Visit(s.Then);
            var thenDA = this.stack.Pop();

            this.stack.Push(new List <ExprVar>());
            var @else  = (Stmt)this.Visit(s.Else);
            var elseDA = this.stack.Pop();

            var intersection = thenDA.Intersect(elseDA, (IEqualityComparer <ExprVar>) this.phiComparer).ToArray();

            this.stack.Peek().AddRange(intersection);

            var conditionVars = VisitorFindVars.V(condition);
            var needAssigning = conditionVars.Except(this.stack.SelectMany(x => x), (IEqualityComparer <ExprVar>) this.phiComparer).ToArray();

            if (needAssigning.Any())
            {
                var replacements = needAssigning.Select(x => {
                    var newExpr = ctx.Local(x.Type);
                    var phi     = new ExprVarPhi(ctx)
                    {
                        Exprs = new[] { x, newExpr }
                    };
                    return(new { orgExpr = x, newExpr, phi });
                }).ToArray();
                foreach (var replace in replacements)
                {
                    this.stack.Peek().Add(replace.newExpr);
                    this.stack.Peek().Add(replace.phi);
                    condition = (Expr)VisitorReplace.V(condition, replace.orgExpr, replace.phi);
                }
                this.ensureAssigned.Add(s, replacements.Select(x => x.newExpr).ToArray());
            }

            if (condition != s.Condition || then != s.Then || @else != s.Else)
            {
                var newS = new StmtIf(ctx, condition, then, @else);
                this.stmtMap.Add(newS, s);
                return(newS);
            }
            else
            {
                return(s);
            }
        }
Пример #4
0
        public static ICode V(ICode ast)
        {
            var ctx       = ast.Ctx;
            var blockInfo = VisitorSubstituteIrreducable.FindSuitableBlocks.GetInfo(ast);
            var bInfo     = blockInfo.Select(x => new {
                toCount   = VisitorContToCounter.GetCount(x.Key, ast),
                ast       = x.Key,
                codeCount = x.Value.numICodes,
            }).ToArray();
            var block = bInfo.Where(x => x.toCount >= 2).OrderBy(x => x.toCount * x.codeCount).FirstOrDefault();

            if (block == null)
            {
                return(ast);
            }

            var phis        = new Dictionary <Expr, Expr>();
            var blockCopies = Enumerable.Range(0, block.toCount - 1)
                              .Select(x => {
                var v   = new VisitorDuplicateCode();
                var ret = v.Visit(block.ast);
                phis    = phis.Merge(v.phiMap, (a, b) => new ExprVarPhi(ctx)
                {
                    Exprs = new[] { a, b }
                });
                return(ret);
            })
                              .Concat(block.ast)
                              .ToArray();

            var contTos = VisitorFindContinuationsRecursive.Get(ast).Where(x => x.To == block.ast).ToArray();

            for (int i = 0; i < contTos.Length; i++)
            {
                var contTo    = contTos[i];
                var blockCopy = blockCopies[i];
                ast = VisitorReplace.V(ast, contTo, blockCopy);
            }

            ast = VisitorReplaceExprUse.V(ast, phis);

            return(ast);
        }
Пример #5
0
        protected override ICode VisitDoLoop(StmtDoLoop s)
        {
            var ctx    = s.Ctx;
            var body   = (Stmt)this.Visit(s.Body);
            var @while = (Expr)this.Visit(s.While);

            var conditionVars = VisitorFindVars.V(@while);
            var needAssigning = conditionVars.Except(this.stack.SelectMany(x => x), (IEqualityComparer <ExprVar>) this.phiComparer).ToArray();

            if (needAssigning.Any())
            {
                var replacements = needAssigning.Select(x => {
                    var newExpr = ctx.Local(x.Type);
                    var phi     = new ExprVarPhi(ctx)
                    {
                        Exprs = new[] { x, newExpr }
                    };
                    return(new { orgExpr = x, newExpr, phi });
                }).ToArray();
                foreach (var replace in replacements)
                {
                    this.stack.Peek().Add(replace.newExpr);
                    this.stack.Peek().Add(replace.phi);
                    @while = (Expr)VisitorReplace.V(@while, replace.orgExpr, replace.phi);
                }
                var assignmentStmts = replacements
                                      .Select(x => new StmtAssignment(ctx, x.newExpr, new ExprDefaultValue(ctx, x.newExpr.Type)))
                                      .ToArray();
                body = new StmtBlock(ctx, assignmentStmts.Concat(body));
            }

            if (body != s.Body || @while != s.While)
            {
                return(new StmtDoLoop(ctx, body, @while));
            }
            else
            {
                return(s);
            }
        }
        // TODO: Restrict movement across try/catch/finally borders

        public static ICode V(ICode ast)
        {
            var v               = new VisitorSsaCopyPropagation();
            var ast2            = v.Visit(ast);
            var alreadyReplaced = new Dictionary <Expr, Expr>();

            foreach (var a in v.assignments.Values)
            {
                if (a.mustKeep)
                {
                    continue;
                }
                if (a.assignment == null)
                {
                    continue;
                }
                if (a.count == 1)
                {
                    if (!VisitorFindSpecials.Any(a.assignment, Expr.Special.PossibleSideEffects))
                    {
                        ast2 = VisitorReplace.V(ast2, a.assignment, null);
                    }
                }
                else if (a.count == 2 /*||
                                       * (IsSimple(alreadyReplaced.ValueOrDefault(a.assignment.Expr, a.assignment.Expr)) && !a.assignment.Expr.Type.IsNonPrimitiveValueType())*/)
                {
                    var updater = new Updater(a.assignment.Target);
                    ast2 = updater.Visit(ast2);
                    foreach (var replaced in updater.Replaced)
                    {
                        alreadyReplaced[replaced.Item1] = replaced.Item2;
                    }
                }
            }
            return(ast2);
        }
Пример #7
0
        public static ICode V(ICode ast)
        {
            var ctx       = ast.Ctx;
            var blockInfo = FindSuitableBlocks.GetInfo(ast);
            var bestBlock = blockInfo
                            .Where(x => !x.Value.containsLeaveProtectedRegion && x.Value.numConts <= 1)
                            .OrderBy(x => x.Value.numConts == 0 ? 1000 : x.Value.numConts)
                            .ThenBy(x => x.Value.numICodes)
                            .FirstOrDefault();

            if (bestBlock.Key == null)
            {
                return(ast);
            }
            if (bestBlock.Value.numConts > 1)
            {
                // Best block must have just one continuation
                return(ast);
            }
            Stmt addContTo = null;

            if (bestBlock.Value.numConts == 0)
            {
                addContTo = (Stmt)blockInfo.FirstOrDefault(x => x.Value.numConts == 0 && x.Key != bestBlock.Key).Key;
                if (addContTo == null)
                {
                    return(ast);
                }
            }
            var blockAst = (Stmt)bestBlock.Key;

            if (blockAst.StmtType != Stmt.NodeType.Block)
            {
                // Best block must be StmtBlock
                return(ast);
            }
            var stmtBlock = (StmtBlock)blockAst;
            var stmts     = stmtBlock.Statements.ToArray();
            var cont      = bestBlock.Value.numConts == 0 ? new StmtContinuation(ctx, addContTo, false) : (StmtContinuation)stmts.Last();

            var ifSkipContentPhi      = new ExprVarPhi(ctx);
            var ifSkipInitialVar      = ctx.Local(ctx.Boolean);
            var ifSkipContentVar      = ctx.Local(ctx.Boolean);
            var ifSkipContentPhiExprs = new List <Expr> {
                ifSkipInitialVar, ifSkipContentVar
            };
            var ifSkipReset = new StmtAssignment(ctx, ifSkipContentVar, ctx.Literal(false));

            var inIfBlock = new StmtBlock(ctx, stmts.Take(stmts.Length - (bestBlock.Value.numConts == 0 ? 0 : 1)));
            var ifBlock   = new StmtIf(ctx, ctx.ExprGen.Not(ifSkipContentPhi), inIfBlock, null);
            var newBlock  = new StmtBlock(ctx, ifBlock, ifSkipReset, cont);

            ast = VisitorReplace.V(ast, blockAst, newBlock);

            var allConts          = VisitorFindContinuationsRecursive.Get(ast);
            var contsNeedChanging = allConts.Where(x => x != cont && x.To == cont.To).ToArray();
            var contsReplaceInfo  = contsNeedChanging
                                    .Select(x => {
                var ifVar   = ctx.Local(ctx.Boolean);
                var newCont = new StmtBlock(ctx,
                                            new StmtAssignment(ctx, ifVar, ctx.Literal(true)),
                                            new StmtContinuation(ctx, newBlock, x.LeaveProtectedRegion));
                return(new { oldCont = x, ifVar, newCont });
            })
                                    .ToArray();

            foreach (var contReplace in contsReplaceInfo)
            {
                ifSkipContentPhiExprs.Add(contReplace.ifVar);
                ast = VisitorReplace.V(ast, contReplace.oldCont, contReplace.newCont);
            }
            ifSkipContentPhi.Exprs = ifSkipContentPhiExprs;

            // TODO: Shouldn't be required, but definite-assignment doesn't quite work properly, so is required
            var initalSkipVarAssignment = new StmtAssignment(ctx, ifSkipInitialVar, ctx.Literal(false));
            var newAst = new StmtBlock(ctx, initalSkipVarAssignment, (Stmt)ast);

            return(newAst);
        }
 public static ICode V(ICode ast, ICode find, ICode replace) {
     var v = new VisitorReplace(find, replace);
     return v.Visit(ast);
 }
        public static ICode V(ICode ast, ICode find, ICode replace)
        {
            var v = new VisitorReplace(find, replace);

            return(v.Visit(ast));
        }