Ejemplo n.º 1
0
        public static void RunExpressionTest(InstructionSpan instructions, Expression expectedExpression)
        {
            // Add a `pop` to the end to make it a full statement
            instructions = BuildSpan(
                instructions.First.Offset,
                Enumerable.Concat(instructions, new[] { Instruction.Create(OpCodes.Pop) }));

            var controlFlowGraph = ControlFlowGraphBuilder.Build(instructions.ToList(), Array.Empty <ExceptionHandler>());
            var actualGraph      = SyntaxGraphBuilder.Create(controlFlowGraph, new MethodVariables());

            // Extract the expression
            Assert.Equal(1, actualGraph.Nodes.Count);

            var node = actualGraph.Nodes.First();

            Assert.Equal(1, node.Statements.Count);
            var discardStatement = Assert.IsType <DiscardStatement>(node.Statements.Single());

            Assert.Equal(expectedExpression, discardStatement.Value);
        }
Ejemplo n.º 2
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();
        }
Ejemplo n.º 3
0
        private static async Task <int> Execute(string assemblyPath, string typeName, string memberName, string outFile, string format)
        {
            var disassembler = new DisassemblerSession();

            var disassembly = await disassembler.LoadAsync(assemblyPath);

            var type = disassembly.FindType(typeName);

            if (type == null)
            {
                return(Error($"could not find type: {typeName}"));
            }
            var member = type.Members.FirstOrDefault(t => t.Name.Equals(memberName));

            if (member == null)
            {
                return(Error($"could not find member: {memberName} in type {typeName}"));
            }

            ControlFlowGraph graph = null;

            if (member.MemberType == MemberType.Method)
            {
                graph = ControlFlowGraphBuilder.Build(((MethodDefinition)member.Definition).Body);
            }
            else
            {
                return(Error($"Member type not supported: {member.MemberType}"));
            }

            if (!string.IsNullOrEmpty(outFile))
            {
                format = string.IsNullOrEmpty(format) ? "dot" : format;
                if (!Formats.TryGetValue(format, out var handler))
                {
                    return(Error($"Unknown format: {format}"));
                }
                await handler(graph, outFile);
            }
            else
            {
                Console.WriteLine($"Control flow graph for {typeName}.{memberName}");

                foreach (var node in graph.Nodes)
                {
                    Console.WriteLine();
                    Console.WriteLine(node.ToString());
                }

                // Write Exception handlers
                foreach (var handler in graph.ExceptionHandlers)
                {
                    Console.WriteLine();
                    Console.WriteLine("  .try {");
                    Console.WriteLine($"    IL_{handler.TryStart.Offset:X4} -> IL_{handler.TryEnd.Offset:X4}");
                    Console.WriteLine("  }");
                    Console.WriteLine($"  {FormatHandlerType(handler)} {{");
                    if (handler.HandlerType == ExceptionHandlerType.Filter)
                    {
                        Console.WriteLine($"    IL_{handler.FilterStart.Offset:X4} -> IL_{handler.HandlerStart.Offset:X4}");
                        Console.WriteLine("  }");
                        Console.WriteLine("  .catch {");
                    }
                    Console.WriteLine($"    IL_{handler.HandlerStart.Offset:X4} -> IL_{handler.HandlerEnd.Offset:X4}");
                    Console.WriteLine("  }");
                }
            }

            Console.WriteLine();

            return(0);
        }
Ejemplo n.º 4
0
        private static async Task <int> Execute(string assemblyPath, string typeName, string memberName)
        {
            var disassembler = new DisassemblerSession();

            var disassembly = await disassembler.LoadAsync(assemblyPath);

            var type = disassembly.FindType(typeName);

            if (type == null)
            {
                return(Error($"could not find type: {typeName}"));
            }
            var member = type.Members.FirstOrDefault(t => t.Name.Equals(memberName));

            if (member == null)
            {
                return(Error($"could not find member: {memberName} in type {typeName}"));
            }

            ControlFlowGraph graph  = null;
            MethodDefinition method = null;

            if (member.MemberType == MemberType.Method)
            {
                method = (MethodDefinition)member.Definition;
                graph  = ControlFlowGraphBuilder.Build(method.Body);
            }
            else
            {
                return(Error($"Member type not supported: {member.MemberType}"));
            }

            var syntax = SyntaxGraphBuilder.Create(graph, method);

            var arguments = string.Join(", ", method.Parameters.Select(p => $"{p.ParameterType.FullName} {p.Name}"));

            Console.WriteLine($"Syntax analysis for {typeName}.{memberName}({arguments})");

            if (method.Body.Variables.Any())
            {
                Console.WriteLine();

                foreach (var local in method.Body.Variables)
                {
                    Console.WriteLine($"  .local {local.VariableType.FullName} _{local.Index}");
                }
            }

            foreach (var node in syntax.Nodes)
            {
                Console.WriteLine();
                Console.WriteLine($"  {node.DisplayName} : {{");
                foreach (var statement in node.Statements)
                {
                    Console.WriteLine($"    {statement}");
                }
                Console.WriteLine($"  }}{FormatLinks(node)}");
            }

            Console.WriteLine();

            return(0);
        }
Ejemplo n.º 5
0
        public static void RunControlFlowTest(InstructionSpan instructions, ControlFlowGraph expectedGraph)
        {
            var actualGraph = ControlFlowGraphBuilder.Build(instructions.ToList(), Array.Empty <ExceptionHandler>());

            Assert.Equal(expectedGraph, actualGraph, TestControlFlowGraphComparer.Instance);
        }
Ejemplo n.º 6
0
        private static ConstructorDeclaration BuildDefaultConstructor(
            ClassDeclarationSyntax classDeclaration)
        {
            var className       = classDeclaration.FullName;
            var constructorName = className.Qualify(SpecialName.New);
            var selfType        = ((Metatype)classDeclaration.Type.Resolved()).Instance;
            var selfName        = className.Qualify(SpecialName.Self);
            var selfParameter   = new Parameter(true, selfName, selfType);
            var parameters      = selfParameter.Yield().ToFixedList();
            var constructorType = new FunctionType(selfType.Yield(), selfType);

            var graph = new ControlFlowGraphBuilder();

            graph.AddParameter(true, selfType, SpecialName.Self);
            var block = graph.NewBlock();

            block.AddReturn();
            var defaultConstructor = new ConstructorDeclaration(constructorName, constructorType,
                                                                parameters, selfType, graph.Build());

            return(defaultConstructor);
        }