mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-12 14:23:33 +00:00
Merge pull request #6208 from JesseRMeyer/lto-support
Add ThinLTO support via -lto:thin and -lto:thin-files flags
This commit is contained in:
@@ -420,6 +420,12 @@ struct BuildCacheData {
|
||||
};
|
||||
|
||||
|
||||
enum LTOKind : i32 {
|
||||
LTO_None,
|
||||
LTO_Thin,
|
||||
LTO_Thin_Files,
|
||||
};
|
||||
|
||||
enum LinkerChoice : i32 {
|
||||
Linker_Invalid = -1,
|
||||
Linker_Default = 0,
|
||||
@@ -560,6 +566,7 @@ struct BuildContext {
|
||||
|
||||
bool use_single_module;
|
||||
bool use_separate_modules;
|
||||
LTOKind lto_kind;
|
||||
bool module_per_file;
|
||||
bool cached;
|
||||
BuildCacheData build_cache_data;
|
||||
@@ -2030,6 +2037,29 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
bc->use_separate_modules = false;
|
||||
}
|
||||
|
||||
if (bc->lto_kind == LTO_Thin || bc->lto_kind == LTO_Thin_Files) {
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
gb_printf_err("-lto:thin requires LLVM 17 or later\n");
|
||||
gb_exit(1);
|
||||
#endif
|
||||
if (bc->build_mode == BuildMode_Assembly || bc->build_mode == BuildMode_LLVM_IR) {
|
||||
gb_printf_err("-lto:thin is incompatible with -build-mode:asm and -build-mode:llvm-ir\n");
|
||||
gb_exit(1);
|
||||
}
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
if (bc->linker_choice != Linker_lld) {
|
||||
gb_printf_err("-lto:thin on Windows requires -linker:lld\n");
|
||||
gb_exit(1);
|
||||
}
|
||||
#endif
|
||||
if (bc->use_single_module) {
|
||||
gb_printf_err("Warning: -lto:thin overrides -use-single-module; separate modules will be used\n");
|
||||
}
|
||||
bc->use_separate_modules = true;
|
||||
if (bc->lto_kind == LTO_Thin_Files) {
|
||||
bc->module_per_file = true;
|
||||
}
|
||||
}
|
||||
|
||||
bc->ODIN_VALGRIND_SUPPORT = false;
|
||||
if (build_context.metrics.os != TargetOs_windows) {
|
||||
|
||||
@@ -328,6 +328,12 @@ try_cross_linking:;
|
||||
String windows_sdk_bin_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Win_SDK_Bin_Path]);
|
||||
defer (gb_free(heap_allocator(), windows_sdk_bin_path.text));
|
||||
|
||||
gbString lld_lto_flags = gb_string_make(heap_allocator(), "");
|
||||
defer (gb_string_free(lld_lto_flags));
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
lld_lto_flags = gb_string_append_fmt(lld_lto_flags, "/lldltojobs:%d ", build_context.thread_count);
|
||||
}
|
||||
|
||||
switch (build_context.linker_choice) {
|
||||
case Linker_lld:
|
||||
result = system_exec_command_line_app("msvc-lld-link",
|
||||
@@ -336,13 +342,15 @@ try_cross_linking:;
|
||||
"%.*s "
|
||||
"%.*s "
|
||||
"%s "
|
||||
"%s "
|
||||
"",
|
||||
LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename),
|
||||
link_settings,
|
||||
LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]),
|
||||
LIT(build_context.link_flags),
|
||||
LIT(build_context.extra_linker_flags),
|
||||
lib_str
|
||||
lib_str,
|
||||
lld_lto_flags
|
||||
);
|
||||
|
||||
if (result) {
|
||||
@@ -966,6 +974,12 @@ try_cross_linking:;
|
||||
link_command_line = gb_string_appendc(link_command_line, clang_path);
|
||||
}
|
||||
link_command_line = gb_string_appendc(link_command_line, " -Wno-unused-command-line-argument ");
|
||||
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
link_command_line = gb_string_appendc(link_command_line, " -flto=thin");
|
||||
link_command_line = gb_string_append_fmt(link_command_line, " -flto-jobs=%d ", build_context.thread_count);
|
||||
}
|
||||
|
||||
link_command_line = gb_string_appendc(link_command_line, object_files);
|
||||
link_command_line = gb_string_append_fmt(link_command_line, " -o \"%.*s\" ", LIT(output_filename));
|
||||
link_command_line = gb_string_append_fmt(link_command_line, " %s ", platform_lib_str);
|
||||
|
||||
@@ -171,7 +171,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) {
|
||||
LLVMValueRef other_global = nullptr;
|
||||
if (ec.e->kind == Entity_Variable) {
|
||||
other_global = LLVMGetNamedGlobal(ec.other_module->mod, ec.cname);
|
||||
if (other_global) {
|
||||
if (other_global && (LLVMGetInitializer(other_global) != nullptr || LLVMIsExternallyInitialized(other_global))) {
|
||||
LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global);
|
||||
if (!ec.e->Variable.is_export && !ec.e->Variable.is_foreign) {
|
||||
LLVMSetVisibility(other_global, LLVMHiddenVisibility);
|
||||
@@ -179,7 +179,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) {
|
||||
}
|
||||
} else if (ec.e->kind == Entity_Procedure) {
|
||||
other_global = LLVMGetNamedFunction(ec.other_module->mod, ec.cname);
|
||||
if (other_global) {
|
||||
if (other_global && LLVMCountBasicBlocks(other_global) != 0) {
|
||||
LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global);
|
||||
if (!ec.e->Procedure.is_export && !ec.e->Procedure.is_foreign) {
|
||||
LLVMSetVisibility(other_global, LLVMHiddenVisibility);
|
||||
@@ -2332,7 +2332,12 @@ gb_internal WORKER_TASK_PROC(lb_llvm_emit_worker_proc) {
|
||||
|
||||
auto wd = cast(lbLLVMEmitWorker *)data;
|
||||
|
||||
if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) {
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
if (LLVMWriteBitcodeToFile(wd->m->mod, cast(char *)wd->filepath_obj.text)) {
|
||||
gb_printf_err("Failed to write bitcode file: %.*s\n", LIT(wd->filepath_obj));
|
||||
exit_with_errors();
|
||||
}
|
||||
} else if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
exit_with_errors();
|
||||
}
|
||||
@@ -2701,7 +2706,9 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
|
||||
|
||||
String ext = {};
|
||||
|
||||
if (build_context.build_mode == BuildMode_Assembly) {
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
ext = STR_LIT("bc");
|
||||
} else if (build_context.build_mode == BuildMode_Assembly) {
|
||||
ext = STR_LIT("S");
|
||||
} else if (build_context.build_mode == BuildMode_Object) {
|
||||
// Allow a user override for the object extension.
|
||||
@@ -2776,7 +2783,13 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading)
|
||||
|
||||
TIME_SECTION_WITH_LEN(section_name, gb_string_length(section_name));
|
||||
|
||||
if (LLVMTargetMachineEmitToFile(m->target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
|
||||
if (build_context.lto_kind != LTO_None) {
|
||||
if (LLVMWriteBitcodeToFile(m->mod, cast(char *)filepath_obj.text)) {
|
||||
gb_printf_err("Failed to write bitcode file: %.*s\n", LIT(filepath_obj));
|
||||
exit_with_errors();
|
||||
return false;
|
||||
}
|
||||
} else if (LLVMTargetMachineEmitToFile(m->target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
|
||||
gb_printf_err("LLVM Error: %s\n", llvm_error);
|
||||
exit_with_errors();
|
||||
return false;
|
||||
|
||||
@@ -163,7 +163,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
||||
map_init(&gen->modules_through_ctx, gen->info->packages.count*2);
|
||||
|
||||
if (USE_SEPARATE_MODULES) {
|
||||
bool module_per_file = build_context.module_per_file && build_context.optimization_level <= 0;
|
||||
bool module_per_file = build_context.module_per_file && (build_context.optimization_level <= 0 || build_context.lto_kind != LTO_None);
|
||||
for (auto const &entry : gen->info->packages) {
|
||||
AstPackage *pkg = entry.value;
|
||||
auto m = gb_alloc_item(permanent_allocator(), lbModule);
|
||||
|
||||
14
src/main.cpp
14
src/main.cpp
@@ -413,6 +413,7 @@ enum BuildFlagKind {
|
||||
BuildFlag_Tilde,
|
||||
|
||||
BuildFlag_Sanitize,
|
||||
BuildFlag_LTO,
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
BuildFlag_IgnoreVsSearch,
|
||||
@@ -643,6 +644,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
#endif
|
||||
|
||||
add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true);
|
||||
add_flag(&build_flags, BuildFlag_LTO, str_lit("lto"), BuildFlagParam_String, Command__does_build);
|
||||
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
@@ -1636,6 +1638,18 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
}
|
||||
break;
|
||||
|
||||
case BuildFlag_LTO:
|
||||
GB_ASSERT(value.kind == ExactValue_String);
|
||||
if (str_eq_ignore_case(value.value_string, str_lit("thin"))) {
|
||||
build_context.lto_kind = LTO_Thin;
|
||||
} else if (str_eq_ignore_case(value.value_string, str_lit("thin-files"))) {
|
||||
build_context.lto_kind = LTO_Thin_Files;
|
||||
} else {
|
||||
gb_printf_err("-lto:<string> options are 'thin' and 'thin-files'\n");
|
||||
bad_flags = true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
case BuildFlag_IgnoreVsSearch: {
|
||||
|
||||
Reference in New Issue
Block a user