Merge pull request #6560 from roc-lang/llvm-gen-from-mono-improvement

emit-ir and style improvement
This commit is contained in:
Folkert de Vries 2024-03-06 18:42:29 +01:00 committed by GitHub
commit 074fcd0683
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -166,12 +166,11 @@ fn gen_from_mono_module_llvm<'a>(
let context = Context::create(); let context = Context::create();
let module = arena.alloc(module_from_builtins(target, &context, "app")); let module = arena.alloc(module_from_builtins(target, &context, "app"));
// mark our zig-defined builtins as internal
let app_ll_file = { let app_ll_file = {
let mut temp = PathBuf::from(roc_file_path); let mut roc_file_path_buf = PathBuf::from(roc_file_path);
temp.set_extension("ll"); roc_file_path_buf.set_extension("ll");
temp roc_file_path_buf
}; };
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); 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: // Uncomment this to see the module's optimized LLVM instruction output:
// env.module.print_to_stderr(); // 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 gen_sanitizers = cfg!(feature = "sanitizers") && std::env::var("ROC_SANITIZERS").is_ok();
let memory_buffer = if fuzz || gen_sanitizers { let memory_buffer = if fuzz || gen_sanitizers {
let dir = tempfile::tempdir().unwrap(); let dir = tempfile::tempdir().unwrap();
let dir = dir.into_path(); let dir = dir.into_path();
let app_ll_file = dir.join("app.ll"); let temp_app_ll_file = dir.join("app.ll");
let app_bc_file = dir.join("app.bc"); let temp_app_processed_file = dir.join("app_processed.ll"); // app.ll with llvm passes applied
let app_o_file = dir.join("app.o"); 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 // 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. // Apply coverage passes.
// Note, this is specifically tailored for `cargo afl` and afl++. // 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; 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, // write the .o file. Note that this builds the .o for the local machine,
// and ignores the `target_machine` entirely. // and ignores the `target_machine` entirely.
// //
// different systems name this executable differently, so we shotgun for // different systems name this executable differently, so we shotgun for
// the most common ones and then give up. // the most common ones and then give up.
let bc_to_object = Command::new("llc") let bc_to_object_output = Command::new("llc")
.args([ .args([
"-relocation-model=pic", "-relocation-model=pic",
"-filetype=obj", "-filetype=obj",
app_bc_file.to_str().unwrap(), &temp_app_processed_file_str,
"-o", "-o",
app_o_file.to_str().unwrap(), temp_app_o_file.to_str().unwrap(),
]) ])
.output() .output()
.unwrap(); .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 { } 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 // Emit the .o file
use target_lexicon::Architecture; use target_lexicon::Architecture;
match target.architecture { match target.architecture {