Commit 6279fb1c authored by qinsoon's avatar qinsoon

add an extra block for passing normal destination arguments for inlined

functions
parent cd0e3739
......@@ -470,7 +470,17 @@ impl Destination {
ret
}
pub fn get_arguments_as_node(&self, ops: &Vec<P<TreeNode>>) -> Vec<P<TreeNode>> {
vec_utils::map(&self.args,
|x| {
match x {
&DestArg::Normal(i) => ops[i].clone(),
&DestArg::Freshbound(_) => unimplemented!()
}
})
}
pub fn get_arguments(&self, ops: &Vec<P<TreeNode>>) -> Vec<P<Value>> {
vec_utils::map(&self.args,
|x| {
......
......@@ -218,15 +218,49 @@ impl Inlining {
// add branch to current block
cur_block.content.as_mut().unwrap().body.push(TreeNode::new_boxed_inst(branch));
// next block
let mut next_block = resume.normal_dest.target;
// if normal_dest expects different number of arguments
// other than the inlined function returns, we need an intermediate block to pass extra arguments
if resume.normal_dest.args.len() != inlined_fv_guard.sig.ret_tys.len() {
unimplemented!()
debug!("need an extra block for passing normal dest arguments");
let mut intermediate_block = Block::new(vm.next_id());
vm.set_name(intermediate_block.as_entity(), format!("inline_{}_arg_pass", inst_id));
// branch to normal_dest with normal_dest arguments
let normal_dest_args = resume.normal_dest.get_arguments_as_node(&ops);
let normal_dest_args_len = normal_dest_args.len();
let branch = Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(normal_dest_args),
v: Instruction_::Branch1(Destination {
target: resume.normal_dest.target,
args: (0..normal_dest_args_len).map(|x| DestArg::Normal(x)).collect()
})
};
intermediate_block.content = Some(BlockContent {
args: {
match inst.value {
Some(ref vec) => vec.clone(),
None => vec![]
}
},
exn_arg: None,
body: vec![TreeNode::new_boxed_inst(branch)],
keepalives: None
});
trace!("extra block: {:?}", intermediate_block);
next_block = intermediate_block.id();
new_blocks.push(intermediate_block);
}
// deal with inlined function
let next_block = resume.normal_dest.target;
copy_inline_blocks(&mut new_blocks, next_block,
inlined_fv_guard.get_orig_ir().unwrap(), new_inlined_entry_id,
vm);
......
......@@ -574,7 +574,10 @@ impl <'a> VM {
pub fn id_of_by_refstring(&self, name: &String) -> MuID {
let map = self.name_id_map.read().unwrap();
*map.get(name).unwrap()
match map.get(name) {
Some(id) => *id,
None => panic!("cannot find id for name: {}", name)
}
}
pub fn id_of(&self, name: &str) -> MuID {
......
......@@ -341,7 +341,7 @@ macro_rules! inst {
});
};
// CALL
// EXPRCALL
(($vm: expr, $fv: ident) $name: ident: $res: ident = EXPRCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), +)) => {
let ops = vec![$func.clone(), $($val.clone()), *];
let ops_len = ops.len();
......@@ -359,7 +359,7 @@ macro_rules! inst {
}
});
};
(($vm: expr, $fv: ident) $name: ident: EXPRCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), +)) => {
(($vm: expr, $fv: ident) $name: ident: EXPRCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), +)) => {
let ops = vec![$func.clone(), $($val.clone()), *];
let ops_len = ops.len();
let $name = $fv.new_inst(Instruction{
......@@ -376,7 +376,34 @@ macro_rules! inst {
}
});
};
// CALL
(($vm: expr, $fv: ident) $name: ident:
$res: ident = CALL ($($op: ident), *) FUNC($func: expr) ($args: expr) $cc: expr,
normal: $norm_dest: ident ($norm_args: expr),
exc: $exc_dest: ident ($exc_args: expr)) => {
let $name = $fv.new_inst(Instruction {
hdr : MuEntityHeader::unnamed($vm.next_id()),
value: Some(vec![$res.clone_value()]),
ops : RwLock::new(vec![$($op.clone()),*]),
v : Instruction_::Call {
data: CallData {
func: $func,
args: $args,
convention: $cc
},
resume: ResumptionData {
normal_dest: Destination {
target: $norm_dest.id(),
args : $norm_args
},
exn_dest: Destination {
target: $exc_dest.id(),
args : $exc_args
}
}
}
});
};
// RET
(($vm: expr, $fv: ident) $name: ident: RET ($($val: ident), +)) => {
......
......@@ -161,3 +161,118 @@ fn inline_add_twice() -> VM {
vm
}
#[test]
fn test_inline_add_with_extra_norm_args() {
let lib = testutil::compile_fncs("inline_add_with_extra_norm_args", vec!["add_with_extra_norm_args", "add"], &inline_add_with_extra_norm_args);
unsafe {
let add_twice : libloading::Symbol<unsafe extern fn(u64, u64, u64) -> u64> = lib.get(b"add_with_extra_norm_args").unwrap();
let res = add_twice(1, 1, 1);
println!("add(1, 1, 1) = {}", res);
assert!(res == 103);
}
}
fn inline_add_with_extra_norm_args() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = (int64, int64) -> (int64));
funcdecl! ((vm) <sig> add);
{
// add
funcdef! ((vm) <sig> add VERSION add_v1);
block! ((vm, add_v1) blk_entry);
ssa! ((vm, add_v1) <int64> x);
ssa! ((vm, add_v1) <int64> y);
ssa! ((vm, add_v1) <int64> res);
inst! ((vm, add_v1) blk_entry_add:
res = BINOP (BinOp::Add) x y
);
inst! ((vm, add_v1) blk_entry_ret:
RET (res)
);
define_block! ((vm, add_v1) blk_entry(x, y) {blk_entry_add, blk_entry_ret});
define_func_ver!((vm) add_v1 (entry: blk_entry) {blk_entry});
}
{
// inline_add_with_extra_norm_args
typedef! ((vm) funcref_to_sig = mu_funcref(sig));
constdef! ((vm) <funcref_to_sig> funcref_add = Constant::FuncRef(add));
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_100 = Constant::Int(100));
funcsig! ((vm) sig_add_with_extra_norm_args = (int64, int64, int64) -> (int64));
funcdecl! ((vm) <sig_add_with_extra_norm_args> add_with_extra_norm_args);
funcdef! ((vm) <sig_add_with_extra_norm_args> add_with_extra_norm_args VERSION add_with_extra_norm_args_v1);
block! ((vm, add_with_extra_norm_args_v1) blk_entry);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> x);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> y);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> arg);
block! ((vm, add_with_extra_norm_args_v1) blk_norm);
block! ((vm, add_with_extra_norm_args_v1) blk_exn);
consta! ((vm, add_with_extra_norm_args_v1) funcref_add_local = funcref_add);
consta! ((vm, add_with_extra_norm_args_v1) int64_100_local = int64_100);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> res);
inst! ((vm, add_with_extra_norm_args_v1) call:
// 0 , 1, 2, 3 , 4 , 5
res = CALL (funcref_add_local, x, y, res, arg, int64_100_local) FUNC(0) (vec![1, 2]) CallConvention::Mu,
normal: blk_norm (vec![DestArg::Normal(3), DestArg::Normal(4), DestArg::Normal(5)]),
exc: blk_exn (vec![])
);
define_block!((vm, add_with_extra_norm_args_v1) blk_entry(x, y, arg) {call});
// blk_normal
ssa! ((vm, add_with_extra_norm_args_v1) <int64> normal_a);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> normal_b);
ssa! ((vm, add_with_extra_norm_args_v1) <int64> normal_c);
// normal_res1 = add a, b
ssa! ((vm, add_with_extra_norm_args_v1) <int64> normal_res1);
inst! ((vm, add_with_extra_norm_args_v1) add1:
normal_res1 = BINOP (BinOp::Add) normal_a normal_b
);
// normal_res2 = add normal_res1, c
ssa! ((vm, add_with_extra_norm_args_v1) <int64> normal_res2);
inst! ((vm, add_with_extra_norm_args_v1) add2:
normal_res2 = BINOP (BinOp::Add) normal_res1 normal_c
);
// RET normal_res2
inst! ((vm, add_with_extra_norm_args_v1) normal_ret:
RET (normal_res2)
);
define_block!((vm, add_with_extra_norm_args_v1) blk_norm(normal_a, normal_b, normal_c) {
add1, add2, normal_ret
});
// blk_exn
consta! ((vm, add_with_extra_norm_args_v1) int64_0_local = int64_0);
inst! ((vm, add_with_extra_norm_args_v1) exn_ret:
RET (int64_0_local)
);
define_block!((vm, add_with_extra_norm_args_v1) blk_exn() {
exn_ret
});
define_func_ver!((vm) add_with_extra_norm_args_v1 (entry: blk_entry) {blk_entry, blk_norm, blk_exn});
}
vm
}
\ No newline at end of file
......@@ -1040,7 +1040,6 @@ def test_rpytarget_print_argv():
assert res.out == '[%s, abc, 123]\n' % exe
@pytest.mark.skipif("True")
@may_spawn_proc
def test_rpytarget_sha1sum():
john1 = \
......
......@@ -4,7 +4,6 @@ use mu::runtime::thread;
use mu::runtime::thread::MuThread;
use mu::vm::VM;
use std::usize;
use std::sync::Arc;
#[test]
......
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