-
Notifications
You must be signed in to change notification settings - Fork 158
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
WASM_X64: Support printing integers #1379
Conversation
It seems that there is no instruction push_imm64() available in x64 assembly
39225ed
to
836d82e
Compare
This is ready. Please possibly review and please share feedback. |
m_a.asm_mov_r64_imm64(X64Reg::rax, 60); // sys_exit | ||
m_a.asm_syscall(); // syscall | ||
m_a.asm_call_label("print_i64"); | ||
m_a.asm_pop_r64(X64Reg::r15); // pop the passed argument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this is merged, let's document what the "calling convention" is. It looks like the caller is responsible to put arguments on stack, as well as removing them from stack once the called function (print_i64
in this case) finishes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the caller is responsible to put arguments on stack.
In wasm
, the arguments are used up by the called function (that is there is no need to explicitly remove them).
In assembly x86
and/or x64
, we are currently manually/explicitly removing the passed arguments in the visit_Call()
function:
lpython/src/libasr/codegen/wasm_to_x64.cpp
Lines 97 to 123 in 7aaedcc
void visit_Call(uint32_t func_idx) { | |
if (func_idx <= 6U) { | |
call_imported_function(func_idx); | |
return; | |
} | |
func_idx -= 7u; // adjust function index as per imports | |
m_a.asm_call_label(exports[func_idx].name); | |
// Pop the passed function arguments | |
wasm::FuncType func_type = func_types[type_indices[func_idx]]; | |
for (uint32_t i = 0; i < func_type.param_types.size(); i++) { | |
m_a.asm_pop_r64(X64Reg::rax); | |
} | |
// Adjust the return values of the called function | |
X64Reg base = X64Reg::rsp; | |
for (uint32_t i = 0; i < func_type.result_types.size(); i++) { | |
// take value into eax | |
m_a.asm_mov_r64_m64(X64Reg::rax, &base, nullptr, 1, | |
-8 * (func_type.param_types.size() + 2 + | |
codes[func_idx].locals.size() + 1)); | |
// push eax value onto stack | |
m_a.asm_push_r64(X64Reg::rax); | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the print_i64
, as it is an imported function and as this is an initial support, we are removing the passed arguments just after the call:
lpython/src/libasr/codegen/wasm_to_x64.cpp
Lines 50 to 56 in 7aaedcc
void call_imported_function(uint32_t func_idx) { | |
switch (func_idx) { | |
case 0: { // print_i32 | |
m_a.asm_call_label("print_i64"); | |
m_a.asm_pop_r64(X64Reg::r15); // pop the passed argument | |
break; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should follow the WASM convention and the function should remove them, so in this case print_i64
should remove the arguments from stack. What do you think?
I opened up an issue so that we do not forget: #1381
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks great! Thanks for this.
Thank you for the approval and merging. |
Example:
Binary Output:
Text Format Output: