diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-07-28 16:01:18 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-28 16:01:18 +0200 |
| commit | 674ebe395f1feba70becaac75c4fb9451f74f84c (patch) | |
| tree | 78589612bd458269904d53de46d0accf4f58a7af /src/llvm_backend.cpp | |
| parent | 9746e25784c208cf8a7883bcb2e1ac2317117aeb (diff) | |
| parent | 96eecaab54cea02499e9cf418aa39eb5a9c9ec75 (diff) | |
Merge branch 'master' into master
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 198 |
1 files changed, 170 insertions, 28 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 304effb7f..cf7389ec1 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -29,29 +29,53 @@ void lb_add_foreign_library_path(lbModule *m, Entity *e) { GB_ASSERT(e->kind == Entity_LibraryName); GB_ASSERT(e->flags & EntityFlag_Used); - for_array(i, e->LibraryName.paths) { - String library_path = e->LibraryName.paths[i]; - if (library_path.len == 0) { - continue; - } + mutex_lock(&m->gen->foreign_mutex); + if (!ptr_set_update(&m->gen->foreign_libraries_set, e)) { + array_add(&m->gen->foreign_libraries, e); + } + mutex_unlock(&m->gen->foreign_mutex); +} - bool ok = true; - for_array(path_index, m->foreign_library_paths) { - String path = m->foreign_library_paths[path_index]; - #if defined(GB_SYSTEM_WINDOWS) - if (str_eq_ignore_case(path, library_path)) { - #else - if (str_eq(path, library_path)) { - #endif - ok = false; - break; - } +GB_COMPARE_PROC(foreign_library_cmp) { + int cmp = 0; + Entity *x = *(Entity **)a; + Entity *y = *(Entity **)b; + if (x == y) { + return 0; + } + GB_ASSERT(x->kind == Entity_LibraryName); + GB_ASSERT(y->kind == Entity_LibraryName); + + cmp = i64_cmp(x->LibraryName.priority_index, y->LibraryName.priority_index); + if (cmp) { + return cmp; + } + + if (x->pkg != y->pkg) { + isize order_x = x->pkg ? x->pkg->order : 0; + isize order_y = y->pkg ? y->pkg->order : 0; + cmp = isize_cmp(order_x, order_y); + if (cmp) { + return cmp; } + } + if (x->file != y->file) { + String fullpath_x = x->file ? x->file->fullpath : (String{}); + String fullpath_y = y->file ? y->file->fullpath : (String{}); + String file_x = filename_from_path(fullpath_x); + String file_y = filename_from_path(fullpath_y); - if (ok) { - array_add(&m->foreign_library_paths, library_path); + cmp = string_compare(file_x, file_y); + if (cmp) { + return cmp; } } + + cmp = u64_cmp(x->order_in_src, y->order_in_src); + if (cmp) { + return cmp; + } + return i32_cmp(x->token.pos.offset, y->token.pos.offset); } void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name) { @@ -624,6 +648,9 @@ struct lbGlobalVariable { }; lbProcedure *lb_create_startup_type_info(lbModule *m) { + if (build_context.disallow_rtti) { + return nullptr; + } LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod); lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level); LLVMFinalizeFunctionPassManager(default_function_pass_manager); @@ -652,7 +679,54 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) { return p; } -lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, Array<lbGlobalVariable> &global_variables) { // Startup Runtime +lbProcedure *lb_create_objc_names(lbModule *main_module) { + if (build_context.metrics.os != TargetOs_darwin) { + return nullptr; + } + Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl); + lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit("__$init_objc_names"), proc_type); + p->is_startup = true; + return p; +} + +void lb_finalize_objc_names(lbProcedure *p) { + if (p == nullptr) { + return; + } + lbModule *m = p->module; + + LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod); + lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level); + LLVMFinalizeFunctionPassManager(default_function_pass_manager); + + + auto args = array_make<lbValue>(permanent_allocator(), 1); + + LLVMSetLinkage(p->value, LLVMInternalLinkage); + lb_begin_procedure_body(p); + for_array(i, m->objc_classes.entries) { + auto const &entry = m->objc_classes.entries[i]; + String name = entry.key.string; + args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); + lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args); + lb_addr_store(p, entry.value, ptr); + } + + for_array(i, m->objc_selectors.entries) { + auto const &entry = m->objc_selectors.entries[i]; + String name = entry.key.string; + args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); + lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args); + lb_addr_store(p, entry.value, ptr); + } + + lb_end_procedure_body(p); + + lb_run_function_pass_manager(default_function_pass_manager, p); + +} + +lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(main_module->mod); lb_populate_function_pass_manager(main_module, default_function_pass_manager, false, build_context.optimization_level); LLVMFinalizeFunctionPassManager(default_function_pass_manager); @@ -664,7 +738,13 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start lb_begin_procedure_body(p); - LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, ""); + if (startup_type_info) { + LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, ""); + } + + if (objc_names) { + LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, ""); + } for_array(i, global_variables) { auto *var = &global_variables[i]; @@ -911,7 +991,12 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) } String lb_filepath_ll_for_module(lbModule *m) { - String path = m->gen->output_base; + String path = concatenate3_strings(permanent_allocator(), + build_context.build_paths[BuildPath_Output].basename, + STR_LIT("/"), + build_context.build_paths[BuildPath_Output].name + ); + if (m->pkg) { path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name); } else if (USE_SEPARATE_MODULES) { @@ -922,7 +1007,12 @@ String lb_filepath_ll_for_module(lbModule *m) { return path; } String lb_filepath_obj_for_module(lbModule *m) { - String path = m->gen->output_base; + String path = concatenate3_strings(permanent_allocator(), + build_context.build_paths[BuildPath_Output].basename, + STR_LIT("/"), + build_context.build_paths[BuildPath_Output].name + ); + if (m->pkg) { path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name); } @@ -945,6 +1035,19 @@ String lb_filepath_obj_for_module(lbModule *m) { case TargetOs_essence: ext = STR_LIT(".o"); break; + + case TargetOs_freestanding: + switch (build_context.metrics.abi) { + default: + case TargetABI_Default: + case TargetABI_SysV: + ext = STR_LIT(".o"); + break; + case TargetABI_Win64: + ext = STR_LIT(".obj"); + break; + } + break; } } } @@ -1197,6 +1300,8 @@ void lb_generate_code(lbGenerator *gen) { LLVMCodeModel code_mode = LLVMCodeModelDefault; if (is_arch_wasm()) { code_mode = LLVMCodeModelJITDefault; + } else if (build_context.metrics.os == TargetOs_freestanding) { + code_mode = LLVMCodeModelKernel; } char const *host_cpu_name = LLVMGetHostCPUName(); @@ -1219,10 +1324,18 @@ void lb_generate_code(lbGenerator *gen) { // x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL if (ODIN_LLVM_MINIMUM_VERSION_12) { - llvm_cpu = "x86-64-v2"; + if (build_context.metrics.os == TargetOs_freestanding) { + llvm_cpu = "x86-64"; + } else { + llvm_cpu = "x86-64-v2"; + } } } + if (build_context.target_features_set.entries.count != 0) { + llvm_features = target_features_set_to_cstring(permanent_allocator(), false); + } + // GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target)); LLVMCodeGenOptLevel code_gen_level = LLVMCodeGenLevelNone; @@ -1244,6 +1357,24 @@ void lb_generate_code(lbGenerator *gen) { reloc_mode = LLVMRelocPIC; } + switch (build_context.reloc_mode) { + case RelocMode_Default: + if (build_context.metrics.os == TargetOs_openbsd) { + // Always use PIC for OpenBSD: it defaults to PIE + reloc_mode = LLVMRelocPIC; + } + break; + case RelocMode_Static: + reloc_mode = LLVMRelocStatic; + break; + case RelocMode_PIC: + reloc_mode = LLVMRelocPIC; + break; + case RelocMode_DynamicNoPIC: + reloc_mode = LLVMRelocDynamicNoPic; + break; + } + for_array(i, gen->modules.entries) { target_machines[i] = LLVMCreateTargetMachine( target, target_triple, llvm_cpu, @@ -1310,7 +1441,7 @@ void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Global Variables"); - { + if (!build_context.disallow_rtti) { lbModule *m = default_module; { // Add type info data @@ -1417,9 +1548,8 @@ void lb_generate_code(lbGenerator *gen) { if ((e->scope->flags&ScopeFlag_Init) && name == "main") { GB_ASSERT(e == info->entry_point); } - if (e->Procedure.is_export || - (e->Procedure.link_name.len > 0) || - ((e->scope->flags&ScopeFlag_File) && e->Procedure.link_name.len > 0)) { + if (build_context.command_kind == Command_test && + (e->Procedure.is_export || e->Procedure.link_name.len > 0)) { String link_name = e->Procedure.link_name; if (e->pkg->kind == Package_Runtime) { if (link_name == "main" || @@ -1570,8 +1700,10 @@ void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Runtime Type Information Creation"); lbProcedure *startup_type_info = lb_create_startup_type_info(default_module); + lbProcedure *objc_names = lb_create_objc_names(default_module); + TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)"); - lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, global_variables); + lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables); gb_unused(startup_runtime); TIME_SECTION("LLVM Global Procedures and Types"); @@ -1641,6 +1773,11 @@ void lb_generate_code(lbGenerator *gen) { } } + if (build_context.command_kind == Command_test && !already_has_entry_point) { + TIME_SECTION("LLVM main"); + lb_create_main_procedure(default_module, startup_runtime); + } + for_array(j, gen->modules.entries) { lbModule *m = gen->modules.entries[j].value; for_array(i, m->missing_procedures_to_check) { @@ -1650,6 +1787,8 @@ void lb_generate_code(lbGenerator *gen) { } } + lb_finalize_objc_names(objc_names); + if (build_context.ODIN_DEBUG) { TIME_SECTION("LLVM Debug Info Complete Types and Finalize"); for_array(j, gen->modules.entries) { @@ -1662,6 +1801,7 @@ void lb_generate_code(lbGenerator *gen) { } + TIME_SECTION("LLVM Function Pass"); for_array(i, gen->modules.entries) { lbModule *m = gen->modules.entries[i].value; @@ -1806,4 +1946,6 @@ void lb_generate_code(lbGenerator *gen) { } } } + + gb_sort_array(gen->foreign_libraries.data, gen->foreign_libraries.count, foreign_library_cmp); } |