public void ReachingDefinitions()
        {
            var program   = @"
var i, m, j, n, a, u1, u2, u3, k;
1: i = m - 1;
2: j = n;
3: a = u1;

for k = 0, 1
{
    i = i + 1;
    j = j - 1;

    if i < j
        a = u2;
    i = u3;
}
";
            var graph     = GenCFG(program);
            var algorithm = new LiveVariables();

            _ = algorithm.Execute(graph);
            var iterationsFast = algorithm.Iterations;

            _ = algorithm.Execute(graph, false);
            var iterationsSlow = algorithm.Iterations;

            Assert.LessOrEqual(iterationsFast, iterationsSlow);
        }
        public void LiveVariables()
        {
            var program   = @"
var a, b, c, i;

for i = 1, b
{
    input(a);
    c = c + a;
    print(c);
    if c < b
        c = c + 1;
    else
    {
        b = b - 1;
        print(b);
        print(c);
    }
}

print(c + a + b);
";
            var graph     = GenCFG(program);
            var algorithm = new LiveVariables();

            _ = algorithm.Execute(graph);
            var iterationsFast = algorithm.Iterations;

            _ = algorithm.Execute(graph, false);
            var iterationsSlow = algorithm.Iterations;

            Assert.LessOrEqual(iterationsFast, iterationsSlow);
        }
Exemple #3
0
        private List <(HashSet <string> IN, HashSet <string> OUT)> Execute(List <Instruction> TAC)
        {
            var cfg = GenCFG(TAC);

            var liveAct = new LiveVariables();

            liveAct.ExecuteInternal(cfg);

            var listAct = liveAct.dictInOut
                          .Select(x => x.Value)
                          .Select(y => (y.IN as HashSet <string>, y.OUT as HashSet <string>));

            return(listAct.ToList());
        }
Exemple #4
0
        public static void DeleteDeadCode(ControlFlowGraph cfg)
        {
            var info = new LiveVariables().Execute(cfg);

            foreach (var block in cfg.GetCurrentBasicBlocks())
            {
                var blockInfo = info[block].Out;
                (var wasChanged, var newInstructions) = DeleteDeadCodeWithDeadVars.DeleteDeadCode(block.GetInstructions(), blockInfo);
                if (wasChanged)
                {
                    block.ClearInstructions();
                    block.AddRangeOfInstructions(newInstructions);
                }
            }
        }
Exemple #5
0
        private void Transform(FunctionDeclarationSyntax function, LiveVariables liveness)
        {
            var graph   = function.ControlFlow;
            var builder = new ControlFlowGraphBuilder(graph.VariableDeclarations);

            foreach (var block in graph.BasicBlocks)
            {
                var blockBuilder = builder.NewBlock();
                if (block.Number != blockBuilder.BlockNumber)
                {
                    throw new Exception("New block number does not match old block number");
                }

                foreach (var statement in block.ExpressionStatements)
                {
                    // Copy the existing statement
                    blockBuilder.Add(statement);

                    var before = liveness.Before(statement);
                    var after  = liveness.After(statement);
                    // dead = live before and not live after
                    var dead = ((BitArray)after.Clone()).Not().And(before);
                    foreach (var variableNumber in dead.TrueIndexes())
                    {
                        var variable = graph.VariableDeclarations[variableNumber];
                        if (variable.Type is ObjectType type &&
                            type.IsOwned)
                        {
                            // The delete happens after the last statement
                            var span = new TextSpan(statement.Span.End, 0);
                            blockBuilder.AddDelete(new VariableReference(variableNumber, span), type, span);
                        }
                    }
                }
                // TODO what about if there is a variable delete after the terminator?
                blockBuilder.Add(block.Terminator);
            }

            function.ControlFlow = builder.Build();
        }
