tidepool_codegen/emit/
join.rs1use crate::emit::expr::ensure_heap_ptr;
2use crate::emit::*;
3use cranelift_codegen::ir::{types, BlockArg, InstBuilder, Value};
4use cranelift_frontend::FunctionBuilder;
5use tidepool_repr::*;
6
7#[allow(clippy::too_many_arguments)]
11pub fn emit_join(
12 ctx: &mut EmitContext,
13 sess: &mut EmitSession,
14 builder: &mut FunctionBuilder,
15 label: &JoinId,
16 params: &[VarId],
17 rhs_idx: usize,
18 body_idx: usize,
19) -> Result<SsaVal, EmitError> {
20 let join_block = builder.create_block();
22
23 for _ in params {
25 builder.append_block_param(join_block, types::I64);
26 }
27
28 let merge_block = builder.create_block();
30 builder.append_block_param(merge_block, types::I64); let dummy_val = Value::from_u32(0);
35 ctx.join_blocks.register(
36 *label,
37 JoinInfo {
38 block: join_block,
39 param_types: params.iter().map(|_| SsaVal::HeapPtr(dummy_val)).collect(),
40 },
41 );
42
43 let body_result = ctx.emit_node(sess, builder, body_idx, TailCtx::NonTail)?;
45 let body_val = ensure_heap_ptr(builder, sess.vmctx, sess.gc_sig, sess.oom_func, body_result);
46 builder
47 .ins()
48 .jump(merge_block, &[BlockArg::Value(body_val)]);
49
50 builder.switch_to_block(join_block);
52 ctx.declare_env(builder);
53
54 let block_params = builder.block_params(join_block).to_vec();
56 let mut scope = EnvScope::new();
57 for (i, param_var) in params.iter().enumerate() {
60 let val = block_params[i];
61 builder.declare_value_needs_stack_map(val); ctx.env
63 .insert_scoped(&mut scope, *param_var, SsaVal::HeapPtr(val));
64 }
65
66 let rhs_result = ctx.emit_node(sess, builder, rhs_idx, TailCtx::NonTail)?;
67 let rhs_val = ensure_heap_ptr(builder, sess.vmctx, sess.gc_sig, sess.oom_func, rhs_result);
68 builder.ins().jump(merge_block, &[BlockArg::Value(rhs_val)]);
69
70 builder.seal_block(join_block);
73 builder.seal_block(merge_block);
75
76 builder.switch_to_block(merge_block);
78 let result = builder.block_params(merge_block)[0];
79 builder.declare_value_needs_stack_map(result); ctx.declare_env(builder);
81
82 ctx.join_blocks.remove(label);
84 ctx.env.restore_scope(scope);
85
86 Ok(SsaVal::HeapPtr(result))
88}
89
90#[allow(clippy::too_many_arguments)]
93pub fn emit_jump(
94 ctx: &mut EmitContext,
95 sess: &mut EmitSession,
96 builder: &mut FunctionBuilder,
97 label: &JoinId,
98 arg_indices: &[usize],
99) -> Result<SsaVal, EmitError> {
100 let join_block = ctx.join_blocks.get(label)?.block;
102
103 let mut arg_values: Vec<BlockArg> = Vec::new();
105 for &arg_idx in arg_indices {
106 let val = ctx.emit_node(sess, builder, arg_idx, TailCtx::NonTail)?;
110 arg_values.push(BlockArg::Value(ensure_heap_ptr(
112 builder,
113 sess.vmctx,
114 sess.gc_sig,
115 sess.oom_func,
116 val,
117 )));
118 }
119
120 builder.ins().jump(join_block, &arg_values);
122
123 let unreachable_block = builder.create_block();
126 builder.switch_to_block(unreachable_block);
127 builder.seal_block(unreachable_block);
128
129 Ok(SsaVal::Raw(
131 builder.ins().iconst(types::I64, 0),
132 LIT_TAG_INT,
133 ))
134}