public void Bool_non_constant_unary_expression_compiled_successfully(string expressionString, Opcode expectedOp)
        {
            var expressionSyntax = ParseExpression(expressionString);
            var method           = new CompiledMethod("Test::Method");
            var builder          = new BasicBlockGraphBuilder().GetInitialBlockBuilder();
            var diagnostics      = new TestingDiagnosticSink();
            var variableMap      = new ScopedVariableMap();

            variableMap.PushScope();
            variableMap.TryAddVariable("a", method.AddLocal(SimpleType.Bool, LocalFlags.None));

            var localIndex = ExpressionCompiler.TryCompileExpression(expressionSyntax,
                                                                     SimpleType.Bool, method, builder, new TestingResolver(variableMap), diagnostics);

            Assert.That(diagnostics.Diagnostics, Is.Empty);
            Assert.That(localIndex, Is.EqualTo(1));
            Assert.That(method.Values[localIndex].Type, Is.EqualTo(SimpleType.Bool));
            Assert.That(builder.Instructions, Has.Exactly(1).Items);

            var instruction = builder.Instructions[0];

            Assert.That(instruction.Operation, Is.EqualTo(expectedOp));
            Assert.That(instruction.Left, Is.EqualTo(0));
            Assert.That(instruction.Destination, Is.EqualTo(1));
        }
        public void Graph_with_two_returning_branches_and_empty_block_succeeds()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var firstBuilder = graphBuilder.GetInitialBlockBuilder();

            var leftBuilder = firstBuilder.CreateSuccessorBlock();

            leftBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);
            var rightBuilder = firstBuilder.CreateBranch(7);

            rightBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);

            // This block does not return nor is referenced, therefore it should be dropped
            var finalBuilder = leftBuilder.CreateSuccessorBlock();

            finalBuilder.AppendInstruction(Opcode.CopyValue, 1, 2, 3);

            var graph = graphBuilder.Build();

            Assert.That(graph.BasicBlocks, Has.Exactly(3).Items);
            Assert.That(graph.BasicBlocks[0].Instructions, Has.Exactly(1).Items);
            Assert.That(graph.BasicBlocks[0].Instructions[0].Operation, Is.EqualTo(Opcode.BranchIf));
            Assert.That(graph.BasicBlocks[0].Instructions[0].Left, Is.EqualTo(7));
            Assert.That(graph.BasicBlocks[0].DefaultSuccessor, Is.EqualTo(1));
            Assert.That(graph.BasicBlocks[0].AlternativeSuccessor, Is.EqualTo(2));

            Assert.That(graph.BasicBlocks[1].Instructions, Has.Exactly(1).Items);
            Assert.That(graph.BasicBlocks[1].DefaultSuccessor, Is.EqualTo(-1));
            CollectionAssert.AreEqual(new[] { 0 }, graph.BasicBlocks[1].Predecessors);

            Assert.That(graph.BasicBlocks[2].Instructions, Has.Exactly(1).Items);
            Assert.That(graph.BasicBlocks[2].DefaultSuccessor, Is.EqualTo(-1));
            CollectionAssert.AreEqual(new[] { 0 }, graph.BasicBlocks[2].Predecessors);
        }
        public void GetInitialBlockBuilder_cannot_be_called_twice()
        {
            var graphBuilder = new BasicBlockGraphBuilder();

            Assert.That(() => graphBuilder.GetInitialBlockBuilder(), Throws.Nothing);
            Assert.That(() => graphBuilder.GetInitialBlockBuilder(), Throws.InvalidOperationException);
        }
        public void Branch_cannot_be_created_if_block_already_ends_in_branch()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            Assert.That(() => blockBuilder.CreateBranch(0), Throws.Nothing);
            Assert.That(() => blockBuilder.CreateBranch(0), Throws.InvalidOperationException);
        }
        public void SetAlternativeSuccessor_cannot_be_called_twice()
        {
            var blockBuilder = new BasicBlockGraphBuilder().GetInitialBlockBuilder();

            Assert.That(() => blockBuilder.SetAlternativeSuccessor(0), Throws.Nothing);
            Assert.That(blockBuilder.AlternativeSuccessor, Is.EqualTo(0));
            Assert.That(() => blockBuilder.SetAlternativeSuccessor(0), Throws.InvalidOperationException);
        }
        public void Branch_cannot_be_created_if_block_ends_in_return()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            blockBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);

            Assert.That(() => blockBuilder.CreateBranch(0), Throws.InvalidOperationException);
        }
        public void Graph_with_out_of_bounds_default_successor_fails(int successor)
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            blockBuilder.SetSuccessor(successor);

            Assert.That(() => graphBuilder.Build(), Throws.InvalidOperationException);
        }
        public void Block_cannot_be_appended_to_after_setting_successor()
        {
            var blockBuilder = new BasicBlockGraphBuilder().GetInitialBlockBuilder();

            blockBuilder.SetSuccessor(0);

            blockBuilder.AppendInstruction(Opcode.Nop, 0, 0, 0);
            Assert.That(blockBuilder.Instructions, Is.Empty);
        }
        public void SetAlternativeSuccessor_does_nothing_if_return_exists()
        {
            var blockBuilder = new BasicBlockGraphBuilder().GetInitialBlockBuilder();

            blockBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);

            Assert.That(() => blockBuilder.SetAlternativeSuccessor(0), Throws.Nothing);
            Assert.That(blockBuilder.AlternativeSuccessor, Is.EqualTo(-1));
        }
        public void Branch_without_default_successor_is_invalid()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            blockBuilder.CreateBranch(0).AppendInstruction(Opcode.Return, 0, 0, 0);

            Assert.That(() => graphBuilder.Build(), Throws.InvalidOperationException);
        }
        public void Appending_to_block_after_adding_return_does_nothing()
        {
            var blockBuilder = new BasicBlockGraphBuilder().GetInitialBlockBuilder();

            blockBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);
            Assert.That(blockBuilder.Instructions, Has.Exactly(1).Items);

            blockBuilder.AppendInstruction(Opcode.Nop, 0, 0, 0);
            Assert.That(blockBuilder.Instructions, Has.Exactly(1).Items);
        }
        public void Branch_without_alternative_successor_is_invalid()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            blockBuilder.AppendInstruction(Opcode.BranchIf, 0, 0, 0);
            blockBuilder.SetSuccessor(0);

            Assert.That(() => graphBuilder.Build(), Throws.InvalidOperationException);
        }
        public void Graph_with_non_returning_branch_fails()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var firstBuilder = graphBuilder.GetInitialBlockBuilder();

            var leftBuilder = firstBuilder.CreateSuccessorBlock();

            leftBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);

            firstBuilder.CreateBranch(7); // This branch has no exit behavior

            Assert.That(() => graphBuilder.Build(), Throws.InvalidOperationException);
        }
        public void GetBuilderByBlockIndex_returns_existent_builders()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var first        = graphBuilder.GetInitialBlockBuilder();

            // Out-of-bounds indices are not tolerated
            Assert.That(() => graphBuilder.GetBuilderByBlockIndex(1), Throws.InstanceOf <ArgumentOutOfRangeException>());

            var second = graphBuilder.GetNewBasicBlock();

            Assert.That(graphBuilder.GetBuilderByBlockIndex(0), Is.SameAs(first));
            Assert.That(graphBuilder.GetBuilderByBlockIndex(1), Is.SameAs(second));
        }
