Skip to content

Wasm to x86 backend #1223

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 5 commits into from
Nov 2, 2022
Merged

Wasm to x86 backend #1223

merged 5 commits into from
Nov 2, 2022

Conversation

ubaidsk
Copy link
Collaborator

@ubaidsk ubaidsk commented Oct 22, 2022

towards #1222


namespace wasm {

class WASMDecoder {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This WASMDecoder class is being repeated (it is already defined in src/libasr/codegen/wasm_to_wat.cpp). We should extract it and place in a common file.

doubt: Where should we place this WASMDecoder class? Creating a new file (e.g. wasm_disassembler.cpp or wasm_decoder.cpp) seems possible, but I am unsure if this is the right way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I temporarily moved this class into a new file wasm_decoder.h.

@ubaidsk ubaidsk marked this pull request as draft October 22, 2022 19:41
@certik
Copy link
Contributor

certik commented Oct 23, 2022

Awesome, thanks for this! Will review it tomorrow.

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

I am an facing the following error.

Traceback (most recent call last):
  Binary file "/home/ubaid/OpenSource/lpython/src/bin/lpython", in _start()
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", in __libc_start_main()
  File "/home/ubaid/OpenSource/lpython/src/bin/lpython.cpp", line 1555, in ??
    return compile_to_binary_wasm_to_x86(arg_file, outfile,
  File "/home/ubaid/OpenSource/lpython/src/bin/lpython.cpp", line 856, in ??
    LFortran::Result<int> res = LFortran::wasm_to_x86(r3.result, al,  outfile, time_report, diagnostics);
  File "/home/ubaid/OpenSource/lpython/src/libasr/codegen/wasm_to_x86.cpp", line 98, in LFortran::wasm_to_x86(LFortran::Vec<unsigned char>&, Allocator&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, LFortran::diag::Diagnostics&)
    x86_generator.get_x86_bytes(m_a);
  File "/home/ubaid/OpenSource/lpython/src/libasr/codegen/wasm_to_x86.cpp", line 53, in LFortran::wasm::X86Generator::get_x86_bytes(LFortran::X86Assembler&)
    v.decode_instructions();
  File "/home/ubaid/OpenSource/lpython/src/libasr/../libasr/wasm_visitor.h", line 926, in LFortran::WASM_INSTS_VISITOR::BaseWASMVisitor<LFortran::WASM_INSTS_VISITOR::X86Visitor>::decode_instructions()
    self().visit_Call(funcidx);
  File "/home/ubaid/OpenSource/lpython/src/libasr/../libasr/codegen/wasm_to_x86.h", line 52, in LFortran::WASM_INSTS_VISITOR::X86Visitor::visit_Call(unsigned int)
    m_a.asm_call_label(exports[func_index].name);
  File "/home/ubaid/OpenSource/lpython/src/libasr/../libasr/codegen/x86_assembler.h", line 691, in LFortran::X86Assembler::asm_call_label(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    uint32_t imm32 = relative_symbol(label);
  File "/home/ubaid/OpenSource/lpython/src/libasr/../libasr/codegen/x86_assembler.h", line 365, in LFortran::X86Assembler::relative_symbol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    return reference_symbol(name, 2).value-pos()-4;
  File "/home/ubaid/OpenSource/lpython/src/libasr/../libasr/codegen/x86_assembler.h", line 333, in LFortran::X86Assembler::reference_symbol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
    if (m_symbols.find(name) == m_symbols.end()) {
  File "/usr/include/c++/9/bits/stl_map.h", line 1169, in std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, LFortran::Symbol, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> > >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    { return _M_t.find(__x); }
  File "/usr/include/c++/9/bits/stl_tree.h", line 2562, in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> > >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
  File "/usr/include/c++/9/bits/stl_tree.h", line 1934, in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> > >::_M_lower_bound(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, LFortran::Symbol> >*, std::_Rb_tree_node_base*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    if (!_M_impl._M_key_compare(_S_key(__x), __k))
  File "/usr/include/c++/9/bits/stl_function.h", line 386, in std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator()(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
    { return __x < __y; }
  File "/usr/include/c++/9/bits/basic_string.h", line 6232, in bool std::operator< <char, std::char_traits<char>, std::allocator<char> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
    { return __lhs.compare(__rhs) < 0; }
  Binary file "/lib/x86_64-linux-gnu/libstdc++.so.6", in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", in __nss_database_lookup()
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", in killpg()
Segfault: Signal SIGSEGV (segmentation fault) received

Could someone possibly try this PR and help with the bug, please?

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

The wasm to x86 backend can be used as lpython examples/expr2.py --backend wasm_x86.

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

For #1223 (comment), the I am here flow that is being generated using the wasm to x86 backend is

(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ lpython examples/expr2.py --backend wasm_x86
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 4
I am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1
I am here - 4
I am here - 1
I am here - 4
Call to imported function with index 5 not yet supportedI am here - 1
I am here - 2
I am here - 3
I am here - 4
I am here - 1

and compile_to_binary_wasm_to_x86()
Define and use WATGenerator class in wasm_to_wat.cpp
Instructions can be decoded from this offset as required
@ubaidsk ubaidsk force-pushed the wasm_to_x86_backend branch from 4315a4a to 16b6436 Compare October 25, 2022 21:35
@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

This #1223 (comment) seems to be solved now.

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

The following example works with both the x86 backends.

def Main0():
    x: i32
    x = (2+3)*5
    y: i32
    z: i32
    y = 14
    z = 2
    print(x + y * z)

Main0()

# Not implemented yet in LPython:
#if __name__ == "__main__":
#    main()
(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ lpython examples/expr2.py --backend x86
(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ ./a.out 
53
(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ lpython examples/expr2.py --backend wasm_x86
(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ ./a.out 
53(lp) ubaid@ubaid-Lenovo-ideapad-330-15ARR:~/OpenSource/lpython$ 

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

Notes:

  • We are needing to name the main0 function as Main0 so that it gets defined before the _lpython_main_program() which calls it.
  • Only Non-Negative integers are currently supported as it seems x86_assembler does not support negative integers fully. (It seems there is no printing support for negative integers).
  • Functions are supported, but returning values from functions is not yet supported.

@ubaidsk ubaidsk marked this pull request as ready for review October 25, 2022 21:50
@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 25, 2022

This is ready. Please possibly review and please share feedback.

@ubaidsk ubaidsk requested a review from certik October 25, 2022 21:50
@certik
Copy link
Contributor

certik commented Oct 29, 2022

At a high level this looks good. I need to review in more detail.

The changes in lpython.cpp seem long. We should try to figure out if there is an easier way to do this there, possibly in subsequent PRs.

@certik
Copy link
Contributor

certik commented Oct 29, 2022

I will only have time next week to play with this --- in the meantime why don't you setup a CI to automatically test this? We'll need that anyway.

@ubaidsk
Copy link
Collaborator Author

ubaidsk commented Oct 30, 2022

in the meantime why don't you setup a CI to automatically test this? We'll need that anyway.

I was hoping to submit a PR for setting up the CI, but it seems the current wasm to x86 backend is very early and does/might not support even basic integration tests. I am working on supporting return values from function calls. It seems to work. I will be sending a PR soon.

For CI, it seems we might also need support for visit_Assert() as several integration tests seem to use assert in them.

@certik certik merged commit 37f6b2c into lcompilers:main Nov 2, 2022
@ubaidsk ubaidsk deleted the wasm_to_x86_backend branch November 2, 2022 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants