Merge remote-tracking branch 'origin/trunk' into gen-dev/quicksort

This commit is contained in:
Brendan Hansknecht 2022-07-22 23:28:46 -07:00
commit fae2ed7a2b
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
130 changed files with 10112 additions and 2543 deletions

View file

@ -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

View file

@ -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)
)
};

View file

@ -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(),
)
}

View file

@ -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>,