Merge branch 'resetref' into Frame-Limited

This commit is contained in:
J.Teeuwissen 2023-04-03 10:02:31 +02:00
commit 87abe8df7d
No known key found for this signature in database
GPG key ID: DB5F7A1ED8D478AD
13 changed files with 387 additions and 16 deletions

View file

@ -1235,6 +1235,59 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
phi.as_basic_value()
}
}
ResetRef {
symbol,
update_mode,
} => {
let bytes = update_mode.to_bytes();
let update_var = UpdateModeVar(&bytes);
let update_mode = func_spec_solutions
.update_mode(update_var)
.unwrap_or(UpdateMode::Immutable);
let (tag_ptr, layout) = load_symbol_and_layout(scope, symbol);
let tag_ptr = tag_ptr.into_pointer_value();
// reset is only generated for union values
let union_layout = match layout_interner.get(layout) {
Layout::Union(ul) => ul,
_ => unreachable!(),
};
let ctx = env.context;
let not_unique_block = ctx.append_basic_block(parent, "else_decref");
let cont_block = ctx.append_basic_block(parent, "cont");
let refcount_ptr =
PointerToRefcount::from_ptr_to_data(env, tag_pointer_clear_tag_id(env, tag_ptr));
let is_unique = match update_mode {
UpdateMode::InPlace => env.context.bool_type().const_int(1, false),
UpdateMode::Immutable => refcount_ptr.is_1(env),
};
let parent_block = env.builder.get_insert_block().unwrap();
env.builder
.build_conditional_branch(is_unique, cont_block, not_unique_block);
{
// If reset is used on a shared, non-reusable reference, it behaves
// like dec and returns NULL, which instructs reuse to behave like ctor
env.builder.position_at_end(not_unique_block);
refcount_ptr.decrement(env, layout_interner, layout);
env.builder.build_unconditional_branch(cont_block);
}
{
env.builder.position_at_end(cont_block);
let phi = env.builder.build_phi(tag_ptr.get_type(), "branch");
let null_ptr = tag_ptr.get_type().const_null();
phi.add_incoming(&[(&tag_ptr, parent_block), (&null_ptr, not_unique_block)]);
phi.as_basic_value()
}
}
StructAtIndex {
index, structure, ..