Commit c4c0922f authored by Eduardo Souza's avatar Eduardo Souza

Spilling ref values to the stack on exceptional paths; Adding test for GC with Exception Handling.

parent ecfd94ff
Pipeline #5697 failed with stages
in 2 minutes and 22 seconds
...@@ -376,6 +376,33 @@ pub unsafe fn add_args_to_destination( ...@@ -376,6 +376,33 @@ pub unsafe fn add_args_to_destination(
ins_args.insert(dest.target.id(), block_args); ins_args.insert(dest.target.id(), block_args);
} }
pub unsafe fn add_args_to_exceptional_destination(
llvm_internal_context: &mut AOTLLVMInternalContext,
dest: &Destination,
mut store: &mut HashMap<MuID, LLVMValueRef>,
ins_args: &mut HashMap<MuID, Vec<(LLVMTypeRef, LLVMValueRef)>>,
ins: &Instruction
) {
let mut args_pos = vec![];
let mut args = vec![];
for arg in &dest.args {
match arg {
DestArg::Normal(a) => args_pos.push(*a),
_ => ()
}
}
for pos in args_pos {
args.push(ins.ops.get(pos).unwrap());
}
let block_args =
process_inst_exc_args(llvm_internal_context, &args, &mut store);
ins_args.insert(dest.target.id(), block_args);
}
pub unsafe fn add_multiple_args_to_same_destination( pub unsafe fn add_multiple_args_to_same_destination(
llvm_internal_context: &mut AOTLLVMInternalContext, llvm_internal_context: &mut AOTLLVMInternalContext,
cond: LLVMValueRef, cond: LLVMValueRef,
...@@ -386,7 +413,6 @@ pub unsafe fn add_multiple_args_to_same_destination( ...@@ -386,7 +413,6 @@ pub unsafe fn add_multiple_args_to_same_destination(
ins: &Instruction ins: &Instruction
) { ) {
assert_eq!(true_dest.target, false_dest.target); assert_eq!(true_dest.target, false_dest.target);
let mut true_args_pos = vec![]; let mut true_args_pos = vec![];
let mut true_args = vec![]; let mut true_args = vec![];
...@@ -1133,6 +1159,14 @@ pub unsafe fn gen_instr_call( ...@@ -1133,6 +1159,14 @@ pub unsafe fn gen_instr_call(
let exception_dest = &resume.exn_dest; let exception_dest = &resume.exn_dest;
let normal_dest = &resume.normal_dest; let normal_dest = &resume.normal_dest;
add_args_to_exceptional_destination(
llvm_internal_context,
exception_dest,
store,
ins_args,
ins
);
let llvm_exception_dest = llvm_internal_context let llvm_exception_dest = llvm_internal_context
.blocks_map .blocks_map
.get(&exception_dest.target.id()) .get(&exception_dest.target.id())
...@@ -1164,13 +1198,6 @@ pub unsafe fn gen_instr_call( ...@@ -1164,13 +1198,6 @@ pub unsafe fn gen_instr_call(
ins_args, ins_args,
ins ins
); );
add_args_to_destination(
llvm_internal_context,
exception_dest,
store,
ins_args,
ins
);
} }
pub unsafe fn gen_instr_exprcall( pub unsafe fn gen_instr_exprcall(
...@@ -2765,6 +2792,75 @@ pub unsafe fn process_inst_args( ...@@ -2765,6 +2792,75 @@ pub unsafe fn process_inst_args(
llvm_args llvm_args
} }
pub unsafe fn process_inst_exc_args(
llvm_internal_context: &mut AOTLLVMInternalContext,
ops: &Vec<&P<TreeNode>>,
store: &mut HashMap<MuID, LLVMValueRef>
) -> Vec<(LLVMTypeRef, LLVMValueRef)> {
let mut llvm_args = vec![];
for op in ops {
if op.is_value() {
let value = op.as_value();
let value_type = gen_llvm_type(llvm_internal_context, &value.ty);
if value.ty.is_heap_reference() {
// build alloca and pass the alloca to be loaded instead
let alloca_name = format!("{}_alloca\0", value.hdr.name());
let alloca = LLVMBuildAlloca(
llvm_internal_context.builder,
value_type,
alloca_name.as_str().as_ptr() as *const c_char
);
let value_llvm =
gen_llvm_value(llvm_internal_context, *op, store);
LLVMBuildStore(
llvm_internal_context.builder,
value_llvm,
alloca
);
let addr_alloca = LLVMBuildPointerCast(
llvm_internal_context.builder,
alloca,
LLVMInt64Type(),
"alloca_addr\0".as_ptr() as *const c_char
);
let add_spilled_addr = LLVMGetNamedFunction(
llvm_internal_context.module,
"add_spilled_address_to_roots\0".as_ptr() as *const c_char
);
if add_spilled_addr.is_null() {
unimplemented!()
}
let mut args = vec![addr_alloca];
LLVMBuildCall(
llvm_internal_context.builder,
add_spilled_addr,
args.as_mut_ptr(),
args.len() as u32,
"\0".as_ptr() as *const c_char
);
llvm_args.push((LLVMPointerType(value_type, 0), alloca));
} else {
let value_llvm =
gen_llvm_value(llvm_internal_context, *op, store);
llvm_args.push((value_type, value_llvm));
}
} else {
// TODO handle non-const arguments
unimplemented!()
}
}
llvm_args
}
pub unsafe fn process_inst_args_with_select( pub unsafe fn process_inst_args_with_select(
llvm_internal_context: &mut AOTLLVMInternalContext, llvm_internal_context: &mut AOTLLVMInternalContext,
cond: LLVMValueRef, cond: LLVMValueRef,
......
...@@ -497,6 +497,27 @@ fn visit_inst_custom( ...@@ -497,6 +497,27 @@ fn visit_inst_custom(
) )
); );
} }
let function_name =
"add_spilled_address_to_roots\0".as_ptr() as *const c_char;
let mut params = vec![LLVMInt64Type()];
let function = LLVMGetNamedFunction(
llvm_internal_context.module,
function_name
);
if function.is_null() {
LLVMAddFunction(
llvm_internal_context.module,
function_name,
LLVMFunctionType(
LLVMVoidType(),
params.as_mut_ptr(),
1,
false as i32
)
);
}
} }
let exception_block = resume.exn_dest.target.id(); let exception_block = resume.exn_dest.target.id();
...@@ -763,7 +784,7 @@ unsafe fn emit_llvm_asm_code( ...@@ -763,7 +784,7 @@ unsafe fn emit_llvm_asm_code(
// (no need to create phi nodes for first block) // (no need to create phi nodes for first block)
for (label, block) in blocks { for (label, block) in blocks {
// process block parameters // process block parameters
let mut store = process_block_params( let (mut args_to_load, mut store) = process_block_params(
llvm_internal_context, llvm_internal_context,
block, block,
create_phi_nodes create_phi_nodes
...@@ -776,7 +797,8 @@ unsafe fn emit_llvm_asm_code( ...@@ -776,7 +797,8 @@ unsafe fn emit_llvm_asm_code(
label, label,
block, block,
&mut store, &mut store,
function function,
args_to_load
)); ));
} else { } else {
instr_args.push(gen_llvm_block_contents( instr_args.push(gen_llvm_block_contents(
...@@ -911,8 +933,7 @@ unsafe fn create_llvm_function_type( ...@@ -911,8 +933,7 @@ unsafe fn create_llvm_function_type(
) -> LLVMTypeRef { ) -> LLVMTypeRef {
let mut llvm_arg_types = vec![]; let mut llvm_arg_types = vec![];
for arg_ty in &function_sig.arg_tys { for arg_ty in &function_sig.arg_tys {
llvm_arg_types llvm_arg_types.push(gen_llvm_type(llvm_internal_context, arg_ty));
.push(gen_llvm_type(llvm_internal_context, arg_ty));
} }
let mut llvm_ret_types = vec![]; let mut llvm_ret_types = vec![];
...@@ -944,10 +965,14 @@ unsafe fn process_block_params( ...@@ -944,10 +965,14 @@ unsafe fn process_block_params(
llvm_internal_context: &mut AOTLLVMInternalContext, llvm_internal_context: &mut AOTLLVMInternalContext,
block: &Block, block: &Block,
create_phi_nodes: bool create_phi_nodes: bool
) -> HashMap<MuID, LLVMValueRef> { ) -> (
Vec<(LLVMValueRef, String, MuID)>,
HashMap<MuID, LLVMValueRef>
) {
let mut store = HashMap::new(); let mut store = HashMap::new();
let mut args_to_load = vec![];
if create_phi_nodes { if create_phi_nodes && !block.is_receiving_exception_arg() {
let llvm_block = llvm_internal_context let llvm_block = llvm_internal_context
.blocks_map .blocks_map
.get(&block.hdr.id()) .get(&block.hdr.id())
...@@ -979,6 +1004,49 @@ unsafe fn process_block_params( ...@@ -979,6 +1004,49 @@ unsafe fn process_block_params(
llvm_internal_context llvm_internal_context
.block_args .block_args
.insert(block.hdr.id(), (*llvm_block, block_args)); .insert(block.hdr.id(), (*llvm_block, block_args));
} else if create_phi_nodes && block.is_receiving_exception_arg() {
let llvm_block = llvm_internal_context
.blocks_map
.get(&block.hdr.id())
.unwrap();
LLVMPositionBuilderAtEnd(llvm_internal_context.builder, *llvm_block);
let args = block.content.as_ref().unwrap();
let mut block_args = vec![];
for i in 0..args.args.len() {
let param_name = args.args.get(i).unwrap().hdr.name();
let param_name_llvm = format!("{}\0", param_name);
let param_id = args.args.get(i).unwrap().hdr.id();
let param_type = &args.args.get(i).unwrap().ty;
let mut llvm_param_type =
gen_llvm_type(llvm_internal_context, param_type);
// in an exceptional block, reference parameters should expect an
// alloca
if param_type.is_heap_reference() {
llvm_param_type = LLVMPointerType(llvm_param_type, 0);
}
// each mu basic block parameter becomes a phi node
let phi = LLVMBuildPhi(
llvm_internal_context.builder,
llvm_param_type,
param_name_llvm.as_str().as_ptr() as *const c_char
);
// load from the alloca in case of a heap reference
if param_type.is_heap_reference() {
let ref_name = format!("{}_loaded\0", param_name);
args_to_load.push((phi, ref_name, param_id));
} else {
store.insert(param_id, phi);
}
block_args.push((llvm_param_type, phi));
}
let llvm_block = llvm_internal_context
.blocks_map
.get(&block.hdr.id())
.unwrap();
llvm_internal_context
.block_args
.insert(block.hdr.id(), (*llvm_block, block_args));
} else { } else {
let block_params = llvm_internal_context let block_params = llvm_internal_context
.block_args .block_args
...@@ -998,11 +1066,11 @@ unsafe fn process_block_params( ...@@ -998,11 +1066,11 @@ unsafe fn process_block_params(
store.insert(mu_param.hdr.id(), *llvm_param); store.insert(mu_param.hdr.id(), *llvm_param);
} }
} }
None => return store None => return (args_to_load, store)
} }
} }
store (args_to_load, store)
} }
pub unsafe fn gen_llvm_type( pub unsafe fn gen_llvm_type(
...@@ -1158,7 +1226,8 @@ unsafe fn gen_llvm_exception_block_contents( ...@@ -1158,7 +1226,8 @@ unsafe fn gen_llvm_exception_block_contents(
label: &usize, label: &usize,
block: &Block, block: &Block,
store: &mut HashMap<MuID, LLVMValueRef>, store: &mut HashMap<MuID, LLVMValueRef>,
function: LLVMValueRef function: LLVMValueRef,
args_to_load: Vec<(LLVMValueRef, String, MuID)>
) -> HashMap<MuID, Vec<(LLVMBasicBlockRef, Vec<(LLVMTypeRef, LLVMValueRef)>)>> { ) -> HashMap<MuID, Vec<(LLVMBasicBlockRef, Vec<(LLVMTypeRef, LLVMValueRef)>)>> {
let llvm_block = llvm_internal_context.blocks_map.get(label).unwrap(); let llvm_block = llvm_internal_context.blocks_map.get(label).unwrap();
LLVMPositionBuilderAtEnd(llvm_internal_context.builder, *llvm_block); LLVMPositionBuilderAtEnd(llvm_internal_context.builder, *llvm_block);
...@@ -1237,6 +1306,16 @@ unsafe fn gen_llvm_exception_block_contents( ...@@ -1237,6 +1306,16 @@ unsafe fn gen_llvm_exception_block_contents(
None => () None => ()
} }
// load ref args from phi nodes
for (phi, name, id) in args_to_load {
let loaded_arg = LLVMBuildLoad(
llvm_internal_context.builder,
phi,
name.as_str().as_ptr() as *const c_char
);
store.insert(id, loaded_arg);
}
for instruction in &instructions.body { for instruction in &instructions.body {
let mut args_inst = gen_llvm_instruction( let mut args_inst = gen_llvm_instruction(
llvm_internal_context, llvm_internal_context,
......
...@@ -50,7 +50,7 @@ fn test_exception_throw_catch_simple() { ...@@ -50,7 +50,7 @@ fn test_exception_throw_catch_simple() {
// } // }
} }
fn declare_commons(vm: &VM) { pub fn declare_commons(vm: &VM) {
typedef! ((vm) int64 = mu_int(64)); typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) ref_int64 = mu_ref(int64)); typedef! ((vm) ref_int64 = mu_ref(int64));
typedef! ((vm) iref_int64 = mu_iref(int64)); typedef! ((vm) iref_int64 = mu_iref(int64));
...@@ -141,7 +141,7 @@ fn create_catch_exception_func( ...@@ -141,7 +141,7 @@ fn create_catch_exception_func(
); );
} }
fn create_throw_exception_func(vm: &VM) -> MuEntityHeader { pub fn create_throw_exception_func(vm: &VM) -> MuEntityHeader {
let int64 = vm.get_type(vm.id_of("int64")); let int64 = vm.get_type(vm.id_of("int64"));
let ref_int64 = vm.get_type(vm.id_of("ref_int64")); let ref_int64 = vm.get_type(vm.id_of("ref_int64"));
let iref_int64 = vm.get_type(vm.id_of("iref_int64")); let iref_int64 = vm.get_type(vm.id_of("iref_int64"));
...@@ -159,6 +159,15 @@ fn create_throw_exception_func(vm: &VM) -> MuEntityHeader { ...@@ -159,6 +159,15 @@ fn create_throw_exception_func(vm: &VM) -> MuEntityHeader {
exception_obj = NEW <int64> exception_obj = NEW <int64>
); );
ssa! ((vm, throw_exception_v1) <int64> i);
inst! ((vm, throw_exception_v1) blk_entry_convop:
i = CONVOP (ConvOp::PTRCAST) <ref_int64 int64> exception_obj
);
inst! ((vm, throw_exception_v1) blk_entry_print1:
PRINTHEX i
);
// %exception_obj_iref = GETIREF <@int64> %exception_obj // %exception_obj_iref = GETIREF <@int64> %exception_obj
ssa! ((vm, throw_exception_v1) <iref_int64> exception_obj_iref); ssa! ((vm, throw_exception_v1) <iref_int64> exception_obj_iref);
inst! ((vm, throw_exception_v1) blk_0_getiref: inst! ((vm, throw_exception_v1) blk_0_getiref:
...@@ -179,6 +188,8 @@ fn create_throw_exception_func(vm: &VM) -> MuEntityHeader { ...@@ -179,6 +188,8 @@ fn create_throw_exception_func(vm: &VM) -> MuEntityHeader {
define_block!((vm, throw_exception_v1) blk_0() { define_block!((vm, throw_exception_v1) blk_0() {
blk_0_new, blk_0_new,
blk_entry_convop,
blk_entry_print1,
blk_0_getiref, blk_0_getiref,
blk_0_store, blk_0_store,
blk_0_throw blk_0_throw
...@@ -396,7 +407,6 @@ fn create_catch_exception_and_add(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -396,7 +407,6 @@ fn create_catch_exception_and_add(vm: &VM, throw_exception: MuEntityHeader) {
); );
} }
// FIXME TEST FAILS WHEN CONSIDERING GC AND ADDRSPACES
#[test] #[test]
fn test_exception_throw_catch_twice() { fn test_exception_throw_catch_twice() {
build_and_run_llvm_test!(catch_twice AND throw_exception, build_and_run_llvm_test!(catch_twice AND throw_exception,
...@@ -455,12 +465,25 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -455,12 +465,25 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) {
// blk_exception1 // blk_exception1
block! ((vm, catch_twice_v1) blk_exception2); block! ((vm, catch_twice_v1) blk_exception2);
ssa! ((vm, catch_twice_v1) <ref_int64> exc_arg1); ssa! ((vm, catch_twice_v1) <ref_int64> exc_arg1);
ssa! ((vm, catch_twice_v1) <int64> i);
inst! ((vm, catch_twice_v1) blk_entry_convop:
i = CONVOP (ConvOp::PTRCAST) <ref_int64 int64> exc_arg1
);
inst! ((vm, catch_twice_v1) blk_entry_print1:
PRINTHEX i
);
inst! ((vm, catch_twice_v1) blk_exception1_call: inst! ((vm, catch_twice_v1) blk_exception1_call:
CALL (funcref_throw_local, exc_arg1) FUNC(0) (vec![]) CallConvention::Mu, CALL (funcref_throw_local, exc_arg1) FUNC(0) (vec![]) CallConvention::Mu,
normal: blk_normal (vec![]), normal: blk_normal (vec![]),
exc : blk_exception2 (vec![DestArg::Normal(1)]) exc : blk_exception2 (vec![DestArg::Normal(1)])
); );
define_block!((vm, catch_twice_v1) blk_exception1() [exc_arg1] { define_block!((vm, catch_twice_v1) blk_exception1() [exc_arg1] {
blk_entry_convop,
blk_entry_print1,
blk_exception1_call blk_exception1_call
}); });
...@@ -472,6 +495,16 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -472,6 +495,16 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) {
inst! ((vm, catch_twice_v1) blk_exception2_getiref1: inst! ((vm, catch_twice_v1) blk_exception2_getiref1:
blk_exception2_iref_exc1 = GETIREF blk_exception2_exc_arg1 blk_exception2_iref_exc1 = GETIREF blk_exception2_exc_arg1
); );
ssa! ((vm, catch_twice_v1) <int64> i_arg);
inst! ((vm, catch_twice_v1) blk_entry_convop_arg:
i_arg = CONVOP (ConvOp::PTRCAST) <ref_int64 int64> blk_exception2_exc_arg1
);
inst! ((vm, catch_twice_v1) blk_entry_print_arg:
PRINTHEX i_arg
);
ssa! ((vm, catch_twice_v1) <int64> exc_arg1_val); ssa! ((vm, catch_twice_v1) <int64> exc_arg1_val);
inst! ((vm, catch_twice_v1) blk_exception2_load1: inst! ((vm, catch_twice_v1) blk_exception2_load1:
exc_arg1_val = LOAD blk_exception2_exc_arg1 (is_ptr: false, order: MemoryOrder::SeqCst) exc_arg1_val = LOAD blk_exception2_exc_arg1 (is_ptr: false, order: MemoryOrder::SeqCst)
...@@ -488,7 +521,7 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -488,7 +521,7 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) {
ssa! ((vm, catch_twice_v1) <int64> res); ssa! ((vm, catch_twice_v1) <int64> res);
inst! ((vm, catch_twice_v1) blk_exception2_add: inst! ((vm, catch_twice_v1) blk_exception2_add:
res = BINOP (BinOp::Add) exc_arg2_val exc_arg2_val res = BINOP (BinOp::Add) exc_arg1_val exc_arg2_val
); );
inst! ((vm, catch_twice_v1) blk_exception2_ret: inst! ((vm, catch_twice_v1) blk_exception2_ret:
...@@ -497,6 +530,9 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -497,6 +530,9 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) {
define_block! ((vm, catch_twice_v1) blk_exception2(blk_exception2_exc_arg1) [exc_arg2] { define_block! ((vm, catch_twice_v1) blk_exception2(blk_exception2_exc_arg1) [exc_arg2] {
// blk_exception2_getiref1, // blk_exception2_getiref1,
blk_entry_convop_arg,
blk_entry_print_arg,
blk_exception2_load1, blk_exception2_load1,
// blk_exception2_getiref2, // blk_exception2_getiref2,
blk_exception2_load2, blk_exception2_load2,
...@@ -507,8 +543,8 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) { ...@@ -507,8 +543,8 @@ fn create_catch_twice(vm: &VM, throw_exception: MuEntityHeader) {
define_func_ver!((vm) catch_twice_v1 (entry: blk_entry) { define_func_ver!((vm) catch_twice_v1 (entry: blk_entry) {
blk_entry, blk_entry,
blk_normal,
blk_exception1, blk_exception1,
blk_normal,
blk_exception2 blk_exception2
}); });
......
...@@ -1485,3 +1485,165 @@ fn gc_mult_call_mult_obj() -> VM { ...@@ -1485,3 +1485,165 @@ fn gc_mult_call_mult_obj() -> VM {
vm vm
} }
#[test]
fn test_exception_throw_catch_twice_with_gc() {
build_and_run_llvm_test!(catch_twice AND throw_exception,
catch_twice_test2, throw_catch_twice_with_gc);
}
fn throw_catch_twice_with_gc() -> VM {
let opts = String::from("init_mu --generate-llvm");
let vm = VM::new_with_opts(opts.as_str());
crate::tests::test_exception::declare_commons(&vm);
let throw_exc = crate::tests::test_exception::create_throw_exception_func(&vm);
create_catch_twice_with_gc(&vm, throw_exc);
vm
}
fn create_catch_twice_with_gc(vm: &VM, throw_exception: MuEntityHeader) {
let throw_exception_sig = vm.get_func_sig(vm.id_of("throw_exception_sig"));
let ref_int64 = vm.get_type(vm.id_of("ref_int64"));
let iref_int64 = vm.get_type(vm.id_of("iref_int64"));
let int64 = vm.get_type(vm.id_of("int64"));
typedef! ((vm) type_funcref_throw_exception = mu_funcref(throw_exception_sig));
constdef! ((vm) <type_funcref_throw_exception> const_funcref_throw_exception
= Constant::FuncRef(throw_exception));
funcsig! ((vm) catch_exception_sig = () -> (int64));
funcdecl! ((vm) <catch_exception_sig> catch_twice);
funcdef! ((vm) <catch_exception_sig> catch_twice VERSION catch_twice_v1);
// blk_entry
block! ((vm, catch_twice_v1) blk_entry);
block! ((vm, catch_twice_v1) blk_normal);
block! ((vm, catch_twice_v1) blk_exception1);
consta! ((vm, catch_twice_v1) funcref_throw_local = const_funcref_throw_exception);
inst! ((vm, catch_twice_v1) blk_entry_call:
CALL (funcref_throw_local) FUNC(0) (vec![]) CallConvention::Mu,
normal: blk_normal (vec![]),
exc : blk_exception1 (vec![])
);
define_block!((vm, catch_twice_v1) blk_entry() {
blk_entry_call
});
// blk_normal
inst! ((vm, catch_twice_v1) blk_normal_threadexit:
THREADEXIT
);
define_block!((vm, catch_twice_v1) blk_normal() {
blk_normal_threadexit
});
// blk_exception1
block! ((vm, catch_twice_v1) blk_exception2);
ssa! ((vm, catch_twice_v1) <ref_int64> exc_arg1);
ssa! ((vm, catch_twice_v1) <int64> i);
inst! ((vm, catch_twice_v1) blk_entry_convop:
i = CONVOP (ConvOp::PTRCAST) <ref_int64 int64> exc_arg1
);
inst! ((vm, catch_twice_v1) blk_entry_print1:
PRINTHEX i
);
// call trigger gc
funcsig! ((vm) trigger_gc_sig = () -> ());
typedef!((vm) ufp_trigger_gc = mu_ufuncptr(trigger_gc_sig));
constdef!((vm) <ufp_trigger_gc> const_trigger_gc = Constant::ExternSym(C ("trigger_gc_void")));
consta!((vm, catch_twice_v1) const_trigger_gc_local = const_trigger_gc);
inst!((vm, catch_twice_v1) blk_entry_ccall:
EXPRCCALL (CallConvention::Foreign(ForeignFFI::C), is_abort: false) const_trigger_gc_local ()
);
inst! ((vm, catch_twice_v1) blk_exception1_call:
CALL (funcref_throw_local, exc_arg1) FUNC(0) (vec![]) CallConvention::Mu,
normal: blk_normal (vec![]),
exc : blk_exception2 (vec![DestArg::Normal(1)])
);
define_block!((vm, catch_twice_v1) blk_exception1() [exc_arg1] {
blk_entry_convop,
blk_entry_print1,
blk_entry_ccall,
blk_exception1_call
});
// blk_exception2
ssa! ((vm, catch_twice_v1) <ref_int64> blk_exception2_exc_arg1);
ssa! ((vm, catch_twice_v1) <ref_int64> exc_arg2);
ssa! ((vm, catch_twice_v1) <iref_int64> blk_exception2_iref_exc1);
inst! ((vm, catch_twice_v1) blk_exception2_getiref1:
blk_exception2_iref_exc1 = GETIREF blk_exception2_exc_arg1
);
ssa! ((vm, catch_twice_v1) <int64> i_arg);
inst! ((vm, catch_twice_v1) blk_entry_convop_arg:
i_arg = CONVOP (ConvOp::PTRCAST) <ref_int64 int64> blk_exception2_exc_arg1
);
inst! ((vm, catch_twice_v1) blk_entry_print_arg:
PRINTHEX i_arg
);
ssa! ((vm, catch_twice_v1) <int64> exc_arg1_val);
inst! ((vm, catch_twice_v1) blk_exception2_load1:
exc_arg1_val = LOAD blk_exception2_exc_arg1 (is_ptr: false, order: MemoryOrder::SeqCst)
);
ssa! ((vm, catch_twice_v1) <iref_int64> blk_exception2_iref_exc2);
inst! ((vm, catch_twice_v1) blk_exception2_getiref2:
blk_exception2_iref_exc2 = GETIREF exc_arg2
);
ssa! ((vm, catch_twice_v1) <int64> exc_arg2_val);
inst! ((vm, catch_twice_v1) blk_exception2_load2:
exc_arg2_val = LOAD exc_arg2 (is_ptr: false, order: MemoryOrder::SeqCst)
);
ssa! ((vm, catch_twice_v1) <int64> res);
inst! ((vm, catch_twice_v1) blk_exception2_add:
res = BINOP (BinOp::Add) exc_arg1_val exc_arg2_val
);
inst! ((vm, catch_twice_v1) blk_exception2_ret:
RET (res)
);
define_block! ((vm, catch_twice_v1) blk_exception2(blk_exception2_exc_arg1) [exc_arg2] {
// blk_exception2_getiref1,
blk_entry_convop_arg,
blk_entry_print_arg,
blk_exception2_load1,
// blk_exception2_getiref2,
blk_exception2_load2,
blk_exception2_add,
blk_exception2_ret
});
define_func_ver!((vm) catch_twice_v1 (entry: blk_entry) {
blk_entry,
blk_exception1,
blk_normal,
blk_exception2
});
emit_test! ((vm)
catch_twice, catch_twice_test2, catch_twice_test2_v1,
RET Int,
EQ,
catch_exception_sig,
RET int64(2u64),
);
}
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