From ce606916a3d66f0ce2b5b09cc8154806a1a6e41c Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 6 Mar 2024 17:15:34 +0100 Subject: [PATCH] emit-ir and style improvement --- crates/compiler/build/src/program.rs | 76 ++++++++++++++++------------ 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 9881ae8715..ec4a2df693 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -166,12 +166,11 @@ fn gen_from_mono_module_llvm<'a>( let context = Context::create(); let module = arena.alloc(module_from_builtins(target, &context, "app")); - // mark our zig-defined builtins as internal let app_ll_file = { - let mut temp = PathBuf::from(roc_file_path); - temp.set_extension("ll"); + let mut roc_file_path_buf = PathBuf::from(roc_file_path); + roc_file_path_buf.set_extension("ll"); - temp + roc_file_path_buf }; let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); @@ -278,27 +277,21 @@ 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(); - // annotate the LLVM IR output with debug info - // so errors are reported with the line number of the LLVM source let gen_sanitizers = cfg!(feature = "sanitizers") && std::env::var("ROC_SANITIZERS").is_ok(); let memory_buffer = if fuzz || gen_sanitizers { let dir = tempfile::tempdir().unwrap(); let dir = dir.into_path(); - let app_ll_file = dir.join("app.ll"); - let app_bc_file = dir.join("app.bc"); - let app_o_file = dir.join("app.o"); + let temp_app_ll_file = dir.join("app.ll"); + let temp_app_processed_file = dir.join("app_processed.ll"); // app.ll with llvm passes applied + let temp_app_processed_file_str = temp_app_processed_file.to_str().unwrap().to_owned(); + let temp_app_o_file = dir.join("app.o"); // write the ll code to a file, so we can modify it - module.print_to_file(&app_ll_file).unwrap(); + module.print_to_file(&temp_app_ll_file).unwrap(); // Apply coverage passes. // Note, this is specifically tailored for `cargo afl` and afl++. @@ -340,40 +333,59 @@ fn gen_from_mono_module_llvm<'a>( } use std::process::Command; - let mut opt = Command::new("opt"); - opt.args([ - app_ll_file.to_str().unwrap(), - "-o", - app_bc_file.to_str().unwrap(), - ]) - .args(extra_args); - if !passes.is_empty() { - opt.arg(format!("-passes={}", passes.join(","))); - } - let opt = opt.output().unwrap(); - assert!(opt.stderr.is_empty(), "{opt:#?}"); + // apply passes to app.ll + let mut opt_command = Command::new("opt"); + + opt_command + .args([ + temp_app_ll_file.to_str().unwrap(), + "-o", + &temp_app_processed_file_str, + ]) + .args(extra_args); + if !passes.is_empty() { + opt_command.arg(format!("-passes={}", passes.join(","))); + } + + let opt_output = opt_command.output().unwrap(); + + assert!(opt_output.stderr.is_empty(), "{opt_output:#?}"); + + if emit_llvm_ir { + eprintln!("Emitting LLVM IR to {}", &app_ll_file.display()); + + std::fs::copy(temp_app_processed_file, app_ll_file).unwrap(); + } // 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 bc_to_object = Command::new("llc") + let bc_to_object_output = Command::new("llc") .args([ "-relocation-model=pic", "-filetype=obj", - app_bc_file.to_str().unwrap(), + &temp_app_processed_file_str, "-o", - app_o_file.to_str().unwrap(), + temp_app_o_file.to_str().unwrap(), ]) .output() .unwrap(); - assert!(bc_to_object.status.success(), "{bc_to_object:#?}"); + assert!( + bc_to_object_output.status.success(), + "{bc_to_object_output:#?}" + ); - MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works") + MemoryBuffer::create_from_file(&temp_app_o_file).expect("memory buffer creation works") } else { + if emit_llvm_ir { + eprintln!("Emitting LLVM IR to {}", &app_ll_file.display()); + module.print_to_file(&app_ll_file).unwrap(); + } + // Emit the .o file use target_lexicon::Architecture; match target.architecture {