Exemple #15
0
        public void Constant_comparison_compiled_successfully(string expressionString, bool expectedValue)
        {
            var expressionSyntax = ParseExpression(expressionString);
            var method           = new CompiledMethod("Test::Method");
            var builder          = new BasicBlockGraphBuilder().GetInitialBlockBuilder();
            var diagnostics      = new TestingDiagnosticSink();
            var nameResolver     = new TestingResolver(new ScopedVariableMap());

            var localIndex = ExpressionCompiler.TryCompileExpression(expressionSyntax,
                                                                     SimpleType.Bool, method, builder, nameResolver, diagnostics);

            Assert.That(diagnostics.Diagnostics, Is.Empty);
            Assert.That(localIndex, Is.EqualTo(0));
            Assert.That(method.Values[localIndex].Type, Is.EqualTo(SimpleType.Bool));
            AssertSingleLoad(builder, localIndex, expectedValue);
        }
Exemple #16
0
        public void Integer_literal_that_is_too_large_fails()
        {
            var position     = new TextPosition(10, 3, 4);
            var syntax       = new IntegerLiteralSyntax((ulong)int.MaxValue + 1, position);
            var method       = new CompiledMethod("Test::Method");
            var builder      = new BasicBlockGraphBuilder().GetInitialBlockBuilder();
            var nameResolver = new TestingResolver(new ScopedVariableMap());
            var diagnostics  = new TestingDiagnosticSink();

            var localIndex = ExpressionCompiler.TryCompileExpression(
                syntax, SimpleType.Int32, method, builder, nameResolver, diagnostics);

            Assert.That(localIndex, Is.EqualTo(-1));
            diagnostics.AssertDiagnosticAt(DiagnosticCode.TypeMismatch, position)
            .WithActual("uint32").WithExpected("int32");
        }
