Commit 31e3e88a authored by qinsoon's avatar qinsoon

[wip] add tests about passing arguments by stack, fixed impl

parent 74d45d10
......@@ -2034,6 +2034,19 @@ impl <'a> InstructionSelection {
self.backend.emit_lea_r64(dest, &mem);
}
fn emit_push(&mut self, op: &P<Value>) {
if op.is_int_const() {
if x86_64::is_valid_x86_imm(op) {
let int = op.extract_int_const();
self.backend.emit_push_imm32(int as i32);
} else {
unimplemented!();
}
} else {
self.backend.emit_push_r64(op);
}
}
fn emit_udiv (
&mut self,
op1: &TreeNode, op2: &TreeNode,
......@@ -2282,11 +2295,9 @@ impl <'a> InstructionSelection {
{
let mut index = 0;
for arg in stack_args {
self.emit_store_base_offset(&x86_64::RSP, - (stack_arg_offsets[index] as i32), &arg, vm);
self.emit_push(&arg);
index += 1;
}
self.backend.emit_add_r_imm(&x86_64::RSP, (- (stack_arg_size as i32)) as i32);
}
stack_arg_size_with_padding
......
......@@ -143,3 +143,279 @@ fn ccall_exit() -> VM {
vm
}
#[test]
fn test_pass_1arg_by_stack() {
VM::start_logging_trace();
let vm = Arc::new(pass_1arg_by_stack());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_foo = vm.id_of("foo7");
let func_main = vm.id_of("pass_1arg_by_stack");
{
let funcs = vm.funcs().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
{
let func = funcs.get(&func_foo).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
{
let func = funcs.get(&func_main).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
}
vm.make_primordial_thread(func_main, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec![Mu("foo7"), Mu("pass_1arg_by_stack")], "test_pass_1arg_by_stack", &vm);
let output = aot::execute_nocheck(executable);
// exit with (1)
assert!(output.status.code().is_some());
assert_eq!(output.status.code().unwrap(), 1);
}
fn pass_1arg_by_stack() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) int64 = mu_int(64));
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_1 = Constant::Int(1));
constdef! ((vm) <int64> int64_2 = Constant::Int(2));
// foo7
funcsig! ((vm) foo7_sig = (int64, int64, int64, int64, int64, int64, int64) -> (int64));
funcdecl! ((vm) <foo7_sig> foo7);
funcdef! ((vm) <foo7_sig> foo7 VERSION foo7_v1);
// blk_entry
ssa! ((vm, foo7_v1) <int64> v0);
ssa! ((vm, foo7_v1) <int64> v1);
ssa! ((vm, foo7_v1) <int64> v2);
ssa! ((vm, foo7_v1) <int64> v3);
ssa! ((vm, foo7_v1) <int64> v4);
ssa! ((vm, foo7_v1) <int64> v5);
ssa! ((vm, foo7_v1) <int64> v6);
block! ((vm, foo7_v1) blk_entry);
inst! ((vm, foo7_v1) blk_entry_ret:
RET (v6)
);
define_block!((vm, foo7_v1) blk_entry(v0, v1, v2, v3, v4, v5, v6) {
blk_entry_ret
});
define_func_ver!((vm) foo7_v1 (entry: blk_entry) {blk_entry});
// pass_1arg_by_stack
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> pass_1arg_by_stack);
funcdef! ((vm) <sig> pass_1arg_by_stack VERSION pass_1arg_by_stack_v1);
typedef! ((vm) type_funcref_foo7 = mu_funcref(foo7_sig));
constdef! ((vm) <type_funcref_foo7> const_funcref_foo7 = Constant::FuncRef(vm.id_of("foo7")));
// blk_entry
consta! ((vm, pass_1arg_by_stack_v1) int64_0_local = int64_0);
consta! ((vm, pass_1arg_by_stack_v1) int64_1_local = int64_1);
block! ((vm, pass_1arg_by_stack_v1) blk_entry);
block! ((vm, pass_1arg_by_stack_v1) blk_main);
inst! ((vm, pass_1arg_by_stack_v1) blk_entry_branch:
BRANCH blk_main (
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_1_local
)
);
define_block!((vm, pass_1arg_by_stack_v1) blk_entry() {blk_entry_branch});
// blk_main
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a0);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a1);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a2);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a3);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a4);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a5);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> a6);
consta! ((vm, pass_1arg_by_stack_v1) const_funcref_foo7_local = const_funcref_foo7);
ssa! ((vm, pass_1arg_by_stack_v1) <int64> retval);
inst! ((vm, pass_1arg_by_stack_v1) blk_main_call:
retval = EXPRCALL (CallConvention::Mu, is_abort: false) const_funcref_foo7_local (a0, a1, a2, a3, a4, a5, a6)
);
let blk_main_exit = gen_ccall_exit(retval.clone(), &mut pass_1arg_by_stack_v1, &vm);
inst! ((vm, pass_1arg_by_stack_v1) blk_main_ret:
RET
);
define_block!((vm, pass_1arg_by_stack_v1) blk_main(a0, a1, a2, a3, a4, a5, a6) {
blk_main_call,
blk_main_exit,
blk_main_ret
});
define_func_ver!((vm) pass_1arg_by_stack_v1 (entry: blk_entry) {
blk_entry,
blk_main
});
vm
}
#[test]
fn test_pass_2args_by_stack() {
VM::start_logging_trace();
let vm = Arc::new(pass_2args_by_stack());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_foo = vm.id_of("foo8");
let func_main = vm.id_of("pass_2args_by_stack");
{
let funcs = vm.funcs().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
{
let func = funcs.get(&func_foo).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
{
let func = funcs.get(&func_main).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
}
vm.make_primordial_thread(func_main, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec![Mu("foo8"), Mu("pass_2args_by_stack")], "test_pass_2args_by_stack", &vm);
let output = aot::execute_nocheck(executable);
// exit with (2)
assert!(output.status.code().is_some());
assert_eq!(output.status.code().unwrap(), 2);
}
fn pass_2args_by_stack() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) int64 = mu_int(64));
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_1 = Constant::Int(1));
constdef! ((vm) <int64> int64_2 = Constant::Int(2));
// foo8
funcsig! ((vm) foo8_sig = (int64, int64, int64, int64, int64, int64, int64, int64) -> (int64));
funcdecl! ((vm) <foo8_sig> foo8);
funcdef! ((vm) <foo8_sig> foo8 VERSION foo8_v1);
// blk_entry
ssa! ((vm, foo8_v1) <int64> v0);
ssa! ((vm, foo8_v1) <int64> v1);
ssa! ((vm, foo8_v1) <int64> v2);
ssa! ((vm, foo8_v1) <int64> v3);
ssa! ((vm, foo8_v1) <int64> v4);
ssa! ((vm, foo8_v1) <int64> v5);
ssa! ((vm, foo8_v1) <int64> v6);
ssa! ((vm, foo8_v1) <int64> v7);
block! ((vm, foo8_v1) blk_entry);
inst! ((vm, foo8_v1) blk_entry_ret:
RET (v7)
);
define_block!((vm, foo8_v1) blk_entry(v0, v1, v2, v3, v4, v5, v6, v7) {
blk_entry_ret
});
define_func_ver!((vm) foo8_v1 (entry: blk_entry) {blk_entry});
// pass_2args_by_stack
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> pass_2args_by_stack);
funcdef! ((vm) <sig> pass_2args_by_stack VERSION pass_2args_by_stack_v1);
typedef! ((vm) type_funcref_foo8 = mu_funcref(foo8_sig));
constdef! ((vm) <type_funcref_foo8> const_funcref_foo8 = Constant::FuncRef(vm.id_of("foo8")));
// blk_entry
consta! ((vm, pass_2args_by_stack_v1) int64_0_local = int64_0);
consta! ((vm, pass_2args_by_stack_v1) int64_1_local = int64_1);
consta! ((vm, pass_2args_by_stack_v1) int64_2_local = int64_2);
block! ((vm, pass_2args_by_stack_v1) blk_entry);
block! ((vm, pass_2args_by_stack_v1) blk_main);
inst! ((vm, pass_2args_by_stack_v1) blk_entry_branch:
BRANCH blk_main (
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_0_local,
int64_1_local,
int64_2_local
)
);
define_block!((vm, pass_2args_by_stack_v1) blk_entry() {blk_entry_branch});
// blk_main
ssa! ((vm, pass_2args_by_stack_v1) <int64> a0);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a1);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a2);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a3);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a4);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a5);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a6);
ssa! ((vm, pass_2args_by_stack_v1) <int64> a7);
consta! ((vm, pass_2args_by_stack_v1) const_funcref_foo8_local = const_funcref_foo8);
ssa! ((vm, pass_2args_by_stack_v1) <int64> retval);
inst! ((vm, pass_2args_by_stack_v1) blk_main_call:
retval = EXPRCALL (CallConvention::Mu, is_abort: false) const_funcref_foo8_local (a0, a1, a2, a3, a4, a5, a6, a7)
);
let blk_main_exit = gen_ccall_exit(retval.clone(), &mut pass_2args_by_stack_v1, &vm);
inst! ((vm, pass_2args_by_stack_v1) blk_main_ret:
RET
);
define_block!((vm, pass_2args_by_stack_v1) blk_main(a0, a1, a2, a3, a4, a5, a6, a7) {
blk_main_call,
blk_main_exit,
blk_main_ret
});
define_func_ver!((vm) pass_2args_by_stack_v1 (entry: blk_entry) {
blk_entry,
blk_main
});
vm
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment