diff --git a/cli/src/build.rs b/cli/src/build.rs index 82b8242bc7..97af317837 100644 --- a/cli/src/build.rs +++ b/cli/src/build.rs @@ -55,6 +55,7 @@ pub fn build_file<'a>( link_type: LinkType, surgically_link: bool, precompiled: bool, + target_valgrind: bool, ) -> Result> { let compilation_start = SystemTime::now(); let ptr_bytes = target.pointer_width().unwrap().bytes() as u32; @@ -116,6 +117,7 @@ pub fn build_file<'a>( .keys() .map(|x| x.as_str(&loaded.interns).to_string()) .collect(), + target_valgrind ); // TODO try to move as much of this linking as possible to the precompiled @@ -288,6 +290,7 @@ fn spawn_rebuild_thread( binary_path: PathBuf, target: &Triple, exported_symbols: Vec, + target_valgrind: bool ) -> std::thread::JoinHandle { let thread_local_target = target.clone(); std::thread::spawn(move || { @@ -299,6 +302,7 @@ fn spawn_rebuild_thread( &thread_local_target, host_input_path.as_path(), exported_symbols, + target_valgrind, ) .unwrap(); } else { @@ -307,6 +311,7 @@ fn spawn_rebuild_thread( &thread_local_target, host_input_path.as_path(), None, + target_valgrind ); } } diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 543f24981a..2958abbd64 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -33,6 +33,7 @@ pub const FLAG_BACKEND: &str = "backend"; pub const FLAG_TIME: &str = "time"; pub const FLAG_LINK: &str = "roc-linker"; pub const FLAG_PRECOMPILED: &str = "precompiled-host"; +pub const FLAG_VALGRIND: &str = "valgrind"; pub const ROC_FILE: &str = "ROC_FILE"; pub const BACKEND: &str = "BACKEND"; pub const DIRECTORY_OR_FILES: &str = "DIRECTORY_OR_FILES"; @@ -100,6 +101,12 @@ pub fn build_app<'a>() -> App<'a> { .about("Assumes the host has been precompiled and skips recompiling the host.") .required(false), ) + .arg( + Arg::new(FLAG_VALGRIND) + .long(FLAG_VALGRIND) + .about("Some assembly instructions are not supported by valgrind, this flag prevents those from being output when building the host.") + .required(false), + ) ) .subcommand(App::new(CMD_REPL) .about("Launch the interactive Read Eval Print Loop (REPL)") @@ -258,6 +265,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { }; let surgically_link = matches.is_present(FLAG_LINK); let precompiled = matches.is_present(FLAG_PRECOMPILED); + if surgically_link && !roc_linker::supported(&link_type, &target) { panic!( "Link type, {:?}, with target, {}, not supported by roc linker", @@ -287,6 +295,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { }); let src_dir = path.parent().unwrap().canonicalize().unwrap(); + let target_valgrind = matches.is_present(FLAG_VALGRIND); let res_binary_path = build_file( &arena, &target, @@ -298,6 +307,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { link_type, surgically_link, precompiled, + target_valgrind ); match res_binary_path { diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 3251e3b48b..a8975d2ff0 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -53,7 +53,15 @@ mod cli_run { expected_ending: &str, use_valgrind: bool, ) { - let compile_out = run_roc(&[&["build", file.to_str().unwrap()], flags].concat()); + + let mut all_flags = vec![]; + all_flags.extend_from_slice(flags); + + if use_valgrind { + all_flags.extend_from_slice(&["--valgrind"]); + } + + let compile_out = run_roc(&[&["build", file.to_str().unwrap()], &all_flags[..]].concat()); if !compile_out.stderr.is_empty() { panic!("{}", compile_out.stderr); } diff --git a/compiler/build/src/link.rs b/compiler/build/src/link.rs index d5285b3602..484178415b 100644 --- a/compiler/build/src/link.rs +++ b/compiler/build/src/link.rs @@ -86,6 +86,7 @@ pub fn build_zig_host_native( target: &str, opt_level: OptLevel, shared_lib_path: Option<&Path>, + target_valgrind: bool, ) -> Output { let mut command = Command::new("zig"); command @@ -118,6 +119,14 @@ pub fn build_zig_host_native( "-target", target, ]); + + if target_valgrind { + command.args(&[ + "-mcpu", + "x86_64" + ]); + } + if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); } @@ -339,6 +348,7 @@ pub fn rebuild_host( target: &Triple, host_input_path: &Path, shared_lib_path: Option<&Path>, + target_valgrind: bool, ) { let c_host_src = host_input_path.with_file_name("host.c"); let c_host_dest = host_input_path.with_file_name("c_host.o"); @@ -394,6 +404,7 @@ pub fn rebuild_host( "native", opt_level, shared_lib_path, + target_valgrind, ) } Architecture::X86_32(_) => { @@ -407,6 +418,7 @@ pub fn rebuild_host( "i386-linux-musl", opt_level, shared_lib_path, + target_valgrind ) } @@ -421,6 +433,7 @@ pub fn rebuild_host( target_triple_str(target), opt_level, shared_lib_path, + target_valgrind ) } _ => panic!("Unsupported architecture {:?}", target.architecture), diff --git a/linker/src/lib.rs b/linker/src/lib.rs index 769ba7011e..58f801115f 100644 --- a/linker/src/lib.rs +++ b/linker/src/lib.rs @@ -142,10 +142,11 @@ pub fn build_and_preprocess_host( target: &Triple, host_input_path: &Path, exposed_to_host: Vec, + target_valgrind: bool, ) -> io::Result<()> { let dummy_lib = host_input_path.with_file_name("libapp.so"); generate_dynamic_lib(target, exposed_to_host, &dummy_lib)?; - rebuild_host(opt_level, target, host_input_path, Some(&dummy_lib)); + rebuild_host(opt_level, target, host_input_path, Some(&dummy_lib), target_valgrind); let dynhost = host_input_path.with_file_name("dynhost"); let metadata = host_input_path.with_file_name("metadata"); let prehost = host_input_path.with_file_name("preprocessedhost");