From c6a1c234b37b7d7eace0f5de7756cae97f16ec9e Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Fri, 4 Nov 2022 21:35:50 +0530 Subject: [PATCH 01/10] X86: Support diagnostics in asr_to_x86() --- src/bin/lpython.cpp | 2 +- src/libasr/codegen/asr_to_x86.cpp | 10 +++++++--- src/libasr/codegen/asr_to_x86.h | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 38e113f1df..58b71e2779 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -757,7 +757,7 @@ int compile_to_binary_x86( // ASR -> X86 auto asr_to_x86_start = std::chrono::high_resolution_clock::now(); - LFortran::Result r3 = LFortran::asr_to_x86(*asr, al, outfile, time_report); + LFortran::Result r3 = LFortran::asr_to_x86(*asr, al, outfile, time_report, diagnostics); auto asr_to_x86_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("ASR to X86", std::chrono::duration(asr_to_x86_end - asr_to_x86_start).count())); std::cerr << diagnostics.render(input, lm, compiler_options); diff --git a/src/libasr/codegen/asr_to_x86.cpp b/src/libasr/codegen/asr_to_x86.cpp index af0c88722c..e8f8836755 100644 --- a/src/libasr/codegen/asr_to_x86.cpp +++ b/src/libasr/codegen/asr_to_x86.cpp @@ -526,7 +526,8 @@ class ASRToX86Visitor : public ASR::BaseVisitor Result asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al, - const std::string &filename, bool time_report) + const std::string &filename, bool time_report, + diag::Diagnostics &diagnostics) { int time_pass_global=0; int time_pass_do_loops=0; @@ -558,8 +559,8 @@ Result asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al, try { v.visit_asr((ASR::asr_t &)asr); } catch (const CodeGenError &e) { - Error error; - return error; + diagnostics.diagnostics.push_back(e.d); + return Error(); } auto t2 = std::chrono::high_resolution_clock::now(); time_visit_asr = std::chrono::duration_cast(t2 - t1).count(); @@ -579,6 +580,9 @@ Result asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al, time_save = std::chrono::duration_cast(t2 - t1).count(); } + //! Helpful for debugging + // std::cout << v.m_a.get_asm() << std::endl; + if (time_report) { std::cout << "Codegen Time report:" << std::endl; std::cout << "Global: " << std::setw(5) << time_pass_global << std::endl; diff --git a/src/libasr/codegen/asr_to_x86.h b/src/libasr/codegen/asr_to_x86.h index 39b2e5803d..b4a3bce170 100644 --- a/src/libasr/codegen/asr_to_x86.h +++ b/src/libasr/codegen/asr_to_x86.h @@ -7,7 +7,8 @@ namespace LFortran { // Generates a 32-bit x86 Linux executable binary `filename` Result asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al, - const std::string &filename, bool time_report); + const std::string &filename, bool time_report, + diag::Diagnostics &diagnostics); } // namespace LFortran From e36a105bae00180db17c4bed4627b6b95c35ab1c Mon Sep 17 00:00:00 2001 From: Ubaid Date: Fri, 4 Nov 2022 21:18:19 +0530 Subject: [PATCH 02/10] WASM: Emit else always --- src/libasr/codegen/asr_to_wasm.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index ced4b8f0aa..c1227f4287 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -2044,11 +2044,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { for (size_t i = 0; i < x.n_body; i++) { this->visit_stmt(*x.m_body[i]); } - if (x.n_orelse) { - wasm::emit_b8(m_code_section, m_al, 0x05); // starting of else - for (size_t i = 0; i < x.n_orelse; i++) { - this->visit_stmt(*x.m_orelse[i]); - } + wasm::emit_b8(m_code_section, m_al, 0x05); // starting of else + for (size_t i = 0; i < x.n_orelse; i++) { + this->visit_stmt(*x.m_orelse[i]); } nesting_level--; wasm::emit_expr_end(m_code_section, m_al); // emit if end @@ -2115,6 +2113,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } wasm::emit_i32_const(m_code_section, m_al, 1); // non-zero exit code exit(); + wasm::emit_b8(m_code_section, m_al, 0x05); // starting of else wasm::emit_expr_end(m_code_section, m_al); // emit if end } }; From e2a67dc013687239769618250716e13f2c02cafb Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Fri, 4 Nov 2022 21:47:15 +0530 Subject: [PATCH 03/10] WASM_X86: Implement Visit if-else --- src/libasr/codegen/wasm_to_x86.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index fcd24124e4..efe701d70f 100644 --- a/src/libasr/codegen/wasm_to_x86.cpp +++ b/src/libasr/codegen/wasm_to_x86.cpp @@ -16,6 +16,7 @@ class X86Visitor : public WASMDecoder, public: X86Assembler &m_a; uint32_t cur_func_idx; + std::vector unique_id; X86Visitor(X86Assembler &m_a, Allocator &al, diag::Diagnostics &diagonostics, Vec &code) @@ -68,6 +69,27 @@ class X86Visitor : public WASMDecoder, } } + void visit_EmtpyBlockType() {} + + void visit_If() { + unique_id.push_back(offset); + m_a.asm_pop_r32(X86Reg::eax); + m_a.asm_cmp_r32_imm8(LFortran::X86Reg::eax, 1); + m_a.asm_je_label(".then_" + std::to_string(unique_id.back())); + m_a.asm_jmp_label(".else_" + std::to_string(unique_id.back())); + m_a.add_label(".then_" + std::to_string(unique_id.back())); + { + decode_instructions(); + } + m_a.add_label(".endif_" + std::to_string(unique_id.back())); + unique_id.pop_back(); + } + + void visit_Else() { + m_a.asm_jmp_label(".endif_" + std::to_string(unique_id.back())); + m_a.add_label(".else_" + std::to_string(unique_id.back())); + } + void visit_LocalGet(uint32_t localidx) { X86Reg base = X86Reg::ebp; int no_of_params = From 289f4a53eacf4179a50a9ec8307e26ad32788913 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Fri, 4 Nov 2022 21:47:51 +0530 Subject: [PATCH 04/10] WASM_X86: Minor debugging help --- src/libasr/codegen/wasm_to_x86.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index efe701d70f..c298349a20 100644 --- a/src/libasr/codegen/wasm_to_x86.cpp +++ b/src/libasr/codegen/wasm_to_x86.cpp @@ -252,6 +252,9 @@ Result wasm_to_x86(Vec &wasm_bytes, Allocator &al, .count(); } + //! Helpful for debugging + // std::cout << x86_visitor.m_a.get_asm() << std::endl; + if (time_report) { std::cout << "Codegen Time report:" << std::endl; std::cout << "Decode wasm: " << std::setw(5) << time_decode_wasm From e42dd2411dead1c43a98c34ae6332498f512c933 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Fri, 4 Nov 2022 21:49:46 +0530 Subject: [PATCH 05/10] TEST: WASM_X86: Add test for if-else --- integration_tests/if_01.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 integration_tests/if_01.py diff --git a/integration_tests/if_01.py b/integration_tests/if_01.py new file mode 100644 index 0000000000..82a1218d83 --- /dev/null +++ b/integration_tests/if_01.py @@ -0,0 +1,28 @@ +def Test_if_01(): + if True: + print(1) + + if False: + print(0) + + if 1 < 0: + print(0) + else: + print(1) + + if 1 > 0: + print(1) + else: + print(0) + + if 1 < 0: + print(1) + elif 1 > 0: + print(1) + else: + print(0) + +def Verify(): + Test_if_01() + +Verify() From 46e2df01086c515dbd396343cb16e8a76fcfbd8e Mon Sep 17 00:00:00 2001 From: Ubaid Date: Fri, 4 Nov 2022 21:56:21 +0530 Subject: [PATCH 06/10] TEST: WASM_X86: Add another test for if-else --- integration_tests/if_01.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/integration_tests/if_01.py b/integration_tests/if_01.py index 82a1218d83..090928c739 100644 --- a/integration_tests/if_01.py +++ b/integration_tests/if_01.py @@ -22,7 +22,38 @@ def Test_if_01(): else: print(0) +def Test_if_02(): + if True: + print(1) + if True: + print(2) + if False: + print(3) + elif True: + print(4) + else: + print(5) + else: + print(6) + + if True: + print(7) + if False: + print(8) + if False: + print(9) + else: + print(10) + else: + if True: + print(11) + else: + print(12) + print(13) + print(14) + def Verify(): Test_if_01() + Test_if_02() Verify() From 5cefa66962af8c2054c94cef2e4d341309cbde17 Mon Sep 17 00:00:00 2001 From: Ubaid Date: Fri, 4 Nov 2022 21:59:21 +0530 Subject: [PATCH 07/10] TEST: Update reference tests --- tests/reference/wat-loop1-e0046d4.json | 2 +- tests/reference/wat-loop1-e0046d4.stdout | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/reference/wat-loop1-e0046d4.json b/tests/reference/wat-loop1-e0046d4.json index e36e213485..1dfe8a94b6 100644 --- a/tests/reference/wat-loop1-e0046d4.json +++ b/tests/reference/wat-loop1-e0046d4.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "wat-loop1-e0046d4.stdout", - "stdout_hash": "12b741cf8600fa79f42d342a3fd339bc84963713fd1257d6d4b4141b", + "stdout_hash": "f6dfe3c647ade9c3166a32025fac278f4ab5b6e04fea7f2192fb4ce7", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/wat-loop1-e0046d4.stdout b/tests/reference/wat-loop1-e0046d4.stdout index c28ebcb195..5aec19cf8b 100644 --- a/tests/reference/wat-loop1-e0046d4.stdout +++ b/tests/reference/wat-loop1-e0046d4.stdout @@ -48,6 +48,7 @@ local.set 1 local.get 1 return + else end i32.const 1 local.set 2 @@ -119,6 +120,7 @@ local.set 1 local.get 1 return + else end i64.const 1 local.set 2 From 0f1a06478481d71c05238ec02ed33362bb48679e Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Tue, 8 Nov 2022 10:55:38 +0530 Subject: [PATCH 08/10] [WASM_x86] Convert the offset into strings and store it to use as a unique_id --- src/libasr/codegen/wasm_to_x86.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index c298349a20..8b139df3cd 100644 --- a/src/libasr/codegen/wasm_to_x86.cpp +++ b/src/libasr/codegen/wasm_to_x86.cpp @@ -16,7 +16,7 @@ class X86Visitor : public WASMDecoder, public: X86Assembler &m_a; uint32_t cur_func_idx; - std::vector unique_id; + std::vector unique_id; X86Visitor(X86Assembler &m_a, Allocator &al, diag::Diagnostics &diagonostics, Vec &code) @@ -72,22 +72,22 @@ class X86Visitor : public WASMDecoder, void visit_EmtpyBlockType() {} void visit_If() { - unique_id.push_back(offset); + unique_id.push_back(std::to_string(offset)); m_a.asm_pop_r32(X86Reg::eax); m_a.asm_cmp_r32_imm8(LFortran::X86Reg::eax, 1); - m_a.asm_je_label(".then_" + std::to_string(unique_id.back())); - m_a.asm_jmp_label(".else_" + std::to_string(unique_id.back())); - m_a.add_label(".then_" + std::to_string(unique_id.back())); + m_a.asm_je_label(".then_" + unique_id.back()); + m_a.asm_jmp_label(".else_" + unique_id.back()); + m_a.add_label(".then_" + unique_id.back()); { decode_instructions(); } - m_a.add_label(".endif_" + std::to_string(unique_id.back())); + m_a.add_label(".endif_" + unique_id.back()); unique_id.pop_back(); } void visit_Else() { - m_a.asm_jmp_label(".endif_" + std::to_string(unique_id.back())); - m_a.add_label(".else_" + std::to_string(unique_id.back())); + m_a.asm_jmp_label(".endif_" + unique_id.back()); + m_a.add_label(".else_" + unique_id.back()); } void visit_LocalGet(uint32_t localidx) { From 66f6b0ac3793a73436ea991ef00de96c81bcc56e Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 9 Nov 2022 22:01:09 +0530 Subject: [PATCH 09/10] [WASM_x86] Implement Integer compare --- src/libasr/codegen/wasm_to_x86.cpp | 37 +++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index 8b139df3cd..00299eae63 100644 --- a/src/libasr/codegen/wasm_to_x86.cpp +++ b/src/libasr/codegen/wasm_to_x86.cpp @@ -154,6 +154,41 @@ class X86Visitor : public WASMDecoder, m_a.asm_push_r32(X86Reg::eax); } + void handle_I32Compare(const std::string &compare_op) { + unique_id.push_back(std::to_string(offset)); + m_a.asm_pop_r32(X86Reg::ebx); + m_a.asm_pop_r32(X86Reg::eax); + m_a.asm_cmp_r32_r32(X86Reg::eax, X86Reg::ebx); + if (compare_op == "Eq") { + m_a.asm_je_label(".compare_1" + unique_id.back()); + } else if (compare_op == "Gt") { + m_a.asm_jg_label(".compare_1" + unique_id.back()); + } else if (compare_op == "GtE") { + m_a.asm_jge_label(".compare_1" + unique_id.back()); + } else if (compare_op == "Lt") { + m_a.asm_jl_label(".compare_1" + unique_id.back()); + } else if (compare_op == "LtE") { + m_a.asm_jle_label(".compare_1" + unique_id.back()); + } else if (compare_op == "NotEq") { + m_a.asm_jne_label(".compare_1" + unique_id.back()); + } else { + throw CodeGenError("Comparison operator not implemented"); + } + m_a.asm_mov_r32_imm32(X86Reg::eax, 0); + m_a.asm_jmp_label(".compare.end_" + unique_id.back()); + m_a.add_label(".compare_1" + unique_id.back()); + m_a.asm_mov_r32_imm32(X86Reg::eax, 1); + m_a.add_label(".compare.end_" + unique_id.back()); + m_a.asm_push_r32(X86Reg::eax); + } + + void visit_I32Eq() { handle_I32Compare("Eq"); } + void visit_I32GtS() { handle_I32Compare("Gt"); } + void visit_I32GeS() { handle_I32Compare("GtE"); } + void visit_I32LtS() { handle_I32Compare("Lt"); } + void visit_I32LeS() { handle_I32Compare("LtE"); } + void visit_I32Ne() { handle_I32Compare("NotEq"); } + void gen_x86_bytes() { emit_elf32_header(m_a); @@ -253,7 +288,7 @@ Result wasm_to_x86(Vec &wasm_bytes, Allocator &al, } //! Helpful for debugging - // std::cout << x86_visitor.m_a.get_asm() << std::endl; + std::cout << x86_visitor.m_a.get_asm() << std::endl; if (time_report) { std::cout << "Codegen Time report:" << std::endl; From 8036eb9415427f869bdf84f06c12e6deb43a92f2 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Wed, 9 Nov 2022 22:05:50 +0530 Subject: [PATCH 10/10] Add tests --- integration_tests/if_02.py | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 integration_tests/if_02.py diff --git a/integration_tests/if_02.py b/integration_tests/if_02.py new file mode 100644 index 0000000000..e2dd52f6ff --- /dev/null +++ b/integration_tests/if_02.py @@ -0,0 +1,42 @@ +from ltypes import bool, i32 + +def test_if_01(): + x: bool = True + y: i32 = 10 + z: i32 = 0 + + if x: + x = False + if x: + z += 1 + else: + z += 1 + + if y > 5: + z += 1 + if y < 12: + z += 1 + if y == 10: + z += 1 + if y != 10: + z += 1 + else: + z += 1 + if y <= 10: + z += 1 + + y = 5 + if y <= 10: + z += 1 + if y >= 5: + z += 1 + if y >= 2: + z += 1 + + # TODO: replace this an assert statement + print(z) + +def verify(): + test_if_01() + +verify()