Merge branch 'main' into simplify_examples

Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com>
This commit is contained in:
Anton-4 2022-09-28 11:54:44 +02:00 committed by GitHub
commit 735d4c13bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 3568 additions and 3077 deletions

View file

@ -1,3 +1,4 @@
use inkwell::memory_buffer::MemoryBuffer;
pub use roc_gen_llvm::llvm::build::FunctionIterator;
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
@ -6,6 +7,7 @@ use roc_module::symbol::{Interns, ModuleId};
use roc_mono::ir::OptLevel;
use roc_region::all::LineInfo;
use roc_solve_problem::TypeError;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
@ -16,7 +18,6 @@ use roc_collections::all::MutSet;
#[derive(Debug, Clone, Copy, Default)]
pub struct CodeGenTiming {
pub code_gen: Duration,
pub emit_o_file: Duration,
}
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
@ -156,25 +157,39 @@ fn report_problems_help(
}
}
pub enum CodeObject {
MemoryBuffer(MemoryBuffer),
Vector(Vec<u8>),
}
impl Deref for CodeObject {
type Target = [u8];
fn deref(&self) -> &Self::Target {
match self {
CodeObject::MemoryBuffer(memory_buffer) => memory_buffer.as_slice(),
CodeObject::Vector(vector) => vector.as_slice(),
}
}
}
#[allow(clippy::too_many_arguments)]
pub fn gen_from_mono_module(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
roc_file_path: &Path,
target: &target_lexicon::Triple,
app_o_file: &Path,
opt_level: OptLevel,
emit_debug_info: bool,
preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
match opt_level {
OptLevel::Normal | OptLevel::Size | OptLevel::Optimize => gen_from_mono_module_llvm(
arena,
loaded,
roc_file_path,
target,
app_o_file,
opt_level,
emit_debug_info,
),
@ -182,7 +197,6 @@ pub fn gen_from_mono_module(
arena,
loaded,
target,
app_o_file,
preprocessed_host_path,
wasm_dev_stack_bytes,
),
@ -192,15 +206,14 @@ pub fn gen_from_mono_module(
// 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.
pub fn gen_from_mono_module_llvm(
fn gen_from_mono_module_llvm(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
roc_file_path: &Path,
target: &target_lexicon::Triple,
app_o_file: &Path,
opt_level: OptLevel,
emit_debug_info: bool,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
use crate::target::{self, convert_opt_level};
use inkwell::attributes::{Attribute, AttributeLoc};
use inkwell::context::Context;
@ -312,12 +325,9 @@ pub fn gen_from_mono_module_llvm(
// Uncomment this to see the module's optimized LLVM instruction output:
// env.module.print_to_stderr();
let code_gen = code_gen_start.elapsed();
let emit_o_file_start = Instant::now();
// annotate the LLVM IR output with debug info
// so errors are reported with the line number of the LLVM source
if emit_debug_info {
let memory_buffer = if emit_debug_info {
module.strip_debug_info();
let mut app_ll_dbg_file = PathBuf::from(roc_file_path);
@ -326,6 +336,9 @@ pub fn gen_from_mono_module_llvm(
let mut app_bc_file = PathBuf::from(roc_file_path);
app_bc_file.set_extension("bc");
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
@ -384,6 +397,8 @@ pub fn gen_from_mono_module_llvm(
}
_ => unreachable!(),
}
MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works")
} else {
// Emit the .o file
use target_lexicon::Architecture;
@ -394,49 +409,48 @@ pub fn gen_from_mono_module_llvm(
target::target_machine(target, convert_opt_level(opt_level), reloc).unwrap();
target_machine
.write_to_file(env.module, FileType::Object, app_o_file)
.expect("Writing .o file failed");
.write_to_memory_buffer(env.module, FileType::Object)
.expect("Writing .o file failed")
}
Architecture::Wasm32 => {
// Useful for debugging
// module.print_to_file(app_ll_file);
module.write_bitcode_to_path(app_o_file);
module.write_bitcode_to_memory()
}
_ => panic!(
"TODO gracefully handle unsupported architecture: {:?}",
target.architecture
),
}
}
};
let emit_o_file = emit_o_file_start.elapsed();
let code_gen = code_gen_start.elapsed();
CodeGenTiming {
code_gen,
emit_o_file,
}
(
CodeObject::MemoryBuffer(memory_buffer),
CodeGenTiming { code_gen },
)
}
#[cfg(feature = "target-wasm32")]
pub fn gen_from_mono_module_dev(
fn gen_from_mono_module_dev(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
target: &target_lexicon::Triple,
app_o_file: &Path,
preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
use target_lexicon::Architecture;
match target.architecture {
Architecture::Wasm32 => gen_from_mono_module_dev_wasm32(
arena,
loaded,
app_o_file,
preprocessed_host_path,
wasm_dev_stack_bytes,
),
Architecture::X86_64 | Architecture::Aarch64(_) => {
gen_from_mono_module_dev_assembly(arena, loaded, target, app_o_file)
gen_from_mono_module_dev_assembly(arena, loaded, target)
}
_ => todo!(),
}
@ -447,15 +461,14 @@ pub fn gen_from_mono_module_dev(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
target: &target_lexicon::Triple,
app_o_file: &Path,
_host_input_path: &Path,
_wasm_dev_stack_bytes: Option<u32>,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
use target_lexicon::Architecture;
match target.architecture {
Architecture::X86_64 | Architecture::Aarch64(_) => {
gen_from_mono_module_dev_assembly(arena, loaded, target, app_o_file)
gen_from_mono_module_dev_assembly(arena, loaded, target)
}
_ => todo!(),
}
@ -465,10 +478,9 @@ pub fn gen_from_mono_module_dev(
fn gen_from_mono_module_dev_wasm32(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
app_o_file: &Path,
preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
let code_gen_start = Instant::now();
let MonomorphizedModule {
module_id,
@ -513,31 +525,18 @@ fn gen_from_mono_module_dev_wasm32(
roc_gen_wasm::build_app_binary(&env, &mut interns, host_module, procedures);
let code_gen = code_gen_start.elapsed();
let emit_o_file_start = Instant::now();
// The app_o_file is actually the final binary
std::fs::write(&app_o_file, &final_binary_bytes).unwrap_or_else(|e| {
panic!(
"I wasn't able to write to the output file {}\n{}",
app_o_file.display(),
e
)
});
let emit_o_file = emit_o_file_start.elapsed();
CodeGenTiming {
code_gen,
emit_o_file,
}
(
CodeObject::Vector(final_binary_bytes),
CodeGenTiming { code_gen },
)
}
fn gen_from_mono_module_dev_assembly(
arena: &bumpalo::Bump,
loaded: MonomorphizedModule,
target: &target_lexicon::Triple,
app_o_file: &Path,
) -> CodeGenTiming {
) -> (CodeObject, CodeGenTiming) {
let code_gen_start = Instant::now();
let lazy_literals = true;
@ -564,17 +563,10 @@ fn gen_from_mono_module_dev_assembly(
let module_object = roc_gen_dev::build_module(&env, &mut interns, target, procedures);
let code_gen = code_gen_start.elapsed();
let emit_o_file_start = Instant::now();
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 emit_o_file = emit_o_file_start.elapsed();
CodeGenTiming {
code_gen,
emit_o_file,
}
(CodeObject::Vector(module_out), CodeGenTiming { code_gen })
}