mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Don't hardcode elem_bytes in llvm
This commit is contained in:
parent
0a045ccec8
commit
8f51b2d429
1 changed files with 58 additions and 44 deletions
|
@ -129,14 +129,14 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
|||
panic!("TODO create a phi node for &&");
|
||||
}
|
||||
_ => {
|
||||
let mut arg_vals: Vec<BasicValueEnum> =
|
||||
let mut arg_tuples: Vec<(BasicValueEnum, &'a Layout<'a>)> =
|
||||
Vec::with_capacity_in(args.len(), env.arena);
|
||||
|
||||
for (arg, _layout) in args.iter() {
|
||||
arg_vals.push(build_expr(env, scope, parent, arg, procs));
|
||||
for (arg, layout) in args.into_iter() {
|
||||
arg_tuples.push((build_expr(env, scope, parent, arg, procs), layout));
|
||||
}
|
||||
|
||||
call_with_args(*symbol, arg_vals.into_bump_slice(), env)
|
||||
call_with_args(*symbol, arg_tuples.into_bump_slice(), env)
|
||||
}
|
||||
},
|
||||
FunctionPointer(symbol) => {
|
||||
|
@ -172,7 +172,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
|||
.left()
|
||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
||||
}
|
||||
|
||||
Load(symbol) => match scope.get(symbol) {
|
||||
Some((_, ptr)) => env
|
||||
.builder
|
||||
|
@ -854,7 +853,7 @@ pub fn verify_fn(fn_val: FunctionValue<'_>) {
|
|||
#[allow(clippy::cognitive_complexity)]
|
||||
fn call_with_args<'a, 'ctx, 'env>(
|
||||
symbol: Symbol,
|
||||
args: &[BasicValueEnum<'ctx>],
|
||||
args: &[(BasicValueEnum<'ctx>, &'a Layout<'a>)],
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match symbol {
|
||||
|
@ -862,8 +861,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
debug_assert!(args.len() == 2);
|
||||
|
||||
let int_val = env.builder.build_int_add(
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"add_i64",
|
||||
);
|
||||
|
||||
|
@ -873,8 +872,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
debug_assert!(args.len() == 2);
|
||||
|
||||
let float_val = env.builder.build_float_add(
|
||||
args[0].into_float_value(),
|
||||
args[1].into_float_value(),
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"add_f64",
|
||||
);
|
||||
|
||||
|
@ -884,8 +883,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
debug_assert!(args.len() == 2);
|
||||
|
||||
let int_val = env.builder.build_int_sub(
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"sub_I64",
|
||||
);
|
||||
|
||||
|
@ -895,8 +894,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
debug_assert!(args.len() == 2);
|
||||
|
||||
let float_val = env.builder.build_float_sub(
|
||||
args[0].into_float_value(),
|
||||
args[1].into_float_value(),
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"sub_f64",
|
||||
);
|
||||
|
||||
|
@ -906,8 +905,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
debug_assert!(args.len() == 2);
|
||||
|
||||
let int_val = env.builder.build_int_mul(
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"mul_i64",
|
||||
);
|
||||
|
||||
|
@ -918,14 +917,14 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
let int_val = env
|
||||
.builder
|
||||
.build_int_neg(args[0].into_int_value(), "negate_i64");
|
||||
.build_int_neg(args[0].0.into_int_value(), "negate_i64");
|
||||
|
||||
BasicValueEnum::IntValue(int_val)
|
||||
}
|
||||
Symbol::LIST_LEN => {
|
||||
debug_assert!(args.len() == 1);
|
||||
|
||||
let wrapper_struct = args[0].into_struct_value();
|
||||
let wrapper_struct = args[0].0.into_struct_value();
|
||||
let builder = env.builder;
|
||||
|
||||
// Get the usize int length
|
||||
|
@ -934,7 +933,7 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
Symbol::LIST_IS_EMPTY => {
|
||||
debug_assert!(args.len() == 1);
|
||||
|
||||
let list_struct = args[0].into_struct_value();
|
||||
let list_struct = args[0].0.into_struct_value();
|
||||
let builder = env.builder;
|
||||
let list_len = builder.build_extract_value(list_struct, 1, "unwrapped_list_len").unwrap().into_int_value();
|
||||
let zero = env.ptr_int().const_zero();
|
||||
|
@ -947,8 +946,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
let int_val = env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"cmp_i64",
|
||||
);
|
||||
|
||||
|
@ -959,8 +958,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
let int_val = env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"cmp_i1",
|
||||
);
|
||||
|
||||
|
@ -971,8 +970,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
let int_val = env.builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
args[0].into_int_value(),
|
||||
args[1].into_int_value(),
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"cmp_i8",
|
||||
);
|
||||
|
||||
|
@ -983,8 +982,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
let int_val = env.builder.build_float_compare(
|
||||
FloatPredicate::OEQ,
|
||||
args[0].into_float_value(),
|
||||
args[1].into_float_value(),
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"cmp_f64",
|
||||
);
|
||||
|
||||
|
@ -996,18 +995,22 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let wrapper_struct = args[0].into_struct_value();
|
||||
let elem_index = args[1].into_int_value();
|
||||
let (_list_expr, list_layout) = &args[0];
|
||||
|
||||
// Slot 1 in the wrapper struct is the length
|
||||
let wrapper_struct = args[0].0.into_struct_value();
|
||||
let elem_index = args[1].0.into_int_value();
|
||||
|
||||
// Get the length from the wrapper struct
|
||||
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
||||
|
||||
// TODO here, check to see if the requested index exceeds the length of the array.
|
||||
|
||||
// Slot 0 in the wrapper struct is the pointer to the array data
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::List(elem_layout)) => {
|
||||
// Get the pointer to the array data
|
||||
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
||||
|
||||
let elem_bytes = 8; // TODO Look this size up instead of hardcoding it!
|
||||
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
||||
|
||||
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
||||
|
@ -1018,14 +1021,19 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
builder.build_load(elem_ptr, "List.get")
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Invalid List layout for List.get: {:?}", list_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
Symbol::LIST_SET /* TODO clone first for LIST_SET! */ | Symbol::LIST_SET_IN_PLACE => {
|
||||
let builder = env.builder;
|
||||
|
||||
debug_assert!(args.len() == 3);
|
||||
|
||||
let wrapper_struct = args[0].into_struct_value();
|
||||
let elem_index = args[1].into_int_value();
|
||||
let elem = args[2];
|
||||
let wrapper_struct = args[0].0.into_struct_value();
|
||||
let elem_index = args[1].0.into_int_value();
|
||||
let (elem, elem_layout) = args[2];
|
||||
|
||||
// Slot 1 in the wrapper struct is the length
|
||||
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
||||
|
@ -1036,7 +1044,7 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
// Slot 0 in the wrapper struct is the pointer to the array data
|
||||
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
||||
|
||||
let elem_bytes = 8; // TODO Look this size up instead of hardcoding it!
|
||||
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
||||
|
||||
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
||||
|
@ -1057,7 +1065,13 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
.get_function(symbol.ident_string(&env.interns))
|
||||
.unwrap_or_else(|| panic!("Unrecognized function: {:?}", symbol));
|
||||
|
||||
let call = env.builder.build_call(fn_val, args, "tmp");
|
||||
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(args.len(), env.arena);
|
||||
|
||||
for (arg, _layout) in args.into_iter() {
|
||||
arg_vals.push(*arg);
|
||||
}
|
||||
|
||||
let call = env.builder.build_call(fn_val, arg_vals.into_bump_slice(), "call");
|
||||
|
||||
call.try_as_basic_value()
|
||||
.left()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue