From e748d2f2af40895f1b067aaa74ac2ca2b737a243 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Sep 2023 16:15:26 +0100 Subject: Update to LLVM-17 --- src/llvm_backend.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index f8a743102..c1b958302 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -168,7 +168,7 @@ gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { map_set(&m->equal_procs, type, p); lb_begin_procedure_body(p); - lb_add_attribute_to_proc(m, p->value, "readonly"); + // lb_add_attribute_to_proc(m, p->value, "readonly"); lb_add_attribute_to_proc(m, p->value, "nounwind"); LLVMValueRef x = LLVMGetParam(p->value, 0); @@ -337,7 +337,7 @@ gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) { lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); - lb_add_attribute_to_proc(m, p->value, "readonly"); + // lb_add_attribute_to_proc(m, p->value, "readonly"); lb_add_attribute_to_proc(m, p->value, "nounwind"); LLVMValueRef x = LLVMGetParam(p->value, 0); @@ -346,7 +346,7 @@ gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) { lbValue seed = {y, t_uintptr}; lb_add_proc_attribute_at_index(p, 1+0, "nonnull"); - lb_add_proc_attribute_at_index(p, 1+0, "readonly"); + // lb_add_proc_attribute_at_index(p, 1+0, "readonly"); if (is_type_simple_compare(type)) { lbValue res = lb_simple_compare_hash(p, type, data, seed); -- cgit v1.2.3 From f0ab58dfbb4be6103fb7340ec570d218e2137a4b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 20 Sep 2023 10:39:48 +0100 Subject: Begin work with adding the new pass system --- src/llvm_backend.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c1b958302..8ced9ccee 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1449,6 +1449,60 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager(); lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level); LLVMRunPassManager(module_pass_manager, wd->m->mod); + +#if LB_USE_NEW_PASS_SYSTEM + if (build_context.optimization_level == -1) { + // don't do any passes + return 0; + } + + LLVMPassBuilderOptionsRef pb_options = LLVMCreatePassBuilderOptions(); + defer (LLVMDisposePassBuilderOptions(pb_options)); + + LLVMPassBuilderOptionsSetVerifyEach(pb_options, true); + + int inline_threshold = 0; + LLVMPassBuilderOptionsSetInlinerThreshold(pb_options, inline_threshold); + + if (build_context.optimization_level == 2) { + LLVMPassBuilderOptionsSetLoopVectorization(pb_options, true); + LLVMPassBuilderOptionsSetLoopUnrolling (pb_options, true); + LLVMPassBuilderOptionsSetMergeFunctions (pb_options, true); + } + + gbString passes = gb_string_make_reserve(heap_allocator(), 1024); + defer (gb_string_free(passes)); + + switch (build_context.optimization_level) { + case 0: default: + passes = gb_string_appendc(passes, "default"); + break; + case 1: + passes = gb_string_appendc(passes, "default"); + break; + case 2: + passes = gb_string_appendc(passes, "default"); + break; + } + LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes, wd->target_machine, pb_options); + defer (LLVMConsumeError(llvm_err)); + if (llvm_err != nullptr) { + char *llvm_error = LLVMGetErrorMessage(llvm_err); + gb_printf_err("LLVM Error:\n%s\n", llvm_error); + LLVMDisposeErrorMessage(llvm_error); + llvm_error = nullptr; + + if (build_context.keep_temp_files) { + TIME_SECTION("LLVM Print Module to File"); + String filepath_ll = lb_filepath_ll_for_module(wd->m); + if (LLVMPrintModuleToFile(wd->m->mod, cast(char const *)filepath_ll.text, &llvm_error)) { + gb_printf_err("LLVM Error: %s\n", llvm_error); + } + } + gb_exit(1); + return 1; + } +#endif return 0; } -- cgit v1.2.3 From 2160484b62ebde52ba6f486ad652f1a72cfe9143 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 09:40:33 +0100 Subject: Support `-sanitize:` for `address`, `memory`, `thread` for LLVM 17 --- src/build_settings.cpp | 16 ++++++++++++++++ src/llvm_backend.cpp | 18 +++++++++++++++++- src/main.cpp | 19 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 79f6e8a2c..57dac0ca3 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -264,6 +264,14 @@ u64 get_vet_flag_from_name(String const &name) { } +enum SanitizerFlags : u32 { + SanitizerFlag_NONE = 0, + SanitizerFlag_Address = 1u<<0, + SanitizerFlag_Memory = 1u<<1, + SanitizerFlag_Thread = 1u<<2, +}; + + // This stores the information for the specify architecture of this build struct BuildContext { @@ -305,6 +313,7 @@ struct BuildContext { String pdb_filepath; u64 vet_flags; + u32 sanitizer_flags; bool has_resource; String link_flags; @@ -1738,6 +1747,13 @@ gb_internal bool init_build_paths(String init_filename) { return false; } + if (build_context.sanitizer_flags & SanitizerFlag_Memory) { + if (build_context.metrics.os != TargetOs_linux) { + gb_printf_err("-sanitize:memory is only supported on linux\n"); + return false; + } + } + if (bc->target_features_string.len != 0) { enable_target_feature({}, bc->target_features_string); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8ced9ccee..68223d8c9 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1478,12 +1478,28 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { passes = gb_string_appendc(passes, "default"); break; case 1: - passes = gb_string_appendc(passes, "default"); + passes = gb_string_appendc(passes, "default"); break; case 2: passes = gb_string_appendc(passes, "default"); break; } + + // asan - Linux, Darwin, Windows + // msan - linux + // tsan - Linux, Darwin + // ubsan - Linux, Darwin, Windows (NOT SUPPORTED WITH LLVM C-API) + + if (build_context.sanitizer_flags & SanitizerFlag_Address) { + passes = gb_string_appendc(passes, ",asan"); + } + if (build_context.sanitizer_flags & SanitizerFlag_Memory) { + passes = gb_string_appendc(passes, ",msan"); + } + if (build_context.sanitizer_flags & SanitizerFlag_Thread) { + passes = gb_string_appendc(passes, ",tsan"); + } + LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes, wd->target_machine, pb_options); defer (LLVMConsumeError(llvm_err)); if (llvm_err != nullptr) { diff --git a/src/main.cpp b/src/main.cpp index 3d8637757..3d2dd3c44 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -300,6 +300,8 @@ enum BuildFlagKind { BuildFlag_Tilde, + BuildFlag_Sanitize, + #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, BuildFlag_ResourceFile, @@ -486,6 +488,8 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); #endif + add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); + #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_ResourceFile, str_lit("resource"), BuildFlagParam_String, Command__does_build); @@ -1194,6 +1198,21 @@ gb_internal bool parse_build_flags(Array args) { build_context.tilde_backend = true; break; + case BuildFlag_Sanitize: + GB_ASSERT(value.kind == ExactValue_String); + + if (str_eq_ignore_case(value.value_string, str_lit("address"))) { + build_context.sanitizer_flags |= SanitizerFlag_Address; + } else if (str_eq_ignore_case(value.value_string, str_lit("memory"))) { + build_context.sanitizer_flags |= SanitizerFlag_Memory; + } else if (str_eq_ignore_case(value.value_string, str_lit("thread"))) { + build_context.sanitizer_flags |= SanitizerFlag_Thread; + } else { + gb_printf_err("-sanitize: options are 'address', 'memory', and 'thread'\n"); + bad_flags = true; + } + break; + #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From e82b0ea4cd1b8c750b517eee806ea4ae1e2b21a6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 09:48:53 +0100 Subject: Add `-o:aggressive` for LLVM 17 --- src/build_settings.cpp | 2 +- src/llvm_backend.cpp | 29 +++++++++++++++++++---------- src/llvm_backend.hpp | 1 + src/llvm_backend_opt.cpp | 3 +-- src/main.cpp | 22 +++++++++++++++++++++- 5 files changed, 43 insertions(+), 14 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 57dac0ca3..08e591a3a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1390,7 +1390,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = -1; // -o:none } - bc->optimization_level = gb_clamp(bc->optimization_level, -1, 2); + bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); // ENFORCE DYNAMIC MAP CALLS bc->dynamic_map_calls = true; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 68223d8c9..a09cd8b4f 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1358,6 +1358,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { m->function_pass_managers[lbFunctionPassManager_minimal] = LLVMCreateFunctionPassManagerForModule(m->mod); m->function_pass_managers[lbFunctionPassManager_size] = LLVMCreateFunctionPassManagerForModule(m->mod); m->function_pass_managers[lbFunctionPassManager_speed] = LLVMCreateFunctionPassManagerForModule(m->mod); + m->function_pass_managers[lbFunctionPassManager_aggressive] = LLVMCreateFunctionPassManagerForModule(m->mod); LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default]); LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default_without_memcpy]); @@ -1368,10 +1369,11 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { lb_populate_function_pass_manager(m, m->function_pass_managers[lbFunctionPassManager_default], false, build_context.optimization_level); lb_populate_function_pass_manager(m, m->function_pass_managers[lbFunctionPassManager_default_without_memcpy], true, build_context.optimization_level); - lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_none], -1); - lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_minimal], 0); - lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_size], 1); - lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_speed], 2); + lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_none], -1); + lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_minimal], 0); + lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_size], 1); + lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_speed], 2); + lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_aggressive], 3); LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default]); LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default_without_memcpy]); @@ -1379,6 +1381,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_minimal]); LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_size]); LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_speed]); + LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_aggressive]); } if (m == &m->gen->default_module) { @@ -1464,7 +1467,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { int inline_threshold = 0; LLVMPassBuilderOptionsSetInlinerThreshold(pb_options, inline_threshold); - if (build_context.optimization_level == 2) { + if (build_context.optimization_level >= 2) { LLVMPassBuilderOptionsSetLoopVectorization(pb_options, true); LLVMPassBuilderOptionsSetLoopUnrolling (pb_options, true); LLVMPassBuilderOptionsSetMergeFunctions (pb_options, true); @@ -1483,6 +1486,9 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { case 2: passes = gb_string_appendc(passes, "default"); break; + case 3: + passes = gb_string_appendc(passes, "default"); + break; } // asan - Linux, Darwin, Windows @@ -2105,12 +2111,15 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { // GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target)); LLVMCodeGenOptLevel code_gen_level = LLVMCodeGenLevelNone; + if (!LB_USE_NEW_PASS_SYSTEM) { + build_context.optimization_level = gb_clamp(build_context.optimization_level, -1, 2); + } switch (build_context.optimization_level) { - case 0: code_gen_level = LLVMCodeGenLevelNone; break; - case 1: code_gen_level = LLVMCodeGenLevelLess; break; - case 2: code_gen_level = LLVMCodeGenLevelDefault; break; - case 3: code_gen_level = LLVMCodeGenLevelDefault; break; // NOTE(bill): force -opt:3 to be the same as -opt:2 - // case 3: code_gen_level = LLVMCodeGenLevelAggressive; break; + default:/*fallthrough*/ + case 0: code_gen_level = LLVMCodeGenLevelNone; break; + case 1: code_gen_level = LLVMCodeGenLevelLess; break; + case 2: code_gen_level = LLVMCodeGenLevelDefault; break; + case 3: code_gen_level = LLVMCodeGenLevelAggressive; break; } // NOTE(bill): Target Machine Creation diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 9386ed63e..d4da1f18a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -117,6 +117,7 @@ enum lbFunctionPassManagerKind { lbFunctionPassManager_minimal, lbFunctionPassManager_size, lbFunctionPassManager_speed, + lbFunctionPassManager_aggressive, lbFunctionPassManager_COUNT }; diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index b7fdc60bf..2f0dc24fd 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -66,8 +66,7 @@ gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPas #endif gb_internal bool lb_opt_ignore(i32 optimization_level) { - optimization_level = gb_clamp(optimization_level, -1, 2); - return optimization_level == -1; + return optimization_level < 0; } gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) { diff --git a/src/main.cpp b/src/main.cpp index 3d2dd3c44..706bbab87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -664,12 +664,18 @@ gb_internal bool parse_build_flags(Array args) { } else if (value.value_string == "speed") { build_context.custom_optimization_level = true; build_context.optimization_level = 2; + } else if (value.value_string == "aggressive" && LB_USE_NEW_PASS_SYSTEM) { + build_context.custom_optimization_level = true; + build_context.optimization_level = 3; } else { gb_printf_err("Invalid optimization mode for -o:, got %.*s\n", LIT(value.value_string)); gb_printf_err("Valid optimization modes:\n"); gb_printf_err("\tminimal\n"); gb_printf_err("\tsize\n"); gb_printf_err("\tspeed\n"); + if (LB_USE_NEW_PASS_SYSTEM) { + gb_printf_err("\taggressive\n"); + } gb_printf_err("\tnone (useful for -debug builds)\n"); bad_flags = true; } @@ -1668,8 +1674,13 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-o:"); print_usage_line(2, "Set the optimization mode for compilation"); - print_usage_line(2, "Accepted values: minimal, size, speed, none"); + if (LB_USE_NEW_PASS_SYSTEM) { + print_usage_line(2, "Accepted values: none, minimal, size, speed, aggressive"); + } else { + print_usage_line(2, "Accepted values: none, minimal, size, speed"); + } print_usage_line(2, "Example: -o:speed"); + print_usage_line(2, "The default is -o:minimal"); print_usage_line(0, ""); } @@ -1948,6 +1959,15 @@ gb_internal void print_show_help(String const arg0, String const &command) { } + if (run_or_build) { + print_usage_line(1, "-sanitize:"); + print_usage_line(1, "Enables sanitization analysis"); + print_usage_line(1, "Options are 'address', 'memory', and 'thread'"); + print_usage_line(1, "NOTE: This flag can be used multiple times"); + print_usage_line(0, ""); + + } + if (run_or_build) { #if defined(GB_SYSTEM_WINDOWS) print_usage_line(1, "-ignore-vs-search"); -- cgit v1.2.3 From 7a511308ef985897dcfb47ffa4fb5c08bf0481a4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 10:54:02 +0100 Subject: Re-configure the new pass system --- src/array.cpp | 8 ++++++++ src/llvm_backend.cpp | 45 +++++++++++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 18 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/array.cpp b/src/array.cpp index 5d602cebc..4583a31a9 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -314,6 +314,14 @@ gb_internal void array_add(Array *array, T const &t) { array->count++; } +gb_internal void array_add(Array *array, char const *t) { + if (array->capacity < array->count+1) { + array__grow(array, 0); + } + array->data[array->count] = t; + array->count++; +} + template gb_internal T *array_add_and_get(Array *array) { if (array->count < array->capacity) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a09cd8b4f..32b02eb1b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1453,19 +1453,20 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level); LLVMRunPassManager(module_pass_manager, wd->m->mod); + #if LB_USE_NEW_PASS_SYSTEM - if (build_context.optimization_level == -1) { - // don't do any passes - return 0; - } + auto passes = array_make(heap_allocator(), 0, 64); + defer (array_free(&passes)); + + LLVMPassBuilderOptionsRef pb_options = LLVMCreatePassBuilderOptions(); defer (LLVMDisposePassBuilderOptions(pb_options)); LLVMPassBuilderOptionsSetVerifyEach(pb_options, true); - int inline_threshold = 0; - LLVMPassBuilderOptionsSetInlinerThreshold(pb_options, inline_threshold); + // int inline_threshold = 0; + // LLVMPassBuilderOptionsSetInlinerThreshold(pb_options, inline_threshold); if (build_context.optimization_level >= 2) { LLVMPassBuilderOptionsSetLoopVectorization(pb_options, true); @@ -1473,21 +1474,20 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { LLVMPassBuilderOptionsSetMergeFunctions (pb_options, true); } - gbString passes = gb_string_make_reserve(heap_allocator(), 1024); - defer (gb_string_free(passes)); - switch (build_context.optimization_level) { - case 0: default: - passes = gb_string_appendc(passes, "default"); + case -1: + break; + case 0: + array_add(&passes, "default"); break; case 1: - passes = gb_string_appendc(passes, "default"); + array_add(&passes, "default"); break; case 2: - passes = gb_string_appendc(passes, "default"); + array_add(&passes, "default"); break; case 3: - passes = gb_string_appendc(passes, "default"); + array_add(&passes, "default"); break; } @@ -1497,16 +1497,25 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { // ubsan - Linux, Darwin, Windows (NOT SUPPORTED WITH LLVM C-API) if (build_context.sanitizer_flags & SanitizerFlag_Address) { - passes = gb_string_appendc(passes, ",asan"); + array_add(&passes, "asan"); } if (build_context.sanitizer_flags & SanitizerFlag_Memory) { - passes = gb_string_appendc(passes, ",msan"); + array_add(&passes, "msan"); } if (build_context.sanitizer_flags & SanitizerFlag_Thread) { - passes = gb_string_appendc(passes, ",tsan"); + array_add(&passes, "tsan"); + } + + gbString passes_str = gb_string_make_reserve(heap_allocator(), 1024); + defer (gb_string_free(passes_str)); + for_array(i, passes) { + if (i != 0) { + passes_str = gb_string_appendc(passes_str, ","); + } + passes_str = gb_string_appendc(passes_str, passes[i]); } - LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes, wd->target_machine, pb_options); + LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes_str, wd->target_machine, pb_options); defer (LLVMConsumeError(llvm_err)); if (llvm_err != nullptr) { char *llvm_error = LLVMGetErrorMessage(llvm_err); -- cgit v1.2.3 From 735bb147e271fc441f265435dfafc143b1d2e71a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 11:03:25 +0100 Subject: Add asan lib for Windows --- bin/llvm/windows/clang_rt.asan-x86_64.lib | Bin 0 -> 5091492 bytes build.bat | 24 ++++++++++++++++++++---- src/llvm_backend.cpp | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 bin/llvm/windows/clang_rt.asan-x86_64.lib (limited to 'src/llvm_backend.cpp') diff --git a/bin/llvm/windows/clang_rt.asan-x86_64.lib b/bin/llvm/windows/clang_rt.asan-x86_64.lib new file mode 100644 index 000000000..9b6971395 Binary files /dev/null and b/bin/llvm/windows/clang_rt.asan-x86_64.lib differ diff --git a/build.bat b/build.bat index d9ebb5e98..5890ce4e0 100644 --- a/build.bat +++ b/build.bat @@ -82,9 +82,9 @@ set libs= ^ rem DO NOT TOUCH! rem THIS TILDE STUFF IS FOR DEVELOPMENT ONLY! -set tilde_backend=0 +set tilde_backend=1 if %tilde_backend% EQU 1 ( - set libs=%libs% src\tilde\tb.lib + set libs=%libs% src\tilde\tb.lib onecore.lib set compiler_defines=%compiler_defines% -DODIN_TILDE_BACKEND ) rem DO NOT TOUCH! @@ -107,10 +107,26 @@ del *.ilk > NUL 2> NUL cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name% if %errorlevel% neq 0 goto end_of_build -call build_vendor.bat +rem call build_vendor.bat +rem if %errorlevel% neq 0 goto end_of_build + +rem if %release_mode% EQU 0 odin run examples/demo + +rem %exe_name% check examples/all -show-timings +rem %exe_name% build examples/demo -show-timings -keep-temp-files +%exe_name% run examples/bug -show-timings -o:none -sanitize:address +rem %exe_name% run examples/bug -tilde -debug + + if %errorlevel% neq 0 goto end_of_build -if %release_mode% EQU 0 odin run examples/demo +pushd W:\JangaFX\EmberGen\embergen2 + rem W:\Odin\odin build . -show-timings + rem W:\Odin\odin run . -show-timings +popd + + +rem %exe_name% check examples/all -vet -strict-style -show-timings del *.obj > NUL 2> NUL diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 32b02eb1b..492559a4f 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2586,6 +2586,21 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { return false; } + + if (build_context.sanitizer_flags & SanitizerFlag_Address) { + auto paths = array_make(heap_allocator(), 0, 1); + if (build_context.metrics.os == TargetOs_windows) { + String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib")); + array_add(&paths, path); + } + Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib")); + array_add(&gen->foreign_libraries, lib); + } + if (build_context.sanitizer_flags & SanitizerFlag_Memory) { + } + if (build_context.sanitizer_flags & SanitizerFlag_Thread) { + } + gb_sort_array(gen->foreign_libraries.data, gen->foreign_libraries.count, foreign_library_cmp); return true; -- cgit v1.2.3 From 20ce8c4c5109548ffd161f1affbc8eb264172396 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 12:45:11 +0100 Subject: Allow for zero passes --- src/llvm_backend.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 492559a4f..df5ebb176 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1506,6 +1506,11 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { array_add(&passes, "tsan"); } + + if (passes.count == 0) { + return 0; + } + gbString passes_str = gb_string_make_reserve(heap_allocator(), 1024); defer (gb_string_free(passes_str)); for_array(i, passes) { -- cgit v1.2.3 From 963559676e30b44f948b34d0fa1a13bf535c7405 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 16:48:00 +0100 Subject: Fix build times for `-o:` in LLVM-17 --- src/check_decl.cpp | 4 ---- src/check_expr.cpp | 11 ----------- src/check_type.cpp | 18 ------------------ src/llvm_backend.cpp | 30 +++++++++++++++--------------- src/llvm_backend_const.cpp | 11 ----------- src/llvm_backend_proc.cpp | 4 ++-- 6 files changed, 17 insertions(+), 61 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 86a887157..71b897a84 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1336,10 +1336,6 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D is_invalid = true; break; case ProcOverload_Polymorphic: - #if 0 - error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in the procedure group '%.*s' which is not allowed", LIT(name), LIT(proc_group_name)); - is_invalid = true; - #endif break; case ProcOverload_ParamCount: case ProcOverload_ParamTypes: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index abcb7fd72..700412a86 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3673,18 +3673,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ ExactValue b = y->value; if (!is_type_constant_type(x->type)) { - #if 0 - gbString xt = type_to_string(x->type); - gbString err_str = expr_to_string(node); - error(op, "Invalid type, '%s', for constant binary expression '%s'", xt, err_str); - gb_string_free(err_str); - gb_string_free(xt); - x->mode = Addressing_Invalid; - #else - // NOTE(bill, 2021-04-21): The above is literally a useless error message. - // Why did I add it in the first place?! x->mode = Addressing_Value; - #endif return; } diff --git a/src/check_type.cpp b/src/check_type.cpp index cae3ba22e..5e7e76d66 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1056,24 +1056,6 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t } else { Type *elem = check_type_expr(c, bs->elem, nullptr); - #if 0 - if (named_type != nullptr && named_type->kind == Type_Named && - elem->kind == Type_Enum) { - // NOTE(bill): Anonymous enumeration - - String prefix = named_type->Named.name; - String enum_name = concatenate_strings(heap_allocator(), prefix, str_lit(".enum")); - - Token token = make_token_ident(enum_name); - - Entity *e = alloc_entity_type_name(nullptr, token, nullptr, EntityState_Resolved); - Type *named = alloc_type_named(enum_name, elem, e); - e->type = named; - e->TypeName.is_type_alias = true; - elem = named; - } - #endif - type->BitSet.elem = elem; if (!is_type_valid_bit_set_elem(elem)) { error(bs->elem, "Expected an enum type for a bit_set"); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index df5ebb176..7e27b7daf 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1025,6 +1025,8 @@ gb_internal lbProcedure *lb_create_startup_type_info(lbModule *m) { LLVMSetLinkage(p->value, LLVMInternalLinkage); lb_add_attribute_to_proc(m, p->value, "nounwind"); + lb_add_attribute_to_proc(m, p->value, "optnone"); + lb_add_attribute_to_proc(m, p->value, "noinline"); lb_begin_procedure_body(p); @@ -1086,6 +1088,8 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type); p->is_startup = true; + lb_add_attribute_to_proc(p->module, p->value, "optnone"); + lb_add_attribute_to_proc(p->module, p->value, "noinline"); lb_begin_procedure_body(p); @@ -1189,6 +1193,8 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_CLEANUP_RUNTIME_PROC_NAME), proc_type); p->is_startup = true; + lb_add_attribute_to_proc(p->module, p->value, "optnone"); + lb_add_attribute_to_proc(p->module, p->value, "noinline"); lb_begin_procedure_body(p); @@ -1396,6 +1402,8 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { lbFunctionPassManagerKind pass_manager_kind = lbFunctionPassManager_default; if (p->flags & lbProcedureFlag_WithoutMemcpyPass) { pass_manager_kind = lbFunctionPassManager_default_without_memcpy; + lb_add_attribute_to_proc(p->module, p->value, "optnone"); + lb_add_attribute_to_proc(p->module, p->value, "noinline"); } else { if (p->entity && p->entity->kind == Entity_Procedure) { switch (p->entity->Procedure.optimization_mode) { @@ -1405,6 +1413,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { break; case ProcedureOptimizationMode_Size: pass_manager_kind = lbFunctionPassManager_size; + lb_add_attribute_to_proc(p->module, p->value, "optsize"); break; case ProcedureOptimizationMode_Speed: pass_manager_kind = lbFunctionPassManager_speed; @@ -1463,22 +1472,12 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { LLVMPassBuilderOptionsRef pb_options = LLVMCreatePassBuilderOptions(); defer (LLVMDisposePassBuilderOptions(pb_options)); - LLVMPassBuilderOptionsSetVerifyEach(pb_options, true); - - // int inline_threshold = 0; - // LLVMPassBuilderOptionsSetInlinerThreshold(pb_options, inline_threshold); - - if (build_context.optimization_level >= 2) { - LLVMPassBuilderOptionsSetLoopVectorization(pb_options, true); - LLVMPassBuilderOptionsSetLoopUnrolling (pb_options, true); - LLVMPassBuilderOptionsSetMergeFunctions (pb_options, true); - } - switch (build_context.optimization_level) { case -1: break; case 0: - array_add(&passes, "default"); + array_add(&passes, "always-inline"); + array_add(&passes, "function(annotation-remarks)"); break; case 1: array_add(&passes, "default"); @@ -1506,9 +1505,8 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { array_add(&passes, "tsan"); } - if (passes.count == 0) { - return 0; + array_add(&passes, "verify"); } gbString passes_str = gb_string_make_reserve(heap_allocator(), 1024); @@ -1520,7 +1518,10 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { passes_str = gb_string_appendc(passes_str, passes[i]); } + gb_printf_err("LLVMRunPasses [START]\n"); LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes_str, wd->target_machine, pb_options); + gb_printf_err("LLVMRunPasses [END]\n"); + defer (LLVMConsumeError(llvm_err)); if (llvm_err != nullptr) { char *llvm_error = LLVMGetErrorMessage(llvm_err); @@ -2547,7 +2548,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Module Verification"); - if (!lb_llvm_module_verification(gen, do_threading)) { return false; } diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 63debc978..f3c3871ff 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -14,17 +14,6 @@ gb_internal bool lb_is_const_or_global(lbValue value) { if (lb_is_const(value)) { return true; } - // TODO remove use of LLVMGetElementType - #if 0 - if (LLVMGetValueKind(value.value) == LLVMGlobalVariableValueKind) { - LLVMTypeRef t = LLVMGetElementType(LLVMTypeOf(value.value)); - if (!lb_is_type_kind(t, LLVMPointerTypeKind)) { - return false; - } - LLVMTypeRef elem = LLVMGetElementType(t); - return lb_is_type_kind(elem, LLVMFunctionTypeKind); - } - #endif return false; } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 4be0ebf9b..795f2fdd3 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -139,7 +139,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i lb_ensure_abi_function_type(m, p); lb_add_function_type_attributes(p->value, p->abi_function_type, p->abi_function_type->calling_convention); - + if (pt->Proc.diverging) { lb_add_attribute_to_proc(m, p->value, "noreturn"); } @@ -317,7 +317,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i } } - if (p->body && entity->pkg && (entity->pkg->kind == Package_Normal) || (entity->pkg->kind == Package_Init)) { + if (p->body && entity->pkg && ((entity->pkg->kind == Package_Normal) || (entity->pkg->kind == Package_Init))) { if (build_context.sanitizer_flags & SanitizerFlag_Address) { lb_add_attribute_to_proc(m, p->value, "sanitize_address"); } -- cgit v1.2.3 From ac43dd07777d68a8bd96429eb448a563e4804366 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Sep 2023 17:08:45 +0100 Subject: Remove debug text --- src/llvm_backend.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 7e27b7daf..6a32195c8 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1518,9 +1518,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { passes_str = gb_string_appendc(passes_str, passes[i]); } - gb_printf_err("LLVMRunPasses [START]\n"); LLVMErrorRef llvm_err = LLVMRunPasses(wd->m->mod, passes_str, wd->target_machine, pb_options); - gb_printf_err("LLVMRunPasses [END]\n"); defer (LLVMConsumeError(llvm_err)); if (llvm_err != nullptr) { -- cgit v1.2.3 From 5e99289d7afd34cf785b15f727ed2f2d61aa6ffc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Sep 2023 12:11:39 +0100 Subject: Minor clean up --- src/llvm_backend.cpp | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6a32195c8..439140901 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1358,20 +1358,13 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { { GB_ASSERT(m->function_pass_managers[lbFunctionPassManager_default] == nullptr); - m->function_pass_managers[lbFunctionPassManager_default] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_default_without_memcpy] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_none] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_minimal] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_size] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_speed] = LLVMCreateFunctionPassManagerForModule(m->mod); - m->function_pass_managers[lbFunctionPassManager_aggressive] = LLVMCreateFunctionPassManagerForModule(m->mod); - - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default]); - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default_without_memcpy]); - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_none]); - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_minimal]); - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_size]); - LLVMInitializeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_speed]); + for (i32 i = 0; i < lbFunctionPassManager_COUNT; i++) { + m->function_pass_managers[i] = LLVMCreateFunctionPassManagerForModule(m->mod); + } + + for (i32 i = 0; i < lbFunctionPassManager_COUNT; i++) { + LLVMInitializeFunctionPassManager(m->function_pass_managers[i]); + } lb_populate_function_pass_manager(m, m->function_pass_managers[lbFunctionPassManager_default], false, build_context.optimization_level); lb_populate_function_pass_manager(m, m->function_pass_managers[lbFunctionPassManager_default_without_memcpy], true, build_context.optimization_level); @@ -1381,13 +1374,9 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_speed], 2); lb_populate_function_pass_manager_specific(m, m->function_pass_managers[lbFunctionPassManager_aggressive], 3); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_default_without_memcpy]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_none]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_minimal]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_size]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_speed]); - LLVMFinalizeFunctionPassManager(m->function_pass_managers[lbFunctionPassManager_aggressive]); + for (i32 i = 0; i < lbFunctionPassManager_COUNT; i++) { + LLVMFinalizeFunctionPassManager(m->function_pass_managers[i]); + } } if (m == &m->gen->default_module) { @@ -2536,16 +2525,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - TIME_SECTION("LLVM Function Pass"); lb_llvm_function_passes(gen, do_threading && !build_context.ODIN_DEBUG); TIME_SECTION("LLVM Module Pass"); lb_llvm_module_passes(gen, do_threading); - TIME_SECTION("LLVM Module Verification"); - if (!lb_llvm_module_verification(gen, do_threading)) { return false; } -- cgit v1.2.3 From 082324d7b97e521f5d8dada40629da4e689197c9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Sep 2023 14:39:51 +0100 Subject: Begin work on making the type info table be constantly initialized --- src/llvm_abi.cpp | 14 +- src/llvm_backend.cpp | 12 +- src/llvm_backend.hpp | 11 + src/llvm_backend_const.cpp | 14 +- src/llvm_backend_general.cpp | 26 +- src/llvm_backend_opt.cpp | 2 +- src/llvm_backend_type.cpp | 952 ++++++++++++++++++++++++++++++++++++++++--- src/llvm_backend_utility.cpp | 15 +- 8 files changed, 976 insertions(+), 70 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index b0045d869..857b255f3 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1130,14 +1130,14 @@ namespace lbAbiArm64 { return non_struct(c, return_type); } else if (is_homogenous_aggregate(c, return_type, &homo_base_type, &homo_member_count)) { if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) { - return lb_arg_type_direct(return_type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); + return lb_arg_type_direct(return_type, llvm_array_type(homo_base_type, homo_member_count), nullptr, nullptr); } else { //TODO(Platin): do i need to create stuff that can handle the diffrent return type? // else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO(); - //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count); + //LLVMTypeRef array_type = llvm_array_type(homo_base_type, homo_member_count); LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type); return lb_arg_type_indirect(return_type, attr); } @@ -1155,7 +1155,7 @@ namespace lbAbiArm64 { cast_type = LLVMInt64TypeInContext(c); } else { unsigned count = cast(unsigned)((size+7)/8); - cast_type = LLVMArrayType(LLVMInt64TypeInContext(c), count); + cast_type = llvm_array_type(LLVMInt64TypeInContext(c), count); } return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr); } else { @@ -1180,7 +1180,7 @@ namespace lbAbiArm64 { args[i] = non_struct(c, type); } else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) { if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) { - args[i] = lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); + args[i] = lb_arg_type_direct(type, llvm_array_type(homo_base_type, homo_member_count), nullptr, nullptr); } else { args[i] = lb_arg_type_indirect(type, nullptr);; } @@ -1198,7 +1198,7 @@ namespace lbAbiArm64 { cast_type = LLVMIntTypeInContext(c, 64); } else { unsigned count = cast(unsigned)((size+7)/8); - cast_type = LLVMArrayType(LLVMIntTypeInContext(c, 64), count); + cast_type = llvm_array_type(LLVMIntTypeInContext(c, 64), count); } args[i] = lb_arg_type_direct(type, cast_type, nullptr, nullptr); } else { @@ -1439,10 +1439,10 @@ namespace lbAbiArm32 { args[i] = lb_arg_type_indirect(t, nullptr); } else if (a <= 4) { unsigned n = cast(unsigned)((sz + 3) / 4); - args[i] = lb_arg_type_direct(LLVMArrayType(LLVMIntTypeInContext(c, 32), n)); + args[i] = lb_arg_type_direct(llvm_array_type(LLVMIntTypeInContext(c, 32), n)); } else { unsigned n = cast(unsigned)((sz + 7) / 8); - args[i] = lb_arg_type_direct(LLVMArrayType(LLVMIntTypeInContext(c, 64), n)); + args[i] = lb_arg_type_direct(llvm_array_type(LLVMIntTypeInContext(c, 64), n)); } } } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 439140901..db5af0647 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2225,10 +2225,16 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { { // Add type info data isize max_type_info_count = info->minimum_dependency_type_info_set.count+1; - // gb_printf_err("max_type_info_count: %td\n", max_type_info_count); Type *t = alloc_type_array(t_type_info, max_type_info_count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), LB_TYPE_INFO_DATA_NAME); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + + // IMPORTANT NOTE(bill): As LLVM does not have a union type, an array of unions cannot be initialized + // at compile time without cheating in some way. This means to emulate an array of unions is to use + // a giant packed struct of "corrected" data types. + + LLVMTypeRef internal_llvm_type = lb_setup_type_info_data_internal_type(m, max_type_info_count); + + LLVMValueRef g = LLVMAddGlobal(m->mod, internal_llvm_type, LB_TYPE_INFO_DATA_NAME); + LLVMSetInitializer(g, LLVMConstNull(internal_llvm_type)); LLVMSetLinkage(g, USE_SEPARATE_MODULES ? LLVMExternalLinkage : LLVMInternalLinkage); lbValue value = {}; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 048233c08..13a250f00 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -451,6 +451,7 @@ gb_internal lbValue lb_emit_runtime_call(lbProcedure *p, char const *c_name, Arr gb_internal lbValue lb_emit_ptr_offset(lbProcedure *p, lbValue ptr, lbValue index); +gb_internal lbValue lb_const_ptr_offset(lbModule *m, lbValue ptr, lbValue index); gb_internal lbValue lb_string_elem(lbProcedure *p, lbValue string); gb_internal lbValue lb_string_len(lbProcedure *p, lbValue string); gb_internal lbValue lb_cstring_len(lbProcedure *p, lbValue value); @@ -497,6 +498,7 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e); gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value); gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value); gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos); +gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos); gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos); @@ -553,6 +555,15 @@ gb_internal LLVMTypeRef OdinLLVMGetVectorElementType(LLVMTypeRef type); gb_internal String lb_filepath_ll_for_module(lbModule *m); + +gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t ElementCount) { +#if LB_USE_NEW_PASS_SYSTEM + return LLVMArrayType2(ElementType, ElementCount); +#else + return LLVMArrayType(ElementType, cast(unsigned)ElementCount); +#endif +} + #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime" #define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info" diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index f3c3871ff..a16b2293c 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -284,14 +284,12 @@ gb_internal lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type return lb_const_value(m, t, tv.value); } -gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos) { - lbModule *m = p->module; - +gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos) { LLVMValueRef fields[4] = {}; - fields[0]/*file*/ = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)).value; + fields[0]/*file*/ = lb_find_or_add_entity_string(m, get_file_path_string(pos.file_id)).value; fields[1]/*line*/ = lb_const_int(m, t_i32, pos.line).value; fields[2]/*column*/ = lb_const_int(m, t_i32, pos.column).value; - fields[3]/*procedure*/ = lb_find_or_add_entity_string(p->module, procedure).value; + fields[3]/*procedure*/ = lb_find_or_add_entity_string(m, procedure).value; lbValue res = {}; res.value = llvm_const_named_struct(m, t_source_code_location, fields, gb_count_of(fields)); @@ -299,6 +297,12 @@ gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String co return res; } + +gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos) { + lbModule *m = p->module; + return lb_const_source_code_location_const(m, procedure, pos); +} + gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node) { String proc_name = {}; if (p->entity) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index ccc0f2a54..0f0df7ca5 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -278,6 +278,13 @@ gb_internal lbValue lb_zero(lbModule *m, Type *t) { v.type = t; return v; } +gb_internal LLVMValueRef llvm_const_extract_value(lbModule *m, LLVMValueRef agg, unsigned index) { + LLVMValueRef res = agg; + GB_ASSERT(LLVMIsConstant(res)); + res = LLVMBuildExtractValue(m->const_dummy_builder, res, index, ""); + GB_ASSERT(LLVMIsConstant(res)); + return res; +} gb_internal LLVMValueRef llvm_const_extract_value(lbModule *m, LLVMValueRef agg, unsigned *indices, isize count) { // return LLVMConstExtractValue(value, indices, count); @@ -290,6 +297,19 @@ gb_internal LLVMValueRef llvm_const_extract_value(lbModule *m, LLVMValueRef agg, return res; } +gb_internal LLVMValueRef llvm_const_insert_value(lbModule *m, LLVMValueRef agg, LLVMValueRef val, unsigned index) { + GB_ASSERT(LLVMIsConstant(agg)); + GB_ASSERT(LLVMIsConstant(val)); + + LLVMValueRef extracted_value = val; + LLVMValueRef nested = llvm_const_extract_value(m, agg, index); + GB_ASSERT(LLVMIsConstant(nested)); + extracted_value = LLVMBuildInsertValue(m->const_dummy_builder, nested, extracted_value, index, ""); + GB_ASSERT(LLVMIsConstant(extracted_value)); + return extracted_value; +} + + gb_internal LLVMValueRef llvm_const_insert_value(lbModule *m, LLVMValueRef agg, LLVMValueRef val, unsigned *indices, isize count) { GB_ASSERT(LLVMIsConstant(agg)); GB_ASSERT(LLVMIsConstant(val)); @@ -1919,14 +1939,14 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_Array: { m->internal_type_level += 1; - LLVMTypeRef t = LLVMArrayType(lb_type(m, type->Array.elem), cast(unsigned)type->Array.count); + LLVMTypeRef t = llvm_array_type(lb_type(m, type->Array.elem), type->Array.count); m->internal_type_level -= 1; return t; } case Type_EnumeratedArray: { m->internal_type_level += 1; - LLVMTypeRef t = LLVMArrayType(lb_type(m, type->EnumeratedArray.elem), cast(unsigned)type->EnumeratedArray.count); + LLVMTypeRef t = llvm_array_type(lb_type(m, type->EnumeratedArray.elem), type->EnumeratedArray.count); m->internal_type_level -= 1; return t; } @@ -2160,7 +2180,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { m->internal_type_level -= 1; LLVMTypeRef elem = lb_type(m, type->Matrix.elem); - LLVMTypeRef t = LLVMArrayType(elem, cast(unsigned)elem_count); + LLVMTypeRef t = llvm_array_type(elem, elem_count); m->internal_type_level += 1; return t; diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 055cb5bcb..4424bde7c 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -443,7 +443,7 @@ gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef func) { } LLVMTypeRef Int8PtrTy = LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0); - LLVMTypeRef ATy = LLVMArrayType(Int8PtrTy, operands); + LLVMTypeRef ATy = llvm_array_type(Int8PtrTy, operands); constants[operands - 1] = LLVMConstBitCast(func, Int8PtrTy); LLVMValueRef initializer = LLVMConstArray(Int8PtrTy, constants, operands); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 62a67f96a..3654e8005 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -14,18 +14,16 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_ return -1; } -gb_internal lbValue lb_typeid(lbModule *m, Type *type) { +gb_internal u64 lb_typeid_kind(lbModule *m, Type *type, u64 id=0) { GB_ASSERT(!build_context.no_rtti); type = default_type(type); - u64 id = cast(u64)lb_type_info_index(m->info, type); - GB_ASSERT(id >= 0); + if (id == 0) { + id = cast(u64)lb_type_info_index(m->info, type); + } u64 kind = Typeid_Invalid; - u64 named = is_type_named(type) && type->kind != Type_Basic; - u64 special = 0; - u64 reserved = 0; Type *bt = base_type(type); TypeKind tk = bt->kind; @@ -61,6 +59,22 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) { case Type_SoaPointer: kind = Typeid_SoaPointer; break; } + return kind; +} + +gb_internal lbValue lb_typeid(lbModule *m, Type *type) { + GB_ASSERT(!build_context.no_rtti); + + type = default_type(type); + + u64 id = cast(u64)lb_type_info_index(m->info, type); + GB_ASSERT(id >= 0); + + u64 kind = lb_typeid_kind(m, type, id); + u64 named = is_type_named(type) && type->kind != Type_Basic; + u64 special = 0; + u64 reserved = 0; + if (is_type_cstring(type)) { special = 1; } else if (is_type_integer(type) && !is_type_unsigned(type)) { @@ -107,65 +121,905 @@ gb_internal LLVMTypeRef lb_get_procedure_raw_type(lbModule *m, Type *type) { return lb_type_internal_for_procedures_raw(m, type); } +gb_internal lbValue lb_const_array_epi(lbModule *m, lbValue value, isize index) { + GB_ASSERT(is_type_pointer(value.type)); + Type *type = type_deref(value.type); + + LLVMValueRef indices[2] = { + LLVMConstInt(lb_type(m, t_int), 0, false), + LLVMConstInt(lb_type(m, t_int), cast(unsigned long long)index, false), + }; + LLVMTypeRef llvm_type = lb_type(m, type); + lbValue res = {}; + Type *ptr = base_array_type(type); + res.type = alloc_type_pointer(ptr); + GB_ASSERT(LLVMIsConstant(value.value)); + res.value = LLVMConstGEP2(llvm_type, value.value, indices, gb_count_of(indices)); + return res; +} + -gb_internal lbValue lb_type_info_member_types_offset(lbProcedure *p, isize count) { - GB_ASSERT(p->module == &p->module->gen->default_module); - lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_types.addr, lb_global_type_info_member_types_index); +gb_internal lbValue lb_type_info_member_types_offset(lbModule *m, isize count) { + GB_ASSERT(m == &m->gen->default_module); + lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_types.addr, lb_global_type_info_member_types_index); lb_global_type_info_member_types_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_names_offset(lbProcedure *p, isize count) { - GB_ASSERT(p->module == &p->module->gen->default_module); - lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_names.addr, lb_global_type_info_member_names_index); +gb_internal lbValue lb_type_info_member_names_offset(lbModule *m, isize count) { + GB_ASSERT(m == &m->gen->default_module); + lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_names.addr, lb_global_type_info_member_names_index); lb_global_type_info_member_names_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_offsets_offset(lbProcedure *p, isize count) { - GB_ASSERT(p->module == &p->module->gen->default_module); - lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_offsets.addr, lb_global_type_info_member_offsets_index); +gb_internal lbValue lb_type_info_member_offsets_offset(lbModule *m, isize count) { + GB_ASSERT(m == &m->gen->default_module); + lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_offsets.addr, lb_global_type_info_member_offsets_index); lb_global_type_info_member_offsets_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_usings_offset(lbProcedure *p, isize count) { - GB_ASSERT(p->module == &p->module->gen->default_module); - lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_usings.addr, lb_global_type_info_member_usings_index); +gb_internal lbValue lb_type_info_member_usings_offset(lbModule *m, isize count) { + GB_ASSERT(m == &m->gen->default_module); + lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_usings.addr, lb_global_type_info_member_usings_index); lb_global_type_info_member_usings_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) { - GB_ASSERT(p->module == &p->module->gen->default_module); - lbValue offset = lb_emit_array_epi(p, lb_global_type_info_member_tags.addr, lb_global_type_info_member_tags_index); +gb_internal lbValue lb_type_info_member_tags_offset(lbModule *m, isize count) { + GB_ASSERT(m == &m->gen->default_module); + lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_tags.addr, lb_global_type_info_member_tags_index); lb_global_type_info_member_tags_index += cast(i32)count; return offset; } +enum {LB_USE_GIANT_PACKED_STRUCT = false}; -gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data - if (build_context.no_rtti) { - return; +gb_internal LLVMTypeRef lb_setup_type_info_data_internal_type(lbModule *m, isize max_type_info_count) { + if (!LB_USE_GIANT_PACKED_STRUCT) { + Type *t = alloc_type_array(t_type_info, max_type_info_count); + return lb_type(m, t); } + CheckerInfo *info = m->gen->info; - lbModule *m = p->module; - CheckerInfo *info = m->info; - - i64 global_type_info_data_entity_count = 0; - { - // NOTE(bill): Set the type_table slice with the global backing array - lbValue global_type_table = lb_find_runtime_value(m, str_lit("type_table")); - Type *type = base_type(lb_global_type_info_data_entity->type); - GB_ASSERT(is_type_array(type)); - global_type_info_data_entity_count = type->Array.count; + LLVMTypeRef *element_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, max_type_info_count); + defer (gb_free(heap_allocator(), element_types)); - LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; - LLVMValueRef data = LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)); - LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), type->Array.count, true); - Type *t = type_deref(global_type_table.type); - GB_ASSERT(is_type_slice(t)); - LLVMValueRef slice = llvm_const_slice_internal(m, data, len); + auto entries_handled = slice_make(heap_allocator(), max_type_info_count); + defer (gb_free(heap_allocator(), entries_handled.data)); + entries_handled[0] = true; - LLVMSetInitializer(global_type_table.value, slice); + element_types[0] = lb_type(m, t_type_info); + + Type *tibt = base_type(t_type_info); + GB_ASSERT(tibt->kind == Type_Struct); + Type *ut = base_type(tibt->Struct.fields[tibt->Struct.fields.count-1]->type); + GB_ASSERT(ut->kind == Type_Union); + + GB_ASSERT(tibt->Struct.fields.count == 5); + LLVMTypeRef stypes[6] = {}; + stypes[0] = lb_type(m, tibt->Struct.fields[0]->type); + stypes[1] = lb_type(m, tibt->Struct.fields[1]->type); + stypes[2] = lb_type(m, tibt->Struct.fields[2]->type); + isize variant_index = 0; + if (build_context.int_size == 8) { + stypes[3] = lb_type(m, t_i32); // padding + stypes[4] = lb_type(m, tibt->Struct.fields[3]->type); + variant_index = 5; + } else { + stypes[3] = lb_type(m, tibt->Struct.fields[3]->type); + variant_index = 4; + } + + LLVMTypeRef modified_types[32] = {}; + GB_ASSERT(gb_count_of(modified_types) >= ut->Union.variants.count); + modified_types[0] = element_types[0]; + + i64 tag_offset = ut->Union.variant_block_size; + LLVMTypeRef tag = lb_type(m, union_tag_type(ut)); + + for_array(i, ut->Union.variants) { + Type *t = ut->Union.variants[i]; + LLVMTypeRef padding = llvm_array_type(lb_type(m, t_u8), tag_offset-type_size_of(t)); + + LLVMTypeRef vtypes[3] = {}; + vtypes[0] = lb_type(m, t); + vtypes[1] = padding; + vtypes[2] = tag; + LLVMTypeRef variant_type = LLVMStructType(vtypes, gb_count_of(vtypes), true); + + stypes[variant_index] = variant_type; + LLVMTypeRef modified_type = LLVMStructType(stypes, cast(unsigned)(variant_index+1), false); + + modified_types[i] = modified_type; + } + + for_array(type_info_type_index, info->type_info_types) { + Type *t = info->type_info_types[type_info_type_index]; + if (t == nullptr || t == t_invalid) { + continue; + } + isize entry_index = lb_type_info_index(info, t, false); + if (entry_index <= 0) { + continue; + } + + if (entries_handled[entry_index]) { + continue; + } + entries_handled[entry_index] = true; + + + if (t->kind == Type_Named) { + element_types[entry_index] = modified_types[0]; + } else { + i64 variant_index = lb_typeid_kind(m, t); + element_types[entry_index] = modified_types[variant_index]; + } + + GB_ASSERT(element_types[entry_index] != nullptr); + } + + for_array(i, entries_handled) { + GB_ASSERT(entries_handled[i]); } + return LLVMStructType(element_types, cast(unsigned)max_type_info_count, true); +} + + +gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 global_type_info_data_entity_count) { // NOTE(bill): Setup type_info data + CheckerInfo *info = m->info; + + // Useful types + Entity *type_info_flags_entity = find_core_entity(info->checker, str_lit("Type_Info_Flags")); + Type *t_type_info_flags = type_info_flags_entity->type; + gb_unused(t_type_info_flags); + + Type *ut = base_type(t_type_info); + GB_ASSERT(ut->kind == Type_Struct); + ut = base_type(ut->Struct.fields[ut->Struct.fields.count-1]->type); + GB_ASSERT(ut->kind == Type_Union); + + auto entries_handled = slice_make(heap_allocator(), cast(isize)global_type_info_data_entity_count); + defer (gb_free(heap_allocator(), entries_handled.data)); + entries_handled[0] = true; + + + LLVMValueRef giant_struct = lb_global_type_info_data_ptr(m).value; + LLVMTypeRef giant_struct_type = LLVMGlobalGetValueType(giant_struct); + GB_ASSERT(LLVMGetTypeKind(giant_struct_type) == LLVMStructTypeKind); + + LLVMValueRef *giant_const_values = gb_alloc_array(heap_allocator(), LLVMValueRef, global_type_info_data_entity_count); + defer (gb_free(heap_allocator(), giant_const_values)); + + giant_const_values[0] = LLVMConstNull(LLVMStructGetTypeAtIndex(giant_struct_type, 0)); + + + LLVMValueRef *small_const_values = gb_alloc_array(heap_allocator(), LLVMValueRef, 6); + defer (gb_free(heap_allocator(), small_const_values)); + + for_array(type_info_type_index, info->type_info_types) { + Type *t = info->type_info_types[type_info_type_index]; + if (t == nullptr || t == t_invalid) { + continue; + } + + isize entry_index = lb_type_info_index(info, t, false); + if (entry_index <= 0) { + continue; + } + + if (entries_handled[entry_index]) { + continue; + } + entries_handled[entry_index] = true; + + + LLVMTypeRef stype = LLVMStructGetTypeAtIndex(giant_struct_type, cast(unsigned)entry_index); + + i64 size = type_size_of(t); + i64 align = type_align_of(t); + u32 flags = type_info_flags_of_type(t); + lbValue id = lb_typeid(m, t); + GB_ASSERT_MSG(align != 0, "%lld %s", align, type_to_string(t)); + + lbValue type_info_flags = lb_const_int(m, t_type_info_flags, flags); + + small_const_values[0] = LLVMConstInt(lb_type(m, t_int), size, true); + small_const_values[1] = LLVMConstInt(lb_type(m, t_int), align, true); + small_const_values[2] = type_info_flags.value; + + unsigned variant_index = 0; + if (build_context.int_size == 8) { + small_const_values[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 3)); + small_const_values[4] = id.value; + variant_index = 5; + } else { + small_const_values[3] = id.value; + variant_index = 4; + } + + LLVMTypeRef full_variant_type = LLVMStructGetTypeAtIndex(stype, variant_index); + unsigned full_variant_elem_count = LLVMCountStructElementTypes(full_variant_type); + if (full_variant_elem_count != 2) { + GB_ASSERT_MSG(LLVMCountStructElementTypes(full_variant_type) == 3, "%lld %s", entry_index, type_to_string(t)); // blob, padding, tag + } + + LLVMValueRef variant_value = nullptr; + Type *tag_type = nullptr; + + switch (t->kind) { + case Type_Named: { + tag_type = t_type_info_named; + + LLVMValueRef pkg_name = nullptr; + if (t->Named.type_name->pkg) { + pkg_name = lb_const_string(m, t->Named.type_name->pkg->name).value; + } else { + pkg_name = LLVMConstNull(lb_type(m, t_string)); + } + + String proc_name = {}; + if (t->Named.type_name->parent_proc_decl) { + DeclInfo *decl = t->Named.type_name->parent_proc_decl; + if (decl->entity && decl->entity->kind == Entity_Procedure) { + proc_name = decl->entity->token.string; + } + } + TokenPos pos = t->Named.type_name->token.pos; + + lbValue loc = lb_const_source_code_location_const(m, proc_name, pos); + + LLVMValueRef vals[4] = { + lb_const_string(m, t->Named.type_name->token.string).value, + lb_type_info(m, t->Named.base).value, + pkg_name, + loc.value + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + + case Type_Basic: + switch (t->Basic.kind) { + case Basic_bool: + case Basic_b8: + case Basic_b16: + case Basic_b32: + case Basic_b64: + tag_type = t_type_info_boolean; + break; + + case Basic_i8: + case Basic_u8: + case Basic_i16: + case Basic_u16: + case Basic_i32: + case Basic_u32: + case Basic_i64: + case Basic_u64: + case Basic_i128: + case Basic_u128: + + case Basic_i16le: + case Basic_u16le: + case Basic_i32le: + case Basic_u32le: + case Basic_i64le: + case Basic_u64le: + case Basic_i128le: + case Basic_u128le: + case Basic_i16be: + case Basic_u16be: + case Basic_i32be: + case Basic_u32be: + case Basic_i64be: + case Basic_u64be: + case Basic_i128be: + case Basic_u128be: + + case Basic_int: + case Basic_uint: + case Basic_uintptr: { + tag_type = t_type_info_integer; + + lbValue is_signed = lb_const_bool(m, t_bool, (t->Basic.flags & BasicFlag_Unsigned) == 0); + // NOTE(bill): This is matches the runtime layout + u8 endianness_value = 0; + if (t->Basic.flags & BasicFlag_EndianLittle) { + endianness_value = 1; + } else if (t->Basic.flags & BasicFlag_EndianBig) { + endianness_value = 2; + } + lbValue endianness = lb_const_int(m, t_u8, endianness_value); + + LLVMValueRef vals[2] = { + is_signed.value, + endianness.value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + + case Basic_rune: + tag_type = t_type_info_rune; + break; + + case Basic_f16: + case Basic_f32: + case Basic_f64: + case Basic_f16le: + case Basic_f32le: + case Basic_f64le: + case Basic_f16be: + case Basic_f32be: + case Basic_f64be: + { + tag_type = t_type_info_float; + + // NOTE(bill): This is matches the runtime layout + u8 endianness_value = 0; + if (t->Basic.flags & BasicFlag_EndianLittle) { + endianness_value = 1; + } else if (t->Basic.flags & BasicFlag_EndianBig) { + endianness_value = 2; + } + lbValue endianness = lb_const_int(m, t_u8, endianness_value); + + LLVMValueRef vals[1] = { + endianness.value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Basic_complex32: + case Basic_complex64: + case Basic_complex128: + tag_type = t_type_info_complex; + break; + + case Basic_quaternion64: + case Basic_quaternion128: + case Basic_quaternion256: + tag_type = t_type_info_quaternion; + break; + + case Basic_rawptr: + tag_type = t_type_info_pointer; + break; + + case Basic_string: + tag_type = t_type_info_string; + break; + + case Basic_cstring: + { + tag_type = t_type_info_string; + LLVMValueRef vals[1] = { + lb_const_bool(m, t_bool, true).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Basic_any: + tag_type = t_type_info_any; + break; + + case Basic_typeid: + tag_type = t_type_info_typeid; + break; + } + break; + + case Type_Pointer: { + tag_type = t_type_info_pointer; + lbValue gep = lb_type_info(m, t->Pointer.elem); + + LLVMValueRef vals[1] = { + gep.value, + }; + + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_MultiPointer: { + tag_type = t_type_info_multi_pointer; + lbValue gep = lb_type_info(m, t->MultiPointer.elem); + + LLVMValueRef vals[1] = { + gep.value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_SoaPointer: { + tag_type = t_type_info_soa_pointer; + lbValue gep = lb_type_info(m, t->SoaPointer.elem); + + LLVMValueRef vals[1] = { + gep.value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_Array: { + tag_type = t_type_info_array; + i64 ez = type_size_of(t->Array.elem); + + LLVMValueRef vals[3] = { + lb_type_info(m, t->Array.elem).value, + lb_const_int(m, t_int, ez).value, + lb_const_int(m, t_int, t->Array.count).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_EnumeratedArray: { + tag_type = t_type_info_enumerated_array; + + LLVMValueRef vals[7] = { + lb_type_info(m, t->EnumeratedArray.elem).value, + lb_type_info(m, t->EnumeratedArray.index).value, + lb_const_int(m, t_int, type_size_of(t->EnumeratedArray.elem)).value, + lb_const_int(m, t_int, t->EnumeratedArray.count).value, + + // Unions + lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.min_value).value, + lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.max_value).value, + + lb_const_bool(m, t_bool, t->EnumeratedArray.is_sparse).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_DynamicArray: { + tag_type = t_type_info_dynamic_array; + + LLVMValueRef vals[2] = { + lb_type_info(m, t->DynamicArray.elem).value, + lb_const_int(m, t_int, type_size_of(t->DynamicArray.elem)).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_Slice: { + tag_type = t_type_info_slice; + + LLVMValueRef vals[2] = { + lb_type_info(m, t->Slice.elem).value, + lb_const_int(m, t_int, type_size_of(t->Slice.elem)).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_Proc: { + tag_type = t_type_info_procedure; + + LLVMValueRef params = LLVMConstNull(lb_type(m, t_type_info_ptr)); + LLVMValueRef results = LLVMConstNull(lb_type(m, t_type_info_ptr)); + if (t->Proc.params != nullptr) { + params = lb_type_info(m, t->Proc.params).value; + } + if (t->Proc.results != nullptr) { + results = lb_type_info(m, t->Proc.results).value; + } + + LLVMValueRef vals[4] = { + params, + results, + lb_const_bool(m, t_bool, t->Proc.variadic).value, + lb_const_int(m, t_u8, t->Proc.calling_convention).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + case Type_Tuple: { + tag_type = t_type_info_parameters; + // TODO(bill) + // lbValue memory_types = lb_type_info_member_types_offset(m, t->Tuple.variables.count); + // lbValue memory_names = lb_type_info_member_names_offset(m, t->Tuple.variables.count); + + + // for_array(i, t->Tuple.variables) { + // // NOTE(bill): offset is not used for tuples + // Entity *f = t->Tuple.variables[i]; + + // lbValue index = lb_const_int(m, t_int, i); + // lbValue type_info = lb_const_ptr_offset(m, memory_types, index); + + // // TODO(bill): Make this constant if possible, 'lb_const_store' does not work + // lb_emit_store(p, type_info, lb_type_info(m, f->type)); + // if (f->token.string.len > 0) { + // lbValue name = lb_const_ptr_offset(m, memory_names, index); + // lb_emit_store(p, name, lb_const_string(m, f->token.string)); + // } + // } + + // lbValue count = lb_const_int(m, t_int, t->Tuple.variables.count); + + // LLVMValueRef types_slice = llvm_const_slice(m, memory_types, count); + // LLVMValueRef names_slice = llvm_const_slice(m, memory_names, count); + + // LLVMValueRef vals[2] = { + // types_slice, + // names_slice, + // }; + + // variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + + case Type_Enum: + tag_type = t_type_info_enum; + + { + GB_ASSERT(t->Enum.base_type != nullptr); + // GB_ASSERT_MSG(type_size_of(t_type_info_enum_value) == 16, "%lld == 16", cast(long long)type_size_of(t_type_info_enum_value)); + + + LLVMValueRef vals[3] = {}; + vals[0] = lb_type_info(m, t->Enum.base_type).value; + if (t->Enum.fields.count > 0) { + auto fields = t->Enum.fields; + lbValue name_array = lb_generate_global_array(m, t_string, fields.count, + str_lit("$enum_names"), cast(i64)entry_index); + lbValue value_array = lb_generate_global_array(m, t_type_info_enum_value, fields.count, + str_lit("$enum_values"), cast(i64)entry_index); + + + LLVMValueRef *name_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); + LLVMValueRef *value_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); + + GB_ASSERT(is_type_integer(t->Enum.base_type)); + + for_array(i, fields) { + name_values[i] = lb_const_string(m, fields[i]->token.string).value; + value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value; + } + + LLVMValueRef name_init = llvm_const_array(lb_type(m, t_string), name_values, cast(unsigned)fields.count); + LLVMValueRef value_init = llvm_const_array(lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count); + LLVMSetInitializer(name_array.value, name_init); + LLVMSetInitializer(value_array.value, value_init); + LLVMSetGlobalConstant(name_array.value, true); + LLVMSetGlobalConstant(value_array.value, true); + + lbValue v_count = lb_const_int(m, t_int, fields.count); + + vals[1] = llvm_const_slice(m, lbValue{name_array.value, alloc_type_pointer(t_string)}, v_count); + vals[2] = llvm_const_slice(m, lbValue{value_array.value, alloc_type_pointer(t_type_info_enum_value)}, v_count); + } else { + vals[1] = LLVMConstNull(lb_type(m, base_type(t_type_info_enum)->Struct.fields[1]->type)); + vals[2] = LLVMConstNull(lb_type(m, base_type(t_type_info_enum)->Struct.fields[2]->type)); + } + + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Type_Union: { + tag_type = t_type_info_union; + + { + LLVMValueRef vals[7] = {}; + + isize variant_count = gb_max(0, t->Union.variants.count); + lbValue memory_types = lb_type_info_member_types_offset(m, variant_count); + + for (isize variant_index = 0; variant_index < variant_count; variant_index++) { + // TODO(bill) + // Type *vt = t->Union.variants[variant_index]; + // lbValue tip = lb_type_info(m, vt); + + // lbValue index = lb_const_int(m, t_int, variant_index); + // lbValue type_info = lb_const_ptr_offset(m, memory_types, index); + // lb_emit_store(p, type_info, lb_type_info(m, vt)); + } + + lbValue count = lb_const_int(m, t_int, variant_count); + vals[0] = llvm_const_slice(m, memory_types, count); + + i64 tag_size = union_tag_size(t); + if (tag_size > 0) { + i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size); + vals[1] = lb_const_int(m, t_uintptr, tag_offset).value; + vals[2] = lb_type_info(m, union_tag_type(t)).value; + } else { + vals[1] = lb_const_int(m, t_uintptr, 0).value; + vals[2] = LLVMConstNull(lb_type(m, t_type_info_ptr)); + } + + if (is_type_comparable(t) && !is_type_simple_compare(t)) { + vals[3] = lb_equal_proc_for_type(m, t).value; + } + + vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value; + vals[5] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_no_nil).value; + vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value; + + for (isize i = 0; i < gb_count_of(vals); i++) { + if (vals[i] == nullptr) { + vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag_type, i))); + } + } + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + + break; + } + + case Type_Struct: { + tag_type = t_type_info_struct; + + LLVMValueRef vals[13] = {}; + + { + lbValue is_packed = lb_const_bool(m, t_bool, t->Struct.is_packed); + lbValue is_raw_union = lb_const_bool(m, t_bool, t->Struct.is_raw_union); + lbValue is_no_copy = lb_const_bool(m, t_bool, t->Struct.is_no_copy); + lbValue is_custom_align = lb_const_bool(m, t_bool, t->Struct.custom_align != 0); + vals[5] = is_packed.value; + vals[6] = is_raw_union.value; + vals[7] = is_no_copy.value; + vals[8] = is_custom_align.value; + if (is_type_comparable(t) && !is_type_simple_compare(t)) { + vals[9] = lb_equal_proc_for_type(m, t).value; + } + + + if (t->Struct.soa_kind != StructSoa_None) { + Type *kind_type = get_struct_field_type(tag_type, 10); + + lbValue soa_kind = lb_const_value(m, kind_type, exact_value_i64(t->Struct.soa_kind)); + lbValue soa_type = lb_type_info(m, t->Struct.soa_elem); + lbValue soa_len = lb_const_int(m, t_int, t->Struct.soa_count); + + vals[10] = soa_kind.value; + vals[11] = soa_type.value; + vals[12] = soa_len.value; + } + } + + isize count = t->Struct.fields.count; + if (count > 0) { + lbValue memory_types = lb_type_info_member_types_offset (m, count); + lbValue memory_names = lb_type_info_member_names_offset (m, count); + lbValue memory_offsets = lb_type_info_member_offsets_offset(m, count); + lbValue memory_usings = lb_type_info_member_usings_offset (m, count); + lbValue memory_tags = lb_type_info_member_tags_offset (m, count); + + type_set_offsets(t); // NOTE(bill): Just incase the offsets have not been set yet + for (isize source_index = 0; source_index < count; source_index++) { + Entity *f = t->Struct.fields[source_index]; + lbValue tip = lb_type_info(m, f->type); + i64 foffset = 0; + if (!t->Struct.is_raw_union) { + GB_ASSERT(t->Struct.offsets != nullptr); + GB_ASSERT(0 <= f->Variable.field_index && f->Variable.field_index < count); + foffset = t->Struct.offsets[source_index]; + } + GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); + + lbValue index = lb_const_int(m, t_int, source_index); + lbValue type_info = lb_const_ptr_offset(m, memory_types, index); + lbValue offset = lb_const_ptr_offset(m, memory_offsets, index); + lbValue is_using = lb_const_ptr_offset(m, memory_usings, index); + + // TODO(bill) + // lb_emit_store(p, type_info, lb_type_info(m, f->type)); + // if (f->token.string.len > 0) { + // lbValue name = lb_emit_ptr_offset(p, memory_names, index); + // lb_emit_store(p, name, lb_const_string(m, f->token.string)); + // } + // lb_emit_store(p, offset, lb_const_int(m, t_uintptr, foffset)); + // lb_emit_store(p, is_using, lb_const_bool(m, t_bool, (f->flags&EntityFlag_Using) != 0)); + + // if (t->Struct.tags != nullptr) { + // String tag_string = t->Struct.tags[source_index]; + // if (tag_string.len > 0) { + // lbValue tag_ptr = lb_emit_ptr_offset(p, memory_tags, index); + // lb_emit_store(p, tag_ptr, lb_const_string(m, tag_string)); + // } + // } + + } + + lbValue cv = lb_const_int(m, t_int, count); + vals[0] = llvm_const_slice(m, memory_types, cv); + vals[1] = llvm_const_slice(m, memory_names, cv); + vals[2] = llvm_const_slice(m, memory_offsets, cv); + vals[3] = llvm_const_slice(m, memory_usings, cv); + vals[4] = llvm_const_slice(m, memory_tags, cv); + } + for (isize i = 0; i < gb_count_of(vals); i++) { + if (vals[i] == nullptr) { + vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag_type, i))); + } + } + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + + case Type_Map: { + tag_type = t_type_info_map; + init_map_internal_types(t); + + LLVMValueRef vals[3] = { + lb_type_info(m, t->Map.key).value, + lb_type_info(m, t->Map.value).value, + lb_gen_map_info_ptr(m, t).value + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } + + case Type_BitSet: + { + tag_type = t_type_info_bit_set; + + GB_ASSERT(is_type_typed(t->BitSet.elem)); + + + LLVMValueRef vals[4] = { + lb_type_info(m, t->BitSet.elem).value, + LLVMConstNull(lb_type(m, t_type_info_ptr)), + lb_const_int(m, t_i64, t->BitSet.lower).value, + lb_const_int(m, t_i64, t->BitSet.upper).value, + }; + if (t->BitSet.underlying != nullptr) { + vals[1] = lb_type_info(m, t->BitSet.underlying).value; + } + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Type_SimdVector: + { + tag_type = t_type_info_simd_vector; + + LLVMValueRef vals[3] = {}; + + vals[0] = lb_type_info(m, t->SimdVector.elem).value; + vals[1] = lb_const_int(m, t_int, type_size_of(t->SimdVector.elem)).value; + vals[2] = lb_const_int(m, t_int, t->SimdVector.count).value; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Type_RelativePointer: + { + tag_type = t_type_info_relative_pointer; + LLVMValueRef vals[2] = { + lb_type_info(m, t->RelativePointer.pointer_type).value, + lb_type_info(m, t->RelativePointer.base_integer).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Type_RelativeMultiPointer: + { + tag_type = t_type_info_relative_multi_pointer; + LLVMValueRef vals[2] = { + lb_type_info(m, t->RelativeMultiPointer.pointer_type).value, + lb_type_info(m, t->RelativeMultiPointer.base_integer).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Type_Matrix: + { + tag_type = t_type_info_matrix; + i64 ez = type_size_of(t->Matrix.elem); + + LLVMValueRef vals[5] = { + lb_type_info(m, t->Matrix.elem).value, + lb_const_int(m, t_int, ez).value, + lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).value, + lb_const_int(m, t_int, t->Matrix.row_count).value, + lb_const_int(m, t_int, t->Matrix.column_count).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + } + + + + i64 tag_index = 0; + if (tag_type != nullptr) { + tag_index = union_variant_index(ut, tag_type); + } + + LLVMValueRef full_variant_values[3] = {}; + + if (full_variant_elem_count == 2) { + if (variant_value == nullptr) { + full_variant_values[0] = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 0)); + full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 1), tag_index, false); + } else { + full_variant_values[0] = variant_value; + full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 1), tag_index, false); + } + } else { + if (variant_value == nullptr) { + variant_value = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 0)); + } else { + GB_ASSERT_MSG(LLVMStructGetTypeAtIndex(full_variant_type, 0) == LLVMTypeOf(variant_value), + "\n%s -> %s\n%s vs %s\n", + type_to_string(t), LLVMPrintValueToString(variant_value), + LLVMPrintTypeToString(LLVMStructGetTypeAtIndex(full_variant_type, 0)), LLVMPrintTypeToString(LLVMTypeOf(variant_value)) + ); + } + + full_variant_values[0] = variant_value; + full_variant_values[1] = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 1)); + full_variant_values[2] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 2), tag_index, false); + } + LLVMValueRef full_variant_value = LLVMConstNamedStruct(full_variant_type, full_variant_values, full_variant_elem_count); + + small_const_values[variant_index] = full_variant_value; + + giant_const_values[entry_index] = LLVMConstNamedStruct(stype, small_const_values, variant_index+1); + } + + LLVMValueRef giant_const = LLVMConstNamedStruct(giant_struct_type, giant_const_values, cast(unsigned)global_type_info_data_entity_count); + LLVMSetInitializer(giant_struct, giant_const); +} + + +gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data + if (build_context.no_rtti) { + return; + } + + lbModule *m = p->module; + CheckerInfo *info = m->info; + + i64 global_type_info_data_entity_count = 0; + { + // NOTE(bill): Set the type_table slice with the global backing array + lbValue global_type_table = lb_find_runtime_value(m, str_lit("type_table")); + Type *type = base_type(lb_global_type_info_data_entity->type); + GB_ASSERT(type->kind == Type_Array); + global_type_info_data_entity_count = type->Array.count; + + LLVMValueRef data = lb_global_type_info_data_ptr(m).value; + data = LLVMConstPointerCast(data, lb_type(m, alloc_type_pointer(type->Array.elem))); + LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), type->Array.count, true); + Type *t = type_deref(global_type_table.type); + GB_ASSERT(is_type_slice(t)); + LLVMValueRef slice = llvm_const_slice_internal(m, data, len); + + LLVMSetInitializer(global_type_table.value, slice); + } + + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_setup_type_info_data_giant_packed_struct(m, global_type_info_data_entity_count); + return; + } // Useful types Entity *type_info_flags_entity = find_core_entity(info->checker, str_lit("Type_Info_Flags")); @@ -543,8 +1397,8 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup case Type_Tuple: { tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_parameters_ptr); - lbValue memory_types = lb_type_info_member_types_offset(p, t->Tuple.variables.count); - lbValue memory_names = lb_type_info_member_names_offset(p, t->Tuple.variables.count); + lbValue memory_types = lb_type_info_member_types_offset(m, t->Tuple.variables.count); + lbValue memory_names = lb_type_info_member_names_offset(m, t->Tuple.variables.count); for_array(i, t->Tuple.variables) { @@ -639,7 +1493,7 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup LLVMValueRef vals[7] = {}; isize variant_count = gb_max(0, t->Union.variants.count); - lbValue memory_types = lb_type_info_member_types_offset(p, variant_count); + lbValue memory_types = lb_type_info_member_types_offset(m, variant_count); // NOTE(bill): Zeroth is nil so ignore it for (isize variant_index = 0; variant_index < variant_count; variant_index++) { @@ -723,11 +1577,11 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup isize count = t->Struct.fields.count; if (count > 0) { - lbValue memory_types = lb_type_info_member_types_offset (p, count); - lbValue memory_names = lb_type_info_member_names_offset (p, count); - lbValue memory_offsets = lb_type_info_member_offsets_offset(p, count); - lbValue memory_usings = lb_type_info_member_usings_offset (p, count); - lbValue memory_tags = lb_type_info_member_tags_offset (p, count); + lbValue memory_types = lb_type_info_member_types_offset (m, count); + lbValue memory_names = lb_type_info_member_names_offset (m, count); + lbValue memory_offsets = lb_type_info_member_offsets_offset(m, count); + lbValue memory_usings = lb_type_info_member_usings_offset (m, count); + lbValue memory_tags = lb_type_info_member_tags_offset (m, count); type_set_offsets(t); // NOTE(bill): Just incase the offsets have not been set yet for (isize source_index = 0; source_index < count; source_index++) { diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 8dd6b14b6..d8dbfd736 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -980,12 +980,12 @@ gb_internal LLVMTypeRef lb_type_padding_filler(lbModule *m, i64 padding, i64 pad GB_ASSERT_MSG(elem != nullptr, "Invalid lb_type_padding_filler padding and padding_align: %lld", padding_align); if (len != 1) { - return LLVMArrayType(elem, cast(unsigned)len); + return llvm_array_type(elem, len); } else { return elem; } } else { - return LLVMArrayType(lb_type(m, t_u8), cast(unsigned)padding); + return llvm_array_type(lb_type(m, t_u8), padding); } } @@ -1437,6 +1437,17 @@ gb_internal lbValue lb_emit_ptr_offset(lbProcedure *p, lbValue ptr, lbValue inde return res; } +gb_internal lbValue lb_const_ptr_offset(lbModule *m, lbValue ptr, lbValue index) { + LLVMValueRef indices[1] = {index.value}; + lbValue res = {}; + res.type = ptr.type; + LLVMTypeRef type = lb_type(m, type_deref(res.type, true)); + + GB_ASSERT(lb_is_const(ptr) && lb_is_const(index)); + res.value = LLVMConstGEP2(type, ptr.value, indices, 1); + return res; +} + gb_internal lbValue lb_emit_matrix_epi(lbProcedure *p, lbValue s, isize row, isize column) { Type *t = s.type; GB_ASSERT(is_type_pointer(t)); -- cgit v1.2.3 From 61f39ae0a09429610d78961fa1e86cac071dd08c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Sep 2023 15:32:32 +0100 Subject: Use a giant packed struct working for type info table --- core/runtime/core.odin | 1 + src/llvm_backend.cpp | 25 +++++++- src/llvm_backend_type.cpp | 149 ++++++++++++++++++++++++++-------------------- 3 files changed, 109 insertions(+), 66 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 44717f8d0..8abe9938d 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -254,6 +254,7 @@ Typeid_Kind :: enum u8 { Relative_Pointer, Relative_Multi_Pointer, Matrix, + Soa_Pointer, } #assert(len(Typeid_Kind) < 32) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index db5af0647..8f838ea31 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1025,8 +1025,10 @@ gb_internal lbProcedure *lb_create_startup_type_info(lbModule *m) { LLVMSetLinkage(p->value, LLVMInternalLinkage); lb_add_attribute_to_proc(m, p->value, "nounwind"); - lb_add_attribute_to_proc(m, p->value, "optnone"); - lb_add_attribute_to_proc(m, p->value, "noinline"); + if (!LB_USE_GIANT_PACKED_STRUCT) { + lb_add_attribute_to_proc(m, p->value, "optnone"); + lb_add_attribute_to_proc(m, p->value, "noinline"); + } lb_begin_procedure_body(p); @@ -2243,6 +2245,10 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lb_global_type_info_data_entity = alloc_entity_variable(nullptr, make_token_ident(LB_TYPE_INFO_DATA_NAME), t, EntityState_Resolved); lb_add_entity(m, lb_global_type_info_data_entity, value); + + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } } { // Type info member buffer // NOTE(bill): Removes need for heap allocation by making it global memory @@ -2274,6 +2280,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)}); } @@ -2283,6 +2292,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)}); } { @@ -2291,6 +2303,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)}); } @@ -2300,6 +2315,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)}); } @@ -2309,6 +2327,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); + } lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)}); } } diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 3654e8005..954e80881 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -139,38 +139,43 @@ gb_internal lbValue lb_const_array_epi(lbModule *m, lbValue value, isize index) } -gb_internal lbValue lb_type_info_member_types_offset(lbModule *m, isize count) { +gb_internal lbValue lb_type_info_member_types_offset(lbModule *m, isize count, isize *offset_=nullptr) { GB_ASSERT(m == &m->gen->default_module); + if (offset_) *offset_ = lb_global_type_info_member_types_index; lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_types.addr, lb_global_type_info_member_types_index); lb_global_type_info_member_types_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_names_offset(lbModule *m, isize count) { +gb_internal lbValue lb_type_info_member_names_offset(lbModule *m, isize count, isize *offset_=nullptr) { GB_ASSERT(m == &m->gen->default_module); + if (offset_) *offset_ = lb_global_type_info_member_names_index; lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_names.addr, lb_global_type_info_member_names_index); lb_global_type_info_member_names_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_offsets_offset(lbModule *m, isize count) { +gb_internal lbValue lb_type_info_member_offsets_offset(lbModule *m, isize count, isize *offset_=nullptr) { GB_ASSERT(m == &m->gen->default_module); + if (offset_) *offset_ = lb_global_type_info_member_offsets_index; lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_offsets.addr, lb_global_type_info_member_offsets_index); lb_global_type_info_member_offsets_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_usings_offset(lbModule *m, isize count) { +gb_internal lbValue lb_type_info_member_usings_offset(lbModule *m, isize count, isize *offset_=nullptr) { GB_ASSERT(m == &m->gen->default_module); + if (offset_) *offset_ = lb_global_type_info_member_usings_index; lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_usings.addr, lb_global_type_info_member_usings_index); lb_global_type_info_member_usings_index += cast(i32)count; return offset; } -gb_internal lbValue lb_type_info_member_tags_offset(lbModule *m, isize count) { +gb_internal lbValue lb_type_info_member_tags_offset(lbModule *m, isize count, isize *offset_=nullptr) { GB_ASSERT(m == &m->gen->default_module); + if (offset_) *offset_ = lb_global_type_info_member_tags_index; lbValue offset = lb_const_array_epi(m, lb_global_type_info_member_tags.addr, lb_global_type_info_member_tags_index); lb_global_type_info_member_tags_index += cast(i32)count; return offset; } -enum {LB_USE_GIANT_PACKED_STRUCT = false}; +enum {LB_USE_GIANT_PACKED_STRUCT = true}; gb_internal LLVMTypeRef lb_setup_type_info_data_internal_type(lbModule *m, isize max_type_info_count) { if (!LB_USE_GIANT_PACKED_STRUCT) { @@ -292,10 +297,30 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl giant_const_values[0] = LLVMConstNull(LLVMStructGetTypeAtIndex(giant_struct_type, 0)); - LLVMValueRef *small_const_values = gb_alloc_array(heap_allocator(), LLVMValueRef, 6); defer (gb_free(heap_allocator(), small_const_values)); + + #define type_info_allocate_values(name) \ + LLVMValueRef *name##_values = gb_alloc_array(heap_allocator(), LLVMValueRef, type_deref(name.addr.type)->Array.count); \ + defer (gb_free(heap_allocator(), name##_values)); \ + defer ({ \ + Type *at = type_deref(name.addr.type); \ + LLVMTypeRef elem = lb_type(m, at->Array.elem); \ + for (i64 i = 0; i < at->Array.count; i++) { \ + if ((name##_values)[i] == nullptr) { \ + (name##_values)[i] = LLVMConstNull(elem); \ + } \ + } \ + LLVMSetInitializer(name.addr.value, LLVMConstArray2(elem, name##_values, at->Array.count)); \ + }) + + type_info_allocate_values(lb_global_type_info_member_types); + type_info_allocate_values(lb_global_type_info_member_names); + type_info_allocate_values(lb_global_type_info_member_offsets); + type_info_allocate_values(lb_global_type_info_member_usings); + type_info_allocate_values(lb_global_type_info_member_tags); + for_array(type_info_type_index, info->type_info_types) { Type *t = info->type_info_types[type_info_type_index]; if (t == nullptr || t == t_invalid) { @@ -627,37 +652,35 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl } case Type_Tuple: { tag_type = t_type_info_parameters; - // TODO(bill) - // lbValue memory_types = lb_type_info_member_types_offset(m, t->Tuple.variables.count); - // lbValue memory_names = lb_type_info_member_names_offset(m, t->Tuple.variables.count); + i64 type_offset = 0; + i64 name_offset = 0; + lbValue memory_types = lb_type_info_member_types_offset(m, t->Tuple.variables.count, &type_offset); + lbValue memory_names = lb_type_info_member_names_offset(m, t->Tuple.variables.count, &name_offset); + for_array(i, t->Tuple.variables) { + // NOTE(bill): offset is not used for tuples + Entity *f = t->Tuple.variables[i]; - // for_array(i, t->Tuple.variables) { - // // NOTE(bill): offset is not used for tuples - // Entity *f = t->Tuple.variables[i]; - - // lbValue index = lb_const_int(m, t_int, i); - // lbValue type_info = lb_const_ptr_offset(m, memory_types, index); + lbValue index = lb_const_int(m, t_int, i); + lbValue type_info = lb_const_ptr_offset(m, memory_types, index); - // // TODO(bill): Make this constant if possible, 'lb_const_store' does not work - // lb_emit_store(p, type_info, lb_type_info(m, f->type)); - // if (f->token.string.len > 0) { - // lbValue name = lb_const_ptr_offset(m, memory_names, index); - // lb_emit_store(p, name, lb_const_string(m, f->token.string)); - // } - // } + lb_global_type_info_member_types_values[type_offset+i] = lb_type_info(m, f->type).value; + if (f->token.string.len > 0) { + lb_global_type_info_member_names_values[name_offset+i] = lb_const_string(m, f->token.string).value; + } + } - // lbValue count = lb_const_int(m, t_int, t->Tuple.variables.count); + lbValue count = lb_const_int(m, t_int, t->Tuple.variables.count); - // LLVMValueRef types_slice = llvm_const_slice(m, memory_types, count); - // LLVMValueRef names_slice = llvm_const_slice(m, memory_names, count); + LLVMValueRef types_slice = llvm_const_slice(m, memory_types, count); + LLVMValueRef names_slice = llvm_const_slice(m, memory_names, count); - // LLVMValueRef vals[2] = { - // types_slice, - // names_slice, - // }; + LLVMValueRef vals[2] = { + types_slice, + names_slice, + }; - // variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); break; } @@ -717,16 +740,14 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl LLVMValueRef vals[7] = {}; isize variant_count = gb_max(0, t->Union.variants.count); - lbValue memory_types = lb_type_info_member_types_offset(m, variant_count); + i64 variant_offset = 0; + lbValue memory_types = lb_type_info_member_types_offset(m, variant_count, &variant_offset); for (isize variant_index = 0; variant_index < variant_count; variant_index++) { - // TODO(bill) - // Type *vt = t->Union.variants[variant_index]; - // lbValue tip = lb_type_info(m, vt); + Type *vt = t->Union.variants[variant_index]; + lbValue tip = lb_type_info(m, vt); - // lbValue index = lb_const_int(m, t_int, variant_index); - // lbValue type_info = lb_const_ptr_offset(m, memory_types, index); - // lb_emit_store(p, type_info, lb_type_info(m, vt)); + lb_global_type_info_member_types_values[variant_offset+variant_index] = lb_type_info(m, vt).value; } lbValue count = lb_const_int(m, t_int, variant_count); @@ -796,11 +817,17 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl isize count = t->Struct.fields.count; if (count > 0) { - lbValue memory_types = lb_type_info_member_types_offset (m, count); - lbValue memory_names = lb_type_info_member_names_offset (m, count); - lbValue memory_offsets = lb_type_info_member_offsets_offset(m, count); - lbValue memory_usings = lb_type_info_member_usings_offset (m, count); - lbValue memory_tags = lb_type_info_member_tags_offset (m, count); + i64 types_offset = 0; + i64 names_offset = 0; + i64 offsets_offset = 0; + i64 usings_offset = 0; + i64 tags_offset = 0; + + lbValue memory_types = lb_type_info_member_types_offset (m, count, &types_offset); + lbValue memory_names = lb_type_info_member_names_offset (m, count, &names_offset); + lbValue memory_offsets = lb_type_info_member_offsets_offset(m, count, &offsets_offset); + lbValue memory_usings = lb_type_info_member_usings_offset (m, count, &usings_offset); + lbValue memory_tags = lb_type_info_member_tags_offset (m, count, &tags_offset); type_set_offsets(t); // NOTE(bill): Just incase the offsets have not been set yet for (isize source_index = 0; source_index < count; source_index++) { @@ -814,27 +841,21 @@ gb_internal void lb_setup_type_info_data_giant_packed_struct(lbModule *m, i64 gl } GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); - lbValue index = lb_const_int(m, t_int, source_index); - lbValue type_info = lb_const_ptr_offset(m, memory_types, index); - lbValue offset = lb_const_ptr_offset(m, memory_offsets, index); - lbValue is_using = lb_const_ptr_offset(m, memory_usings, index); - - // TODO(bill) - // lb_emit_store(p, type_info, lb_type_info(m, f->type)); - // if (f->token.string.len > 0) { - // lbValue name = lb_emit_ptr_offset(p, memory_names, index); - // lb_emit_store(p, name, lb_const_string(m, f->token.string)); - // } - // lb_emit_store(p, offset, lb_const_int(m, t_uintptr, foffset)); - // lb_emit_store(p, is_using, lb_const_bool(m, t_bool, (f->flags&EntityFlag_Using) != 0)); - - // if (t->Struct.tags != nullptr) { - // String tag_string = t->Struct.tags[source_index]; - // if (tag_string.len > 0) { - // lbValue tag_ptr = lb_emit_ptr_offset(p, memory_tags, index); - // lb_emit_store(p, tag_ptr, lb_const_string(m, tag_string)); - // } - // } + + lb_global_type_info_member_types_values[types_offset+source_index] = lb_type_info(m, f->type).value; + lb_global_type_info_member_offsets_values[offsets_offset+source_index] = lb_const_int(m, t_uintptr, foffset).value; + lb_global_type_info_member_usings_values[usings_offset+source_index] = lb_const_bool(m, t_bool, (f->flags&EntityFlag_Using) != 0).value; + + if (f->token.string.len > 0) { + lb_global_type_info_member_names_values[names_offset+source_index] = lb_const_string(m, f->token.string).value; + } + + if (t->Struct.tags != nullptr) { + String tag_string = t->Struct.tags[source_index]; + if (tag_string.len > 0) { + lb_global_type_info_member_tags_values[tags_offset+source_index] = lb_const_string(m, tag_string).value; + } + } } -- cgit v1.2.3 From c529b1b73ae33d2a1a69c7002ac02c34b8801866 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 27 Sep 2023 11:44:29 +0100 Subject: Generate the global type info member values even if the count is `0` --- src/llvm_backend.cpp | 102 +++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 52 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8f838ea31..ceb4dc1de 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2273,65 +2273,63 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - if (count > 0) { - { - char const *name = LB_TYPE_INFO_TYPES_NAME; - Type *t = alloc_type_array(t_type_info_ptr, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)}); - + { + char const *name = LB_TYPE_INFO_TYPES_NAME; + Type *t = alloc_type_array(t_type_info_ptr, count); + LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); + LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); } - { - char const *name = LB_TYPE_INFO_NAMES_NAME; - Type *t = alloc_type_array(t_string, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)}); + lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)}); + + } + { + char const *name = LB_TYPE_INFO_NAMES_NAME; + Type *t = alloc_type_array(t_string, count); + LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); + LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); } - { - char const *name = LB_TYPE_INFO_OFFSETS_NAME; - Type *t = alloc_type_array(t_uintptr, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)}); + lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)}); + } + { + char const *name = LB_TYPE_INFO_OFFSETS_NAME; + Type *t = alloc_type_array(t_uintptr, count); + LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); + LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); } + lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)}); + } - { - char const *name = LB_TYPE_INFO_USINGS_NAME; - Type *t = alloc_type_array(t_bool, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)}); + { + char const *name = LB_TYPE_INFO_USINGS_NAME; + Type *t = alloc_type_array(t_bool, count); + LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); + LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); } + lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)}); + } - { - char const *name = LB_TYPE_INFO_TAGS_NAME; - Type *t = alloc_type_array(t_string, count); - LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); - LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); - LLVMSetLinkage(g, LLVMInternalLinkage); - if (LB_USE_GIANT_PACKED_STRUCT) { - lb_make_global_private_const(g); - } - lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)}); + { + char const *name = LB_TYPE_INFO_TAGS_NAME; + Type *t = alloc_type_array(t_string, count); + LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); + LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); + LLVMSetLinkage(g, LLVMInternalLinkage); + if (LB_USE_GIANT_PACKED_STRUCT) { + lb_make_global_private_const(g); } + lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)}); } } } -- cgit v1.2.3