diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index bd20442d4b..a64e52a2b6 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -516,6 +516,7 @@ pub const Compilation = struct { opt_level, reloc_mode, llvm.CodeModelDefault, + false // TODO: add -ffunction-sections option ) orelse return error.OutOfMemory; defer llvm.DisposeTargetMachine(comp.target_machine); diff --git a/src-self-hosted/llvm.zig b/src-self-hosted/llvm.zig index 5cb95682ab..40d414e5f7 100644 --- a/src-self-hosted/llvm.zig +++ b/src-self-hosted/llvm.zig @@ -163,8 +163,8 @@ extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8; pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData; -pub const CreateTargetMachine = LLVMCreateTargetMachine; -extern fn LLVMCreateTargetMachine( +pub const CreateTargetMachine = ZigLLVMCreateTargetMachine; +extern fn ZigLLVMCreateTargetMachine( T: *Target, Triple: [*]const u8, CPU: [*]const u8, @@ -172,6 +172,7 @@ extern fn LLVMCreateTargetMachine( Level: CodeGenOptLevel, Reloc: RelocMode, CodeModel: CodeModel, + function_sections: bool, ) ?*TargetMachine; pub const GetHostCPUName = LLVMGetHostCPUName; diff --git a/src/all_types.hpp b/src/all_types.hpp index c1e54baf8d..8e236c4593 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1910,6 +1910,7 @@ struct CodeGen { bool have_pic; bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic bool have_stack_probing; + bool function_sections; Buf *mmacosx_version_min; Buf *mios_version_min; diff --git a/src/codegen.cpp b/src/codegen.cpp index 2399152546..47e5f542e2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8134,8 +8134,9 @@ static void init(CodeGen *g) { target_specific_features = ""; } - g->target_machine = LLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str), - target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, LLVMCodeModelDefault); + g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str), + target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, + LLVMCodeModelDefault, g->function_sections); g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine); @@ -8340,6 +8341,10 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-nostdinc"); args.append("-fno-spell-checking"); + if (g->function_sections) { + args.append("-ffunction-sections"); + } + if (translate_c) { // this gives us access to preprocessing entities, presumably at // the cost of performance @@ -8764,6 +8769,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose cache_int(cache_hash, g->build_mode); cache_bool(cache_hash, g->have_pic); cache_bool(cache_hash, want_valgrind_support(g)); + cache_bool(cache_hash, g->function_sections); for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { cache_str(cache_hash, g->clang_argv[arg_i]); } @@ -9479,6 +9485,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->have_dynamic_link); cache_bool(ch, g->have_stack_probing); cache_bool(ch, g->is_dummy_so); + cache_bool(ch, g->function_sections); cache_buf_opt(ch, g->mmacosx_version_min); cache_buf_opt(ch, g->mios_version_min); cache_usize(ch, g->version_major); diff --git a/src/link.cpp b/src/link.cpp index 277dcbc5c6..401f477760 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -791,6 +791,8 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly; } + child_gen->function_sections = true; + codegen_build_and_link(child_gen); return &child_gen->output_file_path; } diff --git a/src/main.cpp b/src/main.cpp index 016967a889..e2ec829063 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,6 +85,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -isystem [dir] add additional search path for other .h files\n" " -mllvm [arg] forward an arg to LLVM's option processing\n" " --override-std-dir [arg] use an alternate Zig standard library\n" + " -ffunction-sections places each function in a seperate section\n" "\n" "Link Options:\n" " --bundle-compiler-rt [path] for static libraries, include compiler-rt symbols\n" @@ -452,6 +453,7 @@ int main(int argc, char **argv) { ValgrindSupport valgrind_support = ValgrindSupportAuto; WantPIC want_pic = WantPICAuto; WantStackCheck want_stack_check = WantStackCheckAuto; + bool function_sections = false; ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); @@ -690,6 +692,8 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } cur_pkg = cur_pkg->parent; + } else if (strcmp(arg, "-ffunction-sections") == 0) { + function_sections = true; } else if (i + 1 >= argc) { fprintf(stderr, "Expected another argument after %s\n", arg); return print_error_usage(arg0); @@ -1103,6 +1107,7 @@ int main(int argc, char **argv) { g->bundle_compiler_rt = bundle_compiler_rt; codegen_set_errmsg_color(g, color); g->system_linker_hack = system_linker_hack; + g->function_sections = function_sections; for (size_t i = 0; i < lib_dirs.length; i += 1) { codegen_add_lib_dir(g, lib_dirs.at(i)); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index fe1b279cf0..c51c9e1a50 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -39,7 +39,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -93,6 +95,61 @@ static const bool assertions_on = true; static const bool assertions_on = false; #endif +LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, + const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, + LLVMCodeModel CodeModel, bool function_sections) +{ + Optional RM; + switch (Reloc){ + case LLVMRelocStatic: + RM = Reloc::Static; + break; + case LLVMRelocPIC: + RM = Reloc::PIC_; + break; + case LLVMRelocDynamicNoPic: + RM = Reloc::DynamicNoPIC; + break; + case LLVMRelocROPI: + RM = Reloc::ROPI; + break; + case LLVMRelocRWPI: + RM = Reloc::RWPI; + break; + case LLVMRelocROPI_RWPI: + RM = Reloc::ROPI_RWPI; + break; + default: + break; + } + + bool JIT; + Optional CM = unwrap(CodeModel, JIT); + + CodeGenOpt::Level OL; + switch (Level) { + case LLVMCodeGenLevelNone: + OL = CodeGenOpt::None; + break; + case LLVMCodeGenLevelLess: + OL = CodeGenOpt::Less; + break; + case LLVMCodeGenLevelAggressive: + OL = CodeGenOpt::Aggressive; + break; + default: + OL = CodeGenOpt::Default; + break; + } + + TargetOptions opt; + opt.FunctionSections = function_sections; + + TargetMachine *TM = reinterpret_cast(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM, + OL, JIT); + return reinterpret_cast(TM); +} + bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, bool is_small, bool time_report) diff --git a/src/zig_llvm.h b/src/zig_llvm.h index d667e0423d..8b7b0775f7 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -58,6 +58,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, bool is_small, bool time_report); +ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, + const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, + LLVMCodeModel CodeModel, bool function_sections); + ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); enum ZigLLVM_FnInline {