Merge pull request #3234 from odin-lang/rtti-table-layout

Change `runtime.type_table` layout to allow RTTI to be constantly initialized
This commit is contained in:
gingerBill
2024-02-27 16:25:47 +00:00
committed by GitHub
7 changed files with 178 additions and 969 deletions
+2 -2
View File
@@ -280,7 +280,7 @@ Typeid_Kind :: enum u8 {
// NOTE(bill): only the ones that are needed (not all types) // NOTE(bill): only the ones that are needed (not all types)
// This will be set by the compiler // This will be set by the compiler
type_table: []Type_Info type_table: []^Type_Info
args__: []cstring args__: []cstring
@@ -609,7 +609,7 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
if n < 0 || n >= len(type_table) { if n < 0 || n >= len(type_table) {
n = 0 n = 0
} }
return &type_table[n] return type_table[n]
} }
when !ODIN_NO_RTTI { when !ODIN_NO_RTTI {
+10 -54
View File
@@ -1053,41 +1053,6 @@ struct lbGlobalVariable {
bool is_initialized; bool is_initialized;
}; };
gb_internal lbProcedure *lb_create_startup_type_info(lbModule *m) {
if (build_context.no_rtti) {
return nullptr;
}
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_TYPE_INFO_PROC_NAME), proc_type);
p->is_startup = true;
LLVMSetLinkage(p->value, LLVMInternalLinkage);
lb_add_attribute_to_proc(m, p->value, "nounwind");
// lb_add_attribute_to_proc(p->module, p->value, "mustprogress");
// lb_add_attribute_to_proc(p->module, p->value, "nofree");
// lb_add_attribute_to_proc(p->module, p->value, "norecurse");
// lb_add_attribute_to_proc(p->module, p->value, "nosync");
// lb_add_attribute_to_proc(p->module, p->value, "willreturn");
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);
lb_setup_type_info_data(p);
lb_end_procedure_body(p);
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
return p;
}
gb_internal lbProcedure *lb_create_objc_names(lbModule *main_module) { gb_internal lbProcedure *lb_create_objc_names(lbModule *main_module) {
if (build_context.metrics.os != TargetOs_darwin) { if (build_context.metrics.os != TargetOs_darwin) {
@@ -1129,7 +1094,7 @@ gb_internal void lb_finalize_objc_names(lbProcedure *p) {
lb_end_procedure_body(p); lb_end_procedure_body(p);
} }
gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin);
lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type); lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type);
@@ -1139,9 +1104,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
lb_begin_procedure_body(p); lb_begin_procedure_body(p);
if (startup_type_info) { lb_setup_type_info_data(main_module);
LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, startup_type_info->type), startup_type_info->value, nullptr, 0, "");
}
if (objc_names) { if (objc_names) {
LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, ""); LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, "");
@@ -1201,7 +1164,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
lbValue data = lb_emit_struct_ep(p, var.var, 0); lbValue data = lb_emit_struct_ep(p, var.var, 0);
lbValue ti = lb_emit_struct_ep(p, var.var, 1); lbValue ti = lb_emit_struct_ep(p, var.var, 1);
lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr)); lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
lb_emit_store(p, ti, lb_type_info(main_module, var_type)); lb_emit_store(p, ti, lb_type_info(p, var_type));
} else { } else {
LLVMTypeRef vt = llvm_addr_type(p->module, var.var); LLVMTypeRef vt = llvm_addr_type(p->module, var.var);
lbValue src0 = lb_emit_conv(p, var.init, t); lbValue src0 = lb_emit_conv(p, var.init, t);
@@ -1426,7 +1389,6 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) {
} }
if (m == &m->gen->default_module) { if (m == &m->gen->default_module) {
lb_llvm_function_pass_per_function_internal(m, m->gen->startup_type_info);
lb_llvm_function_pass_per_function_internal(m, m->gen->startup_runtime); lb_llvm_function_pass_per_function_internal(m, m->gen->startup_runtime);
lb_llvm_function_pass_per_function_internal(m, m->gen->cleanup_runtime); lb_llvm_function_pass_per_function_internal(m, m->gen->cleanup_runtime);
lb_llvm_function_pass_per_function_internal(m, m->gen->objc_names); lb_llvm_function_pass_per_function_internal(m, m->gen->objc_names);
@@ -2691,17 +2653,19 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
{ // Add type info data { // Add type info data
isize max_type_info_count = info->minimum_dependency_type_info_set.count+1; isize max_type_info_count = info->minimum_dependency_type_info_set.count+1;
Type *t = alloc_type_array(t_type_info, max_type_info_count); Type *t = alloc_type_array(t_type_info_ptr, max_type_info_count);
// IMPORTANT NOTE(bill): As LLVM does not have a union type, an array of unions cannot be initialized // 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 // 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. // a giant packed struct of "corrected" data types.
LLVMTypeRef internal_llvm_type = lb_setup_type_info_data_internal_type(m, max_type_info_count); LLVMTypeRef internal_llvm_type = lb_type(m, t);
LLVMValueRef g = LLVMAddGlobal(m->mod, internal_llvm_type, LB_TYPE_INFO_DATA_NAME); LLVMValueRef g = LLVMAddGlobal(m->mod, internal_llvm_type, LB_TYPE_INFO_DATA_NAME);
LLVMSetInitializer(g, LLVMConstNull(internal_llvm_type)); LLVMSetInitializer(g, LLVMConstNull(internal_llvm_type));
LLVMSetLinkage(g, USE_SEPARATE_MODULES ? LLVMExternalLinkage : LLVMInternalLinkage); LLVMSetLinkage(g, USE_SEPARATE_MODULES ? LLVMExternalLinkage : LLVMInternalLinkage);
LLVMSetUnnamedAddress(g, LLVMGlobalUnnamedAddr);
LLVMSetGlobalConstant(g, /*true*/false);
lbValue value = {}; lbValue value = {};
value.value = g; value.value = g;
@@ -2710,11 +2674,6 @@ 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_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); lb_add_entity(m, lb_global_type_info_data_entity, value);
if (LB_USE_GIANT_PACKED_STRUCT) {
LLVMSetLinkage(g, LLVMPrivateLinkage);
LLVMSetUnnamedAddress(g, LLVMGlobalUnnamedAddr);
LLVMSetGlobalConstant(g, /*true*/false);
}
} }
{ // Type info member buffer { // Type info member buffer
// NOTE(bill): Removes need for heap allocation by making it global memory // NOTE(bill): Removes need for heap allocation by making it global memory
@@ -2750,9 +2709,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name); LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
LLVMSetLinkage(g, LLVMInternalLinkage); LLVMSetLinkage(g, LLVMInternalLinkage);
if (LB_USE_GIANT_PACKED_STRUCT) { lb_make_global_private_const(g);
lb_make_global_private_const(g);
}
return lb_addr({g, alloc_type_pointer(t)}); return lb_addr({g, alloc_type_pointer(t)});
}; };
@@ -2921,12 +2878,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
} }
} }
TIME_SECTION("LLVM Runtime Type Information Creation"); TIME_SECTION("LLVM Runtime Objective-C Names Creation");
gen->startup_type_info = lb_create_startup_type_info(default_module);
gen->objc_names = lb_create_objc_names(default_module); gen->objc_names = lb_create_objc_names(default_module);
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables & @(init))"); TIME_SECTION("LLVM Runtime Startup Creation (Global Variables & @(init))");
gen->startup_runtime = lb_create_startup_runtime(default_module, gen->startup_type_info, gen->objc_names, global_variables); gen->startup_runtime = lb_create_startup_runtime(default_module, gen->objc_names, global_variables);
TIME_SECTION("LLVM Runtime Cleanup Creation & @(fini)"); TIME_SECTION("LLVM Runtime Cleanup Creation & @(fini)");
gen->cleanup_runtime = lb_create_cleanup_runtime(default_module); gen->cleanup_runtime = lb_create_cleanup_runtime(default_module);
+1 -3
View File
@@ -225,7 +225,6 @@ struct lbGenerator : LinkerData {
std::atomic<u32> global_array_index; std::atomic<u32> global_array_index;
std::atomic<u32> global_generated_index; std::atomic<u32> global_generated_index;
lbProcedure *startup_type_info;
lbProcedure *startup_runtime; lbProcedure *startup_runtime;
lbProcedure *cleanup_runtime; lbProcedure *cleanup_runtime;
lbProcedure *objc_names; lbProcedure *objc_names;
@@ -486,7 +485,7 @@ gb_internal lbValue lb_emit_mul_add(lbProcedure *p, lbValue a, lbValue b, lbValu
gb_internal void lb_fill_slice(lbProcedure *p, lbAddr const &slice, lbValue base_elem, lbValue len); gb_internal void lb_fill_slice(lbProcedure *p, lbAddr const &slice, lbValue base_elem, lbValue len);
gb_internal lbValue lb_type_info(lbModule *m, Type *type); gb_internal lbValue lb_type_info(lbProcedure *p, Type *type);
gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str); gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str);
gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent = nullptr); gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent = nullptr);
@@ -587,7 +586,6 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
#define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime" #define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime"
#define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data" #define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
#define LB_TYPE_INFO_TYPES_NAME "__$type_info_types_data" #define LB_TYPE_INFO_TYPES_NAME "__$type_info_types_data"
#define LB_TYPE_INFO_NAMES_NAME "__$type_info_names_data" #define LB_TYPE_INFO_NAMES_NAME "__$type_info_names_data"
+1 -1
View File
@@ -1755,7 +1755,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
TypeAndValue tav = type_and_value_of_expr(arg); TypeAndValue tav = type_and_value_of_expr(arg);
if (tav.mode == Addressing_Type) { if (tav.mode == Addressing_Type) {
Type *t = default_type(type_of_expr(arg)); Type *t = default_type(type_of_expr(arg));
return lb_type_info(p->module, t); return lb_type_info(p, t);
} }
GB_ASSERT(is_type_typeid(tav.type)); GB_ASSERT(is_type_typeid(tav.type));
+1 -1
View File
@@ -748,7 +748,7 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_
i64 enum_count = t->Enum.fields.count; i64 enum_count = t->Enum.fields.count;
lbValue max_count = lb_const_int(m, t_int, enum_count); lbValue max_count = lb_const_int(m, t_int, enum_count);
lbValue ti = lb_type_info(m, t); lbValue ti = lb_type_info(p, t);
lbValue variant = lb_emit_struct_ep(p, ti, 4); lbValue variant = lb_emit_struct_ep(p, ti, 4);
lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr);
lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2));
+160 -908
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -365,6 +365,9 @@ enum Typeid_Kind : u8 {
Typeid_Matrix, Typeid_Matrix,
Typeid_SoaPointer, Typeid_SoaPointer,
Typeid_Bit_Field, Typeid_Bit_Field,
Typeid__COUNT
}; };
// IMPORTANT NOTE(bill): This must match the same as the in core.odin // IMPORTANT NOTE(bill): This must match the same as the in core.odin