Ejemplo n.º 1
0
        protected override ICode VisitVarPhi(ExprVarPhi e)
        {
            if (e.Exprs.Count() == 1)
            {
                return(this.Visit(e.Exprs.First()));
            }
            var exprNew = e.Exprs.Select(x => (Expr)this.Visit(x)).ToArray();
            var exprs   = exprNew
                          .SelectMany(x => {
                if (x == null)
                {
                    return(Enumerable.Empty <Expr>());
                }
                if (x.ExprType == Expr.NodeType.VarPhi)
                {
                    return(((ExprVarPhi)x).Exprs);
                }
                return(new[] { x });
            })
                          .Distinct(Expr.EqComparerExact)
                          .ToArray();

            if (exprs.SequenceEqual(e.Exprs))
            {
                return(e);
            }
            else
            {
                return(new ExprVarPhi(e.Ctx)
                {
                    Exprs = exprs
                });
            }
        }
Ejemplo n.º 2
0
        protected virtual ICode VisitVarPhi(ExprVarPhi e)
        {
            this.ThrowOnNoOverride();
            var c = this.HandleList(e.Exprs, x => (Expr)this.Visit(x));

            if (c == null)
            {
                return(e);
            }
            else
            {
                var exprs = c.SelectMany(x => {
                    if (x == null)
                    {
                        return(Enumerable.Empty <Expr>());
                    }
                    if (x.ExprType == Expr.NodeType.VarPhi)
                    {
                        return(((ExprVarPhi)x).Exprs);
                    }
                    else
                    {
                        return(new[] { x });
                    }
                })
                            .ToArray();
                return(new ExprVarPhi(e.Ctx)
                {
                    Exprs = exprs
                });
            }
        }
Ejemplo n.º 3
0
 protected override ICode VisitVarPhi(ExprVarPhi e)
 {
     if (e.Type.IsBoolean())
     {
         List <Expr> newExprs = null;
         foreach (var expr in e.Exprs)
         {
             var mustConvert = !expr.Type.IsBoolean();
             var newExpr     = mustConvert ? this.ConvertToBoolean(expr) : expr;
             if (mustConvert && newExprs == null)
             {
                 newExprs = new List <Expr>(e.Exprs.TakeWhile(x => x != expr));
             }
             if (newExprs != null)
             {
                 newExprs.Add(newExpr);
             }
         }
         if (newExprs != null)
         {
             return(new ExprVarPhi(e.Ctx)
             {
                 Exprs = newExprs
             });
         }
     }
     return(e);
 }
Ejemplo n.º 4
0
        protected override ICode VisitVarPhi(ExprVarPhi e)
        {
            bool finalise = false;

            if (this.phiSeen == null)
            {
                this.phiSeen = new HashSet <ExprVarPhi>();
                finalise     = true;
            }
            this.code.AppendFormat("phi<{0}>(", e.GetHashCode());
            if (this.phiSeen.Add(e))
            {
                foreach (var v in e.Exprs)
                {
                    this.Visit(v);
                    this.code.Append(",");
                }
                this.code.Length--;
            }
            else
            {
                this.code.AppendFormat("<rec-{0}>", e.GetHashCode());
            }
            this.code.Append(")");
            if (finalise)
            {
                this.phiSeen = null;
            }
            return(e);
        }
        protected override ICode VisitVarPhi(ExprVarPhi e)
        {
            // Variables within phi's cannot be removed
            this.inPhiCount++;
            var ret = base.VisitVarPhi(e);

            this.inPhiCount--;
            return(ret);
        }
Ejemplo n.º 6
0
        protected override ICode VisitAssignment(StmtAssignment s)
        {
            var ctx       = s.Ctx;
            var newTarget = ctx.Local(s.Target.Type);
            var phi       = new ExprVarPhi(ctx)
            {
                Exprs = new[] { s.Target, newTarget }
            };

            this.phiMap.Add(s.Target, phi);
            return(new StmtAssignment(s.Ctx, newTarget, (Expr)this.Visit(s.Expr)));
        }
Ejemplo n.º 7
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);
            }
        }
Ejemplo n.º 8
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);
            }
        }
Ejemplo n.º 9
0
 protected override ICode VisitVarPhi(ExprVarPhi e)
 {
     this.clusters.Add(e.Exprs.OfType <ExprVar>().Concat(e).ToArray());
     return(e);
 }
Ejemplo n.º 10
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);
        }