From: Brendan Hansen Date: Wed, 14 Dec 2022 21:20:51 +0000 (-0600) Subject: debugger code cleanup; added enum and slice types (proper strings wooo!) X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=1e825c29aa4714d276e68e0ff7c2aa183e39d3f4;p=onyx.git debugger code cleanup; added enum and slice types (proper strings wooo!) --- diff --git a/compiler/src/wasm_output.h b/compiler/src/wasm_output.h index 964d1d8b..b6e06144 100644 --- a/compiler/src/wasm_output.h +++ b/compiler/src/wasm_output.h @@ -911,6 +911,12 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { continue; } + if (type->Basic.kind == Basic_Kind_U8) { + output_unsigned_integer(1, §ion_buff); + output_unsigned_integer(5, §ion_buff); + continue; + } + output_unsigned_integer(1, §ion_buff); if (type->Basic.kind == Basic_Kind_Void) output_unsigned_integer(0, §ion_buff); else if (type_is_bool(type)) output_unsigned_integer(4, §ion_buff); @@ -935,9 +941,20 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { } if (type->kind == Type_Kind_Enum) { - output_unsigned_integer(5, §ion_buff); - output_unsigned_integer(2, §ion_buff); + output_unsigned_integer(8, §ion_buff); output_unsigned_integer(type->Enum.backing->id, §ion_buff); + + AstEnumType *e_type = (AstEnumType *) type->ast_type; + assert(e_type->kind == Ast_Kind_Enum_Type); + + output_unsigned_integer(bh_arr_length(e_type->values), §ion_buff); + bh_arr_each(AstEnumValue *, pev, e_type->values) { + AstEnumValue *ev = *pev; + + output_unsigned_integer(get_expression_integer_value(ev->value, NULL), §ion_buff); + output_unsigned_integer(ev->token->length, §ion_buff); + bh_buffer_append(§ion_buff, ev->token->text, ev->token->length); + } continue; } @@ -948,6 +965,12 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { continue; } + if (type->kind == Type_Kind_Slice) { + output_unsigned_integer(7, §ion_buff); + output_unsigned_integer(type->Slice.elem->id, §ion_buff); + continue; + } + if (type_is_structlike_strict(type)) { output_unsigned_integer(3, §ion_buff); diff --git a/interpreter/include/ovm_debug.h b/interpreter/include/ovm_debug.h index 2b8a70a4..c09f0b4c 100644 --- a/interpreter/include/ovm_debug.h +++ b/interpreter/include/ovm_debug.h @@ -56,6 +56,8 @@ typedef enum debug_type_kind_t { debug_type_kind_array = 4, debug_type_kind_alias = 5, debug_type_kind_function = 6, + debug_type_kind_slice = 7, + debug_type_kind_enum = 8, } debug_type_kind_t; typedef enum debug_type_primitive_kind_t { @@ -115,6 +117,21 @@ typedef struct debug_type_function_t { u32 return_type; } debug_type_function_t; +typedef struct debug_type_slice_t { + u32 type; +} debug_type_slice_t; + +typedef struct debug_type_enum_value_t { + u64 value; + char *name; +} debug_type_enum_value_t; + +typedef struct debug_type_enum_t { + u32 backing_type; + u32 value_count; + debug_type_enum_value_t *values; +} debug_type_enum_t; + typedef struct debug_type_info_t { u32 id; char *name; @@ -128,6 +145,8 @@ typedef struct debug_type_info_t { debug_type_array_t array; debug_type_alias_t alias; debug_type_function_t function; + debug_type_slice_t slice; + debug_type_enum_t enumeration; }; } debug_type_info_t; @@ -174,6 +193,8 @@ bool debug_info_lookup_file_by_name(debug_info_t *info, char *name, debug_file_i bool debug_info_lookup_func(debug_info_t *info, u32 func_id, debug_func_info_t *out); i32 debug_info_lookup_instr_by_file_line(debug_info_t *info, char *filename, u32 line); +char *debug_info_type_enum_find_name(debug_info_t *info, u32 enum_type, u64 value); + // // This builder is used in conjunction with code builder to output // debug information for each instruction that is generated in OVM. diff --git a/interpreter/src/debug/debug_info.c b/interpreter/src/debug/debug_info.c index e9fc60d9..0be08ce4 100644 --- a/interpreter/src/debug/debug_info.c +++ b/interpreter/src/debug/debug_info.c @@ -182,6 +182,26 @@ void debug_info_import_type_info(debug_info_t *info, u8 *data, u32 len) { type.function.return_type = uleb128_to_uint(data, &offset); break; + case debug_type_kind_slice: + type.slice.type = uleb128_to_uint(data, &offset); + break; + + case debug_type_kind_enum: + type.enumeration.backing_type = uleb128_to_uint(data, &offset); + type.enumeration.value_count = uleb128_to_uint(data, &offset); + type.enumeration.values = bh_alloc_array(info->alloc, debug_type_enum_value_t, type.enumeration.value_count); + + fori (i, 0, type.enumeration.value_count) { + type.enumeration.values[i].value = uleb128_to_uint(data, &offset); + + u32 name_length = uleb128_to_uint(data, &offset); + type.enumeration.values[i].name = bh_alloc_array(info->alloc, char, name_length + 1); + memcpy(type.enumeration.values[i].name, data + offset, name_length); + type.enumeration.values[i].name[name_length] = 0; + offset += name_length; + } + break; + // Error handling default: assert(("Unrecognized type kind", 0)); } @@ -236,6 +256,19 @@ i32 debug_info_lookup_instr_by_file_line(debug_info_t *info, char *filename, u32 return instr; } +char *debug_info_type_enum_find_name(debug_info_t *info, u32 enum_type, u64 value) { + debug_type_info_t *type = &info->types[enum_type]; + if (type->kind != debug_type_kind_enum) return NULL; + + fori (i, 0, type->enumeration.value_count) { + if (type->enumeration.values[i].value == value) { + return type->enumeration.values[i].name; + } + } + + return NULL; +} + // // For now, this is going to compare the strings exactly. In the future, it might be a good // to do a levenschtein distance or something, so the full path isn't needed. diff --git a/interpreter/src/debug/debug_runtime_values.c b/interpreter/src/debug/debug_runtime_values.c index 0c283161..7d383c5c 100644 --- a/interpreter/src/debug/debug_runtime_values.c +++ b/interpreter/src/debug/debug_runtime_values.c @@ -2,6 +2,8 @@ #include "ovm_debug.h" #include "vm.h" +#include + static char write_buf[4096]; #define WRITE(str) do { \ @@ -36,6 +38,8 @@ static bool lookup_stack_pointer(debug_runtime_value_builder_t *builder, u32 *ou return true; } +static void append_slice_from_memory(debug_runtime_value_builder_t *builder, void *elem_data, u32 count, u32 type_id); + static void append_value_from_memory_with_type(debug_runtime_value_builder_t *builder, void *base, u32 type_id) { debug_type_info_t *type = &builder->info->types[type_id]; @@ -76,6 +80,16 @@ static void append_value_from_memory_with_type(debug_runtime_value_builder_t *bu else { WRITE("false"); } break; + case debug_type_primitive_kind_character: { + unsigned char c = *(u8 *) base; + if (!iscntrl(c) && isascii(c)) { + WRITE_FORMAT("%c", c); + } else { + WRITE_FORMAT("\\x%02hhx", c); + } + break; + } + default: WRITE("(err)"); } @@ -136,10 +150,74 @@ static void append_value_from_memory_with_type(debug_runtime_value_builder_t *bu break; } + case debug_type_kind_slice: { + void *elem_data = bh_pointer_add(builder->state->ovm_engine->memory, *(u32 *) base); + u32 count = *(u32 *) bh_pointer_add(base, 4); + u32 type_id = type->slice.type; + + append_slice_from_memory(builder, elem_data, count, type_id); + break; + } + + case debug_type_kind_enum: { + debug_type_info_t *backing_type = &builder->info->types[type->enumeration.backing_type]; + + u64 value = 0; + switch (backing_type->size) { + case 1: value = *(u8 *) base; break; + case 2: value = *(u16 *) base; break; + case 4: value = *(u32 *) base; break; + case 8: value = *(u64 *) base; break; + } + + char *name = debug_info_type_enum_find_name(builder->info, type_id, value); + if (name) { + WRITE(name); + } else { + WRITE_FORMAT("%lu", value); + } + + break; + } + default: WRITE("(unknown)"); break; } } +static void append_slice_from_memory(debug_runtime_value_builder_t *builder, void *elem_data, u32 count, u32 type_id) { + debug_type_info_t *elem_type = &builder->info->types[type_id]; + + b32 count_overflowed = 0; + if (count > 256) { + count = 256; + count_overflowed = 1; + } + + if (elem_type->kind == debug_type_kind_primitive && + elem_type->primitive.primitive_kind == debug_type_primitive_kind_character) { + WRITE("\""); + + fori (i, 0, (i32) count) { + append_value_from_memory_with_type(builder, bh_pointer_add(elem_data, i * elem_type->size), elem_type->id); + } + + if (count_overflowed) WRITE("..."); + WRITE("\""); + return; + } + + WRITE("["); + + fori (i, 0, (i32) count) { + if (i != 0) WRITE(", "); + append_value_from_memory_with_type(builder, bh_pointer_add(elem_data, i * elem_type->size), elem_type->id); + } + + if (count_overflowed) WRITE("..."); + WRITE("]"); +} + + static void append_ovm_value_with_type(debug_runtime_value_builder_t *builder, ovm_value_t value, u32 type_id) { debug_type_info_t *type = &builder->info->types[type_id]; @@ -220,6 +298,17 @@ static void append_ovm_value_with_type(debug_runtime_value_builder_t *builder, o break; } + case debug_type_kind_enum: { + char *name = debug_info_type_enum_find_name(builder->info, type_id, value.u64); + if (name == NULL) { + WRITE_FORMAT("%lu", value.u64); + } else { + WRITE(name); + } + + break; + } + default: WRITE("(unknown)"); break; } } @@ -260,6 +349,20 @@ static void append_value_from_register(debug_runtime_value_builder_t *builder, u return; } + if (type->kind == debug_type_kind_slice) { + ovm_value_t base_reg; + ovm_value_t count_reg; + + if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, reg, &base_reg)) return; + if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, reg + 1, &count_reg)) return; + + void *elem_data = bh_pointer_add(builder->state->ovm_engine->memory, base_reg.u32); + u32 count = count_reg.u32; + + append_slice_from_memory(builder, elem_data, count, type->slice.type); + return; + } + if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, reg, &value)) { WRITE("(err)") return; @@ -272,7 +375,8 @@ static u32 get_subvalues_for_type(debug_runtime_value_builder_t *builder, u32 ty debug_type_info_t *t = &builder->info->types[type]; switch (t->kind) { case debug_type_kind_primitive: return 0; - case debug_type_kind_function: return 0; + case debug_type_kind_function: return 0; + case debug_type_kind_enum: return 0; case debug_type_kind_modifier: if (t->modifier.modifier_kind == debug_type_modifier_kind_pointer) return 1; @@ -285,6 +389,36 @@ static u32 get_subvalues_for_type(debug_runtime_value_builder_t *builder, u32 ty return t->structure.member_count; case debug_type_kind_array: return t->array.count; + + case debug_type_kind_slice: { + // :Refactor + u32 count = 0; + if (builder->base_loc_kind == debug_sym_loc_register) { + ovm_value_t value; + if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, builder->base_loc + 1, &value)) { + return 0; + } + + count = value.u32; + } + + else if (builder->base_loc_kind == debug_sym_loc_stack) { + u32 stack_ptr; + if (!lookup_stack_pointer(builder, &stack_ptr)) { + return 0; + } + + u32 *ptr_loc = bh_pointer_add(builder->state->ovm_engine->memory, stack_ptr + builder->base_loc + 4); + count = *ptr_loc; + } + + else if (builder->base_loc_kind == debug_sym_loc_global) { + u32 *ptr_loc = bh_pointer_add(builder->state->ovm_engine->memory, builder->base_loc + 4); + count = *ptr_loc; + } + + return count; + } } } @@ -311,19 +445,14 @@ void debug_runtime_value_build_set_location(debug_runtime_value_builder_t *build } void debug_runtime_value_build_descend(debug_runtime_value_builder_t *builder, u32 index) { - builder->it_index = 0; - debug_type_info_t *type = &builder->info->types[builder->base_type]; + if (type->kind == debug_type_kind_modifier && type->modifier.modifier_kind == debug_type_modifier_kind_pointer) { if (index > 0) { goto bad_case; } builder->base_type = type->modifier.modified_type; - type = &builder->info->types[builder->base_type]; - - builder->max_index = get_subvalues_for_type(builder, builder->base_type); - builder->it_index = 0; if (builder->base_loc_kind == debug_sym_loc_register) { ovm_value_t value; @@ -350,8 +479,6 @@ void debug_runtime_value_build_descend(debug_runtime_value_builder_t *builder, u u32 *ptr_loc = bh_pointer_add(builder->state->ovm_engine->memory, builder->base_loc); builder->base_loc = *ptr_loc; } - - return; } if (type->kind == debug_type_kind_structure) { @@ -361,7 +488,6 @@ void debug_runtime_value_build_descend(debug_runtime_value_builder_t *builder, u debug_type_structure_member_t *mem = &type->structure.members[index]; builder->base_type = mem->type; - builder->max_index = get_subvalues_for_type(builder, builder->base_type); builder->it_name = mem->name; if (builder->base_loc_kind == debug_sym_loc_register) { @@ -371,24 +497,13 @@ void debug_runtime_value_build_descend(debug_runtime_value_builder_t *builder, u else if (builder->base_loc_kind == debug_sym_loc_stack || builder->base_loc_kind == debug_sym_loc_global) { builder->base_loc += mem->offset; } - - return; } if (type->kind == debug_type_kind_array) { builder->base_type = type->array.type; - builder->max_index = get_subvalues_for_type(builder, builder->base_type); debug_type_info_t *sub_type = &builder->info->types[builder->base_type]; - // Double buffering here so if there are multiple - // pointer descentions, the names don't get mangled. - static char name_buffer[2048]; - static char tmp_buffer[2048]; - snprintf(tmp_buffer, 2048, "[%d]", index); - strncpy(name_buffer, tmp_buffer, 2048); - builder->it_name = name_buffer; - if (builder->base_loc_kind == debug_sym_loc_register) { ovm_value_t value; if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, builder->base_loc, &value)) { @@ -402,10 +517,44 @@ void debug_runtime_value_build_descend(debug_runtime_value_builder_t *builder, u else if (builder->base_loc_kind == debug_sym_loc_stack || builder->base_loc_kind == debug_sym_loc_global) { builder->base_loc += sub_type->size * index; } + } - return; + if (type->kind == debug_type_kind_slice) { + builder->base_type = type->slice.type; + debug_type_info_t *sub_type = &builder->info->types[builder->base_type]; + + if (builder->base_loc_kind == debug_sym_loc_register) { + ovm_value_t value; + if (!lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, builder->base_loc, &value)) { + goto bad_case; + } + + builder->base_loc_kind = debug_sym_loc_global; + builder->base_loc = value.u32 + sub_type->size * index; + } + + else if (builder->base_loc_kind == debug_sym_loc_stack) { + u32 stack_ptr; + if (!lookup_stack_pointer(builder, &stack_ptr)) { + goto bad_case; + } + + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, stack_ptr + builder->base_loc); + + builder->base_loc_kind = debug_sym_loc_global; + builder->base_loc = *data_loc + index * sub_type->size; + } + + else if (builder->base_loc_kind == debug_sym_loc_global) { + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, builder->base_loc); + builder->base_loc = *data_loc + index * sub_type->size; + } } + builder->max_index = get_subvalues_for_type(builder, builder->base_type); + builder->it_index = 0; + return; + bad_case: builder->base_loc_kind = debug_sym_loc_unknown; return; @@ -424,16 +573,46 @@ bool debug_runtime_value_build_step(debug_runtime_value_builder_t *builder) { snprintf(tmp_buffer, 2048, "*%s", builder->it_name); strncpy(name_buffer, tmp_buffer, 2048); - builder->it_loc_kind = builder->base_loc_kind; - builder->it_loc = builder->base_loc; builder->it_name = name_buffer; builder->it_type = type->modifier.modified_type; builder->it_has_children = get_subvalues_for_type(builder, builder->it_type) > 0; + + // builder->it_loc_kind = debug_sym_loc_global; + // builder->it_loc = builder->base_loc; + if (builder->base_loc_kind == debug_sym_loc_register) { + ovm_value_t value; + if (lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, builder->base_loc, &value)) { + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = value.u32; + } + } + + if (builder->base_loc_kind == debug_sym_loc_stack) { + u32 stack_ptr; + if (!lookup_stack_pointer(builder, &stack_ptr)) { + return false; + } + + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, stack_ptr + builder->base_loc); + + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = *data_loc; + } + + if (builder->base_loc_kind == debug_sym_loc_global) { + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, builder->base_loc); + + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = *data_loc; + } } if (type->kind == debug_type_kind_structure) { debug_type_structure_member_t *mem = &type->structure.members[builder->it_index]; - builder->it_name = mem->name; + snprintf(tmp_buffer, 2048, "%s", mem->name); + strncpy(name_buffer, tmp_buffer, 2048); + + builder->it_name = name_buffer; builder->it_has_children = get_subvalues_for_type(builder, mem->type) > 0; builder->it_type = mem->type; @@ -481,6 +660,42 @@ bool debug_runtime_value_build_step(debug_runtime_value_builder_t *builder) { } } + if (type->kind == debug_type_kind_slice) { + snprintf(tmp_buffer, 2048, "[%d]", builder->it_index); + strncpy(name_buffer, tmp_buffer, 2048); + builder->it_name = name_buffer; + builder->it_type = type->slice.type; + builder->it_has_children = get_subvalues_for_type(builder, builder->it_type) > 0; + + debug_type_info_t *sub_type = &builder->info->types[builder->it_type]; + + if (builder->base_loc_kind == debug_sym_loc_register) { + ovm_value_t value; + if (lookup_register_in_frame(builder->ovm_state, builder->ovm_frame, builder->base_loc, &value)) { + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = value.u32 + sub_type->size * builder->it_index; + } + } + + if (builder->base_loc_kind == debug_sym_loc_stack) { + u32 stack_ptr; + if (!lookup_stack_pointer(builder, &stack_ptr)) { + return false; + } + + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, stack_ptr + builder->base_loc); + + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = *data_loc + sub_type->size * builder->it_index; + } + + if (builder->base_loc_kind == debug_sym_loc_global) { + u32 *data_loc = bh_pointer_add(builder->state->ovm_engine->memory, builder->base_loc); + + builder->it_loc_kind = debug_sym_loc_global; + builder->it_loc = *data_loc + sub_type->size * builder->it_index; + } + } builder->it_index++; return true;