diff --git a/cli/src/build.rs b/cli/src/build.rs index 3bde999b76..2cbb70d078 100644 --- a/cli/src/build.rs +++ b/cli/src/build.rs @@ -98,9 +98,12 @@ pub fn build_file( let compilation_end = compilation_start.elapsed().unwrap(); + let size = std::fs::metadata(&app_o_file).unwrap().len(); + println!( - "Finished compilation and code gen in {} ms\n", - compilation_end.as_millis() + "Finished compilation and code gen in {} ms\n\nProduced a app.o file of size {:?}\n", + compilation_end.as_millis(), + size, ); let cwd = app_o_file.parent().unwrap(); diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index fb5ebafbaa..8b5537be97 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -2,6 +2,7 @@ use crate::target; use bumpalo::Bump; use inkwell::context::Context; use inkwell::targets::{CodeModel, FileType, RelocMode}; +use inkwell::values::FunctionValue; use roc_gen::llvm::build::{build_proc, build_proc_header, module_from_builtins, OptLevel, Scope}; use roc_load::file::MonomorphizedModule; use roc_mono::layout::LayoutIds; @@ -70,6 +71,15 @@ pub fn gen_from_mono_module( // strip Zig debug stuff // module.strip_debug_info(); + // mark our zig-defined builtins as internal + use inkwell::module::Linkage; + for function in FunctionIterator::from_module(module) { + let name = function.get_name().to_str().unwrap(); + if name.starts_with("roc_builtins") { + function.set_linkage(Linkage::Internal); + } + } + let builder = context.create_builder(); let (dibuilder, compile_unit) = roc_gen::llvm::build::Env::new_debug_info(module); let (mpm, fpm) = roc_gen::llvm::build::construct_optimization_passes(module, opt_level); @@ -159,3 +169,30 @@ pub fn gen_from_mono_module( .write_to_file(&env.module, FileType::Object, &app_o_file) .expect("Writing .o file failed"); } + +struct FunctionIterator<'ctx> { + next: Option>, +} + +impl<'ctx> FunctionIterator<'ctx> { + fn from_module(module: &inkwell::module::Module<'ctx>) -> Self { + Self { + next: module.get_first_function(), + } + } +} + +impl<'ctx> Iterator for FunctionIterator<'ctx> { + type Item = FunctionValue<'ctx>; + + fn next(&mut self) -> Option { + match self.next { + Some(function) => { + self.next = function.get_next_function(); + + Some(function) + } + None => None, + } + } +} diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index bbf716d03e..acc1840eb4 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -384,6 +384,9 @@ pub fn construct_optimization_passes<'a>( fpm.add_instruction_combining_pass(); fpm.add_tail_call_elimination_pass(); + // remove unused global values (e.g. those defined by zig, but unused in user code) + mpm.add_global_dce_pass(); + let pmb = PassManagerBuilder::create(); match opt_level { OptLevel::Normal => {