diff --git a/integration_tests/if_01.py b/integration_tests/if_01.py new file mode 100644 index 0000000000..090928c739 --- /dev/null +++ b/integration_tests/if_01.py @@ -0,0 +1,59 @@ +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 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() diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index a9db92cc38..67c91fd395 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -775,7 +775,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_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index 7cd873b482..7111abfa6d 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -2048,11 +2048,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 @@ -2119,6 +2117,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 } }; 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 diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index fcd24124e4..c298349a20 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 = @@ -230,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 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