mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
work on dicts
This commit is contained in:
parent
d01d539d6b
commit
f3199ed2a7
5 changed files with 150 additions and 77 deletions
|
@ -414,8 +414,11 @@ const HashFn = fn (u64, ?[*]u8) callconv(.C) u64;
|
||||||
const EqFn = fn (?[*]u8, ?[*]u8) callconv(.C) bool;
|
const EqFn = fn (?[*]u8, ?[*]u8) callconv(.C) bool;
|
||||||
|
|
||||||
const Inc = fn (?[*]u8) callconv(.C) void;
|
const Inc = fn (?[*]u8) callconv(.C) void;
|
||||||
|
const IncN = fn (?[*]u8, usize) callconv(.C) void;
|
||||||
const Dec = fn (?[*]u8) callconv(.C) void;
|
const Dec = fn (?[*]u8) callconv(.C) void;
|
||||||
|
|
||||||
|
const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||||
|
|
||||||
// Dict.insert : Dict k v, k, v -> Dict k v
|
// Dict.insert : Dict k v, k, v -> Dict k v
|
||||||
pub fn dictInsert(input: RocDict, alignment: Alignment, key: Opaque, key_width: usize, value: Opaque, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Dec, dec_value: Dec, output: *RocDict) callconv(.C) void {
|
pub fn dictInsert(input: RocDict, alignment: Alignment, key: Opaque, key_width: usize, value: Opaque, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Dec, dec_value: Dec, output: *RocDict) callconv(.C) void {
|
||||||
var seed: u64 = INITIAL_SEED;
|
var seed: u64 = INITIAL_SEED;
|
||||||
|
@ -759,14 +762,31 @@ pub fn setFromList(list: RocList, alignment: Alignment, key_width: usize, value_
|
||||||
decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const StepperCaller = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
pub fn dictWalk(
|
||||||
pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, accum: Opaque, alignment: Alignment, key_width: usize, value_width: usize, accum_width: usize, inc_key: Inc, inc_value: Inc, output: Opaque) callconv(.C) void {
|
dict: RocDict,
|
||||||
|
caller: Caller3,
|
||||||
|
data: Opaque,
|
||||||
|
inc_n_data: IncN,
|
||||||
|
data_is_owned: bool,
|
||||||
|
accum: Opaque,
|
||||||
|
alignment: Alignment,
|
||||||
|
key_width: usize,
|
||||||
|
value_width: usize,
|
||||||
|
accum_width: usize,
|
||||||
|
inc_key: Inc,
|
||||||
|
inc_value: Inc,
|
||||||
|
output: Opaque,
|
||||||
|
) callconv(.C) void {
|
||||||
// allocate space to write the result of the stepper into
|
// allocate space to write the result of the stepper into
|
||||||
// experimentally aliasing the accum and output pointers is not a good idea
|
// experimentally aliasing the accum and output pointers is not a good idea
|
||||||
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
||||||
var b1 = output orelse unreachable;
|
var b1 = output orelse unreachable;
|
||||||
var b2 = alloc;
|
var b2 = alloc;
|
||||||
|
|
||||||
|
if (data_is_owned) {
|
||||||
|
inc_n_data(data, dict.len());
|
||||||
|
}
|
||||||
|
|
||||||
@memcpy(b2, accum orelse unreachable, accum_width);
|
@memcpy(b2, accum orelse unreachable, accum_width);
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
@ -777,7 +797,7 @@ pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, a
|
||||||
const key = dict.getKey(i, alignment, key_width, value_width);
|
const key = dict.getKey(i, alignment, key_width, value_width);
|
||||||
const value = dict.getValue(i, alignment, key_width, value_width);
|
const value = dict.getValue(i, alignment, key_width, value_width);
|
||||||
|
|
||||||
stepper_caller(stepper, key, value, b2, b1);
|
caller(data, key, value, b2, b1);
|
||||||
|
|
||||||
const temp = b1;
|
const temp = b1;
|
||||||
b2 = b1;
|
b2 = b1;
|
||||||
|
@ -789,7 +809,4 @@ pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, a
|
||||||
|
|
||||||
@memcpy(output orelse unreachable, b2, accum_width);
|
@memcpy(output orelse unreachable, b2, accum_width);
|
||||||
std.heap.c_allocator.free(alloc[0..accum_width]);
|
std.heap.c_allocator.free(alloc[0..accum_width]);
|
||||||
|
|
||||||
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
|
|
||||||
decref(std.heap.c_allocator, alignment, dict.dict_bytes, data_bytes);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,7 +516,18 @@ pub fn listKeepResult(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, output: Opaque) callconv(.C) void {
|
pub fn listWalk(
|
||||||
|
list: RocList,
|
||||||
|
caller: Caller2,
|
||||||
|
data: Opaque,
|
||||||
|
inc_n_data: IncN,
|
||||||
|
data_is_owned: bool,
|
||||||
|
accum: Opaque,
|
||||||
|
alignment: usize,
|
||||||
|
element_width: usize,
|
||||||
|
accum_width: usize,
|
||||||
|
output: Opaque,
|
||||||
|
) callconv(.C) void {
|
||||||
if (accum_width == 0) {
|
if (accum_width == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -526,6 +537,10 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data_is_owned) {
|
||||||
|
inc_n_data(data, list.len());
|
||||||
|
}
|
||||||
|
|
||||||
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
||||||
var b1 = output orelse unreachable;
|
var b1 = output orelse unreachable;
|
||||||
var b2 = alloc;
|
var b2 = alloc;
|
||||||
|
@ -537,7 +552,7 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
|
||||||
const size = list.len();
|
const size = list.len();
|
||||||
while (i < size) : (i += 1) {
|
while (i < size) : (i += 1) {
|
||||||
const element = source_ptr + i * element_width;
|
const element = source_ptr + i * element_width;
|
||||||
stepper_caller(stepper, element, b2, b1);
|
caller(data, element, b2, b1);
|
||||||
|
|
||||||
const temp = b1;
|
const temp = b1;
|
||||||
b2 = b1;
|
b2 = b1;
|
||||||
|
@ -547,12 +562,20 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
|
||||||
|
|
||||||
@memcpy(output orelse unreachable, b2, accum_width);
|
@memcpy(output orelse unreachable, b2, accum_width);
|
||||||
std.heap.c_allocator.free(alloc[0..accum_width]);
|
std.heap.c_allocator.free(alloc[0..accum_width]);
|
||||||
|
|
||||||
const data_bytes = list.len() * element_width;
|
|
||||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, output: Opaque) callconv(.C) void {
|
pub fn listWalkBackwards(
|
||||||
|
list: RocList,
|
||||||
|
caller: Caller2,
|
||||||
|
data: Opaque,
|
||||||
|
inc_n_data: IncN,
|
||||||
|
data_is_owned: bool,
|
||||||
|
accum: Opaque,
|
||||||
|
alignment: usize,
|
||||||
|
element_width: usize,
|
||||||
|
accum_width: usize,
|
||||||
|
output: Opaque,
|
||||||
|
) callconv(.C) void {
|
||||||
if (accum_width == 0) {
|
if (accum_width == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -562,6 +585,10 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data_is_owned) {
|
||||||
|
inc_n_data(data, list.len());
|
||||||
|
}
|
||||||
|
|
||||||
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
const alloc: [*]u8 = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, accum_width) catch unreachable);
|
||||||
var b1 = output orelse unreachable;
|
var b1 = output orelse unreachable;
|
||||||
var b2 = alloc;
|
var b2 = alloc;
|
||||||
|
@ -574,7 +601,7 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
const element = source_ptr + i * element_width;
|
const element = source_ptr + i * element_width;
|
||||||
stepper_caller(stepper, element, b2, b1);
|
caller(data, element, b2, b1);
|
||||||
|
|
||||||
const temp = b1;
|
const temp = b1;
|
||||||
b2 = b1;
|
b2 = b1;
|
||||||
|
@ -584,12 +611,21 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
|
||||||
|
|
||||||
@memcpy(output orelse unreachable, b2, accum_width);
|
@memcpy(output orelse unreachable, b2, accum_width);
|
||||||
std.heap.c_allocator.free(alloc[0..accum_width]);
|
std.heap.c_allocator.free(alloc[0..accum_width]);
|
||||||
|
|
||||||
const data_bytes = list.len() * element_width;
|
|
||||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, dec: Dec, output: Opaque) callconv(.C) void {
|
pub fn listWalkUntil(
|
||||||
|
list: RocList,
|
||||||
|
caller: Caller2,
|
||||||
|
data: Opaque,
|
||||||
|
inc_n_data: IncN,
|
||||||
|
data_is_owned: bool,
|
||||||
|
accum: Opaque,
|
||||||
|
alignment: usize,
|
||||||
|
element_width: usize,
|
||||||
|
accum_width: usize,
|
||||||
|
dec: Dec,
|
||||||
|
output: Opaque,
|
||||||
|
) callconv(.C) void {
|
||||||
// [ Continue a, Stop a ]
|
// [ Continue a, Stop a ]
|
||||||
const CONTINUE: usize = 0;
|
const CONTINUE: usize = 0;
|
||||||
|
|
||||||
|
@ -611,7 +647,12 @@ pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, ac
|
||||||
const size = list.len();
|
const size = list.len();
|
||||||
while (i < size) : (i += 1) {
|
while (i < size) : (i += 1) {
|
||||||
const element = source_ptr + i * element_width;
|
const element = source_ptr + i * element_width;
|
||||||
stepper_caller(stepper, element, alloc + TAG_WIDTH, alloc);
|
|
||||||
|
if (data_is_owned) {
|
||||||
|
inc_n_data(data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
caller(data, element, alloc + TAG_WIDTH, alloc);
|
||||||
|
|
||||||
const usizes: [*]usize = @ptrCast([*]usize, @alignCast(8, alloc));
|
const usizes: [*]usize = @ptrCast([*]usize, @alignCast(8, alloc));
|
||||||
if (usizes[0] != 0) {
|
if (usizes[0] != 0) {
|
||||||
|
@ -627,9 +668,6 @@ pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, ac
|
||||||
|
|
||||||
@memcpy(output orelse unreachable, alloc + TAG_WIDTH, accum_width);
|
@memcpy(output orelse unreachable, alloc + TAG_WIDTH, accum_width);
|
||||||
std.heap.c_allocator.free(alloc[0 .. TAG_WIDTH + accum_width]);
|
std.heap.c_allocator.free(alloc[0 .. TAG_WIDTH + accum_width]);
|
||||||
|
|
||||||
const data_bytes = list.len() * element_width;
|
|
||||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List.contains : List k, k -> Bool
|
// List.contains : List k, k -> Bool
|
||||||
|
|
|
@ -2332,6 +2332,40 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
env.builder.build_unconditional_branch(done);
|
env.builder.build_unconditional_branch(done);
|
||||||
env.builder.position_at_end(done);
|
env.builder.position_at_end(done);
|
||||||
}
|
}
|
||||||
|
Layout::Builtin(Builtin::Dict(_, _)) => {
|
||||||
|
debug_assert!(value.is_struct_value());
|
||||||
|
|
||||||
|
let refcount_ptr = PointerToRefcount::from_list_wrapper(
|
||||||
|
env,
|
||||||
|
value.into_struct_value(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// because of how we insert DECREF for lists, we can't guarantee that
|
||||||
|
// the list is non-empty. When the list is empty, the pointer to the
|
||||||
|
// elements is NULL, and trying to get to the RC address will
|
||||||
|
// underflow, causing a segfault. Therefore, in this case we must
|
||||||
|
// manually check that the list is non-empty
|
||||||
|
let not_empty = env.context.append_basic_block(parent, "not_null");
|
||||||
|
let done = env.context.append_basic_block(parent, "done");
|
||||||
|
|
||||||
|
let length = dict_len(env, scope, *symbol).into_int_value();
|
||||||
|
let is_empty = env.builder.build_int_compare(
|
||||||
|
IntPredicate::EQ,
|
||||||
|
length,
|
||||||
|
length.get_type().const_zero(),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
env.builder
|
||||||
|
.build_conditional_branch(is_empty, done, not_empty);
|
||||||
|
|
||||||
|
env.builder.position_at_end(not_empty);
|
||||||
|
|
||||||
|
refcount_ptr.decrement(env, layout);
|
||||||
|
|
||||||
|
env.builder.build_unconditional_branch(done);
|
||||||
|
env.builder.position_at_end(done);
|
||||||
|
}
|
||||||
|
|
||||||
_ if layout.is_refcounted() => {
|
_ if layout.is_refcounted() => {
|
||||||
if value.is_pointer_value() {
|
if value.is_pointer_value() {
|
||||||
|
@ -4066,18 +4100,30 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
// no elements, so `key` is not in here
|
// no elements, so `key` is not in here
|
||||||
panic!("key type unknown")
|
panic!("key type unknown")
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => dict_walk(
|
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||||
env,
|
let argument_layouts = &[**key_layout, **value_layout, *default_layout];
|
||||||
layout_ids,
|
|
||||||
dict,
|
let roc_function_call = roc_function_call(
|
||||||
function,
|
env,
|
||||||
closure,
|
layout_ids,
|
||||||
*closure_layout,
|
function,
|
||||||
default,
|
closure,
|
||||||
key_layout,
|
*closure_layout,
|
||||||
value_layout,
|
function_owns_closure_data,
|
||||||
default_layout,
|
argument_layouts,
|
||||||
),
|
);
|
||||||
|
|
||||||
|
dict_walk(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
roc_function_call,
|
||||||
|
dict,
|
||||||
|
default,
|
||||||
|
key_layout,
|
||||||
|
value_layout,
|
||||||
|
default_layout,
|
||||||
|
)
|
||||||
|
}
|
||||||
_ => unreachable!("invalid dict layout"),
|
_ => unreachable!("invalid dict layout"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4584,7 +4630,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
DictEmpty => {
|
DictEmpty => {
|
||||||
debug_assert_eq!(args.len(), 0);
|
debug_assert_eq!(args.len(), 0);
|
||||||
dict_empty(env, scope)
|
dict_empty(env)
|
||||||
}
|
}
|
||||||
DictInsert => {
|
DictInsert => {
|
||||||
debug_assert_eq!(args.len(), 3);
|
debug_assert_eq!(args.len(), 3);
|
||||||
|
@ -4734,7 +4780,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => dict_empty(env, scope),
|
Layout::Builtin(Builtin::EmptyList) => dict_empty(env),
|
||||||
Layout::Builtin(Builtin::List(_, key_layout)) => {
|
Layout::Builtin(Builtin::List(_, key_layout)) => {
|
||||||
set_from_list(env, layout_ids, list, key_layout)
|
set_from_list(env, layout_ids, list, key_layout)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::debug_info_init;
|
use crate::debug_info_init;
|
||||||
use crate::llvm::bitcode::{
|
use crate::llvm::bitcode::{
|
||||||
build_dec_wrapper, build_eq_wrapper, build_inc_wrapper, build_transform_caller_new,
|
build_dec_wrapper, build_eq_wrapper, build_inc_wrapper, call_bitcode_fn, call_void_bitcode_fn,
|
||||||
call_bitcode_fn, call_void_bitcode_fn,
|
|
||||||
};
|
};
|
||||||
use crate::llvm::build::{
|
use crate::llvm::build::{
|
||||||
complex_bitcast, load_symbol, load_symbol_and_layout, set_name, Env, Scope,
|
complex_bitcast, load_symbol, load_symbol_and_layout, set_name, Env, RocFunctionCall, Scope,
|
||||||
};
|
};
|
||||||
|
use crate::llvm::build_list::{layout_width, pass_as_opaque};
|
||||||
use crate::llvm::convert::{as_const_zero, basic_type_from_layout};
|
use crate::llvm::convert::{as_const_zero, basic_type_from_layout};
|
||||||
use crate::llvm::refcounting::Mode;
|
use crate::llvm::refcounting::Mode;
|
||||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||||
|
@ -71,10 +71,7 @@ pub fn dict_len<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dict_empty<'a, 'ctx, 'env>(
|
pub fn dict_empty<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> {
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
|
||||||
_scope: &Scope<'a, 'ctx>,
|
|
||||||
) -> BasicValueEnum<'ctx> {
|
|
||||||
// get the RocDict type defined by zig
|
// get the RocDict type defined by zig
|
||||||
let roc_dict_type = env.module.get_struct_type("dict.RocDict").unwrap();
|
let roc_dict_type = env.module.get_struct_type("dict.RocDict").unwrap();
|
||||||
|
|
||||||
|
@ -639,10 +636,8 @@ fn dict_intersect_or_difference<'a, 'ctx, 'env>(
|
||||||
pub fn dict_walk<'a, 'ctx, 'env>(
|
pub fn dict_walk<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
|
roc_function_call: RocFunctionCall<'ctx>,
|
||||||
dict: BasicValueEnum<'ctx>,
|
dict: BasicValueEnum<'ctx>,
|
||||||
transform: FunctionValue<'ctx>,
|
|
||||||
closure_data: BasicValueEnum<'ctx>,
|
|
||||||
closure_data_layout: Layout<'a>,
|
|
||||||
accum: BasicValueEnum<'ctx>,
|
accum: BasicValueEnum<'ctx>,
|
||||||
key_layout: &Layout<'a>,
|
key_layout: &Layout<'a>,
|
||||||
value_layout: &Layout<'a>,
|
value_layout: &Layout<'a>,
|
||||||
|
@ -656,34 +651,10 @@ pub fn dict_walk<'a, 'ctx, 'env>(
|
||||||
let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr");
|
let dict_ptr = builder.build_alloca(zig_dict_type, "dict_ptr");
|
||||||
env.builder.build_store(dict_ptr, dict);
|
env.builder.build_store(dict_ptr, dict);
|
||||||
|
|
||||||
let closure_data_ptr = builder.build_alloca(closure_data.get_type(), "closure_data_ptr");
|
|
||||||
env.builder.build_store(closure_data_ptr, closure_data);
|
|
||||||
|
|
||||||
let stepper_caller = build_transform_caller_new(
|
|
||||||
env,
|
|
||||||
transform,
|
|
||||||
closure_data_layout,
|
|
||||||
&[*key_layout, *value_layout, *accum_layout],
|
|
||||||
)
|
|
||||||
.as_global_value()
|
|
||||||
.as_pointer_value();
|
|
||||||
|
|
||||||
let accum_bt = basic_type_from_layout(env, accum_layout);
|
let accum_bt = basic_type_from_layout(env, accum_layout);
|
||||||
let accum_ptr = builder.build_alloca(accum_bt, "accum_ptr");
|
let accum_ptr = builder.build_alloca(accum_bt, "accum_ptr");
|
||||||
env.builder.build_store(accum_ptr, accum);
|
env.builder.build_store(accum_ptr, accum);
|
||||||
|
|
||||||
let key_width = env
|
|
||||||
.ptr_int()
|
|
||||||
.const_int(key_layout.stack_size(env.ptr_bytes) as u64, false);
|
|
||||||
|
|
||||||
let value_width = env
|
|
||||||
.ptr_int()
|
|
||||||
.const_int(value_layout.stack_size(env.ptr_bytes) as u64, false);
|
|
||||||
|
|
||||||
let accum_width = env
|
|
||||||
.ptr_int()
|
|
||||||
.const_int(accum_layout.stack_size(env.ptr_bytes) as u64, false);
|
|
||||||
|
|
||||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.ptr_bytes);
|
||||||
let alignment_iv = env.context.i8_type().const_int(alignment as u64, false);
|
let alignment_iv = env.context.i8_type().const_int(alignment as u64, false);
|
||||||
|
|
||||||
|
@ -696,14 +667,15 @@ pub fn dict_walk<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
dict_ptr.into(),
|
dict_ptr.into(),
|
||||||
env.builder
|
roc_function_call.caller.into(),
|
||||||
.build_bitcast(closure_data_ptr, u8_ptr, "to_opaque"),
|
pass_as_opaque(env, roc_function_call.data),
|
||||||
stepper_caller.into(),
|
roc_function_call.inc_n_data.into(),
|
||||||
|
roc_function_call.data_is_owned.into(),
|
||||||
env.builder.build_bitcast(accum_ptr, u8_ptr, "to_opaque"),
|
env.builder.build_bitcast(accum_ptr, u8_ptr, "to_opaque"),
|
||||||
alignment_iv.into(),
|
alignment_iv.into(),
|
||||||
key_width.into(),
|
layout_width(env, key_layout),
|
||||||
value_width.into(),
|
layout_width(env, value_layout),
|
||||||
accum_width.into(),
|
layout_width(env, accum_layout),
|
||||||
inc_key_fn.as_global_value().as_pointer_value().into(),
|
inc_key_fn.as_global_value().as_pointer_value().into(),
|
||||||
inc_value_fn.as_global_value().as_pointer_value().into(),
|
inc_value_fn.as_global_value().as_pointer_value().into(),
|
||||||
env.builder.build_bitcast(output_ptr, u8_ptr, "to_opaque"),
|
env.builder.build_bitcast(output_ptr, u8_ptr, "to_opaque"),
|
||||||
|
|
|
@ -72,7 +72,7 @@ fn pass_list_as_i128<'a, 'ctx, 'env>(
|
||||||
complex_bitcast(env.builder, list, env.context.i128_type().into(), "to_i128")
|
complex_bitcast(env.builder, list, env.context.i128_type().into(), "to_i128")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_width<'a, 'ctx, 'env>(
|
pub fn layout_width<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
@ -81,7 +81,7 @@ fn layout_width<'a, 'ctx, 'env>(
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pass_as_opaque<'a, 'ctx, 'env>(
|
pub fn pass_as_opaque<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
ptr: PointerValue<'ctx>,
|
ptr: PointerValue<'ctx>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue