mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-24 00:17:54 +00:00
Begin work on setting up type information table
This commit is contained in:
+27
-1
@@ -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);
|
||||
|
||||
@@ -214,6 +214,7 @@ struct cgModule {
|
||||
|
||||
RwMutex values_mutex;
|
||||
PtrMap<Entity *, cgValue> values;
|
||||
PtrMap<Entity *, TB_Symbol *> symbols;
|
||||
StringMap<cgValue> members;
|
||||
StringMap<cgProcedure *> procedures;
|
||||
PtrMap<TB_Function *, Entity *> 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);
|
||||
|
||||
+70
-2
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+265
-16
@@ -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<bool>(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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user