From 28c97a94670b2b1cad801e9e9d3b5d465f9435d8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jul 2023 17:12:23 +0100 Subject: [PATCH] Begin work on setting up type information table --- src/tilde.cpp | 28 +++- src/tilde.hpp | 2 + src/tilde_const.cpp | 72 +++++++++- src/tilde_proc.cpp | 2 + src/tilde_type_info.cpp | 281 +++++++++++++++++++++++++++++++++++++--- 5 files changed, 366 insertions(+), 19 deletions(-) diff --git a/src/tilde.cpp b/src/tilde.cpp index 7574ea6b9..82d30215e 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -199,6 +199,13 @@ gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) { } } +gb_internal void cg_add_symbol(cgModule *m, Entity *e, TB_Symbol *symbol) { + if (e) { + rw_mutex_lock(&m->values_mutex); + map_set(&m->symbols, e, symbol); + rw_mutex_unlock(&m->values_mutex); + } +} gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) { if (e) { @@ -221,12 +228,27 @@ gb_internal void cg_add_procedure_value(cgModule *m, cgProcedure *p) { rw_mutex_lock(&m->values_mutex); if (p->entity != nullptr) { map_set(&m->procedure_values, p->func, p->entity); + if (p->symbol != nullptr) { + map_set(&m->symbols, p->entity, p->symbol); + } } string_map_set(&m->procedures, p->name, p); rw_mutex_unlock(&m->values_mutex); } +gb_internal TB_Symbol *cg_find_symbol_from_entity(cgModule *m, Entity *e) { + if (e) { + rw_mutex_lock(&m->values_mutex); + defer (rw_mutex_unlock(&m->values_mutex)); + TB_Symbol **found = map_get(&m->symbols, e); + if (found) { + return *found; + } + } + return nullptr; +} + gb_internal isize cg_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) { auto *set = &info->minimum_dependency_type_info_set; isize index = type_info_index(info, type, err_on_not_found); @@ -449,11 +471,13 @@ gb_internal bool cg_global_variables_create(cgModule *m) { var.is_initialized = true; } } else { - tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), 0); + i64 max_regions = cg_global_const_calculate_region_count_from_basic_type(e->type); + tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), max_regions); } array_add(&global_variables, var); + cg_add_symbol(m, e, cast(TB_Symbol *)global); cg_add_entity(m, e, g); cg_add_member(m, name, g); } @@ -478,6 +502,7 @@ gb_internal cgModule *cg_module_create(Checker *c) { tb_module_set_tls_index(m->mod, 10, "_tls_index"); map_init(&m->values); + map_init(&m->symbols); map_init(&m->file_id_map); @@ -500,6 +525,7 @@ gb_internal cgModule *cg_module_create(Checker *c) { gb_internal void cg_module_destroy(cgModule *m) { map_destroy(&m->values); + map_destroy(&m->symbols); map_destroy(&m->file_id_map); map_destroy(&m->debug_type_map); map_destroy(&m->proc_debug_type_map); diff --git a/src/tilde.hpp b/src/tilde.hpp index 2d7b2e1c3..e4f047017 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -214,6 +214,7 @@ struct cgModule { RwMutex values_mutex; PtrMap values; + PtrMap symbols; StringMap members; StringMap procedures; PtrMap procedure_values; @@ -257,6 +258,7 @@ gb_internal void cg_add_procedure_to_queue(cgProcedure *p); gb_internal void cg_setup_type_info_data(cgModule *m); gb_internal isize cg_global_const_calculate_region_count(ExactValue const &value, Type *type); +gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *type); gb_internal bool cg_global_const_add_region(cgModule *m, ExactValue const &value, Type *type, TB_Global *global, i64 offset); gb_internal cgValue cg_value(TB_Global * g, Type *type); diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp index 11126e07a..60f8e636b 100644 --- a/src/tilde_const.cpp +++ b/src/tilde_const.cpp @@ -143,6 +143,33 @@ gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Ty return global; } +gb_internal void cg_global_source_code_location_const(cgModule *m, String const &proc_name, TokenPos pos, TB_Global *global, i64 offset) { + // Source_Code_Location :: struct { + // file_path: string, + // line, column: i32, + // procedure: string, + // } + + i64 file_path_offset = type_offset_of(t_source_code_location, 0); + i64 line_offset = type_offset_of(t_source_code_location, 1); + i64 column_offset = type_offset_of(t_source_code_location, 2); + i64 procedure_offset = type_offset_of(t_source_code_location, 3); + + String file_path = get_file_path_string(pos.file_id); + if (file_path.len != 0) { + cg_global_const_string(m, file_path, t_string, global, offset+file_path_offset); + } + + void *line_ptr = tb_global_add_region(m->mod, global, offset+line_offset, 4); + void *column_ptr = tb_global_add_region(m->mod, global, offset+column_offset, 4); + cg_write_int_at_ptr(line_ptr, pos.line, t_i32); + cg_write_int_at_ptr(column_ptr, pos.column, t_i32); + + if (proc_name.len != 0) { + cg_global_const_string(m, proc_name, t_string, global, offset+procedure_offset); + } +} + gb_internal bool cg_elem_type_can_be_constant(Type *t) { t = base_type(t); if (t == t_invalid) { @@ -201,10 +228,11 @@ gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *typ return 1; case Type_Pointer: case Type_MultiPointer: + return 2; // allows for offsets case Type_Proc: - return true; + return 1; case Type_Slice: - return 2; + return 3; // alows for offsets case Type_DynamicArray: return 5; case Type_Map: @@ -221,6 +249,46 @@ gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *typ case Type_Matrix: return 1; + case Type_Array: + { + Type *elem = type->Array.elem; + i64 count = cg_global_const_calculate_region_count_from_basic_type(elem); + return count*type->Array.count; + } + case Type_EnumeratedArray: + { + Type *elem = type->EnumeratedArray.elem; + i64 count = cg_global_const_calculate_region_count_from_basic_type(elem); + return count*type->EnumeratedArray.count; + } + + case Type_Struct: + if (type->Struct.is_raw_union) { + i64 max_count = 0; + for (Entity *f : type->Struct.fields) { + i64 count = cg_global_const_calculate_region_count_from_basic_type(f->type); + max_count = gb_max(count, max_count); + } + return max_count; + } else { + i64 max_count = 0; + for (Entity *f : type->Struct.fields) { + max_count += cg_global_const_calculate_region_count_from_basic_type(f->type); + } + return max_count; + } + break; + case Type_Union: + { + i64 max_count = 0; + for (Type *t : type->Union.variants) { + i64 count = cg_global_const_calculate_region_count_from_basic_type(t); + max_count = gb_max(count, max_count); + } + return max_count+1; + } + break; + default: GB_PANIC("TODO(bill): %s", type_to_string(type)); break; diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index acc31ce67..a805b2985 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -103,6 +103,8 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i } p->value = cg_value(p->symbol, p->type); + + cg_add_symbol(m, entity, p->symbol); cg_add_entity(m, entity, p->value); cg_add_member(m, p->name, p->value); cg_add_procedure_value(m, p); diff --git a/src/tilde_type_info.cpp b/src/tilde_type_info.cpp index d3613cde8..1e86f6644 100644 --- a/src/tilde_type_info.cpp +++ b/src/tilde_type_info.cpp @@ -1,3 +1,16 @@ +gb_internal void cg_global_const_type_info_ptr(cgModule *m, TB_Global *type_info_array, Type *type, TB_Global *global, i64 offset) { + i64 index_in_bytes = cast(i64)cg_type_info_index(m->info, type); + index_in_bytes *= type_size_of(t_type_info); + + void *ti_ptr_ptr = tb_global_add_region(m->mod, global, offset, build_context.ptr_size); + // NOTE(bill): define the byte offset for the pointer + cg_write_int_at_ptr(ti_ptr_ptr, index_in_bytes, t_uintptr); + + // NOTE(bill): this will add to the byte offset set previously + tb_global_add_symbol_reloc(m->mod, global, offset, cast(TB_Symbol *)type_info_array); +} + + gb_internal void cg_setup_type_info_data(cgModule *m) { if (build_context.no_rtti) { return; @@ -9,11 +22,14 @@ gb_internal void cg_setup_type_info_data(cgModule *m) { // 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); + i64 max_objects = cast(i64)max_type_info_count * cg_global_const_calculate_region_count_from_basic_type(t_type_info); + TB_Global *g = tb_global_create(m->mod, -1, CG_TYPE_INFO_DATA_NAME, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, max_type_info_count); + tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, max_objects); cgValue value = cg_value(g, alloc_type_pointer(t)); cg_global_type_info_data_entity = alloc_entity_variable(nullptr, make_token_ident(CG_TYPE_INFO_DATA_NAME), t, EntityState_Resolved); + cg_add_symbol(m, cg_global_type_info_data_entity, cast(TB_Symbol *)g); cg_add_entity(m, cg_global_type_info_data_entity, value); } @@ -83,22 +99,255 @@ gb_internal void cg_setup_type_info_data(cgModule *m) { gb_unused(info); - // i64 global_type_info_data_entity_count = 0; - // { - // // NOTE(bill): Set the type_table slice with the global backing array - // cgValue global_type_table = cg_find_runtime_value(m, str_lit("type_table")); - // Type *type = base_type(cg_global_type_info_data_entity->type); - // GB_ASSERT(is_type_array(type)); - // global_type_info_data_entity_count = type->Array.count; + i64 global_type_info_data_entity_count = 0; - // LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; - // LLVMValueRef data = LLVMConstInBoundsGEP2(cg_type(m, cg_global_type_info_data_entity->type), cg_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)); - // LLVMValueRef len = LLVMConstInt(cg_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); + // NOTE(bill): Set the type_table slice with the global backing array + TB_Global *type_table_slice = cast(TB_Global *)cg_find_symbol_from_entity(m, scope_lookup_current(m->info->runtime_package->scope, str_lit("type_table"))); + GB_ASSERT(type_table_slice != nullptr); - // LLVMSetInitializer(global_type_table.value, slice); - // } + TB_Global *type_table_array = cast(TB_Global *)cg_find_symbol_from_entity(m, cg_global_type_info_data_entity); + GB_ASSERT(type_table_array != nullptr); + Type *type = base_type(cg_global_type_info_data_entity->type); + GB_ASSERT(is_type_array(type)); + global_type_info_data_entity_count = type->Array.count; + + tb_global_add_symbol_reloc(m->mod, type_table_slice, 0, cast(TB_Symbol *)type_table_array); + + void *len_ptr = tb_global_add_region(m->mod, type_table_slice, build_context.int_size, build_context.int_size); + cg_write_int_at_ptr(len_ptr, type->Array.count, t_int); + + // 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_ASSERT(type_size_of(t_type_info_flags) == 4); + + 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; + + + i64 type_info_size = type_size_of(t_type_info); + i64 size_offset = type_offset_of(t_type_info, 0); + i64 align_offset = type_offset_of(t_type_info, 1); + i64 flags_offset = type_offset_of(t_type_info, 2); + i64 id_offset = type_offset_of(t_type_info, 3); + i64 variant_offset = type_offset_of(t_type_info, 4); + + Type *type_info_union = base_type(t_type_info)->Struct.fields[4]->type; + GB_ASSERT(type_info_union->kind == Type_Union); + + i64 union_tag_offset = type_info_union->Union.variant_block_size; + Type *ti_union_tag_type = union_tag_type(type_info_union); + u64 union_tag_type_size = type_size_of(ti_union_tag_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 = cg_type_info_index(info, t, false); + if (entry_index <= 0) { + continue; + } + + if (entries_handled[entry_index]) { + continue; + } + entries_handled[entry_index] = true; + + TB_Global *global = type_table_array; + + i64 offset = entry_index * type_info_size; + + i64 size = type_size_of(t); + i64 align = type_align_of(t); + u32 flags = type_info_flags_of_type(t); + u64 id = cg_typeid_as_u64(m, t); + + void *size_ptr = tb_global_add_region(m->mod, global, offset+size_offset, build_context.int_size); + void *align_ptr = tb_global_add_region(m->mod, global, offset+align_offset, build_context.int_size); + void *flags_ptr = tb_global_add_region(m->mod, global, offset+flags_offset, 4); + void *id_ptr = tb_global_add_region(m->mod, global, offset+id_offset, build_context.ptr_size); + cg_write_int_at_ptr (size_ptr, size, t_int); + cg_write_int_at_ptr (align_ptr, align, t_int); + cg_write_int_at_ptr (flags_ptr, flags, t_u32); + cg_write_uint_at_ptr(id_ptr, id, t_typeid); + + + // add data to the offset to make it easier to deal with later on + offset += variant_offset; + + Type *tag_type = nullptr; + + switch (t->kind) { + case Type_Named: { + // Type_Info_Named :: struct { + // name: string, + // base: ^Type_Info, + // pkg: string, + // loc: Source_Code_Location, + // } + tag_type = t_type_info_named; + + if (t->Named.type_name->pkg) { + i64 pkg_offset = type_offset_of(tag_type, 2); + String pkg_name = t->Named.type_name->pkg->name; + cg_global_const_string(m, pkg_name, t_string, global, offset+pkg_offset); + } + + 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) { + i64 name_offset = type_offset_of(tag_type, 0); + proc_name = decl->entity->token.string; + cg_global_const_string(m, proc_name, t_string, global, offset+name_offset); + } + } + + i64 loc_offset = type_offset_of(tag_type, 3); + TokenPos pos = t->Named.type_name->token.pos; + cg_global_source_code_location_const(m, proc_name, pos, global, offset+loc_offset); + + i64 base_offset = type_offset_of(tag_type, 1); + cg_global_const_type_info_ptr(m, type_table_array, t->Named.base, global, offset+base_offset); + 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; + + bool is_signed = (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; + } + u8 *signed_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+0, 1); + u8 *endianness_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+1, 1); + *signed_ptr = is_signed; + *endianness_ptr = endianness_value; + 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; + } + + u8 *ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+0, 1); + *ptr = endianness_value; + } + 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; + bool *b = cast(bool *)tb_global_add_region(m->mod, global, offset+0, 1); + *b = true; + } + break; + + case Basic_any: + tag_type = t_type_info_any; + break; + + case Basic_typeid: + tag_type = t_type_info_typeid; + break; + } + break; + } + + if (tag_type != nullptr) { + i64 union_index = union_variant_index(type_info_union, tag_type); + GB_ASSERT(union_index != 0); + void *tag_ptr = tb_global_add_region(m->mod, global, offset+union_tag_offset, union_tag_type_size); + cg_write_int_at_ptr(tag_ptr, union_index, ti_union_tag_type); + } + + } } \ No newline at end of file