Exemple #6
0
        public static void Main()
        {
            var FileName = @"../../../a.txt";

            try
            {
                var Text = File.ReadAllText(FileName);

                var scanner = new Scanner();
                scanner.SetSource(Text, 0);

                var parser = new Parser(scanner);

                var b = parser.Parse();
                if (!b)
                {
                    Console.WriteLine("Error");
                }
                else
                {
                    Console.WriteLine("Syntax tree built");

                    var fillParents = new FillParentsVisitor();
                    parser.root.Visit(fillParents);

                    var pp = new PrettyPrintVisitor();
                    parser.root.Visit(pp);
                    Console.WriteLine(pp.Text);

                    ASTOptimizer.Optimize(parser);
                    Console.WriteLine("\n\nAfter AST optimizations");
                    pp = new PrettyPrintVisitor();
                    parser.root.Visit(pp);
                    Console.WriteLine(pp.Text);

                    Console.WriteLine("\n\nThree address code");
                    var threeAddrCodeVisitor = new ThreeAddrGenVisitor();
                    parser.root.Visit(threeAddrCodeVisitor);
                    var threeAddressCode = threeAddrCodeVisitor.Instructions;
                    foreach (var instruction in threeAddressCode)
                    {
                        Console.WriteLine(instruction);
                    }

                    Console.WriteLine("\n\nOptimized three address code");
                    var optResult = ThreeAddressCodeOptimizer.OptimizeAll(threeAddressCode);
                    foreach (var x in optResult)
                    {
                        Console.WriteLine(x);
                    }

                    Console.WriteLine("\n\nDivided three address code");
                    var divResult = BasicBlockLeader.DivideLeaderToLeader(optResult);


                    foreach (var x in divResult)
                    {
                        foreach (var y in x.GetInstructions())
                        {
                            Console.WriteLine(y);
                        }
                        Console.WriteLine("--------------");
                    }

                    var cfg = new ControlFlowGraph(divResult);

                    Console.WriteLine("\n\n Edge Classification");
                    Console.WriteLine("----------");

                    foreach (var pair in cfg.ClassifiedEdges)
                    {
                        Console.WriteLine(pair);
                    }

                    Console.WriteLine("----------");


                    foreach (var block in cfg.GetCurrentBasicBlocks())
                    {
                        Console.WriteLine($"{cfg.VertexOf(block)}  {block.GetInstructions()[0]}");
                        var children    = cfg.GetChildrenBasicBlocks(cfg.VertexOf(block));
                        var childrenStr = string.Join(" | ", children.Select(v => v.block.GetInstructions()[0].ToString()));
                        Console.WriteLine($" children: {childrenStr}");

                        var parents    = cfg.GetParentsBasicBlocks(cfg.VertexOf(block));
                        var parentsStr = string.Join(" | ", parents.Select(v => v.block.GetInstructions()[0].ToString()));
                        Console.WriteLine($" parents: {parentsStr}");
                    }

                    ///
                    /// LiveVariableAnalysisAlgorithm
                    ///
                    Console.WriteLine("------------");
                    Console.WriteLine();
                    var activeVariable    = new LiveVariables();
                    var resActiveVariable = activeVariable.Execute(cfg);

                    foreach (var x in resActiveVariable)
                    {
                        foreach (var y in x.Value.In)
                        {
                            Console.WriteLine("In " + y);
                        }
                        Console.WriteLine();
                        foreach (var y in x.Value.Out)
                        {
                            Console.WriteLine("Out " + y);
                        }
                    }


                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine("NatLoop");
                    var natLoops = NaturalLoop.GetAllNaturalLoops(cfg);
                    foreach (var x in natLoops)
                    {
                        if (x.Count == 0)
                        {
                            continue;
                        }
                        //Console.WriteLine("Loop");
                        for (var i = 0; i < x.Count; i++)
                        {
                            Console.WriteLine("NumberBlock:" + i);
                            foreach (var xfrom in x[i].GetInstructions())
                            {
                                Console.WriteLine(xfrom.ToString());
                            }
                        }
                        Console.WriteLine();
                        Console.WriteLine("-------------");
                    }

                    Console.WriteLine(" \nDone");
                }
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("File {0} not found", FileName);
            }
            catch (LexException e)
            {
                Console.WriteLine("Lex Error. " + e.Message);
            }
            catch (SyntaxException e)
            {
                Console.WriteLine("Syntax Error. " + e.Message);
            }
            _ = Console.ReadLine();
        }
