GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

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