add seamless slices for str

This commit is contained in:
Brendan Hansknecht 2023-03-13 22:26:04 -07:00
parent 24c403eba0
commit 3978059aa2
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
5 changed files with 122 additions and 35 deletions

View file

@ -63,3 +63,19 @@ pub(crate) fn str_equal<'a, 'ctx, 'env>(
bitcode::STR_EQUAL,
)
}
// Gets a pointer to just after the refcount for a list or seamless slice.
// The value is just after the refcount so that normal lists and seamless slices can share code paths easily.
pub(crate) fn str_refcount_ptr<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
value: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> {
call_str_bitcode_fn(
env,
&[value],
&[],
BitcodeReturns::Basic,
bitcode::STR_REFCOUNT_PTR,
)
.into_pointer_value()
}

View file

@ -2,18 +2,19 @@ use crate::debug_info_init;
use crate::llvm::bitcode::call_void_bitcode_fn;
use crate::llvm::build::BuilderExt;
use crate::llvm::build::{
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, use_roc_value, Env,
FAST_CALL_CONV,
add_func, cast_basic_basic, create_entry_block_alloca, get_tag_id, tag_pointer_clear_tag_id,
use_roc_value, Env, FAST_CALL_CONV,
};
use crate::llvm::build_list::{
incrementing_elem_loop, list_capacity_or_ref_ptr, list_refcount_ptr, load_list,
};
use crate::llvm::build_str::str_refcount_ptr;
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
use bumpalo::collections::Vec;
use inkwell::basic_block::BasicBlock;
use inkwell::module::Linkage;
use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
use inkwell::{AddressSpace, IntPredicate};
use roc_module::symbol::Interns;
use roc_module::symbol::Symbol;
@ -75,16 +76,6 @@ impl<'ctx> PointerToRefcount<'ctx> {
}
}
fn from_list_wrapper(env: &Env<'_, 'ctx, '_>, list_wrapper: StructValue<'ctx>) -> Self {
let data_ptr = env
.builder
.build_extract_value(list_wrapper, Builtin::WRAPPER_PTR, "read_list_ptr")
.unwrap()
.into_pointer_value();
Self::from_ptr_to_data(env, data_ptr)
}
pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> {
let current = self.get_refcount(env);
let one = match env.target_info.ptr_width() {
@ -815,9 +806,9 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
let parent = fn_val;
let str_type = zig_str_type(env);
let arg_val =
if Layout::Builtin(Builtin::Str).is_passed_by_reference(layout_interner, env.target_info) {
let str_type = zig_str_type(env);
env.builder
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
} else {
@ -848,7 +839,11 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
builder.build_conditional_branch(is_big_and_non_empty, modification_block, cont_block);
builder.position_at_end(modification_block);
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, str_wrapper);
let str_alloca = create_entry_block_alloca(env, parent, str_type.into(), "str_alloca");
env.builder.build_store(str_alloca, str_wrapper);
let refcount_ptr =
PointerToRefcount::from_ptr_to_data(env, str_refcount_ptr(env, str_alloca.into()));
let call_mode = mode_to_call_mode(fn_val, mode);
refcount_ptr.modify(call_mode, layout, env, layout_interner);