Exemple #7
0
        public void LiveVariables()
        {
            var program = @"
var a, b, c;

input(b);
a = b + 1;
if a < c
    c = b - a;
else
    c = b + a;
print(c);
";

            var cfg = GenCFG(program);
            var resActiveVariable = new LiveVariables().Execute(cfg);
            var actual            = cfg.GetCurrentBasicBlocks()
                                    .Select(z => resActiveVariable[z])
                                    .Select(p => ((IEnumerable <string>)p.In, (IEnumerable <string>)p.Out))
                                    .ToList();

            var expected =
                new List <(IEnumerable <string>, IEnumerable <string>)>()
            {
                (new HashSet <string>()
                {
                    "c"
                }, new HashSet <string>()
                {
                    "c"
                }),
                (new HashSet <string>()
                {
                    "c"
                }, new HashSet <string>()
                {
                    "a", "b"
                }),
                (new HashSet <string>()
                {
                    "a", "b"
                }, new HashSet <string>()
                {
                    "c"
                }),
                (new HashSet <string>()
                {
                    "a", "b"
                }, new HashSet <string>()
                {
                    "c"
                }),
                (new HashSet <string>()
                {
                    "c"
                }, new HashSet <string>()
                {
                }),
                (new HashSet <string>()
                {
                }, new HashSet <string>()
                {
                })
            };

            AssertSet(expected, actual);
        }
Exemple #8
0
        private static LiveVariables ComputeLiveness(ControlFlowGraph function, Edges edges)
        {
            var blocks = new Queue <BasicBlock>();

            blocks.EnqueueRange(function.ExitBlocks);
            var liveVariables     = new LiveVariables(function);
            var numberOfVariables = function.VariableDeclarations.Count;

            while (blocks.TryDequeue(out var block))
            {
                var liveBeforeBlock = new BitArray(liveVariables.Before(block.Statements.First()));

                var liveAfterBlock = new BitArray(numberOfVariables);
                foreach (var successor in edges.From(block))
                {
                    liveAfterBlock.Or(liveVariables.Before(successor.Statements.Last()));
                }

                var liveAfterStatement = liveAfterBlock;

                foreach (var statement in block.Statements.Reverse())
                {
                    var liveSet = liveVariables.Before(statement);
                    liveSet.Or(liveAfterStatement);
                    switch (statement)
                    {
                    case AssignmentStatement assignment:
                        KillVariables(liveSet, assignment.Place);
                        EnlivenVariables(liveSet, assignment.Value);
                        break;

                    case ActionStatement action:
                        EnlivenVariables(liveSet, action.Value);
                        break;

                    case DeleteStatement _:
                        throw new InvalidOperationException("Delete statements are supposed to be added after liveness analysis");

                    //liveSet[deleteStatement.Place.CoreVariable()] = true;
                    //break;
                    case IfStatement _:
                    case GotoStatement _:
                        // We already or'ed together the live variables from successor blocks
                        break;

                    case ReturnStatement _:
                        // No effect on variables?
                        // TODO should we check the liveSet is empty?
                        break;

                    default:
                        throw NonExhaustiveMatchException.For(statement);
                    }

                    // For the next statement
                    liveAfterStatement = liveSet;
                }

                if (!liveBeforeBlock.ValuesEqual(liveVariables.Before(block.Statements.First())))
                {
                    foreach (var basicBlock in edges.To(block)
                             .Where(fromBlock => !blocks.Contains(fromBlock)).ToList())
                    {
                        blocks.Enqueue(basicBlock);
                    }
                }
            }
            return(liveVariables);
        }