Skip to content

Implement if-else in wasm_to_x86 backend #1264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions integration_tests/if_01.py
Original file line number Diff line number Diff line change
@@ -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()
2 changes: 1 addition & 1 deletion src/bin/lpython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ int compile_to_binary_x86(

// ASR -> X86
auto asr_to_x86_start = std::chrono::high_resolution_clock::now();
LFortran::Result<int> r3 = LFortran::asr_to_x86(*asr, al, outfile, time_report);
LFortran::Result<int> 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<double, std::milli>(asr_to_x86_end - asr_to_x86_start).count()));
std::cerr << diagnostics.render(input, lm, compiler_options);
Expand Down
9 changes: 4 additions & 5 deletions src/libasr/codegen/asr_to_wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2048,11 +2048,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
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
Expand Down Expand Up @@ -2119,6 +2117,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
}
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
}
};
Expand Down
10 changes: 7 additions & 3 deletions src/libasr/codegen/asr_to_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ class ASRToX86Visitor : public ASR::BaseVisitor<ASRToX86Visitor>


Result<int> 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;
Expand Down Expand Up @@ -558,8 +559,8 @@ Result<int> 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<std::chrono::milliseconds>(t2 - t1).count();
Expand All @@ -579,6 +580,9 @@ Result<int> asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al,
time_save = std::chrono::duration_cast<std::chrono::milliseconds>(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;
Expand Down
3 changes: 2 additions & 1 deletion src/libasr/codegen/asr_to_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace LFortran {

// Generates a 32-bit x86 Linux executable binary `filename`
Result<int> 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

Expand Down
25 changes: 25 additions & 0 deletions src/libasr/codegen/wasm_to_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
public:
X86Assembler &m_a;
uint32_t cur_func_idx;
std::vector<uint32_t> unique_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later:

Suggested change
std::vector<uint32_t> unique_id;
uint32_t unique_id;


X86Visitor(X86Assembler &m_a, Allocator &al,
diag::Diagnostics &diagonostics, Vec<uint8_t> &code)
Expand Down Expand Up @@ -68,6 +69,27 @@ class X86Visitor : public WASMDecoder<X86Visitor>,
}
}

void visit_EmtpyBlockType() {}

void visit_If() {
unique_id.push_back(offset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unique_id.push_back(offset);
unique_id++;
uint32_t label = unique_id;

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()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For later (but probably quite soon): we should not be using strings for labels, but just unique integers. The unique integer can just be a counter in this visitor, just an integer, see above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(we might need to have a stack of unique ids...)

{
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 =
Expand Down Expand Up @@ -230,6 +252,9 @@ Result<int> wasm_to_x86(Vec<uint8_t> &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
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/wat-loop1-e0046d4.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/reference/wat-loop1-e0046d4.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
local.set 1
local.get 1
return
else
end
i32.const 1
local.set 2
Expand Down Expand Up @@ -119,6 +120,7 @@
local.set 1
local.get 1
return
else
end
i64.const 1
local.set 2
Expand Down