mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Merge remote-tracking branch 'origin/trunk' into gen-dev/quicksort
This commit is contained in:
commit
fae2ed7a2b
130 changed files with 10112 additions and 2543 deletions
|
@ -433,14 +433,15 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
|||
arguments_cast.push(argument);
|
||||
}
|
||||
|
||||
match closure_data_layout.runtime_representation() {
|
||||
Layout::Struct {
|
||||
field_layouts: &[], ..
|
||||
} => {
|
||||
// nothing to add
|
||||
match (
|
||||
closure_data_layout.is_represented().is_some(),
|
||||
closure_data_layout.runtime_representation(),
|
||||
) {
|
||||
(false, _) => {
|
||||
// the function doesn't expect a closure argument, nothing to add
|
||||
}
|
||||
other => {
|
||||
let closure_type = basic_type_from_layout(env, &other).ptr_type(AddressSpace::Generic);
|
||||
(true, layout) => {
|
||||
let closure_type = basic_type_from_layout(env, &layout).ptr_type(AddressSpace::Generic);
|
||||
|
||||
let closure_cast = env
|
||||
.builder
|
||||
|
|
|
@ -841,16 +841,20 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
|
|||
&Layout::UNIT,
|
||||
);
|
||||
|
||||
let (roc_return, output_type) = match roc_main_fn.get_type().get_return_type() {
|
||||
Some(return_type) => {
|
||||
let output_type = return_type.ptr_type(AddressSpace::Generic);
|
||||
(RocReturn::Return, output_type.into())
|
||||
}
|
||||
None => {
|
||||
assert_eq!(roc_main_fn.get_type().get_param_types().len(), 1);
|
||||
let output_type = roc_main_fn.get_type().get_param_types()[0];
|
||||
(RocReturn::ByPointer, output_type)
|
||||
}
|
||||
};
|
||||
|
||||
let main_fn = {
|
||||
let c_function_spec = {
|
||||
match roc_main_fn.get_type().get_return_type() {
|
||||
Some(return_type) => {
|
||||
let output_type = return_type.ptr_type(AddressSpace::Generic);
|
||||
FunctionSpec::cconv(env, CCReturn::Return, Some(output_type.into()), &[])
|
||||
}
|
||||
None => todo!(),
|
||||
}
|
||||
};
|
||||
let c_function_spec = FunctionSpec::cconv(env, CCReturn::Return, Some(output_type), &[]);
|
||||
|
||||
let c_function = add_func(
|
||||
env.context,
|
||||
|
@ -870,42 +874,43 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
|
|||
let entry = context.append_basic_block(c_function, "entry");
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// call the main roc function
|
||||
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
|
||||
|
||||
// reserve space for the result on the heap
|
||||
// pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
||||
let (size, alignment) = top_level.result.stack_size_and_alignment(env.target_info);
|
||||
let roc_alloc = env.module.get_function("roc_alloc").unwrap();
|
||||
|
||||
let call = builder.build_call(
|
||||
roc_alloc,
|
||||
&[
|
||||
env.ptr_int().const_int(size as _, false).into(),
|
||||
env.context
|
||||
.i32_type()
|
||||
.const_int(alignment as _, false)
|
||||
.into(),
|
||||
],
|
||||
"result_ptr",
|
||||
);
|
||||
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
|
||||
|
||||
call.set_call_convention(C_CALL_CONV);
|
||||
let void_ptr = call.try_as_basic_value().left().unwrap();
|
||||
match roc_return {
|
||||
RocReturn::Return => {
|
||||
let call = builder.build_call(
|
||||
roc_alloc,
|
||||
&[
|
||||
env.ptr_int().const_int(size as _, false).into(),
|
||||
env.context
|
||||
.i32_type()
|
||||
.const_int(alignment as _, false)
|
||||
.into(),
|
||||
],
|
||||
"result_ptr",
|
||||
);
|
||||
|
||||
let ptr = builder.build_pointer_cast(
|
||||
void_ptr.into_pointer_value(),
|
||||
c_function
|
||||
.get_type()
|
||||
.get_return_type()
|
||||
.unwrap()
|
||||
.into_pointer_type(),
|
||||
"cast_ptr",
|
||||
);
|
||||
call.set_call_convention(C_CALL_CONV);
|
||||
let void_ptr = call.try_as_basic_value().left().unwrap();
|
||||
|
||||
builder.build_store(ptr, roc_main_fn_result);
|
||||
|
||||
builder.build_return(Some(&ptr));
|
||||
let ptr = builder.build_pointer_cast(
|
||||
void_ptr.into_pointer_value(),
|
||||
output_type.into_pointer_type(),
|
||||
"cast_ptr",
|
||||
);
|
||||
builder.build_store(ptr, roc_main_fn_result);
|
||||
builder.build_return(Some(&ptr));
|
||||
}
|
||||
RocReturn::ByPointer => {
|
||||
assert!(roc_main_fn_result.is_pointer_value());
|
||||
builder.build_return(Some(&roc_main_fn_result));
|
||||
}
|
||||
}
|
||||
|
||||
c_function
|
||||
};
|
||||
|
@ -984,7 +989,7 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
|
|||
if str_literal.len() < env.small_str_bytes() as usize {
|
||||
match env.small_str_bytes() {
|
||||
24 => small_str_ptr_width_8(env, parent, str_literal).into(),
|
||||
12 => small_str_ptr_width_4(env, parent, str_literal).into(),
|
||||
12 => small_str_ptr_width_4(env, str_literal).into(),
|
||||
_ => unreachable!("incorrect small_str_bytes"),
|
||||
}
|
||||
} else {
|
||||
|
@ -1051,9 +1056,8 @@ fn small_str_ptr_width_8<'a, 'ctx, 'env>(
|
|||
|
||||
fn small_str_ptr_width_4<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
str_literal: &str,
|
||||
) -> PointerValue<'ctx> {
|
||||
) -> StructValue<'ctx> {
|
||||
debug_assert_eq!(env.target_info.ptr_width() as u8, 4);
|
||||
|
||||
let mut array = [0u8; 12];
|
||||
|
@ -1074,7 +1078,11 @@ fn small_str_ptr_width_4<'a, 'ctx, 'env>(
|
|||
let ptr_type = env.context.i8_type().ptr_type(address_space);
|
||||
let ptr = env.builder.build_int_to_ptr(ptr, ptr_type, "to_u8_ptr");
|
||||
|
||||
const_str_alloca_ptr(env, parent, ptr, len, cap)
|
||||
struct_from_fields(
|
||||
env,
|
||||
zig_str_type(env),
|
||||
[(0, ptr.into()), (1, len.into()), (2, cap.into())].into_iter(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||
|
@ -2412,7 +2420,7 @@ fn list_literal<'a, 'ctx, 'env>(
|
|||
.build_in_bounds_gep(global, &[zero, offset], "first_element_pointer")
|
||||
};
|
||||
|
||||
super::build_list::store_list(env, ptr, list_length_intval)
|
||||
super::build_list::store_list(env, ptr, list_length_intval).into()
|
||||
} else {
|
||||
// some of our elements are non-constant, so we must allocate space on the heap
|
||||
let ptr = allocate_list(env, element_layout, list_length_intval);
|
||||
|
@ -2436,7 +2444,7 @@ fn list_literal<'a, 'ctx, 'env>(
|
|||
builder.build_store(elem_ptr, val);
|
||||
}
|
||||
|
||||
super::build_list::store_list(env, ptr, list_length_intval)
|
||||
super::build_list::store_list(env, ptr, list_length_intval).into()
|
||||
}
|
||||
} else {
|
||||
let ptr = allocate_list(env, element_layout, list_length_intval);
|
||||
|
@ -2455,7 +2463,7 @@ fn list_literal<'a, 'ctx, 'env>(
|
|||
store_roc_value(env, *element_layout, elem_ptr, val);
|
||||
}
|
||||
|
||||
super::build_list::store_list(env, ptr, list_length_intval)
|
||||
super::build_list::store_list(env, ptr, list_length_intval).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4837,8 +4845,9 @@ fn build_closure_caller<'a, 'ctx, 'env>(
|
|||
|
||||
// e.g. `roc__main_1_Fx_caller`
|
||||
let function_name = format!(
|
||||
"roc__{}_{}_caller",
|
||||
"roc__{}_{}_{}_caller",
|
||||
def_name,
|
||||
alias_symbol.module_string(&env.interns),
|
||||
alias_symbol.as_str(&env.interns)
|
||||
);
|
||||
|
||||
|
@ -4952,15 +4961,17 @@ fn build_host_exposed_alias_size_help<'a, 'ctx, 'env>(
|
|||
let size_function_spec = FunctionSpec::cconv(env, CCReturn::Return, Some(i64), &[]);
|
||||
let size_function_name: String = if let Some(label) = opt_label {
|
||||
format!(
|
||||
"roc__{}_{}_{}_size",
|
||||
"roc__{}_{}_{}_{}_size",
|
||||
def_name,
|
||||
alias_symbol.module_string(&env.interns),
|
||||
alias_symbol.as_str(&env.interns),
|
||||
label
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"roc__{}_{}_size",
|
||||
"roc__{}_{}_{}_size",
|
||||
def_name,
|
||||
alias_symbol.module_string(&env.interns),
|
||||
alias_symbol.as_str(&env.interns)
|
||||
)
|
||||
};
|
||||
|
|
|
@ -15,7 +15,10 @@ use roc_builtins::bitcode;
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||
|
||||
use super::build::{create_entry_block_alloca, load_roc_value, load_symbol, store_roc_value};
|
||||
use super::build::{
|
||||
create_entry_block_alloca, load_roc_value, load_symbol, store_roc_value, struct_from_fields,
|
||||
};
|
||||
use super::convert::zig_list_type;
|
||||
|
||||
pub fn list_symbol_to_c_abi<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -28,7 +31,7 @@ pub fn list_symbol_to_c_abi<'a, 'ctx, 'env>(
|
|||
.and_then(|b| b.get_parent())
|
||||
.unwrap();
|
||||
|
||||
let list_type = super::convert::zig_list_type(env);
|
||||
let list_type = zig_list_type(env);
|
||||
let list_alloca = create_entry_block_alloca(env, parent, list_type.into(), "list_alloca");
|
||||
|
||||
let list = load_symbol(scope, &symbol);
|
||||
|
@ -319,21 +322,28 @@ pub fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
// Load the element and returned list into a struct.
|
||||
let old_element = env.builder.build_load(element_ptr, "load_element");
|
||||
|
||||
let result = env
|
||||
.context
|
||||
.struct_type(
|
||||
&[super::convert::zig_list_type(env).into(), element_type],
|
||||
false,
|
||||
)
|
||||
.const_zero();
|
||||
// the list has the same alignment as a usize / ptr. The element comes first in the struct if
|
||||
// its alignment is bigger than that of a list.
|
||||
let element_align = element_layout.alignment_bytes(env.target_info);
|
||||
let element_first = element_align > env.target_info.ptr_width() as u32;
|
||||
|
||||
let fields = if element_first {
|
||||
[element_type, zig_list_type(env).into()]
|
||||
} else {
|
||||
[zig_list_type(env).into(), element_type]
|
||||
};
|
||||
|
||||
let result = env.context.struct_type(&fields, false).const_zero();
|
||||
|
||||
let (list_index, element_index) = if element_first { (1, 0) } else { (0, 1) };
|
||||
|
||||
let result = env
|
||||
.builder
|
||||
.build_insert_value(result, new_list, 0, "insert_list")
|
||||
.build_insert_value(result, new_list, list_index, "insert_list")
|
||||
.unwrap();
|
||||
|
||||
env.builder
|
||||
.build_insert_value(result, old_element, 1, "insert_value")
|
||||
.build_insert_value(result, old_element, element_index, "insert_value")
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
.into()
|
||||
|
@ -412,7 +422,7 @@ pub fn list_map<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(element_layout),
|
||||
env.alignment_intvalue(return_layout),
|
||||
layout_width(env, element_layout),
|
||||
layout_width(env, return_layout),
|
||||
],
|
||||
|
@ -757,7 +767,7 @@ where
|
|||
}
|
||||
|
||||
pub fn empty_polymorphic_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> {
|
||||
let struct_type = super::convert::zig_list_type(env);
|
||||
let struct_type = zig_list_type(env);
|
||||
|
||||
// The pointer should be null (aka zero) and the length should be zero,
|
||||
// so the whole struct should be a const_zero
|
||||
|
@ -816,40 +826,19 @@ pub fn store_list<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
pointer_to_first_element: PointerValue<'ctx>,
|
||||
len: IntValue<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
) -> StructValue<'ctx> {
|
||||
let ptr = pass_as_opaque(env, pointer_to_first_element);
|
||||
let cap = len;
|
||||
|
||||
let struct_type = super::convert::zig_list_type(env);
|
||||
|
||||
// Store the pointer
|
||||
let mut struct_val = builder
|
||||
.build_insert_value(
|
||||
struct_type.get_undef(),
|
||||
pass_as_opaque(env, pointer_to_first_element),
|
||||
Builtin::WRAPPER_PTR,
|
||||
"insert_ptr_store_list",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Store the length
|
||||
struct_val = builder
|
||||
.build_insert_value(struct_val, len, Builtin::WRAPPER_LEN, "insert_len")
|
||||
.unwrap();
|
||||
|
||||
// Store the capacity
|
||||
struct_val = builder
|
||||
.build_insert_value(
|
||||
struct_val,
|
||||
len,
|
||||
Builtin::WRAPPER_CAPACITY,
|
||||
"insert_capacity",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder.build_bitcast(
|
||||
struct_val.into_struct_value(),
|
||||
super::convert::zig_list_type(env),
|
||||
"cast_collection",
|
||||
struct_from_fields(
|
||||
env,
|
||||
zig_list_type(env),
|
||||
[
|
||||
(Builtin::WRAPPER_PTR as usize, ptr),
|
||||
(Builtin::WRAPPER_LEN as usize, len.into()),
|
||||
(Builtin::WRAPPER_CAPACITY as usize, cap.into()),
|
||||
]
|
||||
.into_iter(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::llvm::bitcode::{call_bitcode_fn, call_str_bitcode_fn};
|
||||
use crate::llvm::bitcode::call_str_bitcode_fn;
|
||||
use crate::llvm::build::{Env, Scope};
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::values::{BasicValueEnum, IntValue, PointerValue, StructValue};
|
||||
|
@ -8,6 +8,7 @@ use roc_module::symbol::Symbol;
|
|||
use roc_mono::layout::{Builtin, Layout};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
use super::bitcode::call_bitcode_fn;
|
||||
use super::build::{create_entry_block_alloca, load_symbol};
|
||||
|
||||
pub static CHAR_LAYOUT: Layout = Layout::u8();
|
||||
|
@ -137,7 +138,7 @@ pub fn dec_to_str<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
/// Str.equal : Str, Str -> Bool
|
||||
pub fn str_equal<'a, 'ctx, 'env>(
|
||||
pub(crate) fn str_equal<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
value1: BasicValueEnum<'ctx>,
|
||||
value2: BasicValueEnum<'ctx>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue