public void Boolean_binary_ops(string highOp, string expectedLowOp) { var source = $@" ; #0 bool ; #1 bool ; #2 bool BB_0: Load true -> #0 Load false -> #1 {highOp} #0 ?? #1 -> #2 Return #2 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); var expected = $@" ; #0 bool [?] ; #1 bool [?] ; #2 bool [?] ; #3 bool [rax] LB_0: LoadInt 0 0 1 -> 0 LoadInt 0 0 0 -> 1 {expectedLowOp} 0 1 0 -> 2 Move 2 0 0 -> 3 Return 3 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Boolean_set_from_comparison(string highOp, string expectedLowOp) { var source = $@" ; #0 int32 ; #1 int32 ; #2 bool BB_0: Load 1234 -> #0 Load 5678 -> #1 {highOp} #0 ?? #1 -> #2 Return #2 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); var expected = $@" ; #0 int32 [?] ; #1 int32 [?] ; #2 bool [?] ; #3 bool [rax] LB_0: LoadInt 0 0 1234 -> 0 LoadInt 0 0 5678 -> 1 Compare 0 1 0 -> 0 {expectedLowOp} 0 0 0 -> 2 Move 2 0 0 -> 3 Return 3 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Boolean_negation() { const string source = @" ; #0 bool ; #1 bool BB_0: Load false -> #0 BitwiseNot #0 -> #1 Return #1 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); const string expected = @" ; #0 bool [?] ; #1 bool [?] ; #2 bool [rax] LB_0: LoadInt 0 0 0 -> 0 Test 0 0 0 -> 0 SetIfEqual 0 0 0 -> 1 Move 1 0 0 -> 2 Return 2 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Integer_shift(string highOp, string expectedLowOp) { var source = $@" ; #0 int32 ; #1 int32 ; #2 int32 BB_0: Load 1234 -> #0 Load 5678 -> #1 {highOp} #0 ?? #1 -> #2 Return #2 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); var expected = $@" ; #0 int32 [?] ; #1 int32 [?] ; #2 int32 [?] ; #3 int32 [rcx] ; #4 int32 [rax] LB_0: LoadInt 0 0 1234 -> 0 LoadInt 0 0 5678 -> 1 Move 1 0 0 -> 3 {expectedLowOp} 0 3 0 -> 2 Move 2 0 0 -> 4 Return 4 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Integer_modulo() { const string source = @" ; #0 int32 ; #1 int32 ; #2 int32 BB_0: Load 1234 -> #0 Load 56 -> #1 Modulo #0 % #1 -> #2 Return #2 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); // The dividend must be in RAX and the result in RDX const string expected = @" ; #0 int32 [?] ; #1 int32 [?] ; #2 int32 [?] ; #3 int32 [rax] ; #4 int32 [rdx] ; #5 int32 [rax] LB_0: LoadInt 0 0 1234 -> 0 LoadInt 0 0 56 -> 1 Move 0 0 0 -> 3 IntegerModulo 3 1 0 -> 4 Move 4 0 0 -> 2 Move 2 0 0 -> 5 Return 5 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Integer_unary_arithmetic(string highOp, string expectedLowOp) { var source = $@" ; #0 int32 ; #1 int32 BB_0: Load 1234 -> #0 {highOp} #0 -> #1 Return #1 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); var expected = $@" ; #0 int32 [?] ; #1 int32 [?] ; #2 int32 [rax] LB_0: LoadInt 0 0 1234 -> 0 {expectedLowOp} 0 0 0 -> 1 Move 1 0 0 -> 2 Return 2 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Integer_compare_and_branch() { const string source = @" ; #0 int32 ; #1 int32 ; #2 bool ; #3 int32 ; #4 int32 BB_0: Load 1234 -> #0 Load 5678 -> #1 Equal #0 == #1 -> #2 BranchIf #2 ==> BB_1 ==> BB_2 BB_1: Load 1 -> #3 Return #3 BB_2: Load 2 -> #4 Return #4 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); const string expected = @" ; #0 int32 [?] ; #1 int32 [?] ; #2 bool [?] ; #3 int32 [?] ; #4 int32 [?] ; #5 int32 [rax] ; #6 int32 [rax] LB_0: LoadInt 0 0 1234 -> 0 LoadInt 0 0 5678 -> 1 Compare 0 1 0 -> 0 SetIfEqual 0 0 0 -> 2 Test 2 0 0 -> 0 JumpIfNotEqual 0 0 0 -> 1 Jump 0 0 0 -> 2 LB_1: LoadInt 0 0 1 -> 3 Move 3 0 0 -> 5 Return 5 0 0 -> 0 LB_2: LoadInt 0 0 2 -> 4 Move 4 0 0 -> 6 Return 6 0 0 -> 0 "; AssertDump(lowered, expected); Assert.That(lowered.Blocks[0].Predecessors, Is.Empty); Assert.That(lowered.Blocks[0].Successors, Is.EqualTo(new int[] { 1, 2 })); Assert.That(lowered.Blocks[1].Predecessors, Is.EqualTo(new int[] { 0 })); Assert.That(lowered.Blocks[1].Successors, Is.Empty); Assert.That(lowered.Blocks[2].Predecessors, Is.EqualTo(new int[] { 0 })); Assert.That(lowered.Blocks[2].Successors, Is.Empty); }
public void Boolean_compare_and_branch() { const string source = @" ; #0 bool ; #1 int32 ; #2 int32 BB_0: Load true -> #0 BranchIf #0 ==> BB_1 ==> BB_2 BB_1: Load 1 -> #1 Return #1 BB_2: Load 2 -> #2 Return #2 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); const string expected = @" ; #0 bool [?] ; #1 int32 [?] ; #2 int32 [?] ; #3 int32 [rax] ; #4 int32 [rax] LB_0: LoadInt 0 0 1 -> 0 Test 0 0 0 -> 0 JumpIfNotEqual 0 0 0 -> 1 Jump 0 0 0 -> 2 LB_1: LoadInt 0 0 1 -> 1 Move 1 0 0 -> 3 Return 3 0 0 -> 0 LB_2: LoadInt 0 0 2 -> 2 Move 2 0 0 -> 4 Return 4 0 0 -> 0 "; AssertDump(lowered, expected); }
public void Constant_integer_load_and_return() { const string source = @" ; #0 int32 BB_0: Load 1234 -> #0 Return #0 "; var method = MethodAssembler.Assemble(source, "Test::Method"); var lowered = LoweringX64.Lower(method); const string expected = @" ; #0 int32 [?] ; #1 int32 [rax] LB_0: LoadInt 0 0 1234 -> 0 Move 0 0 0 -> 1 Return 1 0 0 -> 0 "; AssertDump(lowered, expected); }