mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
commit
a57f29e780
15 changed files with 95 additions and 173 deletions
|
@ -76,7 +76,7 @@ To run the test suite (via `cargo test`), you additionally need to install:
|
|||
- [`valgrind`](https://www.valgrind.org/) (needs special treatment to [install on macOS](https://stackoverflow.com/a/61359781)
|
||||
Alternatively, you can use `cargo test --no-fail-fast` or `cargo test -p specific_tests` to skip over the valgrind failures & tests.
|
||||
|
||||
For debugging LLVM IR, we use [DebugIR](https://github.com/vaivaswatha/debugir). This dependency is only required to build with the `--debug` flag, and for normal development you should be fine without it.
|
||||
For emitting LLVM IR for debugging purposes, the `--emit-llvm-ir` flag can be used.
|
||||
|
||||
### libxcb libraries
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ pub const CMD_GLUE: &str = "glue";
|
|||
pub const CMD_GEN_STUB_LIB: &str = "gen-stub-lib";
|
||||
pub const CMD_PREPROCESS_HOST: &str = "preprocess-host";
|
||||
|
||||
pub const FLAG_DEBUG: &str = "debug";
|
||||
pub const FLAG_EMIT_LLVM_IR: &str = "emit-llvm-ir";
|
||||
pub const FLAG_PROFILING: &str = "profiling";
|
||||
pub const FLAG_BUNDLE: &str = "bundle";
|
||||
pub const FLAG_DEV: &str = "dev";
|
||||
pub const FLAG_OPTIMIZE: &str = "optimize";
|
||||
|
@ -102,9 +103,15 @@ pub fn build_app() -> Command {
|
|||
.action(ArgAction::SetTrue)
|
||||
.required(false);
|
||||
|
||||
let flag_debug = Arg::new(FLAG_DEBUG)
|
||||
.long(FLAG_DEBUG)
|
||||
.help("Store LLVM debug information in the generated program")
|
||||
let flag_emit_llvm_ir = Arg::new(FLAG_EMIT_LLVM_IR)
|
||||
.long(FLAG_EMIT_LLVM_IR)
|
||||
.help("Emit a `.ll` file containing the LLVM IR of the program")
|
||||
.action(ArgAction::SetTrue)
|
||||
.required(false);
|
||||
|
||||
let flag_profiling = Arg::new(FLAG_PROFILING)
|
||||
.long(FLAG_PROFILING)
|
||||
.help("Keep debug info in the final generated program even in optmized builds")
|
||||
.action(ArgAction::SetTrue)
|
||||
.required(false);
|
||||
|
||||
|
@ -163,7 +170,8 @@ pub fn build_app() -> Command {
|
|||
.arg(flag_max_threads.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_emit_llvm_ir.clone())
|
||||
.arg(flag_profiling.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_prebuilt.clone())
|
||||
|
@ -212,7 +220,8 @@ pub fn build_app() -> Command {
|
|||
.arg(flag_max_threads.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_emit_llvm_ir.clone())
|
||||
.arg(flag_profiling.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_prebuilt.clone())
|
||||
|
@ -234,7 +243,8 @@ pub fn build_app() -> Command {
|
|||
.arg(flag_max_threads.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_emit_llvm_ir.clone())
|
||||
.arg(flag_profiling.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_prebuilt.clone())
|
||||
|
@ -247,7 +257,8 @@ pub fn build_app() -> Command {
|
|||
.arg(flag_max_threads.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_emit_llvm_ir.clone())
|
||||
.arg(flag_profiling.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_prebuilt.clone())
|
||||
|
@ -376,7 +387,8 @@ pub fn build_app() -> Command {
|
|||
.arg(flag_max_threads)
|
||||
.arg(flag_opt_size)
|
||||
.arg(flag_dev)
|
||||
.arg(flag_debug)
|
||||
.arg(flag_emit_llvm_ir)
|
||||
.arg(flag_profiling)
|
||||
.arg(flag_time)
|
||||
.arg(flag_linker)
|
||||
.arg(flag_prebuilt)
|
||||
|
@ -696,7 +708,13 @@ pub fn build(
|
|||
CodeGenBackend::Llvm(backend_mode)
|
||||
};
|
||||
|
||||
let emit_debug_info = matches.get_flag(FLAG_DEBUG);
|
||||
let emit_llvm_ir = matches.get_flag(FLAG_EMIT_LLVM_IR);
|
||||
if emit_llvm_ir && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) {
|
||||
user_error!("Cannot emit llvm ir while using a dev backend.");
|
||||
}
|
||||
|
||||
let emit_debug_info = matches.get_flag(FLAG_PROFILING)
|
||||
|| matches!(opt_level, OptLevel::Development | OptLevel::Normal);
|
||||
let emit_timings = matches.get_flag(FLAG_TIME);
|
||||
|
||||
let threading = match matches.get_one::<usize>(FLAG_MAX_THREADS) {
|
||||
|
@ -745,6 +763,7 @@ pub fn build(
|
|||
backend: code_gen_backend,
|
||||
opt_level,
|
||||
emit_debug_info,
|
||||
emit_llvm_ir,
|
||||
};
|
||||
|
||||
let load_config = standard_load_config(&triple, build_ordering, threading);
|
||||
|
|
|
@ -85,6 +85,7 @@ pub struct CodeGenOptions {
|
|||
pub backend: CodeGenBackend,
|
||||
pub opt_level: OptLevel,
|
||||
pub emit_debug_info: bool,
|
||||
pub emit_llvm_ir: bool,
|
||||
}
|
||||
|
||||
type GenFromMono<'a> = (CodeObject, CodeGenTiming, ExpectMetadata<'a>);
|
||||
|
@ -101,6 +102,7 @@ pub fn gen_from_mono_module<'a>(
|
|||
) -> GenFromMono<'a> {
|
||||
let path = roc_file_path;
|
||||
let debug = code_gen_options.emit_debug_info;
|
||||
let emit_llvm_ir = code_gen_options.emit_llvm_ir;
|
||||
let opt = code_gen_options.opt_level;
|
||||
|
||||
match code_gen_options.backend {
|
||||
|
@ -120,15 +122,23 @@ pub fn gen_from_mono_module<'a>(
|
|||
wasm_dev_stack_bytes,
|
||||
backend_mode,
|
||||
),
|
||||
CodeGenBackend::Llvm(backend_mode) => {
|
||||
gen_from_mono_module_llvm(arena, loaded, path, target, opt, backend_mode, debug)
|
||||
}
|
||||
CodeGenBackend::Llvm(backend_mode) => gen_from_mono_module_llvm(
|
||||
arena,
|
||||
loaded,
|
||||
path,
|
||||
target,
|
||||
opt,
|
||||
backend_mode,
|
||||
debug,
|
||||
emit_llvm_ir,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO how should imported modules factor into this? What if those use builtins too?
|
||||
// TODO this should probably use more helper functions
|
||||
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn gen_from_mono_module_llvm<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
|
@ -137,6 +147,7 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
opt_level: OptLevel,
|
||||
backend_mode: LlvmBackendMode,
|
||||
emit_debug_info: bool,
|
||||
emit_llvm_ir: bool,
|
||||
) -> GenFromMono<'a> {
|
||||
use crate::target::{self, convert_opt_level};
|
||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||
|
@ -151,9 +162,6 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
let context = Context::create();
|
||||
let module = arena.alloc(module_from_builtins(target, &context, "app"));
|
||||
|
||||
// strip Zig debug stuff
|
||||
// module.strip_debug_info();
|
||||
|
||||
// mark our zig-defined builtins as internal
|
||||
let app_ll_file = {
|
||||
let mut temp = PathBuf::from(roc_file_path);
|
||||
|
@ -245,8 +253,9 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// we don't use the debug info, and it causes weird errors.
|
||||
module.strip_debug_info();
|
||||
if !emit_debug_info {
|
||||
module.strip_debug_info();
|
||||
}
|
||||
|
||||
// Uncomment this to see the module's optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
@ -265,6 +274,11 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
);
|
||||
}
|
||||
|
||||
if emit_llvm_ir {
|
||||
eprintln!("Emitting LLVM IR to {}", &app_ll_file.display());
|
||||
module.print_to_file(&app_ll_file).unwrap();
|
||||
}
|
||||
|
||||
// Uncomment this to see the module's optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
@ -359,65 +373,6 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
|
||||
assert!(bc_to_object.status.success(), "{bc_to_object:#?}");
|
||||
|
||||
MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works")
|
||||
} else if emit_debug_info {
|
||||
module.strip_debug_info();
|
||||
|
||||
let mut app_ll_dbg_file = PathBuf::from(roc_file_path);
|
||||
app_ll_dbg_file.set_extension("dbg.ll");
|
||||
|
||||
let mut app_o_file = PathBuf::from(roc_file_path);
|
||||
app_o_file.set_extension("o");
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
// write the ll code to a file, so we can modify it
|
||||
module.print_to_file(&app_ll_file).unwrap();
|
||||
|
||||
// run the debugir https://github.com/vaivaswatha/debugir tool
|
||||
match Command::new("debugir")
|
||||
.args(["-instnamer", app_ll_file.to_str().unwrap()])
|
||||
.output()
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
use std::io::ErrorKind;
|
||||
match error.kind() {
|
||||
ErrorKind::NotFound => internal_error!(
|
||||
r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir"
|
||||
),
|
||||
_ => internal_error!("{:?}", error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use target_lexicon::Architecture;
|
||||
match target.architecture {
|
||||
Architecture::X86_64
|
||||
| Architecture::X86_32(_)
|
||||
| Architecture::Aarch64(_)
|
||||
| Architecture::Wasm32 => {
|
||||
// write the .o file. Note that this builds the .o for the local machine,
|
||||
// and ignores the `target_machine` entirely.
|
||||
//
|
||||
// different systems name this executable differently, so we shotgun for
|
||||
// the most common ones and then give up.
|
||||
let ll_to_object = Command::new("llc")
|
||||
.args([
|
||||
"-relocation-model=pic",
|
||||
"-filetype=obj",
|
||||
app_ll_dbg_file.to_str().unwrap(),
|
||||
"-o",
|
||||
app_o_file.to_str().unwrap(),
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
assert!(ll_to_object.stderr.is_empty(), "{ll_to_object:#?}");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works")
|
||||
} else {
|
||||
// Emit the .o file
|
||||
|
@ -1326,6 +1281,7 @@ pub fn build_str_test<'a>(
|
|||
backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary),
|
||||
opt_level: OptLevel::Normal,
|
||||
emit_debug_info: false,
|
||||
emit_llvm_ir: false,
|
||||
};
|
||||
|
||||
let emit_timings = false;
|
||||
|
|
|
@ -7,7 +7,7 @@ const CrossTarget = std.zig.CrossTarget;
|
|||
const Arch = std.Target.Cpu.Arch;
|
||||
|
||||
pub fn build(b: *Build) void {
|
||||
// const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast });
|
||||
// const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .Debug });
|
||||
const mode = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast });
|
||||
|
||||
// Options
|
||||
|
@ -58,6 +58,7 @@ fn generateLlvmIrFile(
|
|||
) void {
|
||||
const obj = b.addObject(.{ .name = object_name, .root_source_file = main_path, .optimize = mode, .target = target, .use_llvm = true });
|
||||
obj.strip = true;
|
||||
obj.disable_stack_probing = true;
|
||||
|
||||
// Generating the bin seems required to get zig to generate the llvm ir.
|
||||
_ = obj.getEmittedBin();
|
||||
|
@ -89,6 +90,7 @@ fn generateObjectFile(
|
|||
obj.strip = true;
|
||||
obj.link_function_sections = true;
|
||||
obj.force_pic = true;
|
||||
obj.disable_stack_probing = true;
|
||||
|
||||
const obj_file = obj.getEmittedBin();
|
||||
|
||||
|
|
|
@ -1230,6 +1230,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;
|
||||
|
@ -4367,6 +4369,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;
|
||||
|
@ -4375,8 +4379,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();
|
||||
|
@ -4422,6 +4424,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
let call_result = if env.mode.returns_roc_result() {
|
||||
debug_assert_eq!(args.len(), roc_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!(
|
||||
|
@ -4430,6 +4433,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
);
|
||||
|
||||
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(
|
||||
|
@ -4515,6 +4519,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;
|
||||
|
@ -4523,8 +4529,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();
|
||||
|
@ -4571,10 +4575,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);
|
||||
|
||||
|
@ -4626,12 +4632,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));
|
||||
|
||||
|
@ -4717,6 +4723,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;
|
||||
|
@ -4945,12 +4953,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()
|
||||
|
@ -5347,6 +5355,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);
|
||||
|
||||
|
@ -5823,6 +5833,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(
|
||||
|
|
|
@ -469,6 +469,8 @@ fn build_clone_tag<'a, 'ctx>(
|
|||
let subprogram = env.new_subprogram(&fn_name);
|
||||
function_value.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, function_value);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
build_clone_tag_help(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::debug_info_init;
|
||||
use crate::llvm::bitcode::call_void_bitcode_fn;
|
||||
use crate::llvm::build::{add_func, get_panic_msg_ptr, get_panic_tag_ptr, BuilderExt, C_CALL_CONV};
|
||||
use crate::llvm::build::{CCReturn, Env, FunctionSpec};
|
||||
|
@ -254,6 +255,8 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
|||
let subprogram = env.new_subprogram("roc_panic");
|
||||
fn_val.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, fn_val);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// Add a basic block for the entry point
|
||||
|
|
|
@ -156,6 +156,8 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
let subprogram = env.new_subprogram(fn_name);
|
||||
function_value.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, function_value);
|
||||
|
||||
Self::build_decrement_function_body(env, function_value, alignment);
|
||||
|
||||
function_value
|
||||
|
@ -1049,6 +1051,8 @@ pub fn build_header_help<'ctx>(
|
|||
let subprogram = env.new_subprogram(fn_name);
|
||||
fn_val.set_subprogram(subprogram);
|
||||
|
||||
debug_info_init!(env, fn_val);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
fn_val
|
||||
|
|
|
@ -57,7 +57,7 @@ fn roc_function<'a, 'b>(
|
|||
let config = helpers::llvm::HelperConfig {
|
||||
mode: LlvmBackendMode::GenTest,
|
||||
ignore_problems: false,
|
||||
add_debug_info: true,
|
||||
emit_debug_info: true,
|
||||
opt_level: OptLevel::Optimize,
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ fn roc_function<'a>(
|
|||
let config = helpers::llvm::HelperConfig {
|
||||
mode: LlvmBackendMode::GenTest,
|
||||
ignore_problems: false,
|
||||
add_debug_info: true,
|
||||
emit_debug_info: true,
|
||||
opt_level: OptLevel::Optimize,
|
||||
};
|
||||
|
||||
|
|
|
@ -233,9 +233,6 @@ fn create_llvm_module<'a>(
|
|||
exposed_to_host: MutSet::default(),
|
||||
};
|
||||
|
||||
// strip Zig debug stuff
|
||||
module.strip_debug_info();
|
||||
|
||||
// Add roc_alloc, roc_realloc, and roc_dealloc, since the repl has no
|
||||
// platform to provide them.
|
||||
add_default_roc_externs(&env);
|
||||
|
@ -279,9 +276,6 @@ fn create_llvm_module<'a>(
|
|||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// strip all debug info: we don't use it at the moment and causes weird validation issues
|
||||
module.strip_debug_info();
|
||||
|
||||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
@ -325,7 +319,7 @@ fn create_llvm_module<'a>(
|
|||
pub struct HelperConfig {
|
||||
pub mode: LlvmBackendMode,
|
||||
pub ignore_problems: bool,
|
||||
pub add_debug_info: bool,
|
||||
pub emit_debug_info: bool,
|
||||
pub opt_level: OptLevel,
|
||||
}
|
||||
|
||||
|
@ -343,56 +337,16 @@ pub fn helper<'a>(
|
|||
let (main_fn_name, delayed_errors, module) =
|
||||
create_llvm_module(arena, src, config, context, &target, function_kind);
|
||||
|
||||
let res_lib = if config.add_debug_info {
|
||||
let module = annotate_with_debug_info(module, context);
|
||||
llvm_module_to_dylib(&module, &target, config.opt_level)
|
||||
} else {
|
||||
llvm_module_to_dylib(module, &target, config.opt_level)
|
||||
};
|
||||
if !config.emit_debug_info {
|
||||
module.strip_debug_info();
|
||||
}
|
||||
let res_lib = llvm_module_to_dylib(module, &target, config.opt_level);
|
||||
|
||||
let lib = res_lib.expect("Error loading compiled dylib for test");
|
||||
|
||||
(main_fn_name, delayed_errors, lib)
|
||||
}
|
||||
|
||||
fn annotate_with_debug_info<'ctx>(
|
||||
module: &Module<'ctx>,
|
||||
context: &'ctx inkwell::context::Context,
|
||||
) -> Module<'ctx> {
|
||||
use std::process::Command;
|
||||
|
||||
let app_ll_file = "/tmp/roc-debugir.ll";
|
||||
let app_dbg_ll_file = "/tmp/roc-debugir.dbg.ll";
|
||||
let app_bc_file = "/tmp/roc-debugir.bc";
|
||||
|
||||
// write the ll code to a file, so we can modify it
|
||||
module.print_to_file(app_ll_file).unwrap();
|
||||
|
||||
// run the debugir https://github.com/vaivaswatha/debugir tool
|
||||
match Command::new("debugir")
|
||||
.args(["-instnamer", app_ll_file])
|
||||
.output()
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
use std::io::ErrorKind;
|
||||
match error.kind() {
|
||||
ErrorKind::NotFound => panic!(
|
||||
r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir"
|
||||
),
|
||||
_ => panic!("{error:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Command::new("llvm-as")
|
||||
.args([app_dbg_ll_file, "-o", app_bc_file])
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
inkwell::module::Module::parse_bitcode_from_path(app_bc_file, context).unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn wasm32_target_tripple() -> Triple {
|
||||
use target_lexicon::{Architecture, BinaryFormat};
|
||||
|
@ -533,7 +487,7 @@ where
|
|||
|
||||
let config = HelperConfig {
|
||||
mode: LlvmBackendMode::WasmGenTest,
|
||||
add_debug_info: false,
|
||||
emit_debug_info: false,
|
||||
ignore_problems,
|
||||
opt_level: OPT_LEVEL,
|
||||
};
|
||||
|
@ -611,7 +565,7 @@ pub(crate) fn llvm_evals_to<T, U, F>(
|
|||
|
||||
let config = crate::helpers::llvm::HelperConfig {
|
||||
mode: LlvmBackendMode::GenTest,
|
||||
add_debug_info: false,
|
||||
emit_debug_info: false,
|
||||
ignore_problems,
|
||||
opt_level: crate::helpers::llvm::OPT_LEVEL,
|
||||
};
|
||||
|
|
|
@ -55,6 +55,7 @@ pub fn generate(
|
|||
backend,
|
||||
opt_level: OptLevel::Development,
|
||||
emit_debug_info: false,
|
||||
emit_llvm_ir: false,
|
||||
};
|
||||
|
||||
let load_config = standard_load_config(
|
||||
|
|
|
@ -255,9 +255,6 @@ fn mono_module_to_dylib_llvm<'a>(
|
|||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// we don't use the debug info, and it causes weird errors.
|
||||
module.strip_debug_info();
|
||||
|
||||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
|
|
@ -713,9 +713,6 @@ pub fn expect_mono_module_to_dylib<'a>(
|
|||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// we don't use the debug info, and it causes weird errors.
|
||||
module.strip_debug_info();
|
||||
|
||||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
|
25
flake.nix
25
flake.nix
|
@ -64,29 +64,6 @@
|
|||
curl # for wasm-bindgen-cli libcurl (see ./ci/www-repl.sh)
|
||||
]);
|
||||
|
||||
# For debugging LLVM IR
|
||||
debugir = pkgs.stdenv.mkDerivation {
|
||||
name = "debugir";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "vaivaswatha";
|
||||
repo = "debugir";
|
||||
rev = "b981e0b74872d9896ba447dd6391dfeb63332b80";
|
||||
sha256 = "Gzey0SF0NZkpiObk5e29nbc41dn4Olv1dx+6YixaZH0=";
|
||||
};
|
||||
buildInputs = with pkgs; [ cmake libxml2 llvmPkgs.llvm.dev ];
|
||||
buildPhase = ''
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DLLVM_DIR=${llvmPkgs.llvm.dev} -DCMAKE_BUILD_TYPE=Release ../
|
||||
cmake --build ../
|
||||
cp ../debugir .
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp debugir $out/bin
|
||||
'';
|
||||
};
|
||||
|
||||
sharedInputs = (with pkgs; [
|
||||
# build libraries
|
||||
cmake
|
||||
|
@ -109,8 +86,6 @@
|
|||
python3
|
||||
libiconv # for examples/gui
|
||||
libxkbcommon # for examples/gui
|
||||
# debugir needs to be updated to llvm 15
|
||||
# debugir # used in crates/compiler/build/src/program.rs
|
||||
cargo-criterion # for benchmarks
|
||||
simple-http-server # to view roc website when trying out edits
|
||||
wasm-pack # for repl_wasm
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue