From dcdaaf4328a7823e46585c6499b45f48c032e1b4 Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 11 Sep 2023 17:08:09 +0200 Subject: [PATCH] enable dev backend repl --- Cargo.lock | 3 ++ crates/repl_cli/Cargo.toml | 3 ++ crates/repl_cli/src/cli_gen.rs | 85 +++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6785a19ed6..470e012054 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2813,10 +2813,12 @@ dependencies = [ "const_format", "inkwell", "libloading", + "roc_bitcode", "roc_build", "roc_builtins", "roc_collections", "roc_error_macros", + "roc_gen_dev", "roc_gen_llvm", "roc_load", "roc_mono", @@ -2831,6 +2833,7 @@ dependencies = [ "rustyline", "rustyline-derive", "target-lexicon", + "tempfile", "unicode-segmentation", ] diff --git a/crates/repl_cli/Cargo.toml b/crates/repl_cli/Cargo.toml index 8b0bfe91e2..c69ba39883 100644 --- a/crates/repl_cli/Cargo.toml +++ b/crates/repl_cli/Cargo.toml @@ -17,8 +17,10 @@ target-x86_64 = ["roc_build/target-x86_64"] [dependencies] roc_build = { path = "../compiler/build" } roc_builtins = { path = "../compiler/builtins" } +roc_bitcode = { path = "../compiler/builtins/bitcode" } roc_collections = { path = "../compiler/collections" } roc_gen_llvm = { path = "../compiler/gen_llvm" } +roc_gen_dev = { path = "../compiler/gen_dev" } roc_load = { path = "../compiler/load" } roc_mono = { path = "../compiler/mono" } roc_parse = { path = "../compiler/parse" } @@ -31,6 +33,7 @@ roc_types = { path = "../compiler/types" } roc_error_macros = { path = "../error_macros" } roc_repl_ui = { path = "../repl_ui" } +tempfile.workspace = true bumpalo.workspace = true const_format.workspace = true inkwell.workspace = true diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index b191478e20..81c651c1d1 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -54,8 +54,15 @@ pub fn eval_llvm( let interns = loaded.interns.clone(); + #[cfg(not(target_os = "linux"))] let (lib, main_fn_name, subs, layout_interner) = - mono_module_to_dylib(&arena, target, loaded, opt_level).expect("we produce a valid Dylib"); + mono_module_to_dylib_llvm(&arena, target, loaded, opt_level) + .expect("we produce a valid Dylib"); + + #[cfg(target_os = "linux")] + let (lib, main_fn_name, subs, layout_interner) = + mono_module_to_dylib_asm(&arena, target, loaded, opt_level) + .expect("we produce a valid Dylib"); let mut app = CliApp { lib }; @@ -159,7 +166,8 @@ impl ReplAppMemory for CliMemory { } } -fn mono_module_to_dylib<'a>( +#[cfg_attr(target_os = "linux", allow(unused))] +fn mono_module_to_dylib_llvm<'a>( arena: &'a Bump, target: &Triple, loaded: MonomorphizedModule<'a>, @@ -260,3 +268,76 @@ fn mono_module_to_dylib<'a>( llvm_module_to_dylib(env.module, target, opt_level) .map(|lib| (lib, main_fn_name, subs, layout_interner)) } + +fn mono_module_to_dylib_asm<'a>( + arena: &'a Bump, + target: &Triple, + loaded: MonomorphizedModule<'a>, + _opt_level: OptLevel, +) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> { + // let dir = std::env::temp_dir().join("roc_repl"); + let dir = tempfile::tempdir().unwrap(); + + let app_o_file = dir.path().join("app.o"); + + let _target_info = TargetInfo::from(target); + + let MonomorphizedModule { + module_id, + procedures, + host_exposed_lambda_sets: _, + exposed_to_host, + mut interns, + subs, + mut layout_interner, + .. + } = loaded; + + let lazy_literals = true; + let env = roc_gen_dev::Env { + arena, + module_id, + exposed_to_host: exposed_to_host.top_level_values.keys().copied().collect(), + lazy_literals, + mode: roc_gen_dev::AssemblyBackendMode::Test, + }; + + let target = target_lexicon::Triple::host(); + let module_object = roc_gen_dev::build_module( + &env, + &mut interns, + &mut layout_interner, + &target, + procedures, + ); + + let module_out = module_object + .write() + .expect("failed to build output object"); + std::fs::write(&app_o_file, module_out).expect("failed to write object to file"); + + let builtins_host_tempfile = + roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); + + let (mut child, dylib_path) = roc_build::link::link( + &target, + app_o_file.clone(), + // Long term we probably want a smarter way to link in zig builtins. + // With the current method all methods are kept and it adds about 100k to all outputs. + &[ + app_o_file.to_str().unwrap(), + builtins_host_tempfile.path().to_str().unwrap(), + ], + roc_build::link::LinkType::Dylib, + ) + .expect("failed to link dynamic library"); + + child.wait().unwrap(); + + // Load the dylib + let path = dylib_path.as_path().to_str().unwrap(); + + let lib = unsafe { Library::new(path) }?; + + Ok((lib, "test_main", subs, layout_interner)) +}