Commit e0be1d23 authored by qinsoon's avatar qinsoon

use move to push stack arguments and fixed some problems

parent 49f01f07
......@@ -2294,25 +2294,48 @@ impl <'a> InstructionSelection {
// (32, if __m256 is passed on stack) byte boundary." - x86 ABI
// if we need to special align the args, we do it now
// (then the args will be put to stack following their regular alignment)
// reserve stack args - we want to layout stack args as below
// RSP -> .............
// (padding)
// (padding)
// RSP -> argN, argN-1, ...
// so we need to layout args in reverse order
stack_args.reverse();
let stack_arg_tys = stack_args.iter().map(|x| x.ty.clone()).collect();
let (stack_arg_size, _, stack_arg_offsets) = backend::sequetial_layout(&stack_arg_tys, vm);
let mut stack_arg_size_with_padding = stack_arg_size;
let mut stack_arg_padding = 0;
if stack_arg_size % 16 == 0 {
// do not need to adjust rsp
} else if stack_arg_size % 8 == 0 {
// adjust rsp by -8 (push a random padding value)
self.backend.emit_push_imm32(0x7777);
// adjust rsp by -8
stack_arg_padding = 8;
stack_arg_size_with_padding += 8;
} else {
panic!("expecting stack arguments to be at least 8-byte aligned, but it has size of {}", stack_arg_size);
let rem = stack_arg_size % 16;
stack_arg_padding = 16 - rem;
stack_arg_size_with_padding += stack_arg_padding;
}
// now, we just put all the args on the stack
{
let mut index = 0;
for arg in stack_args {
self.emit_push(&arg);
index += 1;
if stack_arg_size_with_padding != 0 {
let mut index = 0;
let mut rsp_offset_before_call = - (stack_arg_size_with_padding as i32);
for arg in stack_args {
self.emit_store_base_offset(&x86_64::RSP, rsp_offset_before_call + (stack_arg_offsets[index]) as i32, &arg, vm);
index += 1;
}
self.backend.emit_sub_r_imm(&x86_64::RSP, stack_arg_size_with_padding as i32);
}
}
......
......@@ -4,6 +4,7 @@ use mu::ast::types::*;
use mu::ast::ir::*;
use mu::ast::ptr::*;
use mu::ast::inst::*;
use mu::ast::op::*;
use mu::vm::*;
use mu::compiler::*;
......@@ -423,6 +424,155 @@ fn pass_2args_by_stack() -> VM {
vm
}
#[test]
fn test_pass_2_int8_args_by_stack() {
VM::start_logging_trace();
let vm = Arc::new(pass_2_int8_args_by_stack());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_foo = vm.id_of("foo8");
let func_main = vm.id_of("pass_2_int8_args_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_2_int8_args_by_stack")], "test_pass_2_int8_args_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_2_int8_args_by_stack() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) int8 = mu_int(8));
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_1 = Constant::Int(1));
constdef! ((vm) <int64> int64_2 = Constant::Int(2));
constdef! ((vm) <int8> int8_1 = Constant::Int(1));
constdef! ((vm) <int8> int8_2 = Constant::Int(2));
// foo8
funcsig! ((vm) foo8_sig = (int64, int64, int64, int64, int64, int64, int8, int8) -> (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) <int8> v6);
ssa! ((vm, foo8_v1) <int8> v7);
block! ((vm, foo8_v1) blk_entry);
ssa! ((vm, foo8_v1) <int64> res);
inst! ((vm, foo8_v1) blk_entry_zext:
res = CONVOP (ConvOp::ZEXT) <int8 int64> v7
);
inst! ((vm, foo8_v1) blk_entry_ret:
RET (res)
);
define_block!((vm, foo8_v1) blk_entry(v0, v1, v2, v3, v4, v5, v6, v7) {
blk_entry_zext,
blk_entry_ret
});
define_func_ver!((vm) foo8_v1 (entry: blk_entry) {blk_entry});
// pass_2_int8_args_by_stack
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> pass_2_int8_args_by_stack);
funcdef! ((vm) <sig> pass_2_int8_args_by_stack VERSION pass_2_int8_args_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_2_int8_args_by_stack_v1) int64_0_local = int64_0);
consta! ((vm, pass_2_int8_args_by_stack_v1) int8_1_local = int8_1);
consta! ((vm, pass_2_int8_args_by_stack_v1) int8_2_local = int8_2);
block! ((vm, pass_2_int8_args_by_stack_v1) blk_entry);
block! ((vm, pass_2_int8_args_by_stack_v1) blk_main);
inst! ((vm, pass_2_int8_args_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,
int8_1_local,
int8_2_local
)
);
define_block!((vm, pass_2_int8_args_by_stack_v1) blk_entry() {blk_entry_branch});
// blk_main
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a0);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a1);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a2);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a3);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a4);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> a5);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int8> a6);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int8> a7);
consta! ((vm, pass_2_int8_args_by_stack_v1) const_funcref_foo8_local = const_funcref_foo8);
ssa! ((vm, pass_2_int8_args_by_stack_v1) <int64> retval);
inst! ((vm, pass_2_int8_args_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_2_int8_args_by_stack_v1, &vm);
inst! ((vm, pass_2_int8_args_by_stack_v1) blk_main_ret:
RET
);
define_block!((vm, pass_2_int8_args_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_2_int8_args_by_stack_v1 (entry: blk_entry) {
blk_entry,
blk_main
});
vm
}
#[test]
fn test_pass_fp_arg() {
let lib = testutil::compile_fncs("pass_fp_arg", vec!["pass_fp_arg", "foo"], &pass_fp_arg);
......
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