mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
initial implementation
This commit is contained in:
parent
b3b3b8790c
commit
92f2927046
13 changed files with 313 additions and 2 deletions
|
@ -72,6 +72,11 @@ fn build_hash_layout<'a, 'ctx, 'env>(
|
|||
build_hash_tag(env, layout_ids, layout, union_layout, seed, val)
|
||||
}
|
||||
|
||||
Layout::Boxed(_inner_layout) => {
|
||||
// build_hash_box(env, layout_ids, layout, inner_layout, seed, val)
|
||||
todo!()
|
||||
}
|
||||
|
||||
Layout::RecursivePointer => match when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
unreachable!("recursion pointers should never be hashed directly")
|
||||
|
|
|
@ -182,6 +182,16 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
rhs_val,
|
||||
),
|
||||
|
||||
Layout::Boxed(inner_layout) => build_box_eq(
|
||||
env,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
inner_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
),
|
||||
|
||||
Layout::RecursivePointer => match when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
unreachable!("recursion pointers should never be compared directly")
|
||||
|
@ -345,6 +355,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
|
||||
result.into()
|
||||
}
|
||||
|
||||
Layout::Union(union_layout) => {
|
||||
let is_equal = build_tag_eq(
|
||||
env,
|
||||
|
@ -362,6 +373,23 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
result.into()
|
||||
}
|
||||
|
||||
Layout::Boxed(inner_layout) => {
|
||||
let is_equal = build_box_eq(
|
||||
env,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
inner_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
)
|
||||
.into_int_value();
|
||||
|
||||
let result: IntValue = env.builder.build_not(is_equal, "negate");
|
||||
|
||||
result.into()
|
||||
}
|
||||
|
||||
Layout::RecursivePointer => {
|
||||
unreachable!("recursion pointers should never be compared directly")
|
||||
}
|
||||
|
@ -1252,3 +1280,146 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
)
|
||||
.into_int_value()
|
||||
}
|
||||
|
||||
/// ----
|
||||
|
||||
fn build_box_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
box_layout: &Layout<'a>,
|
||||
inner_layout: &Layout<'a>,
|
||||
tag1: BasicValueEnum<'ctx>,
|
||||
tag2: BasicValueEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, box_layout)
|
||||
.to_symbol_string(symbol, &env.interns);
|
||||
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = basic_type_from_layout_1(env, box_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
&fn_name,
|
||||
env.context.bool_type().into(),
|
||||
&[arg_type, arg_type],
|
||||
);
|
||||
|
||||
build_box_eq_help(
|
||||
env,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
inner_layout,
|
||||
);
|
||||
|
||||
function_value
|
||||
}
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[tag1.into(), tag2.into()], "tag_eq");
|
||||
|
||||
call.set_call_convention(FAST_CALL_CONV);
|
||||
|
||||
call.try_as_basic_value().left().unwrap()
|
||||
}
|
||||
|
||||
fn build_box_eq_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
inner_layout: &Layout<'a>,
|
||||
) {
|
||||
let ctx = env.context;
|
||||
let builder = env.builder;
|
||||
|
||||
{
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
|
||||
let func_scope = parent.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(ctx, loc);
|
||||
}
|
||||
|
||||
// Add args to scope
|
||||
let mut it = parent.get_param_iter();
|
||||
let box1 = it.next().unwrap();
|
||||
let box2 = it.next().unwrap();
|
||||
|
||||
box1.set_name(Symbol::ARG_1.as_str(&env.interns));
|
||||
box2.set_name(Symbol::ARG_2.as_str(&env.interns));
|
||||
|
||||
let return_true = ctx.append_basic_block(parent, "return_true");
|
||||
env.builder.position_at_end(return_true);
|
||||
env.builder
|
||||
.build_return(Some(&env.context.bool_type().const_all_ones()));
|
||||
|
||||
let return_false = ctx.append_basic_block(parent, "return_false");
|
||||
env.builder.position_at_end(return_false);
|
||||
env.builder
|
||||
.build_return(Some(&env.context.bool_type().const_zero()));
|
||||
|
||||
let entry = ctx.append_basic_block(parent, "entry");
|
||||
env.builder.position_at_end(entry);
|
||||
|
||||
let ptr_equal = env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
env.builder
|
||||
.build_ptr_to_int(box1.into_pointer_value(), env.ptr_int(), "pti"),
|
||||
env.builder
|
||||
.build_ptr_to_int(box2.into_pointer_value(), env.ptr_int(), "pti"),
|
||||
"compare_pointers",
|
||||
);
|
||||
|
||||
let compare_inner_value = ctx.append_basic_block(parent, "compare_inner_value");
|
||||
|
||||
env.builder
|
||||
.build_conditional_branch(ptr_equal, return_true, compare_inner_value);
|
||||
|
||||
env.builder.position_at_end(compare_inner_value);
|
||||
|
||||
// clear the tag_id so we get a pointer to the actual data
|
||||
let box1 = box1.into_pointer_value();
|
||||
let box2 = box2.into_pointer_value();
|
||||
|
||||
let value1 = env.builder.build_load(box1, "load_box1");
|
||||
let value2 = env.builder.build_load(box2, "load_box2");
|
||||
|
||||
let is_equal = build_eq(
|
||||
env,
|
||||
layout_ids,
|
||||
value1,
|
||||
value2,
|
||||
inner_layout,
|
||||
inner_layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&is_equal));
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
..
|
||||
} => basic_type_from_record(env, sorted_fields),
|
||||
LambdaSet(lambda_set) => basic_type_from_layout(env, &lambda_set.runtime_representation()),
|
||||
Boxed(inner_layout) => {
|
||||
let inner_type = basic_type_from_layout_1(env, inner_layout);
|
||||
|
||||
inner_type.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
Union(union_layout) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
|
@ -96,6 +101,11 @@ pub fn basic_type_from_layout_1<'a, 'ctx, 'env>(
|
|||
LambdaSet(lambda_set) => {
|
||||
basic_type_from_layout_1(env, &lambda_set.runtime_representation())
|
||||
}
|
||||
Boxed(inner_layout) => {
|
||||
let inner_type = basic_type_from_layout_1(env, inner_layout);
|
||||
|
||||
inner_type.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
Union(union_layout) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
|
|
|
@ -589,6 +589,12 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
modify_refcount_builtin(env, layout_ids, mode, when_recursive, layout, builtin)
|
||||
}
|
||||
|
||||
Boxed(inner) => {
|
||||
let function = modify_refcount_boxed(env, layout_ids, mode, inner);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
||||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
|
@ -890,6 +896,73 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
|||
builder.build_return(None);
|
||||
}
|
||||
|
||||
fn modify_refcount_boxed<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
inner_layout: &Layout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
&env.interns,
|
||||
"increment_boxed",
|
||||
"decrement_boxed",
|
||||
inner_layout,
|
||||
mode,
|
||||
);
|
||||
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = basic_type_from_layout(env, &Layout::Boxed(&inner_layout));
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_box_help(env, mode, inner_layout, function_value);
|
||||
|
||||
function_value
|
||||
}
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
|
||||
function
|
||||
}
|
||||
|
||||
fn modify_refcount_box_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
mode: Mode,
|
||||
inner_layout: &Layout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
debug_info_init!(env, fn_val);
|
||||
|
||||
// Add args to scope
|
||||
let arg_symbol = Symbol::ARG_1;
|
||||
let arg_val = fn_val.get_param_iter().next().unwrap();
|
||||
|
||||
let boxed = arg_val.into_pointer_value();
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
let boxed_layout = Layout::Boxed(&inner_layout);
|
||||
refcount_ptr.modify(call_mode, &boxed_layout, env);
|
||||
|
||||
// this function returns void
|
||||
builder.build_return(None);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn modify_refcount_dict<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue