mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Merge branch 'main' of github.com:roc-lang/roc into clippy-1.74
This commit is contained in:
commit
cd632fe549
271 changed files with 7741 additions and 7417 deletions
|
@ -710,7 +710,7 @@ impl LlvmBackendMode {
|
|||
match self {
|
||||
LlvmBackendMode::Binary => false,
|
||||
LlvmBackendMode::BinaryDev => false,
|
||||
LlvmBackendMode::BinaryGlue => false,
|
||||
LlvmBackendMode::BinaryGlue => true,
|
||||
LlvmBackendMode::GenTest => true,
|
||||
LlvmBackendMode::WasmGenTest => true,
|
||||
LlvmBackendMode::CliTest => true,
|
||||
|
@ -910,16 +910,19 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
&self,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
location: BasicValueEnum<'ctx>,
|
||||
source: BasicValueEnum<'ctx>,
|
||||
message: BasicValueEnum<'ctx>,
|
||||
) {
|
||||
let function = self.module.get_function("roc_dbg").unwrap();
|
||||
|
||||
let loc = self.string_to_arg(env, location);
|
||||
let src = self.string_to_arg(env, source);
|
||||
let msg = self.string_to_arg(env, message);
|
||||
|
||||
let call = self
|
||||
.builder
|
||||
.new_build_call(function, &[loc.into(), msg.into()], "roc_dbg");
|
||||
// TODO: at some point it will be a breaking change, but flip order to (loc, src, msg)
|
||||
let call =
|
||||
self.builder
|
||||
.new_build_call(function, &[loc.into(), msg.into(), src.into()], "roc_dbg");
|
||||
|
||||
call.set_call_convention(C_CALL_CONV);
|
||||
}
|
||||
|
@ -1055,6 +1058,55 @@ pub fn module_from_builtins<'ctx>(
|
|||
let module = Module::parse_bitcode_from_buffer(&memory_buffer, ctx)
|
||||
.unwrap_or_else(|err| panic!("Unable to import builtins bitcode. LLVM error: {err:?}"));
|
||||
|
||||
// In testing, this adds about 20ms extra to compilation.
|
||||
// Long term it would be best if we could do this on the zig side.
|
||||
// The core issue is that we have to properly labael certain functions as private and DCE them.
|
||||
// Otherwise, now that zig bundles all of compiler-rt, we would optimize and compile the entire library.
|
||||
// Anything not depended on by a `roc_builtin.` function could already by DCE'd theoretically.
|
||||
// That said, this workaround is good enough and fixes compilations times.
|
||||
|
||||
// Also, must_keep is the functions we depend on that would normally be provide by libc.
|
||||
// They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd.
|
||||
let must_keep = [
|
||||
"_fltused",
|
||||
"floorf",
|
||||
"memcpy",
|
||||
"memset",
|
||||
// I have no idea why this function is special.
|
||||
// Without it, some tests hang on M1 mac outside of nix.
|
||||
"__muloti4",
|
||||
// fixes `Undefined Symbol in relocation`
|
||||
"__udivti3",
|
||||
// Roc special functions
|
||||
"__roc_force_longjmp",
|
||||
"__roc_force_setjmp",
|
||||
"set_shared_buffer",
|
||||
];
|
||||
for func in module.get_functions() {
|
||||
let has_definition = func.count_basic_blocks() > 0;
|
||||
let name = func.get_name().to_string_lossy();
|
||||
if has_definition
|
||||
&& !name.starts_with("roc_builtins.")
|
||||
&& !must_keep.contains(&name.as_ref())
|
||||
{
|
||||
func.set_linkage(Linkage::Private);
|
||||
}
|
||||
}
|
||||
|
||||
// Note, running DCE here is faster then waiting until full app DCE.
|
||||
let mpm = PassManager::create(());
|
||||
mpm.add_global_dce_pass();
|
||||
mpm.run_on(&module);
|
||||
|
||||
// Now that the unused compiler-rt functions have been removed,
|
||||
// mark that the builtin functions are allowed to be DCE'd if they aren't used.
|
||||
for func in module.get_functions() {
|
||||
let name = func.get_name().to_string_lossy();
|
||||
if name.starts_with("roc_builtins.") {
|
||||
func.set_linkage(Linkage::Private);
|
||||
}
|
||||
}
|
||||
|
||||
// Add LLVM intrinsics.
|
||||
add_intrinsics(ctx, &module);
|
||||
|
||||
|
@ -1227,6 +1279,8 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(main_fn_name);
|
||||
c_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// STEP 2: build the exposed function's body
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
|
@ -3527,17 +3581,17 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
}
|
||||
|
||||
Dbg {
|
||||
source_location,
|
||||
source,
|
||||
symbol,
|
||||
variable: _,
|
||||
remainder,
|
||||
} => {
|
||||
if env.mode.runs_expects() {
|
||||
// TODO: Change location to `filename:line_number`
|
||||
// let region = unsafe { std::mem::transmute::<_, roc_region::all::Region>(*symbol) };
|
||||
let location =
|
||||
build_string_literal(env, parent, symbol.module_string(&env.interns));
|
||||
let location = build_string_literal(env, parent, source_location);
|
||||
let source = build_string_literal(env, parent, source);
|
||||
let message = scope.load_symbol(symbol);
|
||||
env.call_dbg(env, location, message);
|
||||
env.call_dbg(env, location, source, message);
|
||||
}
|
||||
|
||||
build_exp_stmt(
|
||||
|
@ -4363,6 +4417,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(c_function_name);
|
||||
c_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// STEP 2: build the exposed function's body
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
|
@ -4371,8 +4427,6 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// drop the first argument, which is the pointer we write the result into
|
||||
let args_vector = c_function.get_params();
|
||||
let mut args = args_vector.as_slice();
|
||||
|
@ -4413,29 +4467,68 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
|
||||
let arguments_for_call = &arguments_for_call.into_bump_slice();
|
||||
|
||||
let call_result = if env.mode.returns_roc_result() {
|
||||
debug_assert_eq!(args.len(), roc_function.get_params().len());
|
||||
if args.len() == roc_function.get_params().len() {
|
||||
let arguments_for_call = &arguments_for_call.into_bump_slice();
|
||||
|
||||
let roc_wrapper_function =
|
||||
make_exception_catcher(env, layout_interner, roc_function, return_layout);
|
||||
debug_assert_eq!(
|
||||
arguments_for_call.len(),
|
||||
roc_wrapper_function.get_params().len()
|
||||
);
|
||||
let dbg_loc = builder.get_current_debug_location().unwrap();
|
||||
let roc_wrapper_function =
|
||||
make_exception_catcher(env, layout_interner, roc_function, return_layout);
|
||||
debug_assert_eq!(
|
||||
arguments_for_call.len(),
|
||||
roc_wrapper_function.get_params().len()
|
||||
);
|
||||
|
||||
builder.position_at_end(entry);
|
||||
builder.position_at_end(entry);
|
||||
builder.set_current_debug_location(dbg_loc);
|
||||
|
||||
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
wrapped_layout,
|
||||
arguments_for_call,
|
||||
)
|
||||
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
wrapped_layout,
|
||||
arguments_for_call,
|
||||
)
|
||||
} else {
|
||||
debug_assert_eq!(args.len() + 1, roc_function.get_params().len());
|
||||
|
||||
arguments_for_call.push(args[0]);
|
||||
|
||||
let arguments_for_call = &arguments_for_call.into_bump_slice();
|
||||
|
||||
let dbg_loc = builder.get_current_debug_location().unwrap();
|
||||
let roc_wrapper_function =
|
||||
make_exception_catcher(env, layout_interner, roc_function, return_layout);
|
||||
|
||||
builder.position_at_end(entry);
|
||||
builder.set_current_debug_location(dbg_loc);
|
||||
|
||||
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
||||
let call_result = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_wrapper_function,
|
||||
wrapped_layout,
|
||||
arguments_for_call,
|
||||
);
|
||||
|
||||
let output_arg_index = 0;
|
||||
|
||||
let output_arg = c_function
|
||||
.get_nth_param(output_arg_index as u32)
|
||||
.unwrap()
|
||||
.into_pointer_value();
|
||||
|
||||
env.builder.new_build_store(output_arg, call_result);
|
||||
|
||||
builder.new_build_return(None);
|
||||
|
||||
return c_function;
|
||||
}
|
||||
} else {
|
||||
let arguments_for_call = &arguments_for_call.into_bump_slice();
|
||||
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -4459,6 +4552,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
output_arg,
|
||||
call_result,
|
||||
);
|
||||
|
||||
builder.new_build_return(None);
|
||||
|
||||
c_function
|
||||
|
@ -4511,6 +4605,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(c_function_name);
|
||||
c_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// STEP 2: build the exposed function's body
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
|
@ -4519,8 +4615,6 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// drop the final argument, which is the pointer we write the result into
|
||||
let args_vector = c_function.get_params();
|
||||
let mut args = args_vector.as_slice();
|
||||
|
@ -4567,10 +4661,12 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
let (call_result, call_result_layout) = {
|
||||
let last_block = builder.get_insert_block().unwrap();
|
||||
|
||||
let dbg_loc = builder.get_current_debug_location().unwrap();
|
||||
let roc_wrapper_function =
|
||||
make_exception_catcher(env, layout_interner, roc_function, return_layout);
|
||||
|
||||
builder.position_at_end(last_block);
|
||||
builder.set_current_debug_location(dbg_loc);
|
||||
|
||||
let wrapper_result = roc_call_result_layout(env.arena, return_layout);
|
||||
|
||||
|
@ -4622,12 +4718,12 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(&size_function_name);
|
||||
size_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, size_function);
|
||||
|
||||
let entry = context.append_basic_block(size_function, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
debug_info_init!(env, size_function);
|
||||
|
||||
let size: BasicValueEnum = return_type.size_of().unwrap().into();
|
||||
builder.new_build_return(Some(&size));
|
||||
|
||||
|
@ -4713,6 +4809,8 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(c_function_name);
|
||||
c_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, c_function);
|
||||
|
||||
// STEP 2: build the exposed function's body
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
|
@ -4941,12 +5039,12 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(&size_function_name);
|
||||
size_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, size_function);
|
||||
|
||||
let entry = env.context.append_basic_block(size_function, "entry");
|
||||
|
||||
env.builder.position_at_end(entry);
|
||||
|
||||
debug_info_init!(env, size_function);
|
||||
|
||||
let return_type = match env.mode {
|
||||
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest | LlvmBackendMode::CliTest => {
|
||||
roc_call_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
|
||||
|
@ -5343,6 +5441,8 @@ fn make_exception_catching_wrapper<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(wrapper_function_name);
|
||||
wrapper_function.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, wrapper_function);
|
||||
|
||||
// The exposed main function must adhere to the C calling convention, but the wrapper can still be fastcc.
|
||||
wrapper_function.set_call_conventions(FAST_CALL_CONV);
|
||||
|
||||
|
@ -5819,6 +5919,8 @@ fn build_proc_header<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(&fn_name);
|
||||
fn_val.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, fn_val);
|
||||
|
||||
if env.exposed_to_host.contains(&symbol) {
|
||||
let arguments = Vec::from_iter_in(proc.args.iter().map(|(layout, _)| *layout), env.arena);
|
||||
expose_function_to_host(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue