Browse Source

Begin work on setting up type information table

gingerBill 2 years ago
parent
commit
28c97a9467
5 changed files with 366 additions and 19 deletions
  1. 27 1
      src/tilde.cpp
  2. 2 0
      src/tilde.hpp
  3. 70 2
      src/tilde_const.cpp
  4. 2 0
      src/tilde_proc.cpp
  5. 265 16
      src/tilde_type_info.cpp

+ 27 - 1
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);

+ 2 - 0
src/tilde.hpp

@@ -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
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;

+ 2 - 0
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);

+ 265 - 16
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;
+
+	// 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);
+
+	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;
 
-	// 	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);
+			case Basic_quaternion64:
+			case Basic_quaternion128:
+			case Basic_quaternion256:
+				tag_type = t_type_info_quaternion;
+				break;
 
-	// 	LLVMSetInitializer(global_type_table.value, slice);
-	// }
+			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);
+		}
+
+	}
 }