Exemple #17
0
        public void Variable_reference_must_refer_to_existent_variable()
        {
            var position    = new TextPosition(10, 3, 4);
            var syntax      = new IdentifierSyntax("a", position);
            var method      = new CompiledMethod("Test::Method");
            var builder     = new BasicBlockGraphBuilder().GetInitialBlockBuilder();
            var diagnostics = new TestingDiagnosticSink();
            var variableMap = new ScopedVariableMap();

            variableMap.PushScope();

            var localIndex = ExpressionCompiler.TryCompileExpression(
                syntax, SimpleType.Int32, method, builder, new TestingResolver(variableMap), diagnostics);

            Assert.That(localIndex, Is.EqualTo(-1));
            diagnostics.AssertDiagnosticAt(DiagnosticCode.VariableNotFound, position).WithActual("a");
        }
        public void Graph_with_single_basic_block_succeeds()
        {
            var graphBuilder = new BasicBlockGraphBuilder();
            var blockBuilder = graphBuilder.GetInitialBlockBuilder();

            blockBuilder.AppendInstruction(Opcode.Return, 0, 0, 0);

            Assert.That(blockBuilder.Index, Is.EqualTo(0));

            var graph = graphBuilder.Build();

            Assert.That(graph.BasicBlocks, Has.Exactly(1).Items);
            Assert.That(graph.BasicBlocks[0].Instructions, Has.Exactly(1).Items);
            Assert.That(graph.BasicBlocks[0].Instructions[0].Operation, Is.EqualTo(Opcode.Return));
            Assert.That(graph.BasicBlocks[0].DefaultSuccessor, Is.EqualTo(-1));
            Assert.That(graph.BasicBlocks[0].AlternativeSuccessor, Is.EqualTo(-1));
            Assert.That(graph.BasicBlocks[0].Predecessors, Is.Empty);
        }
Exemple #19
0
        public void Int32_division_by_zero_in_constant_expression_fails(BinaryOperation op)
        {
            var position = new TextPosition(10, 3, 4);
            var syntax   = new BinaryExpressionSyntax(op,
                                                      new IntegerLiteralSyntax(2ul, default),
                                                      new IntegerLiteralSyntax(0, default),
                                                      position);
            var method       = new CompiledMethod("Test::Method");
            var builder      = new BasicBlockGraphBuilder().GetInitialBlockBuilder();
            var diagnostics  = new TestingDiagnosticSink();
            var nameResolver = new TestingResolver(new ScopedVariableMap());

            var localIndex = ExpressionCompiler.TryCompileExpression(
                syntax, SimpleType.Int32, method, builder, nameResolver, diagnostics);

            Assert.That(localIndex, Is.EqualTo(-1));
            diagnostics.AssertDiagnosticAt(DiagnosticCode.DivisionByConstantZero, position);
        }