inc/dec string slices

This commit is contained in:
Folkert 2023-05-07 16:40:22 +02:00
parent 62dac6bdf8
commit 736b7c6a83
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -777,6 +777,13 @@ fn refcount_str<'a>(
let layout_isize = root.layout_isize; let layout_isize = root.layout_isize;
let field_layouts = arena.alloc([Layout::OPAQUE_PTR, layout_isize, layout_isize]); let field_layouts = arena.alloc([Layout::OPAQUE_PTR, layout_isize, layout_isize]);
let is_increment = matches!(ctx.op, HelperOp::Inc);
let (modify_rc_ptr, modify_data_ptr) = match is_increment {
true => (LowLevel::RefCountIncRcPtr, LowLevel::RefCountIncDataPtr),
false => (LowLevel::RefCountDecRcPtr, LowLevel::RefCountDecDataPtr),
};
// Get the last word as a signed int // Get the last word as a signed int
let last_word = root.create_symbol(ident_ids, "last_word"); let last_word = root.create_symbol(ident_ids, "last_word");
let last_word_expr = Expr::StructAtIndex { let last_word_expr = Expr::StructAtIndex {
@ -819,6 +826,11 @@ fn refcount_str<'a>(
}; };
let length_stmt = |next| Stmt::Let(length, length_expr, layout_isize, next); let length_stmt = |next| Stmt::Let(length, length_expr, layout_isize, next);
let alignment = root.create_symbol(ident_ids, "alignment");
let alignment_int = root.target_info.ptr_width() as u32;
let alignment_expr = Expr::Literal(Literal::Int((alignment_int as u128).to_ne_bytes()));
let alignment_stmt = |next| Stmt::Let(alignment, alignment_expr, layout_isize, next);
// let is_slice = lowlevel NumLt length zero // let is_slice = lowlevel NumLt length zero
let is_slice = root.create_symbol(ident_ids, "is_slice"); let is_slice = root.create_symbol(ident_ids, "is_slice");
let is_slice_stmt = let is_slice_stmt =
@ -828,39 +840,24 @@ fn refcount_str<'a>(
// Branch on seamless slice vs "real" string // Branch on seamless slice vs "real" string
// //
let jp_chars = JoinPointId(root.create_symbol(ident_ids, "jp_chars")); let second_argument = match is_increment {
let chars = root.create_symbol(ident_ids, "chars"); true => Symbol::ARG_2,
let param_elems = Param { false => alignment,
symbol: chars,
ownership: Ownership::Owned,
layout: Layout::OPAQUE_PTR,
}; };
// one = 1 // when the string is a slice, the capacity field is a pointer to the refcount
let one = root.create_symbol(ident_ids, "one"); let unit = root.create_symbol(ident_ids, "unit");
let one_expr = Expr::Literal(Literal::Int(1i128.to_ne_bytes())); let slice_branch = let_lowlevel(
let one_stmt = |next| Stmt::Let(one, one_expr, layout_isize, next);
// slice_elems = lowlevel NumShiftLeftBy length one
let slice_chars = root.create_symbol(ident_ids, "slice_chars");
let slice_chars_stmt = |next| {
let_lowlevel(
arena, arena,
layout_isize, Layout::UNIT,
slice_chars, unit,
NumShiftLeftBy, modify_rc_ptr,
&[length, one], &[last_word, second_argument],
next, arena.alloc(
)
};
let slice_branch = one_stmt(arena.alloc(
// //
slice_chars_stmt(arena.alloc( Stmt::Ret(unit),
// ),
Stmt::Jump(jp_chars, arena.alloc([slice_chars])), );
)),
));
// Characters pointer for a real string // Characters pointer for a real string
let string_chars = root.create_symbol(ident_ids, "string_chars"); let string_chars = root.create_symbol(ident_ids, "string_chars");
@ -871,11 +868,23 @@ fn refcount_str<'a>(
}; };
let string_chars_stmt = |next| Stmt::Let(string_chars, string_chars_expr, layout_isize, next); let string_chars_stmt = |next| Stmt::Let(string_chars, string_chars_expr, layout_isize, next);
let modify_rc_stmt = let_lowlevel(
arena,
Layout::UNIT,
unit,
modify_data_ptr,
&[string_chars, second_argument],
arena.alloc(
//
Stmt::Ret(unit),
),
);
let string_branch = arena.alloc( let string_branch = arena.alloc(
// //
string_chars_stmt(arena.alloc( string_chars_stmt(arena.alloc(
// //
Stmt::Jump(jp_chars, arena.alloc([string_chars])), modify_rc_stmt,
)), )),
); );
@ -884,49 +893,30 @@ fn refcount_str<'a>(
is_slice, is_slice,
Layout::UNIT, Layout::UNIT,
slice_branch, slice_branch,
root.arena.alloc(string_branch), string_branch,
);
//
// Modify Refcount
//
let alignment = root.target_info.ptr_width() as u32;
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
let modify_rc_stmt = modify_refcount(
root,
ident_ids,
ctx,
chars,
alignment,
arena.alloc(ret_stmt),
); );
// //
// JoinPoint for slice vs list // JoinPoint for slice vs list
// //
let joinpoint_elems = Stmt::Join { let modify_stmt = length_stmt(arena.alloc(
id: jp_chars,
parameters: arena.alloc([param_elems]),
body: arena.alloc(modify_rc_stmt),
remainder: arena.alloc(
//
length_stmt(arena.alloc(
// //
is_slice_stmt(arena.alloc( is_slice_stmt(arena.alloc(
// //
if_slice, if_slice,
)), )),
)), ));
),
};
let if_big_stmt = Stmt::if_then_else( let if_big_stmt = Stmt::if_then_else(
root.arena, root.arena,
is_big_str, is_big_str,
Layout::UNIT, Layout::UNIT,
joinpoint_elems, if is_increment {
modify_stmt
} else {
alignment_stmt(arena.alloc(modify_stmt))
},
root.arena.alloc(rc_return_stmt(root, ident_ids, ctx)), root.arena.alloc(rc_return_stmt(root, ident_ids, ctx)),
); );