From 45a2137d08b84ae94cf8e77b70aef91a251e343f Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 30 Sep 2025 10:02:40 -0700 Subject: [PATCH] linux: fix incorrect gethostname usage, fix build, fix clang warnings --- src/demon/linux/demon_core_linux.h | 2 +- src/os/core/linux/os_core_linux.c | 103 +- src/rdi_from_dwarf/rdi_from_dwarf.c | 1468 +++++++++++++-------------- 3 files changed, 787 insertions(+), 786 deletions(-) diff --git a/src/demon/linux/demon_core_linux.h b/src/demon/linux/demon_core_linux.h index 18347a4f..297fdb3a 100644 --- a/src/demon/linux/demon_core_linux.h +++ b/src/demon/linux/demon_core_linux.h @@ -279,7 +279,7 @@ struct DMN_LNX_State Arena *arena; // rjf: access locking mechanism - OS_Handle access_mutex; + Mutex access_mutex; B32 access_run_state; // rjf: deferred events diff --git a/src/os/core/linux/os_core_linux.c b/src/os/core/linux/os_core_linux.c index 8a22f460..df98d409 100644 --- a/src/os/core/linux/os_core_linux.c +++ b/src/os/core/linux/os_core_linux.c @@ -800,8 +800,8 @@ os_process_kill(OS_Handle handle) //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) -internal OS_Handle -os_thread_launch(ThreadEntryPointFunctionType *func, void *ptr, void *params) +internal Thread +os_thread_launch(ThreadEntryPointFunctionType *func, void *ptr) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Thread); entity->thread.func = func; @@ -814,14 +814,14 @@ os_thread_launch(ThreadEntryPointFunctionType *func, void *ptr, void *params) entity = 0; } } - OS_Handle handle = {(U64)entity}; + Thread handle = {(U64)entity}; return handle; } internal B32 -os_thread_join(OS_Handle handle, U64 endt_us) +os_thread_join(Thread handle, U64 endt_us) { - if(os_handle_match(handle, os_handle_zero())) { return 0; } + if(MemoryIsZeroStruct(&handle)) { return 0; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; int join_result = pthread_join(entity->thread.handle, 0); B32 result = (join_result == 0); @@ -830,9 +830,9 @@ os_thread_join(OS_Handle handle, U64 endt_us) } internal void -os_thread_detach(OS_Handle handle) +os_thread_detach(Thread handle) { - if(os_handle_match(handle, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&handle)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; os_lnx_entity_release(entity); } @@ -842,7 +842,7 @@ os_thread_detach(OS_Handle handle) //- rjf: mutexes -internal OS_Handle +internal Mutex os_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Mutex); @@ -856,38 +856,38 @@ os_mutex_alloc(void) os_lnx_entity_release(entity); entity = 0; } - OS_Handle handle = {(U64)entity}; + Mutex handle = {(U64)entity}; return handle; } internal void -os_mutex_release(OS_Handle mutex) +os_mutex_release(Mutex mutex) { - if(os_handle_match(mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_destroy(&entity->mutex_handle); os_lnx_entity_release(entity); } internal void -os_mutex_take(OS_Handle mutex) +os_mutex_take(Mutex mutex) { - if(os_handle_match(mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_lock(&entity->mutex_handle); } internal void -os_mutex_drop(OS_Handle mutex) +os_mutex_drop(Mutex mutex) { - if(os_handle_match(mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_unlock(&entity->mutex_handle); } //- rjf: reader/writer mutexes -internal OS_Handle +internal RWMutex os_rw_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_RWMutex); @@ -897,23 +897,23 @@ os_rw_mutex_alloc(void) os_lnx_entity_release(entity); entity = 0; } - OS_Handle handle = {(U64)entity}; + RWMutex handle = {(U64)entity}; return handle; } internal void -os_rw_mutex_release(OS_Handle rw_mutex) +os_rw_mutex_release(RWMutex rw_mutex) { - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_destroy(&entity->rwmutex_handle); os_lnx_entity_release(entity); } internal void -os_rw_mutex_take(OS_Handle rw_mutex, B32 write_mode) +os_rw_mutex_take(RWMutex rw_mutex, B32 write_mode) { - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; if(write_mode) { @@ -926,16 +926,16 @@ os_rw_mutex_take(OS_Handle rw_mutex, B32 write_mode) } internal void -os_rw_mutex_drop(OS_Handle rw_mutex, B32 write_mode) +os_rw_mutex_drop(RWMutex rw_mutex, B32 write_mode) { - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_unlock(&entity->rwmutex_handle); } //- rjf: condition variables -internal OS_Handle +internal CondVar os_cond_var_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_ConditionVariable); @@ -956,14 +956,14 @@ os_cond_var_alloc(void) os_lnx_entity_release(entity); entity = 0; } - OS_Handle handle = {(U64)entity}; + CondVar handle = {(U64)entity}; return handle; } internal void -os_cond_var_release(OS_Handle cv) +os_cond_var_release(CondVar cv) { - if(os_handle_match(cv, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_destroy(&entity->cv.cond_handle); pthread_mutex_destroy(&entity->cv.rwlock_mutex_handle); @@ -971,10 +971,10 @@ os_cond_var_release(OS_Handle cv) } internal B32 -os_cond_var_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) +os_cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) { - if(os_handle_match(cv, os_handle_zero())) { return 0; } - if(os_handle_match(mutex, os_handle_zero())) { return 0; } + if(MemoryIsZeroStruct(&cv)) { return 0; } + if(MemoryIsZeroStruct(&mutex)) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *mutex_entity = (OS_LNX_Entity *)mutex.u64[0]; struct timespec endt_timespec; @@ -986,14 +986,14 @@ os_cond_var_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) } internal B32 -os_cond_var_wait_rw(OS_Handle cv, OS_Handle mutex_rw, B32 write_mode, U64 endt_us) +os_cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us) { // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack // this together, but this would probably just be a lot better if we just // implemented the primitives ourselves with e.g. futexes // - if(os_handle_match(cv, os_handle_zero())) { return 0; } - if(os_handle_match(mutex_rw, os_handle_zero())) { return 0; } + if(MemoryIsZeroStruct(&cv)) { return 0; } + if(MemoryIsZeroStruct(&mutex_rw)) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; struct timespec endt_timespec; @@ -1036,27 +1036,27 @@ os_cond_var_wait_rw(OS_Handle cv, OS_Handle mutex_rw, B32 write_mode, U64 endt_u } internal void -os_cond_var_signal(OS_Handle cv) +os_cond_var_signal(CondVar cv) { - if(os_handle_match(cv, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_signal(&cv_entity->cv.cond_handle); } internal void -os_cond_var_broadcast(OS_Handle cv) +os_cond_var_broadcast(CondVar cv) { - if(os_handle_match(cv, os_handle_zero())) { return; } + if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_broadcast(&cv_entity->cv.cond_handle); } //- rjf: cross-process semaphores -internal OS_Handle +internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { - OS_Handle result = {0}; + Semaphore result = {0}; if (name.size > 0) { // TODO: we need to allocate shared memory to store sem_t @@ -1076,26 +1076,26 @@ os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) } internal void -os_semaphore_release(OS_Handle semaphore) +os_semaphore_release(Semaphore semaphore) { int err = munmap((void*)semaphore.u64[0], sizeof(sem_t)); AssertAlways(err == 0); } -internal OS_Handle +internal Semaphore os_semaphore_open(String8 name) { NotImplemented; } internal void -os_semaphore_close(OS_Handle semaphore) +os_semaphore_close(Semaphore semaphore) { NotImplemented; } internal B32 -os_semaphore_take(OS_Handle semaphore, U64 endt_us) +os_semaphore_take(Semaphore semaphore, U64 endt_us) { // TODO(rjf): we need to use `sem_timedwait` here. AssertAlways(endt_us == max_U64); @@ -1116,7 +1116,7 @@ os_semaphore_take(OS_Handle semaphore, U64 endt_us) } internal void -os_semaphore_drop(OS_Handle semaphore) +os_semaphore_drop(Semaphore semaphore) { for(;;) { @@ -1138,17 +1138,17 @@ os_semaphore_drop(OS_Handle semaphore) //- rjf: barriers -internal OS_Handle +internal Barrier os_barrier_alloc(U64 count) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Barrier); pthread_barrier_init(&entity->barrier, 0, count); - OS_Handle result = {IntFromPtr(entity)}; + Barrier result = {IntFromPtr(entity)}; return result; } internal void -os_barrier_release(OS_Handle barrier) +os_barrier_release(Barrier barrier) { OS_LNX_Entity *entity = (OS_LNX_Entity*)PtrFromInt(barrier.u64[0]); pthread_barrier_destroy(&entity->barrier); @@ -1156,7 +1156,7 @@ os_barrier_release(OS_Handle barrier) } internal void -os_barrier_wait(OS_Handle barrier) +os_barrier_wait(Barrier barrier) { OS_LNX_Entity *entity = (OS_LNX_Entity*)PtrFromInt(barrier.u64[0]); pthread_barrier_wait(&entity->barrier); @@ -1288,9 +1288,10 @@ main(int argc, char **argv) for(S64 cap = 4096, r = 0; r < 4; cap *= 2, r += 1) { scratch_end(scratch); - buffer = push_array_no_zero(scratch.arena, U8, cap); - size = gethostname((char*)buffer, cap); - if(size < cap) + buffer = push_array(scratch.arena, U8, cap); + int gethostname_result = gethostname((char*)buffer, cap); + size = cstring8_length(buffer); + if(gethostname_result == 0 && size < cap) { got_final_result = 1; break; diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index 25645a49..e1e279fa 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -8,7 +8,7 @@ // [ ] Error handling //////////////////////////////// - + static const U64 UNIT_CHUNK_CAP = 256; static const U64 UDT_CHUNK_CAP = 256; static const U64 TYPE_CHUNK_CAP = 256; @@ -210,7 +210,7 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag DW_Attrib *hi_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_HighPc); if (lo_pc_attrib->attrib_kind != DW_AttribKind_Null && hi_pc_attrib->attrib_kind != DW_AttribKind_Null) { U64 lo_pc = dw_address_from_attrib(input, cu, lo_pc_attrib); - + U64 hi_pc = 0; DW_AttribClass hi_pc_class = dw_value_class_from_attrib(cu, hi_pc_attrib); if (hi_pc_class == DW_AttribClass_Address) { @@ -221,7 +221,7 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag } else { AssertAlways(!"unexpected attribute encoding"); } - + if (lo_pc >= image_base && hi_pc >= image_base) { if (lo_pc < hi_pc) { rng1u64_list_push(arena, &ranges, rng_1u64(lo_pc - image_base, hi_pc - image_base)); @@ -231,8 +231,8 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag } else { // invalid low and hi PC are likely are caused by an optimization pass during linking } - } else if (lo_pc_attrib->attrib_kind == DW_AttribKind_Null && hi_pc_attrib->attrib_kind != DW_AttribKind_Null || - lo_pc_attrib->attrib_kind != DW_AttribKind_Null && hi_pc_attrib->attrib_kind == DW_AttribKind_Null) { + } else if ((lo_pc_attrib->attrib_kind == DW_AttribKind_Null && hi_pc_attrib->attrib_kind != DW_AttribKind_Null) || + (lo_pc_attrib->attrib_kind != DW_AttribKind_Null && hi_pc_attrib->attrib_kind == DW_AttribKind_Null)) { // TODO: error handling } } @@ -364,9 +364,9 @@ d2r_bytecode_from_expression(Arena *arena, }; struct Frame *stack = 0; #define push_of_type(type) do { \ - struct Frame *f = push_array(scratch.arena, struct Frame, 1); \ - f->value_type = d2r_type_group_from_type_kind(type); \ - SLLStackPush(stack, f); \ +struct Frame *f = push_array(scratch.arena, struct Frame, 1); \ +f->value_type = d2r_type_group_from_type_kind(type); \ +SLLStackPush(stack, f); \ } while (0) #define pop_type() stack->value_type; SLLStackPop(stack) #define peek_type() stack->value_type @@ -918,7 +918,7 @@ d2r_bytecode_from_expression(Arena *arena, rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_TLSOff, 0); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, peek_type()); } break; - + default: InvalidPath; break; } } @@ -941,7 +941,7 @@ d2r_transpile_expression(Arena *arena, RDIM_LocationChunkList *locations, DW_Inp RDIM_LocationInfo *loc_info = push_array(arena, RDIM_LocationInfo, 1); loc_info->kind = is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream; loc_info->bytecode = bytecode; - + loc = rdim_location_chunk_list_push_new(arena, locations, LOCATIONS_CAP, loc_info); } return loc; @@ -1037,7 +1037,7 @@ d2r_var_locset_from_tag(Arena *arena, loc_info->kind = RDI_LocationKind_ValBytecodeStream; loc_info->bytecode = bc; RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, locations, LOCATIONS_CAP, loc_info); - + // push location cases for EachNode(range_n, RDIM_Rng1U64Node, curr_scope->voff_ranges.first) { rdim_push_location_case(arena, scopes, &locset, loc, range_n->v); @@ -1211,19 +1211,19 @@ d2r_tag_iterator_next(Arena *arena, D2R_TagIterator *iter) goto exit; } } - + while (iter->stack) { // go to sibling iter->stack->node = iter->stack->node->sibling; if (iter->stack->node) { break; } - + // no more siblings, go up D2R_TagFrame *f = iter->stack; SLLStackPop(iter->stack); SLLStackPush(iter->free_list, f); } - -exit:; + + exit:; // update iterator iter->visit_children = 1; iter->tag_node = iter->stack ? iter->stack->node : 0; @@ -1281,13 +1281,13 @@ d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *inpu // find type type = d2r_type_from_offset(type_table, ref.info_off); - + // was type converted? if (type == 0) { // issue type conversion DW_TagNode *ref_node = dw_tag_node_from_info_off(cu, ref.info_off); d2r_convert_types(arena, type_table, input, cu, cu_lang, arch_addr_size, ref_node); - + // if we do not have a converted type at this point then debug info is malformed type = d2r_type_from_offset(type_table, ref.info_off); Assert(type); @@ -1313,7 +1313,7 @@ d2r_convert_types(Arena *arena, for (D2R_TagIterator *it = d2r_tag_iterator_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iterator_next(scratch.arena, it)) { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; - + // skip converted tags if (d2r_is_tag_converted(tag_node)) { d2r_tag_iterator_skip_children(it); @@ -1321,376 +1321,376 @@ d2r_convert_types(Arena *arena, } // mark the tag as converted here, because during conversion we may recurse on the same tag d2r_flag_converted_tag(tag_node); - + switch (tag.kind) { - case DW_TagKind_ClassType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_IncompleteClass; - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - Assert(!tag_node->first_child); + case DW_TagKind_ClassType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_IncompleteClass; + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + Assert(!tag_node->first_child); + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_Class; + type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); + type->direct_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); + } + } break; + case DW_TagKind_StructureType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_IncompleteStruct; + + // TODO: error handling + Assert(!tag_node->first_child); + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_Struct; + type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); + } + } break; + case DW_TagKind_UnionType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_IncompleteUnion; + + // TODO: error handling + Assert(!tag_node->first_child); + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_Union; + type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); + } + } break; + case DW_TagKind_EnumerationType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_IncompleteEnum; + // TODO: error handling + Assert(!tag_node->first_child); + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + type->kind = RDI_TypeKind_Enum; + type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); + type->direct_type = enum_base_type; + } + } break; + case DW_TagKind_SubroutineType: { + RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + + // collect parameters + RDIM_TypeList param_list = {0}; + for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind == DW_TagKind_FormalParameter) { + RDIM_Type *param_type = d2r_type_from_attrib(type_table, input, cu, n->tag, DW_AttribKind_Type); + rdim_type_list_push(scratch.arena, ¶m_list, param_type); + } else if (n->tag.kind == DW_TagKind_UnspecifiedParameters) { + rdim_type_list_push(scratch.arena, ¶m_list, type_table->builtin_types[RDI_TypeKind_Variadic]); + } else { + // TODO: error handling + AssertAlways(!"unexpected tag"); + } + } + + // init proceudre type + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Function; + type->byte_size = arch_addr_size; + type->direct_type = ret_type; + type->count = param_list.count; + type->param_types = rdim_array_from_type_list(arena, param_list); + d2r_tag_iterator_skip_children(it); - } else { + } break; + case DW_TagKind_Typedef: { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_Class; - type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); - type->direct_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - } - } break; - case DW_TagKind_StructureType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_IncompleteStruct; - - // TODO: error handling - Assert(!tag_node->first_child); - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_Struct; - type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); - } - } break; - case DW_TagKind_UnionType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_IncompleteUnion; - - // TODO: error handling - Assert(!tag_node->first_child); - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_Union; - type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); - } - } break; - case DW_TagKind_EnumerationType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_IncompleteEnum; - // TODO: error handling - Assert(!tag_node->first_child); - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->direct_type = direct_type; + for (RDIM_Type *n = direct_type; n != 0; n = n->direct_type) { + if (n->byte_size) { + type->byte_size = n->byte_size; + break; + } + } + } break; + case DW_TagKind_BaseType: { + DW_ATE encoding = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Encoding); + U64 byte_size = dw_byte_size_from_tag(input, cu, tag); + + // convert base type encoding to RDI version + RDI_TypeKind kind = RDI_TypeKind_NULL; + switch (encoding) { + case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; + case DW_ATE_Address: kind = RDI_TypeKind_Void; break; + case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; + case DW_ATE_ComplexFloat: { + switch (byte_size) { + case 4: kind = RDI_TypeKind_ComplexF32; break; + case 8: kind = RDI_TypeKind_ComplexF64; break; + case 10: kind = RDI_TypeKind_ComplexF80; break; + case 16: kind = RDI_TypeKind_ComplexF128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Float: { + switch (byte_size) { + case 2: kind = RDI_TypeKind_F16; break; + case 4: kind = RDI_TypeKind_F32; break; + case 6: kind = RDI_TypeKind_F48; break; + case 8: kind = RDI_TypeKind_F64; break; + case 16: kind = RDI_TypeKind_F128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Signed: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_S8; break; + case 2: kind = RDI_TypeKind_S16; break; + case 4: kind = RDI_TypeKind_S32; break; + case 8: kind = RDI_TypeKind_S64; break; + case 16: kind = RDI_TypeKind_S128; break; + case 32: kind = RDI_TypeKind_S256; break; + case 64: kind = RDI_TypeKind_S512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_SignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_Char8; break; + case 2: kind = RDI_TypeKind_Char16; break; + case 4: kind = RDI_TypeKind_Char32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Unsigned: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_U8; break; + case 2: kind = RDI_TypeKind_U16; break; + case 4: kind = RDI_TypeKind_U32; break; + case 8: kind = RDI_TypeKind_U64; break; + case 16: kind = RDI_TypeKind_U128; break; + case 32: kind = RDI_TypeKind_U256; break; + case 64: kind = RDI_TypeKind_U512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_UnsignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_UChar8; break; + case 2: kind = RDI_TypeKind_UChar16; break; + case 4: kind = RDI_TypeKind_UChar32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_ImaginaryFloat: { + NotImplemented; + } break; + case DW_ATE_PackedDecimal: { + NotImplemented; + } break; + case DW_ATE_NumericString: { + NotImplemented; + } break; + case DW_ATE_Edited: { + NotImplemented; + } break; + case DW_ATE_SignedFixed: { + NotImplemented; + } break; + case DW_ATE_UnsignedFixed: { + NotImplemented; + } break; + case DW_ATE_DecimalFloat: { + NotImplemented; + } break; + case DW_ATE_Utf: { + NotImplemented; + } break; + case DW_ATE_Ucs: { + NotImplemented; + } break; + case DW_ATE_Ascii: { + NotImplemented; + } break; + default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling + } + + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->kind = RDI_TypeKind_Enum; - type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); - type->direct_type = enum_base_type; - } - } break; - case DW_TagKind_SubroutineType: { - RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - - // collect parameters - RDIM_TypeList param_list = {0}; - for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind == DW_TagKind_FormalParameter) { - RDIM_Type *param_type = d2r_type_from_attrib(type_table, input, cu, n->tag, DW_AttribKind_Type); - rdim_type_list_push(scratch.arena, ¶m_list, param_type); - } else if (n->tag.kind == DW_TagKind_UnspecifiedParameters) { - rdim_type_list_push(scratch.arena, ¶m_list, type_table->builtin_types[RDI_TypeKind_Variadic]); - } else { - // TODO: error handling - AssertAlways(!"unexpected tag"); + type->direct_type = type_table->builtin_types[kind]; + type->byte_size = byte_size; + } break; + case DW_TagKind_PointerType: { + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + + // TODO: + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Allocated)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Associated)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_AddressClass)); + + U64 byte_size = arch_addr_size; + if (cu->version == DW_Version_5 || cu->relaxed) { + dw_try_byte_size_from_tag(input, cu, tag, &byte_size); } - } - - // init proceudre type - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Function; - type->byte_size = arch_addr_size; - type->direct_type = ret_type; - type->count = param_list.count; - type->param_types = rdim_array_from_type_list(arena, param_list); - - d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_Typedef: { - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->direct_type = direct_type; - for (RDIM_Type *n = direct_type; n != 0; n = n->direct_type) { - if (n->byte_size) { - type->byte_size = n->byte_size; - break; + + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Ptr; + type->byte_size = byte_size; + type->direct_type = direct_type; + } break; + case DW_TagKind_RestrictType: { + // TODO: + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); + + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Restrict; + type->direct_type = direct_type; + } break; + case DW_TagKind_VolatileType: { + // TODO: + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); + + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Volatile; + type->direct_type = direct_type; + } break; + case DW_TagKind_ConstType: { + // TODO: + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); + Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); + + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Const; + type->direct_type = direct_type; + } break; + case DW_TagKind_ArrayType: { + // * DWARF vs RDI Array Type Graph * + // + // For example lets take following decl: + // + // int (*foo[2])[3]; + // + // This compiles to in DWARF: + // + // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] + // \ + // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] + // \ + // -> (B1) DW_TAG_BaseType (int) + // + // RDI expects: + // + // foo -> Array[2] -> Pointer -> Array[3] -> int + // + // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and + // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. + // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from + // B to A. + struct SubrangeNode { struct SubrangeNode *next; U64 count; }; + struct SubrangeNode *subrange_stack = 0; + for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind != DW_TagKind_SubrangeType) { + // TODO: error handling + AssertAlways(!"unexpected tag"); + continue; + } + + // resolve lower bound + U64 lower_bound = 0; + if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_LowerBound)) { + lower_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_LowerBound); + } else { + lower_bound = dw_pick_default_lower_bound(cu_lang); + } + + // resolve upper bound + U64 upper_bound = 0; + if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_Count)) { + U64 count = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_Count); + upper_bound = lower_bound + count; + } else if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_UpperBound)) { + upper_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_UpperBound); + // turn upper bound into exclusive range + upper_bound += 1; + } else { + // zero sized array + } + + struct SubrangeNode *s = push_array(scratch.arena, struct SubrangeNode, 1); + s->count = upper_bound - lower_bound; + SLLStackPush(subrange_stack, s); } - } - } break; - case DW_TagKind_BaseType: { - DW_ATE encoding = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Encoding); - U64 byte_size = dw_byte_size_from_tag(input, cu, tag); - - // convert base type encoding to RDI version - RDI_TypeKind kind = RDI_TypeKind_NULL; - switch (encoding) { - case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; - case DW_ATE_Address: kind = RDI_TypeKind_Void; break; - case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; - case DW_ATE_ComplexFloat: { - switch (byte_size) { - case 4: kind = RDI_TypeKind_ComplexF32; break; - case 8: kind = RDI_TypeKind_ComplexF64; break; - case 10: kind = RDI_TypeKind_ComplexF80; break; - case 16: kind = RDI_TypeKind_ComplexF128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling + + RDIM_Type *array_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = array_base_type; + U64 size_cursor = array_base_type->byte_size; + for EachNode(s, struct SubrangeNode, subrange_stack) { + size_cursor *= s->count; + + RDIM_Type *t; + if (s->next) { t = d2r_create_type(arena, type_table); } + else { t = d2r_create_type_from_offset(arena, type_table, tag.info_off); } + + t->kind = RDI_TypeKind_Array; + t->direct_type = direct_type; + t->byte_size = size_cursor; + t->count = s->count; + + direct_type = t; } + + d2r_tag_iterator_skip_children(it); } break; - case DW_ATE_Float: { - switch (byte_size) { - case 2: kind = RDI_TypeKind_F16; break; - case 4: kind = RDI_TypeKind_F32; break; - case 6: kind = RDI_TypeKind_F48; break; - case 8: kind = RDI_TypeKind_F64; break; - case 16: kind = RDI_TypeKind_F128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Signed: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_S8; break; - case 2: kind = RDI_TypeKind_S16; break; - case 4: kind = RDI_TypeKind_S32; break; - case 8: kind = RDI_TypeKind_S64; break; - case 16: kind = RDI_TypeKind_S128; break; - case 32: kind = RDI_TypeKind_S256; break; - case 64: kind = RDI_TypeKind_S512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_SignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_Char8; break; - case 2: kind = RDI_TypeKind_Char16; break; - case 4: kind = RDI_TypeKind_Char32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Unsigned: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_U8; break; - case 2: kind = RDI_TypeKind_U16; break; - case 4: kind = RDI_TypeKind_U32; break; - case 8: kind = RDI_TypeKind_U64; break; - case 16: kind = RDI_TypeKind_U128; break; - case 32: kind = RDI_TypeKind_U256; break; - case 64: kind = RDI_TypeKind_U512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_UnsignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_UChar8; break; - case 2: kind = RDI_TypeKind_UChar16; break; - case 4: kind = RDI_TypeKind_UChar32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_ImaginaryFloat: { - NotImplemented; - } break; - case DW_ATE_PackedDecimal: { - NotImplemented; - } break; - case DW_ATE_NumericString: { - NotImplemented; - } break; - case DW_ATE_Edited: { - NotImplemented; - } break; - case DW_ATE_SignedFixed: { - NotImplemented; - } break; - case DW_ATE_UnsignedFixed: { - NotImplemented; - } break; - case DW_ATE_DecimalFloat: { - NotImplemented; - } break; - case DW_ATE_Utf: { - NotImplemented; - } break; - case DW_ATE_Ucs: { - NotImplemented; - } break; - case DW_ATE_Ascii: { - NotImplemented; - } break; - default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling - } - - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - type->direct_type = type_table->builtin_types[kind]; - type->byte_size = byte_size; - } break; - case DW_TagKind_PointerType: { - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - - // TODO: - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Allocated)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Associated)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_AddressClass)); - - U64 byte_size = arch_addr_size; - if (cu->version == DW_Version_5 || cu->relaxed) { - dw_try_byte_size_from_tag(input, cu, tag, &byte_size); - } - - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Ptr; - type->byte_size = byte_size; - type->direct_type = direct_type; - } break; - case DW_TagKind_RestrictType: { - // TODO: - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); - - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Restrict; - type->direct_type = direct_type; - } break; - case DW_TagKind_VolatileType: { - // TODO: - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); - - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Volatile; - type->direct_type = direct_type; - } break; - case DW_TagKind_ConstType: { - // TODO: - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); - Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); - - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Const; - type->direct_type = direct_type; - } break; - case DW_TagKind_ArrayType: { - // * DWARF vs RDI Array Type Graph * - // - // For example lets take following decl: - // - // int (*foo[2])[3]; - // - // This compiles to in DWARF: - // - // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] - // \ - // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] - // \ - // -> (B1) DW_TAG_BaseType (int) - // - // RDI expects: - // - // foo -> Array[2] -> Pointer -> Array[3] -> int - // - // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and - // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. - // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from - // B to A. - struct SubrangeNode { struct SubrangeNode *next; U64 count; }; - struct SubrangeNode *subrange_stack = 0; - for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind != DW_TagKind_SubrangeType) { - // TODO: error handling - AssertAlways(!"unexpected tag"); - continue; - } - - // resolve lower bound - U64 lower_bound = 0; - if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_LowerBound)) { - lower_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_LowerBound); - } else { - lower_bound = dw_pick_default_lower_bound(cu_lang); - } - - // resolve upper bound - U64 upper_bound = 0; - if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_Count)) { - U64 count = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_Count); - upper_bound = lower_bound + count; - } else if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_UpperBound)) { - upper_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_UpperBound); - // turn upper bound into exclusive range - upper_bound += 1; - } else { - // zero sized array - } - - struct SubrangeNode *s = push_array(scratch.arena, struct SubrangeNode, 1); - s->count = upper_bound - lower_bound; - SLLStackPush(subrange_stack, s); - } - - RDIM_Type *array_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_Type *direct_type = array_base_type; - U64 size_cursor = array_base_type->byte_size; - for EachNode(s, struct SubrangeNode, subrange_stack) { - size_cursor *= s->count; - - RDIM_Type *t; - if (s->next) { t = d2r_create_type(arena, type_table); } - else { t = d2r_create_type_from_offset(arena, type_table, tag.info_off); } - - t->kind = RDI_TypeKind_Array; - t->direct_type = direct_type; - t->byte_size = size_cursor; - t->count = s->count; - - direct_type = t; - } - - d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_SubrangeType: { - // TODO: error handling - AssertAlways(!"unexpected tag"); - } break; - case DW_TagKind_Inheritance: { - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind != DW_TagKind_StructureType && parent_tag.kind != DW_TagKind_ClassType) { + case DW_TagKind_SubrangeType: { // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - RDIM_Type *parent = d2r_type_from_offset(type_table, parent_tag.info_off); - RDIM_Type *type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); - member->kind = RDI_MemberKind_Base; - member->type = type; - member->off = safe_cast_u32(dw_const_u32_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation)); - } break; + AssertAlways(!"unexpected tag"); + } break; + case DW_TagKind_Inheritance: { + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + if (parent_tag.kind != DW_TagKind_StructureType && parent_tag.kind != DW_TagKind_ClassType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + RDIM_Type *parent = d2r_type_from_offset(type_table, parent_tag.info_off); + RDIM_Type *type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); + member->kind = RDI_MemberKind_Base; + member->type = type; + member->off = safe_cast_u32(dw_const_u32_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation)); + } break; } } scratch_end(scratch); @@ -1710,85 +1710,85 @@ d2r_convert_udts(Arena *arena, DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; switch (tag.kind) { - case DW_TagKind_ClassType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - type->udt = udt; - } - } break; - case DW_TagKind_StructureType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - type->udt = udt; - } - } break; - case DW_TagKind_UnionType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - type->udt = udt; - } - } break; - case DW_TagKind_EnumerationType: { - B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); - if (is_decl) { - d2r_tag_iterator_skip_children(it); - } else { - RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - type->udt = udt; - } - } break; - case DW_TagKind_Member: { - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - B32 is_parent_udt = parent_tag.kind == DW_TagKind_StructureType || - parent_tag.kind == DW_TagKind_ClassType || - parent_tag.kind == DW_TagKind_UnionType; - if (is_parent_udt) { - DW_Attrib *data_member_location = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_DataMemberLocation); - DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); - if (data_member_location_class == DW_AttribClass_LocList) { - AssertAlways(!"UDT member with multiple locations are not supported"); + case DW_TagKind_ClassType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + type->udt = udt; } - - RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); - RDIM_UDTMember *udt_member = rdim_udt_push_member(arena, &udts, parent_type->udt); - udt_member->kind = RDI_MemberKind_DataField; - udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - udt_member->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - udt_member->off = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation); - } else { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - } break; - case DW_TagKind_Enumerator: { - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_EnumerationType) { - RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); - RDIM_UDTEnumVal *udt_member = rdim_udt_push_enum_val(arena, &udts, parent_type->udt); - udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - udt_member->val = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ConstValue); - } else { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - } break; + } break; + case DW_TagKind_StructureType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + type->udt = udt; + } + } break; + case DW_TagKind_UnionType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + type->udt = udt; + } + } break; + case DW_TagKind_EnumerationType: { + B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); + if (is_decl) { + d2r_tag_iterator_skip_children(it); + } else { + RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + type->udt = udt; + } + } break; + case DW_TagKind_Member: { + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + B32 is_parent_udt = parent_tag.kind == DW_TagKind_StructureType || + parent_tag.kind == DW_TagKind_ClassType || + parent_tag.kind == DW_TagKind_UnionType; + if (is_parent_udt) { + DW_Attrib *data_member_location = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_DataMemberLocation); + DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); + if (data_member_location_class == DW_AttribClass_LocList) { + AssertAlways(!"UDT member with multiple locations are not supported"); + } + + RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); + RDIM_UDTMember *udt_member = rdim_udt_push_member(arena, &udts, parent_type->udt); + udt_member->kind = RDI_MemberKind_DataField; + udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + udt_member->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); + udt_member->off = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation); + } else { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + } break; + case DW_TagKind_Enumerator: { + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + if (parent_tag.kind == DW_TagKind_EnumerationType) { + RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); + RDIM_UDTEnumVal *udt_member = rdim_udt_push_enum_val(arena, &udts, parent_type->udt); + udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + udt_member->val = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ConstValue); + } else { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + } break; } } scratch_end(scratch); @@ -1811,37 +1811,110 @@ d2r_convert_symbols(Arena *arena, DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; switch (tag.kind) { - case DW_TagKind_Null: { InvalidPath; } break; - case DW_TagKind_ClassType: - case DW_TagKind_StructureType: - case DW_TagKind_UnionType: { - // visit children to collect methods and variables - } break; - case DW_TagKind_EnumerationType: - case DW_TagKind_SubroutineType: - case DW_TagKind_Typedef: - case DW_TagKind_BaseType: - case DW_TagKind_PointerType: - case DW_TagKind_RestrictType: - case DW_TagKind_VolatileType: - case DW_TagKind_ConstType: - case DW_TagKind_ArrayType: - case DW_TagKind_SubrangeType: - case DW_TagKind_Inheritance: - case DW_TagKind_Enumerator: - case DW_TagKind_Member: { - d2r_tag_iterator_skip_children(it); - } break; - case DW_TagKind_SubProgram: { - DW_InlKind inl = dw_u64_from_attrib(input, cu, tag, DW_AttribKind_Inline); - switch (inl) { - case DW_Inl_NotInlined: { + case DW_TagKind_Null: { InvalidPath; } break; + case DW_TagKind_ClassType: + case DW_TagKind_StructureType: + case DW_TagKind_UnionType: { + // visit children to collect methods and variables + } break; + case DW_TagKind_EnumerationType: + case DW_TagKind_SubroutineType: + case DW_TagKind_Typedef: + case DW_TagKind_BaseType: + case DW_TagKind_PointerType: + case DW_TagKind_RestrictType: + case DW_TagKind_VolatileType: + case DW_TagKind_ConstType: + case DW_TagKind_ArrayType: + case DW_TagKind_SubrangeType: + case DW_TagKind_Inheritance: + case DW_TagKind_Enumerator: + case DW_TagKind_Member: { + d2r_tag_iterator_skip_children(it); + } break; + case DW_TagKind_SubProgram: { + DW_InlKind inl = dw_u64_from_attrib(input, cu, tag, DW_AttribKind_Inline); + switch (inl) { + case DW_Inl_NotInlined: { + U64 param_count = 0; + RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); + + // get return type + RDIM_Type *ret_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); + + // fill out proc type + RDIM_Type *proc_type = d2r_create_type(arena, type_table); + proc_type->kind = RDI_TypeKind_Function; + proc_type->byte_size = arch_addr_size; + proc_type->direct_type = ret_type; + proc_type->count = param_count; + proc_type->param_types = params; + + // get container type + RDIM_Type *container_type = 0; + if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { + container_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); + } + + // get frame base expression + String8 frame_base_expr = dw_exprloc_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_FrameBase); + + // get proc container symbol + RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP); + + // make scope + Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); + RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); + root_scope->symbol = proc; + + // fill out proc + proc->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); + proc->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + proc->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); + proc->type = proc_type; + proc->container_symbol = 0; + proc->container_type = container_type; + proc->root_scope = root_scope; + proc->location_cases = d2r_locset_from_attrib(arena, &scopes, root_scope, &locations, input, cu, image_base, arch, tag, DW_AttribKind_FrameBase); + + // sub program with user-defined parent tag is a method + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + if (parent_tag.kind == DW_TagKind_ClassType || parent_tag.kind == DW_TagKind_StructureType) { + RDI_MemberKind member_kind = RDI_MemberKind_NULL; + DW_VirtualityKind virtuality = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Virtuality); + switch (virtuality) { + case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; + case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; + case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal + //default: InvalidPath; break; + } + + RDIM_Type *type = d2r_type_from_offset(type_table, parent_tag.info_off); + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); + member->kind = member_kind; + member->type = type; + member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + } else if (parent_tag.kind != DW_TagKind_CompileUnit) { + //AssertAlways(!"unexpected tag"); + } + + it->stack->scope = root_scope; + } break; + case DW_Inl_DeclaredNotInlined: + case DW_Inl_DeclaredInlined: + case DW_Inl_Inlined: { + d2r_tag_iterator_skip_children(it); + } break; + default: InvalidPath; break; + } + } break; + case DW_TagKind_InlinedSubroutine: { U64 param_count = 0; RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); - + // get return type RDIM_Type *ret_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - + // fill out proc type RDIM_Type *proc_type = d2r_create_type(arena, type_table); proc_type->kind = RDI_TypeKind_Function; @@ -1849,197 +1922,124 @@ d2r_convert_symbols(Arena *arena, proc_type->direct_type = ret_type; proc_type->count = param_count; proc_type->param_types = params; - + // get container type - RDIM_Type *container_type = 0; + RDIM_Type *owner = 0; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { - container_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); + owner = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); } - - // get frame base expression - String8 frame_base_expr = dw_exprloc_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_FrameBase); - - // get proc container symbol - RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP); - + + // fill out inline site + RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); + inline_site->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + inline_site->type = proc_type; + inline_site->owner = owner; + inline_site->line_table = 0; + // make scope Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); - root_scope->symbol = proc; - - // fill out proc - proc->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); - proc->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - proc->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); - proc->type = proc_type; - proc->container_symbol = 0; - proc->container_type = container_type; - proc->root_scope = root_scope; - proc->location_cases = d2r_locset_from_attrib(arena, &scopes, root_scope, &locations, input, cu, image_base, arch, tag, DW_AttribKind_FrameBase); - - // sub program with user-defined parent tag is a method + root_scope->inline_site = inline_site; + } break; + case DW_TagKind_Variable: { + String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + RDIM_Type *type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_ClassType || parent_tag.kind == DW_TagKind_StructureType) { - RDI_MemberKind member_kind = RDI_MemberKind_NULL; - DW_VirtualityKind virtuality = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Virtuality); - switch (virtuality) { - case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; - case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; - case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal - //default: InvalidPath; break; - } - - RDIM_Type *type = d2r_type_from_offset(type_table, parent_tag.info_off); - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); - member->kind = member_kind; - member->type = type; - member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - } else if (parent_tag.kind != DW_TagKind_CompileUnit) { - //AssertAlways(!"unexpected tag"); - } - - it->stack->scope = root_scope; - } break; - case DW_Inl_DeclaredNotInlined: - case DW_Inl_DeclaredInlined: - case DW_Inl_Inlined: { - d2r_tag_iterator_skip_children(it); - } break; - default: InvalidPath; break; - } - } break; - case DW_TagKind_InlinedSubroutine: { - U64 param_count = 0; - RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); - - // get return type - RDIM_Type *ret_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - - // fill out proc type - RDIM_Type *proc_type = d2r_create_type(arena, type_table); - proc_type->kind = RDI_TypeKind_Function; - proc_type->byte_size = arch_addr_size; - proc_type->direct_type = ret_type; - proc_type->count = param_count; - proc_type->param_types = params; - - // get container type - RDIM_Type *owner = 0; - if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { - owner = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); - } - - // fill out inline site - RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); - inline_site->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - inline_site->type = proc_type; - inline_site->owner = owner; - inline_site->line_table = 0; - - // make scope - Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); - RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); - root_scope->inline_site = inline_site; - } break; - case DW_TagKind_Variable: { - String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - RDIM_Type *type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_SubProgram || - parent_tag.kind == DW_TagKind_InlinedSubroutine || - parent_tag.kind == DW_TagKind_LexicalBlock) { - RDIM_Scope *scope = it->stack->next->scope; - RDIM_Local *local = rdim_scope_push_local(arena, &scopes, scope); - local->kind = RDI_LocalKind_Variable; - local->name = name; - local->type = type; - local->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); - } else { - - // NOTE: due to a bug in clang in stb_sprint.h local variables - // are declared in global scope without a name - if (name.size == 0) { break; } - - B32 is_thread_var = 0; - U64 voff = 0; - { - DW_Attrib *loc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_Location); - DW_AttribClass loc_class = dw_value_class_from_attrib(cu, loc_attrib); - if (loc_class == DW_AttribClass_ExprLoc) { - String8 expr = dw_exprloc_from_attrib(input, cu, loc_attrib); - B32 is_addr = 0; - RDIM_EvalBytecode bc = d2r_bytecode_from_expression(arena, input, image_base, arch_addr_size, arch, cu->addr_lu, expr, cu, &is_addr); - - for EachNode(n, RDIM_EvalBytecodeOp, bc.first_op) { - if (n->op == RDI_EvalOp_TLSOff) { - is_thread_var = 1; - break; + if (parent_tag.kind == DW_TagKind_SubProgram || + parent_tag.kind == DW_TagKind_InlinedSubroutine || + parent_tag.kind == DW_TagKind_LexicalBlock) { + RDIM_Scope *scope = it->stack->next->scope; + RDIM_Local *local = rdim_scope_push_local(arena, &scopes, scope); + local->kind = RDI_LocalKind_Variable; + local->name = name; + local->type = type; + local->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); + } else { + + // NOTE: due to a bug in clang in stb_sprint.h local variables + // are declared in global scope without a name + if (name.size == 0) { break; } + + B32 is_thread_var = 0; + U64 voff = 0; + { + DW_Attrib *loc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_Location); + DW_AttribClass loc_class = dw_value_class_from_attrib(cu, loc_attrib); + if (loc_class == DW_AttribClass_ExprLoc) { + String8 expr = dw_exprloc_from_attrib(input, cu, loc_attrib); + B32 is_addr = 0; + RDIM_EvalBytecode bc = d2r_bytecode_from_expression(arena, input, image_base, arch_addr_size, arch, cu->addr_lu, expr, cu, &is_addr); + + for EachNode(n, RDIM_EvalBytecodeOp, bc.first_op) { + if (n->op == RDI_EvalOp_TLSOff) { + is_thread_var = 1; + break; + } } - } - - if (is_addr) { - if (rdim_is_eval_bytecode_static(bc)) { - voff = rdim_do_static_bytecode_eval(bc, image_base); + + if (is_addr) { + if (rdim_is_eval_bytecode_static(bc)) { + voff = rdim_do_static_bytecode_eval(bc, image_base); + } } } } + + RDIM_SymbolChunkList *var_chunks; U64 var_chunks_cap; + if (is_thread_var) { var_chunks = &tvars; var_chunks_cap = TVAR_CHUNK_CAP; } + else { var_chunks = &gvars; var_chunks_cap = GVAR_CHUNK_CAP; } + + RDIM_Symbol *var = rdim_symbol_chunk_list_push(arena, var_chunks, var_chunks_cap); + var->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); + var->name = name; + var->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); + var->type = type; + var->offset = voff; + var->container_symbol = 0; + var->container_type = 0; // TODO: NotImplemented; } - - RDIM_SymbolChunkList *var_chunks; U64 var_chunks_cap; - if (is_thread_var) { var_chunks = &tvars; var_chunks_cap = TVAR_CHUNK_CAP; } - else { var_chunks = &gvars; var_chunks_cap = GVAR_CHUNK_CAP; } - - RDIM_Symbol *var = rdim_symbol_chunk_list_push(arena, var_chunks, var_chunks_cap); - var->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); - var->name = name; - var->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); - var->type = type; - var->offset = voff; - var->container_symbol = 0; - var->container_type = 0; // TODO: NotImplemented; - } - } break; - case DW_TagKind_FormalParameter: { - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine) { - RDIM_Scope *scope = it->stack->next->scope; - RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); - param->kind = RDI_LocalKind_Parameter; - param->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); - param->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); - param->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); - } else { - // TODO: error handling - AssertAlways(!"this is a local variable"); - } - } break; - case DW_TagKind_LexicalBlock: { - DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); - if (parent_tag.kind == DW_TagKind_SubProgram || - parent_tag.kind == DW_TagKind_InlinedSubroutine || - parent_tag.kind == DW_TagKind_LexicalBlock) { - Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); - d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); - } - } break; - case DW_TagKind_CallSite: { - // TODO - } break; - case DW_TagKind_CallSiteParameter: { - // TODO - } break; - case DW_TagKind_Label: - case DW_TagKind_CompileUnit: - case DW_TagKind_UnspecifiedParameters: - case DW_TagKind_Namespace: - case DW_TagKind_ImportedDeclaration: - case DW_TagKind_PtrToMemberType: - case DW_TagKind_TemplateTypeParameter: - case DW_TagKind_ReferenceType: { - // TODO: - } break; - default: NotImplemented; break; + } break; + case DW_TagKind_FormalParameter: { + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + if (parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine) { + RDIM_Scope *scope = it->stack->next->scope; + RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); + param->kind = RDI_LocalKind_Parameter; + param->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + param->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); + param->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); + } else { + // TODO: error handling + AssertAlways(!"this is a local variable"); + } + } break; + case DW_TagKind_LexicalBlock: { + DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); + if (parent_tag.kind == DW_TagKind_SubProgram || + parent_tag.kind == DW_TagKind_InlinedSubroutine || + parent_tag.kind == DW_TagKind_LexicalBlock) { + Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); + d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); + } + } break; + case DW_TagKind_CallSite: { + // TODO + } break; + case DW_TagKind_CallSiteParameter: { + // TODO + } break; + case DW_TagKind_Label: + case DW_TagKind_CompileUnit: + case DW_TagKind_UnspecifiedParameters: + case DW_TagKind_Namespace: + case DW_TagKind_ImportedDeclaration: + case DW_TagKind_PtrToMemberType: + case DW_TagKind_TemplateTypeParameter: + case DW_TagKind_ReferenceType: { + // TODO: + } break; + default: NotImplemented; break; } } scratch_end(scratch); @@ -2052,68 +2052,68 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) if (lane_idx() == 0) { //////////////////////////////// - + ProfBegin("compute exe hash"); U64 exe_hash = rdi_hash(params->exe_data.str, params->exe_data.size); ProfEnd(); - + //////////////////////////////// - + Arch arch = Arch_Null; U64 image_base = 0; DW_Input input = {0}; - + switch(params->exe_kind) { - default:{}break; - case ExecutableImageKind_CoffPe: { - PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); - String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); - COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(raw_sections, 0, sizeof(COFF_SectionHeader) * pe.section_count); - String8 string_table = str8_substr(params->exe_data, pe.string_table_range); - arch = pe.arch; - image_base = pe.image_base; - binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, pe.section_count, section_table); - input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, pe.section_count, section_table); - } break; - case ExecutableImageKind_Elf32: - case ExecutableImageKind_Elf64: { - ELF_Bin bin = elf_bin_from_data(scratch.arena, params->dbg_data); - arch = arch_from_elf_machine(bin.hdr.e_machine); - image_base = elf_base_addr_from_bin(&bin); - binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs); - input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); - } break; + default:{}break; + case ExecutableImageKind_CoffPe: { + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); + String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); + COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(raw_sections, 0, sizeof(COFF_SectionHeader) * pe.section_count); + String8 string_table = str8_substr(params->exe_data, pe.string_table_range); + arch = pe.arch; + image_base = pe.image_base; + binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, pe.section_count, section_table); + input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, pe.section_count, section_table); + } break; + case ExecutableImageKind_Elf32: + case ExecutableImageKind_Elf64: { + ELF_Bin bin = elf_bin_from_data(scratch.arena, params->dbg_data); + arch = arch_from_elf_machine(bin.hdr.e_machine); + image_base = elf_base_addr_from_bin(&bin); + binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs); + input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); + } break; } - + //////////////////////////////// - + top_level_info = rdim_make_top_level_info(params->exe_name, arch, exe_hash, binary_sections); - + //////////////////////////////// - + U64 arch_addr_size = rdi_addr_size_from_arch(top_level_info.arch); - + //////////////////////////////// - + RDIM_Scope *global_scope = rdim_scope_chunk_list_push(arena, &scopes, SCOPE_CHUNK_CAP); - + //////////////////////////////// - + ProfBegin("Parse Unit Contrib Map"); D2R_CompUnitContribMap cu_contrib_map = {0}; if (input.sec[DW_Section_ARanges].data.size) { cu_contrib_map = d2r_cu_contrib_map_from_aranges(arena, &input, image_base); } ProfEnd(); - + ProfBegin("Parse Comop Unit Ranges"); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input); Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input.sec[DW_Section_Info].data); Rng1U64Array cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Compile Unit Headers"); // TODO(rjf): parse should always be relaxed. any verification checks we do // should just be logged via log_info(...), and then the caller of this @@ -2124,9 +2124,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, &input, lu_input, cu_ranges.v[cu_idx].min, is_parse_relaxed); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Line Tables"); DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); for EachIndex(cu_idx, cu_ranges.count) { @@ -2137,15 +2137,15 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Convert Line Tables"); HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); RDIM_LineTable **cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); for EachIndex(cu_idx, cu_ranges.count) { cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); - + DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; @@ -2164,78 +2164,78 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) } src_file_map[file_idx] = src_file; } - + for EachNode(line_seq, DW_LineSeqNode, line_table->first_seq) { if (line_seq->count == 0) { continue; } - + U64 *voffs = push_array(arena, U64, line_seq->count); U32 *line_nums = push_array(arena, U32, line_seq->count); U16 *col_nums = 0; U64 line_idx = 0; - + DW_LineNode *file_line_n = line_seq->first; U64 file_line_count = 0; - + for EachNode(line_n, DW_LineNode, file_line_n) { if (file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + U64 lines_written = 0; U64 prev_ln = max_U64; DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; for (; file_line_n != sentinel; file_line_n = file_line_n->next) { if (file_line_n->v.line != prev_ln) { if (file_line_n->v.address == 0) { continue; } - + voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; - + ++lines_written; ++line_idx; - + prev_ln = file_line_n->v.line; } } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); - + file_line_count = 1; } else { file_line_count += 1; } } - + // handle last line if (file_line_n) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + for (; file_line_n != 0; file_line_n = file_line_n->next, line_idx += 1) { // TODO: error handling AssertAlways(file_line_n->v.address >= image_base); voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); } - + //Assert(line_idx == line_seq->count); } } ProfEnd(); - + //////////////////////////////// - + RDIM_Type *builtin_types[RDI_TypeKind_Count] = {0}; for (RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) { RDIM_Type *type = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); @@ -2246,53 +2246,53 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) } builtin_types[RDI_TypeKind_Void]->byte_size = arch_addr_size; builtin_types[RDI_TypeKind_Handle]->byte_size = arch_addr_size; - + builtin_types[RDI_TypeKind_Variadic] = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); builtin_types[RDI_TypeKind_Variadic]->kind = RDI_TypeKind_Variadic; - + //////////////////////////////// - + ProfBegin("Convert Units"); for EachIndex(cu_idx, cu_ranges.count) { Temp comp_temp = temp_begin(scratch.arena); - + DW_CompUnit *cu = &cu_arr[cu_idx]; - + // parse and build tag tree DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); - + // skip DWO { if (cu->dwo_id) { goto next_cu; } - + String8 dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_DwoName); if (dwo_name.size) { goto next_cu; } - + String8 gnu_dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_GNU_DwoName); if (gnu_dwo_name.size) { goto next_cu; } } - + // build (info offset -> tag) hash table to resolve tags with abstract origin cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); - + // extract compile unit info String8 cu_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Name); String8 cu_dir = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_CompDir); String8 cu_prod = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Producer); DW_Language cu_lang = dw_const_u64_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Language); - + // init type table D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); type_table->ht = hash_table_init(comp_temp.arena, 0x4000); type_table->types = &types; type_table->type_chunk_cap = TYPE_CHUNK_CAP; type_table->builtin_types = builtin_types; - + // convert debug info d2r_convert_types(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); d2r_convert_udts(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); d2r_convert_symbols(arena, type_table, global_scope, &input, cu, cu_lang, arch_addr_size, image_base, arch, tag_tree.root); - + RDIM_Rng1U64ChunkList cu_voff_ranges = {0}; if (cu_idx < cu_contrib_map.count) { cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); @@ -2300,7 +2300,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) // TODO: synthesize cu ranges from scopes NotImplemented; } - + // convert compile unit { RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); @@ -2314,15 +2314,15 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) unit->line_table = cu_line_tables_rdi[cu_idx]; unit->voff_ranges = cu_voff_ranges; } - + next_cu:; temp_end(comp_temp); } ProfEnd(); } - + lane_sync(); - + RDIM_BakeParams bake_params = {0}; bake_params.top_level_info = top_level_info; bake_params.binary_sections = binary_sections; @@ -2337,7 +2337,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) bake_params.procedures = procs; bake_params.scopes = scopes; bake_params.inline_sites = inline_sites; - + scratch_end(scratch); return bake_params; }