From 4164b30aac68afe265eaba4d126302ebe2e53f01 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 1 Nov 2024 15:18:40 -0700 Subject: [PATCH] move breakpad converter to async layer; eliminate task system --- README.md | 4 +- src/base/base_entry_point.c | 3 - src/raddbg/raddbg_main.c | 2 - .../rdi_breakpad_from_pdb_main.c | 33 +- src/rdi_from_pdb/rdi_from_pdb.c | 2837 ----------------- src/rdi_from_pdb/rdi_from_pdb_main.c | 2 - src/scratch/ryan_scratch.c | 2 - src/task_system/task_system.c | 238 -- src/task_system/task_system.h | 162 - 9 files changed, 20 insertions(+), 3263 deletions(-) delete mode 100644 src/task_system/task_system.c delete mode 100644 src/task_system/task_system.h diff --git a/README.md b/README.md index 3eff971f..be4e9c25 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,8 @@ not depend on any other layers in the codebase. The folders which contain these layers are prefixed with `lib_`, like `lib_rdi_format`. A list of the layers in the codebase and their associated namespaces is below: +- `async` (`ASYNC_`): Implements a system for asynchronous work to be queued + and executed on a thread pool. - `base` (no namespace): Universal, codebase-wide constructs. Strings, math, memory allocators, helper macros, command-line parsing, and so on. Depends on no other codebase layers. @@ -375,8 +377,6 @@ A list of the layers in the codebase and their associated namespaces is below: as-needed basis. Higher level drawing features are implemented in the `draw` layer. - `scratch` (no namespace): Scratch space for small and transient test programs. -- `task_system` (`TS_`): Implements a system for kicking off asynchronous tasks - and obtaining artifacts from those tasks once they've completed. - `texture_cache` (`TEX_`): Implements an asynchronously-filled cache for GPU texture data, filled by data sourced in the `hash_store` layer's cache. Used for asynchronously preparing data for visualization. diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index 069cb5a6..018cb46a 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -33,9 +33,6 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum #if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL) p2r_init(); #endif -#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL) - ts_init(); -#endif #if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL) hs_init(); #endif diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 141a97b2..366127aa 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -574,7 +574,6 @@ #include "base/base_inc.h" #include "os/os_inc.h" #include "async/async.h" -#include "task_system/task_system.h" #include "rdi_format/rdi_format_local.h" #include "rdi_make/rdi_make_local.h" #include "mdesk/mdesk.h" @@ -617,7 +616,6 @@ #include "base/base_inc.c" #include "os/os_inc.c" #include "async/async.c" -#include "task_system/task_system.c" #include "rdi_format/rdi_format_local.c" #include "rdi_make/rdi_make_local.c" #include "mdesk/mdesk.c" diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index fcfa2893..a0f99689 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -25,7 +25,7 @@ //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" -#include "task_system/task_system.h" +#include "async/async.h" #include "rdi_make/rdi_make_local.h" #include "coff/coff.h" #include "codeview/codeview.h" @@ -40,7 +40,7 @@ //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" -#include "task_system/task_system.c" +#include "async/async.c" #include "rdi_make/rdi_make_local.c" #include "coff/coff.c" #include "codeview/codeview.c" @@ -63,9 +63,10 @@ struct P2B_BakeUnitVMapIn RDIM_UnitChunkList *units; }; -internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_vmap_task__entry_point) +ASYNC_WORK_DEF(p2b_bake_unit_vmap_work) { - P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)p; + Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)input; RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); *out = rdim_bake_unit_vmap(arena, in->units); return out; @@ -79,9 +80,10 @@ struct P2B_BakeLineTablesIn RDIM_LineTableChunkList *line_tables; }; -internal TS_TASK_FUNCTION_DEF(p2b_bake_line_table_task__entry_point) +ASYNC_WORK_DEF(p2b_bake_line_table_work) { - P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)p; + Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)input; RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); *out = rdim_bake_line_tables(arena, in->line_tables); return out; @@ -100,9 +102,10 @@ struct P2B_DumpProcChunkIn RDIM_SymbolChunkNode *chunk; }; -internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) +ASYNC_WORK_DEF(p2b_dump_proc_chunk_work) { - P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)p; + Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)input; String8List *out = push_array(arena, String8List, 1); RDI_LineTable *line_tables = in->line_tables_bake->line_tables; RDI_U64 line_tables_count = in->line_tables_bake->line_tables_count; @@ -225,11 +228,11 @@ entry_point(CmdLine *cmdline) //- rjf: kick off unit vmap baking P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units}; - TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, &bake_unit_vmap_in); + ASYNC_Task *bake_unit_vmap_task = async_task_launch(arena, p2b_bake_unit_vmap_work, .input = &bake_unit_vmap_in); //- rjf: kick off line-table baking P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables}; - TS_Ticket bake_line_tables_ticket = ts_kickoff(p2b_bake_line_table_task__entry_point, &bake_line_tables_in); + ASYNC_Task *bake_line_tables_task = async_task_launch(arena, p2b_bake_line_table_work, .input = &bake_line_tables_in); //- rjf: build unit -> line table idx array U64 unit_count = params->units.total_count; @@ -264,19 +267,19 @@ entry_point(CmdLine *cmdline) //- rjf: join unit vmap ProfBegin("join unit vmap"); - RDIM_UnitVMapBakeResult *bake_unit_vmap_out = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + RDIM_UnitVMapBakeResult *bake_unit_vmap_out = async_task_join_struct(bake_unit_vmap_task, RDIM_UnitVMapBakeResult); RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap.vmap; U32 unit_vmap_count = bake_unit_vmap_out->vmap.count; ProfEnd(); //- rjf: join line tables ProfBegin("join line table"); - RDIM_LineTableBakeResult *bake_line_tables_out = ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_LineTableBakeResult); + RDIM_LineTableBakeResult *bake_line_tables_out = async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); ProfEnd(); //- rjf: kick off FUNC & line record dump tasks P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, params->procedures.chunk_count); - TS_Ticket *dump_proc_chunk_tickets = push_array(arena, TS_Ticket, params->procedures.chunk_count); + ASYNC_Task **dump_proc_chunk_tasks = push_array(arena, ASYNC_Task *, params->procedures.chunk_count); ProfScope("kick off FUNC & line record dump tasks") { U64 task_idx = 0; @@ -288,7 +291,7 @@ entry_point(CmdLine *cmdline) dump_proc_chunk_in[task_idx].unit_count = unit_count; dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out; dump_proc_chunk_in[task_idx].chunk = n; - dump_proc_chunk_tickets[task_idx] = ts_kickoff(p2b_dump_proc_chunk_task__entry_point, &dump_proc_chunk_in[task_idx]); + dump_proc_chunk_tasks[task_idx] = async_task_launch(arena, p2b_dump_proc_chunk_work, .input = &dump_proc_chunk_in[task_idx]); } } @@ -297,7 +300,7 @@ entry_point(CmdLine *cmdline) { for(U64 idx = 0; idx < params->procedures.chunk_count; idx += 1) { - String8List *out = ts_join_struct(dump_proc_chunk_tickets[idx], max_U64, String8List); + String8List *out = async_task_join_struct(dump_proc_chunk_tasks[idx], String8List); str8_list_concat_in_place(&dump, out); } } diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index d694738e..6808b955 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -579,66 +579,6 @@ ASYNC_WORK_DEF(p2r_comp_unit_contributions_parse_work) return out; } -//- - -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_exe_hash_task__entry_point) -{ - P2R_EXEHashIn *in = (P2R_EXEHashIn *)p; - U64 *out = push_array(arena, U64, 1); - ProfScope("hash exe") *out = rdi_hash(in->exe_data.str, in->exe_data.size); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_tpi_hash_parse_task__entry_point) -{ - P2R_TPIHashParseIn *in = (P2R_TPIHashParseIn *)p; - void *out = 0; - ProfScope("parse tpi hash") out = pdb_tpi_hash_from_data(arena, in->strtbl, in->tpi, in->hash_data, in->aux_data); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_tpi_leaf_parse_task__entry_point) -{ - P2R_TPILeafParseIn *in = (P2R_TPILeafParseIn *)p; - void *out = 0; - ProfScope("parse tpi leaf") out = cv_leaf_from_data(arena, in->leaf_data, in->itype_first); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_parse_task__entry_point) -{ - P2R_SymbolStreamParseIn *in = (P2R_SymbolStreamParseIn *)p; - void *out = 0; - ProfScope("parse symbol stream") out = cv_sym_from_data(arena, in->data, 4); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_c13_stream_parse_task__entry_point) -{ - P2R_C13StreamParseIn *in = (P2R_C13StreamParseIn *)p; - void *out = 0; - ProfScope("parse c13 stream") out = cv_c13_parsed_from_data(arena, in->data, in->strtbl, in->coff_sections); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_comp_unit_parse_task__entry_point) -{ - P2R_CompUnitParseIn *in = (P2R_CompUnitParseIn *)p; - void *out = 0; - ProfScope("parse comp units") out = pdb_comp_unit_array_from_data(arena, in->data); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_comp_unit_contributions_parse_task__entry_point) -{ - P2R_CompUnitContributionsParseIn *in = (P2R_CompUnitContributionsParseIn *)p; - void *out = 0; - ProfScope("parse comp unit contributions") out = pdb_comp_unit_contribution_array_from_data(arena, in->data, in->coff_sections); - return out; -} -#endif - //////////////////////////////// //~ rjf: Unit Conversion Tasks @@ -1107,474 +1047,6 @@ ASYNC_WORK_DEF(p2r_units_convert_work) return out; } -//- - -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) -{ - Temp scratch = scratch_begin(&arena, 1); - P2R_UnitConvertIn *in = (P2R_UnitConvertIn *)p; - P2R_UnitConvertOut *out = push_array(arena, P2R_UnitConvertOut, 1); - ProfScope("build units, initial src file map, & collect unit source files") - if(in->comp_units != 0) - { - U64 units_chunk_cap = in->comp_units->count; - P2R_SrcFileMap src_file_map = {0}; - src_file_map.slots_count = 65536; - src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); - - //////////////////////////// - //- rjf: pass 1: build per-unit info & per-unit line tables - // - ProfScope("pass 1: build per-unit info & per-unit line tables") - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) - { - PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; - CV_SymParsed *pdb_unit_sym = in->comp_unit_syms[comp_unit_idx]; - CV_C13Parsed *pdb_unit_c13 = in->comp_unit_c13s[comp_unit_idx]; - - //- rjf: produce unit name - String8 unit_name = pdb_unit->obj_name; - if(unit_name.size != 0) - { - String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); - if(unit_name_past_last_slash.size != 0) - { - unit_name = unit_name_past_last_slash; - } - } - - //- rjf: produce obj name - String8 obj_name = pdb_unit->obj_name; - if(str8_match(obj_name, str8_lit("* Linker *"), 0) || - str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) - { - MemoryZeroStruct(&obj_name); - } - - //- rjf: build this unit's line table, fill out primary line info (inline info added after) - RDIM_LineTable *line_table = 0; - for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; - node != 0; - node = node->next) - { - if(node->kind == CV_C13SubSectionKind_Lines) - { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) - { - CV_C13LinesParsed *lines = &lines_n->v; - - // rjf: file name -> normalized file path - String8 file_path = lines->file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); - for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) - { - if(file_path_normalized.str[idx] == '\\') - { - file_path_normalized.str[idx] = '/'; - } - } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) - { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: push sequence into both line table & source file's line map - if(lines->line_count != 0) - { - if(line_table == 0) - { - line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - } - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); - } - } - } - } - - //- rjf: build unit - RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); - dst_unit->unit_name = unit_name; - dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; - dst_unit->object_file = obj_name; - dst_unit->archive_file = pdb_unit->group_name; - dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); - dst_unit->line_table = line_table; - } - - //////////////////////////// - //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table - // - PDB_CompUnitContribution *contrib_ptr = in->comp_unit_contributions->contributions; - PDB_CompUnitContribution *contrib_opl = contrib_ptr + in->comp_unit_contributions->count; - ProfScope("pass 2: build per-unit voff ranges from comp unit contributions table") - for(;contrib_ptr < contrib_opl; contrib_ptr += 1) - { - if(contrib_ptr->mod < in->comp_units->count) - { - RDIM_Unit *unit = &out->units.first->v[contrib_ptr->mod]; - RDIM_Rng1U64 range = {contrib_ptr->voff_first, contrib_ptr->voff_opl}; - rdim_rng1u64_list_push(arena, &unit->voff_ranges, range); - } - } - - //////////////////////////// - //- rjf: pass 3: parse all inlinee line tables - // - out->units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, in->comp_units->count); - ProfScope("pass 3: parse all inlinee line tables") - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) - { - CV_SymParsed *unit_sym = in->comp_unit_syms[comp_unit_idx]; - CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; - CV_RecRange *rec_ranges_first = unit_sym->sym_ranges.ranges; - CV_RecRange *rec_ranges_opl = rec_ranges_first+unit_sym->sym_ranges.count; - U64 base_voff = 0; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: rec range -> symbol info range - U64 sym_off_first = rec_range->off + 2; - U64 sym_off_opl = rec_range->off + rec_range->hdr.size; - - //- rjf: skip invalid ranges - if(sym_off_opl > unit_sym->data.size || sym_off_first > unit_sym->data.size || sym_off_first > sym_off_opl) - { - continue; - } - - //- rjf: unpack symbol info - CV_SymKind kind = rec_range->hdr.kind; - U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = unit_sym->data.str + sym_off_first; - void *sym_data_opl = unit_sym->data.str + sym_off_opl; - - //- rjf: skip bad sizes - if(sym_off_first + sym_header_struct_size > sym_off_opl) - { - continue; - } - - //- rjf: process symbol - switch(kind) - { - default:{}break; - - //- rjf: LPROC32/GPROC32 (gather base address) - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: - { - CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; - COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= in->coff_sections.count) ? &in->coff_sections.v[proc32->sec-1] : 0; - if(section != 0) - { - base_voff = section->voff + proc32->off; - } - }break; - - //- rjf: INLINESITE - case CV_SymKind_INLINESITE: - { - // rjf: unpack sym - CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; - String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); - - // rjf: map inlinee -> parsed cv c13 inlinee line info - CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; - { - U64 hash = cv_hash_from_item_id(sym->inlinee); - U64 slot_idx = hash%unit_c13->inlinee_lines_parsed_slots_count; - for(CV_C13InlineeLinesParsedNode *n = unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) - { - if(n->v.inlinee == sym->inlinee) - { - inlinee_lines_parsed = &n->v; - break; - } - } - } - - // rjf: build line table, fill with parsed binary annotations - RDIM_LineTable *line_table = 0; - if(inlinee_lines_parsed != 0) - { - // rjf: state machine registers - CV_InlineRangeKind range_kind = 0; - U32 code_length = 0; - U32 code_offset = 0; - U32 last_code_offset = code_offset; - String8 file_name = inlinee_lines_parsed->file_name; - String8 last_file_name = file_name; - S32 line = (S32)inlinee_lines_parsed->first_source_ln; - S32 last_line = line; - S32 column = 1; - S32 last_column = column; - - // rjf: gathered lines - typedef struct LineChunk LineChunk; - struct LineChunk - { - LineChunk *next; - U64 cap; - U64 count; - U64 *voffs; // [line_count + 1] (sorted) - U32 *line_nums; // [line_count] - U16 *col_nums; // [2*line_count] - }; - LineChunk *first_line_chunk = 0; - LineChunk *last_line_chunk = 0; - U64 total_line_chunk_line_count = 0; - - // rjf: grab checksums sub-section - CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; - - // rjf: decode loop - U64 read_off = 0; - U64 read_off_opl = binary_annots.size; - for(B32 good = 1; read_off < read_off_opl && good;) - { - // rjf: decode next annotation op - U32 op = CV_InlineBinaryAnnotation_Null; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); - - // rjf: apply op - switch(op) - { - default:{good = 0;}break; - case CV_InlineBinaryAnnotation_Null: - { - good = 0; - }break; - case CV_InlineBinaryAnnotation_CodeOffset: - { - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: - { - good = 0; - // TODO(rjf): currently untested/unknown - first guess below: - // - // U32 delta = 0; - // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); - // code_offset_base = code_offset; - // code_offset_end = code_offset + delta; - // code_offset += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffset: - { - U32 delta = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); - code_offset += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeLength: - { - code_length = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); - }break; - case CV_InlineBinaryAnnotation_ChangeFile: - { - U32 new_file_off = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &new_file_off); - String8 new_file_name = {0}; - if(new_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) - { - CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + new_file_off); - U32 name_off = checksum->name_off; - new_file_name = pdb_strtbl_string_from_off(in->pdb_strtbl, name_off); - } - file_name = new_file_name; - }break; - case CV_InlineBinaryAnnotation_ChangeLineOffset: - { - S32 delta = 0; - read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); - line += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeLineEndDelta: - { - good = 0; - // TODO(rjf): currently untested/unknown - first guess below: - // - // S32 end_delta = 1; - // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); - // line += end_delta; - }break; - case CV_InlineBinaryAnnotation_ChangeRangeKind: - { - good = 0; - // TODO(rjf): currently untested/unknown - first guess below: - // - // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &range_kind); - }break; - case CV_InlineBinaryAnnotation_ChangeColumnStart: - { - good = 0; - // TODO(rjf): currently untested/unknown - first guess below: - // - // S32 delta = 0; - // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); - // column += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: - { - // TODO(rjf): currently untested/unknown - first guess below: - // - // S32 end_delta = 0; - // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); - // column += end_delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: - { - U32 code_offset_and_line_offset = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); - U32 code_delta = (code_offset_and_line_offset & 0xf); - S32 line_delta = cv_inline_annot_signed_from_unsigned_operand(code_offset_and_line_offset >> 4); - code_offset += code_delta; - line += line_delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: - { - U32 offset_delta = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); - code_offset += offset_delta; - }break; - case CV_InlineBinaryAnnotation_ChangeColumnEnd: - { - // TODO(rjf): currently untested/unknown - first guess below: - // - // U32 column_end = 0; - // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &column_end); - }break; - } - - // rjf: gather new lines - if(!good || line != last_line || code_offset != last_code_offset) - { - LineChunk *chunk = last_line_chunk; - if(chunk == 0 || chunk->count+1 >= chunk->cap) - { - chunk = push_array(scratch.arena, LineChunk, 1); - SLLQueuePush(first_line_chunk, last_line_chunk, chunk); - chunk->cap = 256; - chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); - chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); - } - chunk->voffs[chunk->count] = base_voff + code_offset; - chunk->voffs[chunk->count+1] = base_voff + code_offset + code_length; - chunk->line_nums[chunk->count] = (U32)line; - chunk->count += 1; - total_line_chunk_line_count += 1; - } - - // rjf: push line sequence to line table & source file - if(!good || (op == CV_InlineBinaryAnnotation_ChangeFile && !str8_match(last_file_name, file_name, 0))) - { - String8 seq_file_name = last_file_name; // NOTE(rjf): `file_name` is possibly changed to the next sequence, so use previous - - // rjf: file name -> normalized file path - String8 file_path = seq_file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); - for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) - { - if(file_path_normalized.str[idx] == '\\') - { - file_path_normalized.str[idx] = '/'; - } - } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) - { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: gather all lines - RDI_U64 *voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); - RDI_U32 *line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); - RDI_U64 line_count = total_line_chunk_line_count; - { - U64 dst_idx = 0; - for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) - { - MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*chunk->count); - MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); - dst_idx += chunk->count; - } - voffs[dst_idx] = 0xffffffffffffffffull; - } - - // rjf: push - if(line_count != 0) - { - if(line_table == 0) - { - line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - if(out->units_first_inline_site_line_tables[comp_unit_idx] == 0) - { - out->units_first_inline_site_line_tables[comp_unit_idx] = line_table; - } - } - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); - } - - // rjf: clear line chunks for subsequent sequences - first_line_chunk = last_line_chunk = 0; - total_line_chunk_line_count = 0; - } - - // rjf: update prev/current states - last_file_name = file_name; - last_line = line; - last_column = column; - last_code_offset = code_offset; - } - } - }break; - } - } - } - } - scratch_end(scratch); - return out; -} -#endif - //////////////////////////////// //~ rjf: Link Name Map Building Tasks @@ -1631,60 +1103,6 @@ ASYNC_WORK_DEF(p2r_link_name_map_build_work) return 0; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_link_name_map_build_task__entry_point) -{ - P2R_LinkNameMapBuildIn *in = (P2R_LinkNameMapBuildIn *)p; - CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges; - CV_RecRange *rec_ranges_opl = rec_ranges_first + in->sym->sym_ranges.count; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: unpack symbol range info - CV_SymKind kind = rec_range->hdr.kind; - U64 header_struct_size = cv_header_struct_size_from_sym_kind(kind); - U8 *sym_first = in->sym->data.str + rec_range->off + 2; - U8 *sym_opl = sym_first + rec_range->hdr.size; - - //- rjf: skip bad ranges - if(sym_opl > in->sym->data.str + in->sym->data.size || sym_first + header_struct_size > in->sym->data.str + in->sym->data.size) - { - continue; - } - - //- rjf: consume symbol - switch(kind) - { - default:{}break; - case CV_SymKind_PUB32: - { - // rjf: unpack sym - CV_SymPub32 *pub32 = (CV_SymPub32 *)sym_first; - String8 name = str8_cstring_capped(pub32+1, sym_opl); - COFF_SectionHeader *section = (0 < pub32->sec && pub32->sec <= in->coff_sections.count) ? &in->coff_sections.v[pub32->sec-1] : 0; - U64 voff = 0; - if(section != 0) - { - voff = section->voff + pub32->off; - } - - // rjf: commit to link name map - U64 hash = p2r_hash_from_voff(voff); - U64 bucket_idx = hash%in->link_name_map->buckets_count; - P2R_LinkNameNode *node = push_array(arena, P2R_LinkNameNode, 1); - SLLStackPush(in->link_name_map->buckets[bucket_idx], node); - node->voff = voff; - node->name = name; - in->link_name_map->link_name_count += 1; - in->link_name_map->bucket_collision_count += (node->next != 0); - }break; - } - } - return 0; -} -#endif - //////////////////////////////// //~ rjf: Type Parsing/Conversion Tasks @@ -2114,432 +1532,6 @@ ASYNC_WORK_DEF(p2r_itype_chain_build_work) return 0; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_itype_fwd_map_fill_task__entry_point) -{ - P2R_ITypeFwdMapFillIn *in = (P2R_ITypeFwdMapFillIn *)p; - ProfScope("fill itype fwd map") for(CV_TypeId itype = in->itype_first; itype < in->itype_opl; itype += 1) - { - //- rjf: skip if not in the actually stored itype range - if(itype < in->tpi_leaf->itype_first) - { - continue; - } - - //- rjf: determine if this itype resolves to another - CV_TypeId itype_fwd = 0; - CV_RecRange *range = &in->tpi_leaf->leaf_ranges.ranges[itype-in->tpi_leaf->itype_first]; - CV_LeafKind kind = range->hdr.kind; - U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); - if(range->off+range->hdr.size <= in->tpi_leaf->data.size && - range->off+2+header_struct_size <= in->tpi_leaf->data.size && - range->hdr.size >= 2) - { - U8 *itype_leaf_first = in->tpi_leaf->data.str + range->off+2; - U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; - switch(kind) - { - default:{}break; - - //- rjf: CLASS/STRUCTURE - case CV_LeafKind_CLASS: - case CV_LeafKind_STRUCTURE: - { - // rjf: unpack leaf header - CV_LeafStruct *lf_struct = (CV_LeafStruct *)itype_leaf_first; - - // rjf: has fwd ref flag -> lookup itype that this itype resolves to - if(lf_struct->props & CV_TypeProp_FwdRef) - { - // rjf: unpack rest of leaf - U8 *numeric_ptr = (U8 *)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - - // rjf: lookup - B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && - ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); - itype_fwd = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); - } - }break; - - //- rjf: CLASS2/STRUCT2 - case CV_LeafKind_CLASS2: - case CV_LeafKind_STRUCT2: - { - // rjf: unpack leaf header - CV_LeafStruct2 *lf_struct = (CV_LeafStruct2 *)itype_leaf_first; - - // rjf: has fwd ref flag -> lookup itype that this itype resolves to - if(lf_struct->props & CV_TypeProp_FwdRef) - { - // rjf: unpack rest of leaf - U8 *numeric_ptr = (U8 *)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); - U8 *name_ptr = (U8 *)numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - - // rjf: lookup - B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && - ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); - itype_fwd = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); - } - }break; - - //- rjf: UNION - case CV_LeafKind_UNION: - { - // rjf: unpack leaf - CV_LeafUnion *lf_union = (CV_LeafUnion *)itype_leaf_first; - U8 *numeric_ptr = (U8 *)(lf_union + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - - // rjf: has fwd ref flag -> lookup itype that this itype resolves tos - if(lf_union->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = (((lf_union->props & CV_TypeProp_Scoped) != 0) && - ((lf_union->props & CV_TypeProp_HasUniqueName) != 0)); - itype_fwd = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); - } - }break; - - //- rjf: ENUM - case CV_LeafKind_ENUM: - { - // rjf: unpack leaf - CV_LeafEnum *lf_enum = (CV_LeafEnum*)itype_leaf_first; - U8 *name_ptr = (U8 *)(lf_enum + 1); - String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - - // rjf: has fwd ref flag -> lookup itype that this itype resolves to - if(lf_enum->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = (((lf_enum->props & CV_TypeProp_Scoped) != 0) && - ((lf_enum->props & CV_TypeProp_HasUniqueName) != 0)); - itype_fwd = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); - } - }break; - } - } - - //- rjf: if the forwarded itype is nonzero & in TPI range -> save to map - if(itype_fwd != 0 && itype_fwd < in->tpi_leaf->itype_opl) - { - in->itype_fwd_map[itype] = itype_fwd; - } - } - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_itype_chain_build_task__entry_point) -{ - Temp scratch = scratch_begin(&arena, 1); - P2R_ITypeChainBuildIn *in = (P2R_ITypeChainBuildIn *)p; - ProfScope("dependency itype chain build") - { - for(CV_TypeId itype = in->itype_first; itype < in->itype_opl; itype += 1) - { - //- rjf: push initial itype - should be final-visited-itype for this itype - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = itype; - SLLStackPush(in->itype_chains[itype], c); - } - - //- rjf: skip basic types for dependency walk - if(itype < in->tpi_leaf->itype_first) - { - continue; - } - - //- rjf: walk dependent types, push to chain - P2R_TypeIdChain start_walk_task = {0, itype}; - P2R_TypeIdChain *first_walk_task = &start_walk_task; - P2R_TypeIdChain *last_walk_task = &start_walk_task; - for(P2R_TypeIdChain *walk_task = first_walk_task; - walk_task != 0; - walk_task = walk_task->next) - { - CV_TypeId walk_itype = in->itype_fwd_map[walk_task->itype] ? in->itype_fwd_map[walk_task->itype] : walk_task->itype; - if(walk_itype < in->tpi_leaf->itype_first) - { - continue; - } - CV_RecRange *range = &in->tpi_leaf->leaf_ranges.ranges[walk_itype-in->tpi_leaf->itype_first]; - CV_LeafKind kind = range->hdr.kind; - U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); - if(range->off+range->hdr.size <= in->tpi_leaf->data.size && - range->off+2+header_struct_size <= in->tpi_leaf->data.size && - range->hdr.size >= 2) - { - U8 *itype_leaf_first = in->tpi_leaf->data.str + range->off+2; - U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; - switch(kind) - { - default:{}break; - - //- rjf: MODIFIER - case CV_LeafKind_MODIFIER: - { - CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; - - // rjf: push dependent itype to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itype - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: POINTER - case CV_LeafKind_POINTER: - { - CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; - - // rjf: push dependent itype to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itype - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: PROCEDURE - case CV_LeafKind_PROCEDURE: - { - CV_LeafProcedure *lf = (CV_LeafProcedure *)itype_leaf_first; - - // rjf: push return itypes to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->ret_itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk return itype - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->ret_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - - // rjf: unpack arglist range - CV_RecRange *arglist_range = &in->tpi_leaf->leaf_ranges.ranges[lf->arg_itype-in->tpi_leaf->itype_first]; - if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || - arglist_range->hdr.size<2 || - arglist_range->off + arglist_range->hdr.size > in->tpi_leaf->data.size) - { - break; - } - U8 *arglist_first = in->tpi_leaf->data.str + arglist_range->off + 2; - U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; - if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) - { - break; - } - - // rjf: unpack arglist info - CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; - CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); - U32 arglist_itypes_count = arglist->count; - - // rjf: push arg types to chain - for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = arglist_itypes_base[idx]; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk arg types - for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = arglist_itypes_base[idx]; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: MFUNCTION - case CV_LeafKind_MFUNCTION: - { - CV_LeafMFunction *lf = (CV_LeafMFunction *)itype_leaf_first; - - // rjf: push dependent itypes to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->ret_itype; - SLLStackPush(in->itype_chains[itype], c); - } - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->arg_itype; - SLLStackPush(in->itype_chains[itype], c); - } - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->this_itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itypes - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->ret_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->arg_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->this_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - - // rjf: unpack arglist range - CV_RecRange *arglist_range = &in->tpi_leaf->leaf_ranges.ranges[lf->arg_itype-in->tpi_leaf->itype_first]; - if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || - arglist_range->hdr.size<2 || - arglist_range->off + arglist_range->hdr.size > in->tpi_leaf->data.size) - { - break; - } - U8 *arglist_first = in->tpi_leaf->data.str + arglist_range->off + 2; - U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; - if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) - { - break; - } - - // rjf: unpack arglist info - CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; - CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); - U32 arglist_itypes_count = arglist->count; - - // rjf: push arg types to chain - for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = arglist_itypes_base[idx]; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk arg types - for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = arglist_itypes_base[idx]; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: BITFIELD - case CV_LeafKind_BITFIELD: - { - CV_LeafBitField *lf = (CV_LeafBitField *)itype_leaf_first; - - // rjf: push dependent itype to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itype - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: ARRAY - case CV_LeafKind_ARRAY: - { - CV_LeafArray *lf = (CV_LeafArray *)itype_leaf_first; - - // rjf: push dependent itypes to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->entry_itype; - SLLStackPush(in->itype_chains[itype], c); - } - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->index_itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itypes - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->entry_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->index_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - - //- rjf: ENUM - case CV_LeafKind_ENUM: - { - CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; - - // rjf: push dependent itypes to chain - { - P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); - c->itype = lf->base_itype; - SLLStackPush(in->itype_chains[itype], c); - } - - // rjf: push task to walk dependency itypes - { - P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); - c->itype = lf->base_itype; - SLLQueuePush(first_walk_task, last_walk_task, c); - } - }break; - } - } - } - } - } - scratch_end(scratch); - return 0; -} -#endif - //////////////////////////////// //~ rjf: UDT Conversion Tasks @@ -3175,639 +2167,6 @@ ASYNC_WORK_DEF(p2r_udt_convert_work) return udts; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_udt_convert_task__entry_point) -{ - P2R_UDTConvertIn *in = (P2R_UDTConvertIn *)p; -#define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[(in->itype_fwd_map[(itype)] ? in->itype_fwd_map[(itype)] : (itype))]) : 0) - RDIM_UDTChunkList *udts = push_array(arena, RDIM_UDTChunkList, 1); - RDI_U64 udts_chunk_cap = 1024; - ProfScope("convert UDT info") - { - for(CV_TypeId itype = in->itype_first; itype < in->itype_opl; itype += 1) - { - //- rjf: skip basics - if(itype < in->tpi_leaf->itype_first) { continue; } - - //- rjf: grab type for this itype - skip if empty - RDIM_Type *dst_type = in->itype_type_ptrs[itype]; - if(dst_type == 0) { continue; } - - //- rjf: unpack itype leaf range - skip if out-of-range - CV_RecRange *range = &in->tpi_leaf->leaf_ranges.ranges[itype-in->tpi_leaf->itype_first]; - CV_LeafKind kind = range->hdr.kind; - U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); - U8 *itype_leaf_first = in->tpi_leaf->data.str + range->off+2; - U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; - if(range->off+range->hdr.size > in->tpi_leaf->data.size || - range->off+2+header_struct_size > in->tpi_leaf->data.size || - range->hdr.size < 2) - { - continue; - } - - //- rjf: build UDT - CV_TypeId field_itype = 0; - switch(kind) - { - default:{}break; - - //////////////////////// - //- rjf: structs/unions/classes -> equip members - // - case CV_LeafKind_CLASS: - case CV_LeafKind_STRUCTURE: - { - CV_LeafStruct *lf = (CV_LeafStruct *)itype_leaf_first; - if(lf->props & CV_TypeProp_FwdRef) - { - break; - } - field_itype = lf->field_itype; - }goto equip_members; - case CV_LeafKind_UNION: - { - CV_LeafUnion *lf = (CV_LeafUnion *)itype_leaf_first; - if(lf->props & CV_TypeProp_FwdRef) - { - break; - } - field_itype = lf->field_itype; - }goto equip_members; - case CV_LeafKind_CLASS2: - case CV_LeafKind_STRUCT2: - { - CV_LeafStruct2 *lf = (CV_LeafStruct2 *)itype_leaf_first; - if(lf->props & CV_TypeProp_FwdRef) - { - break; - } - field_itype = lf->field_itype; - }goto equip_members; - equip_members: - { - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: grab UDT info - RDIM_UDT *dst_udt = dst_type->udt; - if(dst_udt == 0) - { - dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap); - dst_udt->self_type = dst_type; - } - - //- rjf: gather all fields - typedef struct FieldListTask FieldListTask; - struct FieldListTask - { - FieldListTask *next; - CV_TypeId itype; - }; - FieldListTask start_fl_task = {0, field_itype}; - FieldListTask *fl_todo_stack = &start_fl_task; - FieldListTask *fl_done_stack = 0; - for(;fl_todo_stack != 0;) - { - //- rjf: take & unpack task - FieldListTask *fl_task = fl_todo_stack; - SLLStackPop(fl_todo_stack); - SLLStackPush(fl_done_stack, fl_task); - CV_TypeId field_list_itype = fl_task->itype; - - //- rjf: skip bad itypes - if(field_list_itype < in->tpi_leaf->itype_first || in->tpi_leaf->itype_opl <= field_list_itype) - { - continue; - } - - //- rjf: field list itype -> range - CV_RecRange *range = &in->tpi_leaf->leaf_ranges.ranges[field_list_itype-in->tpi_leaf->itype_first]; - - //- rjf: skip bad headers - if(range->off+range->hdr.size > in->tpi_leaf->data.size || - range->hdr.size < 2 || - range->hdr.kind != CV_LeafKind_FIELDLIST) - { - continue; - } - - //- rjf: loop over all fields - { - U8 *field_list_first = in->tpi_leaf->data.str+range->off+2; - U8 *field_list_opl = field_list_first+range->hdr.size-2; - for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; - read_ptr < field_list_opl; - read_ptr = next_read_ptr) - { - // rjf: unpack field - CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; - U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); - U8 *field_leaf_first = read_ptr+2; - U8 *field_leaf_opl = field_list_opl; - next_read_ptr = field_leaf_opl; - - // rjf: skip out-of-bounds fields - if(field_leaf_first+field_leaf_header_size > field_list_opl) - { - continue; - } - - // rjf: process field - switch(field_kind) - { - //- rjf: unhandled/invalid cases - default: - { - // TODO(rjf): log - }break; - - //- rjf: INDEX - case CV_LeafKind_INDEX: - { - // rjf: unpack leaf - CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; - CV_TypeId new_itype = lf->itype; - - // rjf: bump next read pointer past header - next_read_ptr = (U8 *)(lf+1); - - // rjf: determine if index itype is new - B32 is_new = 1; - for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) - { - if(t->itype == new_itype) - { - is_new = 0; - break; - } - } - - // rjf: if new -> push task to follow new itype - if(is_new) - { - FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); - SLLStackPush(fl_todo_stack, new_task); - new_task->itype = new_itype; - } - }break; - - //- rjf: MEMBER - case CV_LeafKind_MEMBER: - { - // TODO(rjf): log on bad offset - - // rjf: unpack leaf - CV_LeafMember *lf = (CV_LeafMember *)field_leaf_first; - U8 *offset_ptr = (U8 *)(lf+1); - CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); - U64 offset64 = cv_u64_from_numeric(&offset); - U8 *name_ptr = offset_ptr + offset.encoded_size; - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_DataField; - mem->name = name; - mem->type = p2r_type_ptr_from_itype(lf->itype); - mem->off = (U32)offset64; - }break; - - //- rjf: STMEMBER - case CV_LeafKind_STMEMBER: - { - // TODO(rjf): handle attribs - - // rjf: unpack leaf - CV_LeafStMember *lf = (CV_LeafStMember *)field_leaf_first; - U8 *name_ptr = (U8 *)(lf+1); - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_StaticData; - mem->name = name; - mem->type = p2r_type_ptr_from_itype(lf->itype); - }break; - - //- rjf: METHOD - case CV_LeafKind_METHOD: - { - // rjf: unpack leaf - CV_LeafMethod *lf = (CV_LeafMethod *)field_leaf_first; - U8 *name_ptr = (U8 *)(lf+1); - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - //- rjf: method list itype -> range - CV_RecRange *method_list_range = &in->tpi_leaf->leaf_ranges.ranges[lf->list_itype-in->tpi_leaf->itype_first]; - - //- rjf: skip bad method lists - if(method_list_range->off+method_list_range->hdr.size > in->tpi_leaf->data.size || - method_list_range->hdr.size < 2 || - method_list_range->hdr.kind != CV_LeafKind_METHODLIST) - { - break; - } - - //- rjf: loop through all methods & emit members - U8 *method_list_first = in->tpi_leaf->data.str + method_list_range->off + 2; - U8 *method_list_opl = method_list_first + method_list_range->hdr.size-2; - for(U8 *method_read_ptr = method_list_first, *next_method_read_ptr = method_list_opl; - method_read_ptr < method_list_opl; - method_read_ptr = next_method_read_ptr) - { - CV_LeafMethodListMember *method = (CV_LeafMethodListMember*)method_read_ptr; - CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(method->attribs); - RDIM_Type *method_type = p2r_type_ptr_from_itype(method->itype); - next_method_read_ptr = (U8 *)(method+1); - - // TODO(allen): PROBLEM - // We only get offsets for virtual functions (the "vbaseoff") from - // "Intro" and "PureIntro". In C++ inheritance, when we have a chain - // of inheritance (let's just talk single inheritance for now) the - // first class in the chain that introduces a new virtual function - // has this "Intro" method. If a later class in the chain redefines - // the virtual function it only has a "Virtual" method which does - // not update the offset. There is a "Virtual" and "PureVirtual" - // variant of "Virtual". The "Pure" in either case means there - // is no concrete procedure. When there is no "Pure" the method - // should have a corresponding procedure symbol id. - // - // The issue is we will want to mark all of our virtual methods as - // virtual and give them an offset, but that means we have to do - // some extra figuring to propogate offsets from "Intro" methods - // to "Virtual" methods in inheritance trees. That is - IF we want - // to start preserving the offsets of virtuals. There is room in - // the method struct to make this work, but for now I've just - // decided to drop this information. It is not urgently useful to - // us and greatly complicates matters. - - // rjf: read vbaseoff - U32 vbaseoff = 0; - if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) - { - if(next_method_read_ptr+4 <= method_list_opl) - { - vbaseoff = *(U32 *)next_method_read_ptr; - } - next_method_read_ptr += 4; - } - - // rjf: emit method - switch(prop) - { - default: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_Method; - mem->name = name; - mem->type = method_type; - }break; - case CV_MethodProp_Static: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_StaticMethod; - mem->name = name; - mem->type = method_type; - }break; - case CV_MethodProp_Virtual: - case CV_MethodProp_PureVirtual: - case CV_MethodProp_Intro: - case CV_MethodProp_PureIntro: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_VirtualMethod; - mem->name = name; - mem->type = method_type; - }break; - } - } - - }break; - - //- rjf: ONEMETHOD - case CV_LeafKind_ONEMETHOD: - { - // TODO(rjf): handle attribs - - // rjf: unpack leaf - CV_LeafOneMethod *lf = (CV_LeafOneMethod *)field_leaf_first; - CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(lf->attribs); - U8 *vbaseoff_ptr = (U8 *)(lf+1); - U8 *vbaseoff_opl_ptr = vbaseoff_ptr; - U32 vbaseoff = 0; - if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) - { - vbaseoff = *(U32 *)(vbaseoff_ptr); - vbaseoff_opl_ptr += sizeof(U32); - } - U8 *name_ptr = vbaseoff_opl_ptr; - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - RDIM_Type *method_type = p2r_type_ptr_from_itype(lf->itype); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit method - switch(prop) - { - default: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_Method; - mem->name = name; - mem->type = method_type; - }break; - - case CV_MethodProp_Static: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_StaticMethod; - mem->name = name; - mem->type = method_type; - }break; - - case CV_MethodProp_Virtual: - case CV_MethodProp_PureVirtual: - case CV_MethodProp_Intro: - case CV_MethodProp_PureIntro: - { - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_VirtualMethod; - mem->name = name; - mem->type = method_type; - }break; - } - }break; - - //- rjf: NESTTYPE - case CV_LeafKind_NESTTYPE: - { - // rjf: unpack leaf - CV_LeafNestType *lf = (CV_LeafNestType *)field_leaf_first; - U8 *name_ptr = (U8 *)(lf+1); - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_NestedType; - mem->name = name; - mem->type = p2r_type_ptr_from_itype(lf->itype); - }break; - - //- rjf: NESTTYPEEX - case CV_LeafKind_NESTTYPEEX: - { - // TODO(rjf): handle attribs - - // rjf: unpack leaf - CV_LeafNestTypeEx *lf = (CV_LeafNestTypeEx *)field_leaf_first; - U8 *name_ptr = (U8 *)(lf+1); - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_NestedType; - mem->name = name; - mem->type = p2r_type_ptr_from_itype(lf->itype); - }break; - - //- rjf: BCLASS - case CV_LeafKind_BCLASS: - { - // TODO(rjf): log on bad offset - - // rjf: unpack leaf - CV_LeafBClass *lf = (CV_LeafBClass *)field_leaf_first; - U8 *offset_ptr = (U8 *)(lf+1); - CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); - U64 offset64 = cv_u64_from_numeric(&offset); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = offset_ptr+offset.encoded_size; - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_Base; - mem->type = p2r_type_ptr_from_itype(lf->itype); - mem->off = (U32)offset64; - }break; - - //- rjf: VBCLASS/IVBCLASS - case CV_LeafKind_VBCLASS: - case CV_LeafKind_IVBCLASS: - { - // TODO(rjf): log on bad offsets - // TODO(rjf): handle attribs - // TODO(rjf): offsets? - - // rjf: unpack leaf - CV_LeafVBClass *lf = (CV_LeafVBClass *)field_leaf_first; - U8 *num1_ptr = (U8 *)(lf+1); - CV_NumericParsed num1 = cv_numeric_from_data_range(num1_ptr, field_leaf_opl); - U8 *num2_ptr = num1_ptr + num1.encoded_size; - CV_NumericParsed num2 = cv_numeric_from_data_range(num2_ptr, field_leaf_opl); - - // rjf: bump next read pointer past header - next_read_ptr = (U8 *)(lf+1); - - // rjf: emit member - RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); - mem->kind = RDI_MemberKind_VirtualBase; - mem->type = p2r_type_ptr_from_itype(lf->itype); - }break; - - //- rjf: VFUNCTAB - case CV_LeafKind_VFUNCTAB: - { - CV_LeafVFuncTab *lf = (CV_LeafVFuncTab *)field_leaf_first; - - // rjf: bump next read pointer past header - next_read_ptr = (U8 *)(lf+1); - - // NOTE(rjf): currently no-op this case - (void)lf; - }break; - } - - // rjf: align-up next field - next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); - } - } - } - - scratch_end(scratch); - }break; - - //////////////////////// - //- rjf: enums -> equip enumerates - // - case CV_LeafKind_ENUM: - { - CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; - if(lf->props & CV_TypeProp_FwdRef) - { - break; - } - field_itype = lf->field_itype; - }goto equip_enum_vals; - equip_enum_vals:; - { - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: grab UDT info - RDIM_UDT *dst_udt = dst_type->udt; - if(dst_udt == 0) - { - dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap); - dst_udt->self_type = dst_type; - } - - //- rjf: gather all fields - typedef struct FieldListTask FieldListTask; - struct FieldListTask - { - FieldListTask *next; - CV_TypeId itype; - }; - FieldListTask start_fl_task = {0, field_itype}; - FieldListTask *fl_todo_stack = &start_fl_task; - FieldListTask *fl_done_stack = 0; - for(;fl_todo_stack != 0;) - { - //- rjf: take & unpack task - FieldListTask *fl_task = fl_todo_stack; - SLLStackPop(fl_todo_stack); - SLLStackPush(fl_done_stack, fl_task); - CV_TypeId field_list_itype = fl_task->itype; - - //- rjf: skip bad itypes - if(field_list_itype < in->tpi_leaf->itype_first || in->tpi_leaf->itype_opl <= field_list_itype) - { - continue; - } - - //- rjf: field list itype -> range - CV_RecRange *range = &in->tpi_leaf->leaf_ranges.ranges[field_list_itype-in->tpi_leaf->itype_first]; - - //- rjf: skip bad headers - if(range->off+range->hdr.size > in->tpi_leaf->data.size || - range->hdr.size < 2 || - range->hdr.kind != CV_LeafKind_FIELDLIST) - { - continue; - } - - //- rjf: loop over all fields - { - U8 *field_list_first = in->tpi_leaf->data.str+range->off+2; - U8 *field_list_opl = field_list_first+range->hdr.size-2; - for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; - read_ptr < field_list_opl; - read_ptr = next_read_ptr) - { - // rjf: unpack field - CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; - U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); - U8 *field_leaf_first = read_ptr+2; - U8 *field_leaf_opl = field_leaf_first+range->hdr.size-2; - next_read_ptr = field_leaf_opl; - - // rjf: skip out-of-bounds fields - if(field_leaf_first+field_leaf_header_size > field_list_opl) - { - continue; - } - - // rjf: process field - switch(field_kind) - { - //- rjf: unhandled/invalid cases - default: - { - // TODO(rjf): log - }break; - - //- rjf: INDEX - case CV_LeafKind_INDEX: - { - // rjf: unpack leaf - CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; - CV_TypeId new_itype = lf->itype; - - // rjf: determine if index itype is new - B32 is_new = 1; - for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) - { - if(t->itype == new_itype) - { - is_new = 0; - break; - } - } - - // rjf: if new -> push task to follow new itype - if(is_new) - { - FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); - SLLStackPush(fl_todo_stack, new_task); - new_task->itype = new_itype; - } - }break; - - //- rjf: ENUMERATE - case CV_LeafKind_ENUMERATE: - { - // TODO(rjf): attribs - - // rjf: unpack leaf - CV_LeafEnumerate *lf = (CV_LeafEnumerate *)field_leaf_first; - U8 *val_ptr = (U8 *)(lf+1); - CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, field_leaf_opl); - U64 val64 = cv_u64_from_numeric(&val); - U8 *name_ptr = val_ptr + val.encoded_size; - String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); - - // rjf: bump next read pointer past variable length parts - next_read_ptr = name.str+name.size+1; - - // rjf: emit member - RDIM_UDTEnumVal *enum_val = rdim_udt_push_enum_val(arena, udts, dst_udt); - enum_val->name = name; - enum_val->val = val64; - }break; - } - - // rjf: align-up next field - next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); - } - } - } - - scratch_end(scratch); - }break; - } - } - } -#undef p2r_type_ptr_from_itype - return udts; -} -#endif - //////////////////////////////// //~ rjf: Symbol Stream Conversion Path & Thread @@ -4727,923 +3086,6 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) return out; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) -{ - Temp scratch = scratch_begin(&arena, 1); - P2R_SymbolStreamConvertIn *in = (P2R_SymbolStreamConvertIn *)p; -#define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[(in->itype_fwd_map[(itype)] ? in->itype_fwd_map[(itype)] : (itype))]) : 0) - - ////////////////////////// - //- rjf: set up outputs for this sym stream - // - U64 sym_procedures_chunk_cap = 1024; - U64 sym_global_variables_chunk_cap = 1024; - U64 sym_thread_variables_chunk_cap = 1024; - U64 sym_scopes_chunk_cap = 1024; - U64 sym_inline_sites_chunk_cap = 1024; - RDIM_SymbolChunkList sym_procedures = {0}; - RDIM_SymbolChunkList sym_global_variables = {0}; - RDIM_SymbolChunkList sym_thread_variables = {0}; - RDIM_ScopeChunkList sym_scopes = {0}; - RDIM_InlineSiteChunkList sym_inline_sites = {0}; - - ////////////////////////// - //- rjf: symbols pass 1: produce procedure frame info map (procedure -> frame info) - // - U64 procedure_frameprocs_count = 0; - U64 procedure_frameprocs_cap = (in->sym_ranges_opl - in->sym_ranges_first); - CV_SymFrameproc **procedure_frameprocs = push_array_no_zero(scratch.arena, CV_SymFrameproc *, procedure_frameprocs_cap); - ProfScope("symbols pass 1: produce procedure frame info map (procedure -> frame info)") - { - U64 procedure_num = 0; - CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges + in->sym_ranges_first; - CV_RecRange *rec_ranges_opl = in->sym->sym_ranges.ranges + in->sym_ranges_opl; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: rec range -> symbol info range - U64 sym_off_first = rec_range->off + 2; - U64 sym_off_opl = rec_range->off + rec_range->hdr.size; - - //- rjf: skip invalid ranges - if(sym_off_opl > in->sym->data.size || sym_off_first > in->sym->data.size || sym_off_first > sym_off_opl) - { - continue; - } - - //- rjf: unpack symbol info - CV_SymKind kind = rec_range->hdr.kind; - U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = in->sym->data.str + sym_off_first; - - //- rjf: skip bad sizes - if(sym_off_first + sym_header_struct_size > sym_off_opl) - { - continue; - } - - //- rjf: consume symbol based on kind - switch(kind) - { - default:{}break; - - //- rjf: FRAMEPROC - case CV_SymKind_FRAMEPROC: - { - if(procedure_num == 0) { break; } - if(procedure_num > procedure_frameprocs_cap) { break; } - CV_SymFrameproc *frameproc = (CV_SymFrameproc*)sym_header_struct_base; - procedure_frameprocs[procedure_num-1] = frameproc; - procedure_frameprocs_count = Max(procedure_frameprocs_count, procedure_num); - }break; - - //- rjf: LPROC32/GPROC32 - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: - { - procedure_num += 1; - }break; - } - } - U64 scratch_overkill = sizeof(procedure_frameprocs[0])*(procedure_frameprocs_cap-procedure_frameprocs_count); - arena_pop(scratch.arena, scratch_overkill); - } - - ////////////////////////// - //- rjf: symbols pass 2: construct all symbols, given procedure frame info map - // - ProfScope("symbols pass 2: construct all symbols, given procedure frame info map") - { - RDIM_LocationSet *defrange_target = 0; - B32 defrange_target_is_param = 0; - U64 procedure_num = 0; - U64 procedure_base_voff = 0; - CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges + in->sym_ranges_first; - CV_RecRange *rec_ranges_opl = in->sym->sym_ranges.ranges + in->sym_ranges_opl; - typedef struct P2R_ScopeNode P2R_ScopeNode; - struct P2R_ScopeNode - { - P2R_ScopeNode *next; - RDIM_Scope *scope; - }; - P2R_ScopeNode *top_scope_node = 0; - P2R_ScopeNode *free_scope_node = 0; - RDIM_LineTable *inline_site_line_table = in->first_inline_site_line_table; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: rec range -> symbol info range - U64 sym_off_first = rec_range->off + 2; - U64 sym_off_opl = rec_range->off + rec_range->hdr.size; - - //- rjf: skip invalid ranges - if(sym_off_opl > in->sym->data.size || sym_off_first > in->sym->data.size || sym_off_first > sym_off_opl) - { - continue; - } - - //- rjf: unpack symbol info - CV_SymKind kind = rec_range->hdr.kind; - U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = in->sym->data.str + sym_off_first; - void *sym_data_opl = in->sym->data.str + sym_off_opl; - - //- rjf: skip bad sizes - if(sym_off_first + sym_header_struct_size > sym_off_opl) - { - continue; - } - - //- rjf: consume symbol based on kind - switch(kind) - { - default:{}break; - - //- rjf: END - case CV_SymKind_END: - { - P2R_ScopeNode *n = top_scope_node; - if(n != 0) - { - SLLStackPop(top_scope_node); - SLLStackPush(free_scope_node, n); - } - defrange_target = 0; - defrange_target_is_param = 0; - }break; - - //- rjf: BLOCK32 - case CV_SymKind_BLOCK32: - { - // rjf: unpack sym - CV_SymBlock32 *block32 = (CV_SymBlock32 *)sym_header_struct_base; - - // rjf: build scope, insert into current parent scope - RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); - { - if(top_scope_node == 0) - { - // TODO(rjf): log - } - if(top_scope_node != 0) - { - RDIM_Scope *top_scope = top_scope_node->scope; - SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); - scope->parent_scope = top_scope; - scope->symbol = top_scope->symbol; - } - COFF_SectionHeader *section = (0 < block32->sec && block32->sec <= in->coff_sections.count) ? &in->coff_sections.v[block32->sec-1] : 0; - if(section != 0) - { - U64 voff_first = section->voff + block32->off; - U64 voff_last = voff_first + block32->len; - RDIM_Rng1U64 voff_range = {voff_first, voff_last}; - rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range); - } - } - - // rjf: push this scope to scope stack - { - P2R_ScopeNode *node = free_scope_node; - if(node != 0) { SLLStackPop(free_scope_node); } - else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } - node->scope = scope; - SLLStackPush(top_scope_node, node); - } - }break; - - //- rjf: LDATA32/GDATA32 - case CV_SymKind_LDATA32: - case CV_SymKind_GDATA32: - { - // rjf: unpack sym - CV_SymData32 *data32 = (CV_SymData32 *)sym_header_struct_base; - String8 name = str8_cstring_capped(data32+1, sym_data_opl); - COFF_SectionHeader *section = (0 < data32->sec && data32->sec <= in->coff_sections.count) ? &in->coff_sections.v[data32->sec-1] : 0; - U64 voff = (section ? section->voff : 0) + data32->off; - - // rjf: determine if this is an exact duplicate global - // - // PDB likes to have duplicates of these spread across different - // symbol streams so we deduplicate across the entire translation - // context. - // - B32 is_duplicate = 0; - { - // TODO(rjf): @important global symbol dedup - } - - // rjf: is not duplicate -> push new global - if(!is_duplicate) - { - // rjf: unpack global variable's type - RDIM_Type *type = p2r_type_ptr_from_itype(data32->itype); - - // rjf: unpack global's container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2) - { - String8 container_name = str8(name.str, container_name_opl - 2); - CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, container_name, 0); - container_type = p2r_type_ptr_from_itype(cv_type_id); - } - - // rjf: unpack global's container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0 && top_scope_node != 0) - { - container_symbol = top_scope_node->scope->symbol; - } - - // rjf: build symbol - RDIM_Symbol *symbol = rdim_symbol_chunk_list_push(arena, &sym_global_variables, sym_global_variables_chunk_cap); - symbol->is_extern = (kind == CV_SymKind_GDATA32); - symbol->name = name; - symbol->type = type; - symbol->offset = voff; - symbol->container_symbol = container_symbol; - symbol->container_type = container_type; - } - }break; - - //- rjf: LPROC32/GPROC32 - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: - { - // rjf: unpack sym - CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; - String8 name = str8_cstring_capped(proc32+1, sym_data_opl); - RDIM_Type *type = p2r_type_ptr_from_itype(proc32->itype); - - // rjf: unpack proc's container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2 && in->tpi_hash != 0 && in->tpi_leaf != 0) - { - String8 container_name = str8(name.str, container_name_opl - 2); - CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, container_name, 0); - container_type = p2r_type_ptr_from_itype(cv_type_id); - } - - // rjf: unpack proc's container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0 && top_scope_node != 0) - { - container_symbol = top_scope_node->scope->symbol; - } - - // rjf: build procedure's root scope - // - // NOTE: even if there could be a containing scope at this point (which should be - // illegal in C/C++ but not necessarily in another language) we would not use - // it here because these scopes refer to the ranges of code that make up a - // procedure *not* the namespaces, so a procedure's root scope always has - // no parent. - RDIM_Scope *procedure_root_scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); - { - COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= in->coff_sections.count) ? &in->coff_sections.v[proc32->sec-1] : 0; - if(section != 0) - { - U64 voff_first = section->voff + proc32->off; - U64 voff_last = voff_first + proc32->len; - RDIM_Rng1U64 voff_range = {voff_first, voff_last}; - rdim_scope_push_voff_range(arena, &sym_scopes, procedure_root_scope, voff_range); - procedure_base_voff = voff_first; - } - } - - // rjf: root scope voff minimum range -> link name - String8 link_name = {0}; - if(procedure_root_scope->voff_ranges.min != 0) - { - U64 voff = procedure_root_scope->voff_ranges.min; - U64 hash = p2r_hash_from_voff(voff); - U64 bucket_idx = hash%in->link_name_map->buckets_count; - P2R_LinkNameNode *node = 0; - for(P2R_LinkNameNode *n = in->link_name_map->buckets[bucket_idx]; n != 0; n = n->next) - { - if(n->voff == voff) - { - link_name = n->name; - break; - } - } - } - - // rjf: build procedure symbol - RDIM_Symbol *procedure_symbol = rdim_symbol_chunk_list_push(arena, &sym_procedures, sym_procedures_chunk_cap); - procedure_symbol->is_extern = (kind == CV_SymKind_GPROC32); - procedure_symbol->name = name; - procedure_symbol->link_name = link_name; - procedure_symbol->type = type; - procedure_symbol->container_symbol = container_symbol; - procedure_symbol->container_type = container_type; - procedure_symbol->root_scope = procedure_root_scope; - - // rjf: fill root scope's symbol - procedure_root_scope->symbol = procedure_symbol; - - // rjf: push scope to scope stack - { - P2R_ScopeNode *node = free_scope_node; - if(node != 0) { SLLStackPop(free_scope_node); } - else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } - node->scope = procedure_root_scope; - SLLStackPush(top_scope_node, node); - } - - // rjf: increment procedure counter - procedure_num += 1; - }break; - - //- rjf: REGREL32 - case CV_SymKind_REGREL32: - { - // TODO(rjf): apparently some of the information here may end up being - // redundant with "better" information from CV_SymKind_LOCAL record. - // we don't currently handle this, but if those cases arise then it - // will obviously be better to prefer the better information from both - // records. - - // rjf: no containing scope? -> malformed data; locals cannot be produced - // outside of a containing scope - if(top_scope_node == 0) - { - break; - } - - // rjf: unpack sym - CV_SymRegrel32 *regrel32 = (CV_SymRegrel32 *)sym_header_struct_base; - String8 name = str8_cstring_capped(regrel32+1, sym_data_opl); - RDIM_Type *type = p2r_type_ptr_from_itype(regrel32->itype); - CV_Reg cv_reg = regrel32->reg; - U32 var_off = regrel32->reg_off; - - // rjf: determine if this is a parameter - RDI_LocalKind local_kind = RDI_LocalKind_Variable; - { - B32 is_stack_reg = 0; - switch(in->arch) - { - default:{}break; - case RDI_Arch_X86:{is_stack_reg = (cv_reg == CV_Regx86_ESP);}break; - case RDI_Arch_X64:{is_stack_reg = (cv_reg == CV_Regx64_RSP);}break; - } - if(is_stack_reg) - { - U32 frame_size = 0xFFFFFFFF; - if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count) - { - CV_SymFrameproc *frameproc = procedure_frameprocs[procedure_num-1]; - frame_size = frameproc->frame_size; - } - if(var_off > frame_size) - { - local_kind = RDI_LocalKind_Parameter; - } - } - } - - // rjf: build local - RDIM_Scope *scope = top_scope_node->scope; - RDIM_Local *local = rdim_scope_push_local(arena, &sym_scopes, scope); - local->kind = local_kind; - local->name = name; - local->type = type; - - // rjf: add location info to local - if(type != 0) - { - // rjf: determine if we need an extra indirection to the value - B32 extra_indirection_to_value = 0; - switch(in->arch) - { - case RDI_Arch_X86: - { - extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 4 || !IsPow2OrZero(type->byte_size))); - }break; - case RDI_Arch_X64: - { - extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 8 || !IsPow2OrZero(type->byte_size))); - }break; - } - - // rjf: get raddbg register code - RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(in->arch, cv_reg); - // TODO(rjf): real byte_size & byte_pos from cv_reg goes here - U32 byte_size = 8; - U32 byte_pos = 0; - - // rjf: set location case - RDIM_Location *loc = p2r_location_from_addr_reg_off(arena, in->arch, reg_code, byte_size, byte_pos, (S64)(S32)var_off, extra_indirection_to_value); - RDIM_Rng1U64 voff_range = {0, max_U64}; - rdim_location_set_push_case(arena, &sym_scopes, &local->locset, voff_range, loc); - } - }break; - - //- rjf: LTHREAD32/GTHREAD32 - case CV_SymKind_LTHREAD32: - case CV_SymKind_GTHREAD32: - { - // rjf: unpack sym - CV_SymThread32 *thread32 = (CV_SymThread32 *)sym_header_struct_base; - String8 name = str8_cstring_capped(thread32+1, sym_data_opl); - U32 tls_off = thread32->tls_off; - RDIM_Type *type = p2r_type_ptr_from_itype(thread32->itype); - - // rjf: unpack thread variable's container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2) - { - String8 container_name = str8(name.str, container_name_opl - 2); - CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(in->tpi_hash, in->tpi_leaf, container_name, 0); - container_type = p2r_type_ptr_from_itype(cv_type_id); - } - - // rjf: unpack thread variable's container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0 && top_scope_node != 0) - { - container_symbol = top_scope_node->scope->symbol; - } - - // rjf: build symbol - RDIM_Symbol *tvar = rdim_symbol_chunk_list_push(arena, &sym_thread_variables, sym_thread_variables_chunk_cap); - tvar->name = name; - tvar->type = type; - tvar->is_extern = (kind == CV_SymKind_GTHREAD32); - tvar->offset = tls_off; - tvar->container_type = container_type; - tvar->container_symbol = container_symbol; - }break; - - //- rjf: LOCAL - case CV_SymKind_LOCAL: - { - // rjf: no containing scope? -> malformed data; locals cannot be produced - // outside of a containing scope - if(top_scope_node == 0) - { - break; - } - - // rjf: unpack sym - CV_SymLocal *slocal = (CV_SymLocal *)sym_header_struct_base; - String8 name = str8_cstring_capped(slocal+1, sym_data_opl); - RDIM_Type *type = p2r_type_ptr_from_itype(slocal->itype); - - // rjf: determine if this symbol encodes the beginning of a global modification - B32 is_global_modification = 0; - if((slocal->flags & CV_LocalFlag_Global) || - (slocal->flags & CV_LocalFlag_Static)) - { - is_global_modification = 1; - } - - // rjf: is global modification -> emit global modification symbol - if(is_global_modification) - { - // TODO(rjf): add global modification symbols - defrange_target = 0; - defrange_target_is_param = 0; - } - - // rjf: is not a global modification -> emit a local variable - if(!is_global_modification) - { - // rjf: determine local kind - RDI_LocalKind local_kind = RDI_LocalKind_Variable; - if(slocal->flags & CV_LocalFlag_Param) - { - local_kind = RDI_LocalKind_Parameter; - } - - // rjf: build local - RDIM_Scope *scope = top_scope_node->scope; - RDIM_Local *local = rdim_scope_push_local(arena, &sym_scopes, scope); - local->kind = local_kind; - local->name = name; - local->type = type; - - // rjf: save defrange target, for subsequent defrange symbols - defrange_target = &local->locset; - defrange_target_is_param = (local_kind == RDI_LocalKind_Parameter); - } - }break; - - //- rjf: DEFRANGE_REGISTESR - case CV_SymKind_DEFRANGE_REGISTER: - { - // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing - // a local - break immediately - if(defrange_target == 0) - { - break; - } - - // rjf: unpack sym - CV_SymDefrangeRegister *defrange_register = (CV_SymDefrangeRegister*)sym_header_struct_base; - CV_Reg cv_reg = defrange_register->reg; - CV_LvarAddrRange *range = &defrange_register->range; - COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= in->coff_sections.count) ? &in->coff_sections.v[range->sec-1] : 0; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register+1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(in->arch, cv_reg); - - // rjf: build location - RDIM_Location *location = rdim_push_location_val_reg(arena, reg_code); - - // rjf: emit locations over ranges - p2r_location_over_lvar_addr_range(arena, &sym_scopes, defrange_target, location, range, range_section, gaps, gap_count); - }break; - - //- rjf: DEFRANGE_FRAMEPOINTER_REL - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: - { - // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing - // a local - break immediately - if(defrange_target == 0) - { - break; - } - - // rjf: find current procedure's frameproc - CV_SymFrameproc *frameproc = 0; - if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) - { - frameproc = procedure_frameprocs[procedure_num-1]; - } - - // rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange - // without having an actually active procedure - break - if(frameproc == 0) - { - break; - } - - // rjf: unpack sym - CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel*)sym_header_struct_base; - CV_LvarAddrRange *range = &defrange_fprel->range; - COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= in->coff_sections.count) ? &in->coff_sections.v[range->sec-1] : 0; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_fprel + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // rjf: select frame pointer register - CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param); - RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(in->arch, encoded_fp_reg); - - // rjf: build location - B32 extra_indirection = 0; - U32 byte_size = rdi_addr_size_from_arch(in->arch); - U32 byte_pos = 0; - S64 var_off = (S64)defrange_fprel->off; - RDIM_Location *location = p2r_location_from_addr_reg_off(arena, in->arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection); - - // rjf: emit locations over ranges - p2r_location_over_lvar_addr_range(arena, &sym_scopes, defrange_target, location, range, range_section, gaps, gap_count); - }break; - - //- rjf: DEFRANGE_SUBFIELD_REGISTER - case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: - { - // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing - // a local - break immediately - if(defrange_target == 0) - { - break; - } - - // rjf: unpack sym - CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister*)sym_header_struct_base; - CV_Reg cv_reg = defrange_subfield_register->reg; - CV_LvarAddrRange *range = &defrange_subfield_register->range; - COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= in->coff_sections.count) ? &in->coff_sections.v[range->sec-1] : 0; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_subfield_register + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(in->arch, cv_reg); - - // rjf: skip "subfield" location info - currently not supported - if(defrange_subfield_register->field_offset != 0) - { - break; - } - - // rjf: build location - RDIM_Location *location = rdim_push_location_val_reg(arena, reg_code); - - // rjf: emit locations over ranges - p2r_location_over_lvar_addr_range(arena, &sym_scopes, defrange_target, location, range, range_section, gaps, gap_count); - }break; - - //- rjf: DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: - { - // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing - // a local - break immediately - if(defrange_target == 0) - { - break; - } - - // rjf: find current procedure's frameproc - CV_SymFrameproc *frameproc = 0; - if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) - { - frameproc = procedure_frameprocs[procedure_num-1]; - } - - // rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange - // without having an actually active procedure - break - if(frameproc == 0) - { - break; - } - - // rjf: unpack sym - CV_SymDefrangeFramepointerRelFullScope *defrange_fprel_full_scope = (CV_SymDefrangeFramepointerRelFullScope*)sym_header_struct_base; - CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param); - RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(in->arch, encoded_fp_reg); - - // rjf: build location - B32 extra_indirection = 0; - U32 byte_size = rdi_addr_size_from_arch(in->arch); - U32 byte_pos = 0; - S64 var_off = (S64)defrange_fprel_full_scope->off; - RDIM_Location *location = p2r_location_from_addr_reg_off(arena, in->arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection); - - // rjf: emit location over ranges - RDIM_Rng1U64 voff_range = {0, max_U64}; - rdim_location_set_push_case(arena, &sym_scopes, defrange_target, voff_range, location); - }break; - - //- rjf: DEFRANGE_REGISTER_REL - case CV_SymKind_DEFRANGE_REGISTER_REL: - { - // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing - // a local - break immediately - if(defrange_target == 0) - { - break; - } - - // rjf: unpack sym - CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel*)sym_header_struct_base; - CV_Reg cv_reg = defrange_register_rel->reg; - RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(in->arch, cv_reg); - CV_LvarAddrRange *range = &defrange_register_rel->range; - COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= in->coff_sections.count) ? &in->coff_sections.v[range->sec-1] : 0; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register_rel + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // rjf: build location - // TODO(rjf): offset & size from cv_reg code - U32 byte_size = rdi_addr_size_from_arch(in->arch); - U32 byte_pos = 0; - B32 extra_indirection_to_value = 0; - S64 var_off = defrange_register_rel->reg_off; - RDIM_Location *location = p2r_location_from_addr_reg_off(arena, in->arch, reg_code, byte_size, byte_pos, var_off, extra_indirection_to_value); - - // rjf: emit locations over ranges - p2r_location_over_lvar_addr_range(arena, &sym_scopes, defrange_target, location, range, range_section, gaps, gap_count); - }break; - - //- rjf: FILESTATIC - case CV_SymKind_FILESTATIC: - { - CV_SymFileStatic *file_static = (CV_SymFileStatic*)sym_header_struct_base; - String8 name = str8_cstring_capped(file_static+1, sym_data_opl); - RDIM_Type *type = p2r_type_ptr_from_itype(file_static->itype); - // TODO(rjf): emit a global modifier symbol - defrange_target = 0; - defrange_target_is_param = 0; - }break; - - //- rjf: INLINESITE - case CV_SymKind_INLINESITE: - { - // rjf: unpack sym - CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; - String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); - - // rjf: extract external info about inline site - String8 name = str8_zero(); - RDIM_Type *type = 0; - RDIM_Type *owner = 0; - if(in->ipi_leaf != 0 && in->ipi_leaf->itype_first <= sym->inlinee && sym->inlinee < in->ipi_leaf->itype_opl) - { - CV_RecRange rec_range = in->ipi_leaf->leaf_ranges.ranges[sym->inlinee - in->ipi_leaf->itype_first]; - String8 rec_data = str8_substr(in->ipi_leaf->data, rng_1u64(rec_range.off, rec_range.off + rec_range.hdr.size)); - void *raw_leaf = rec_data.str + sizeof(U16); - - // rjf: extract method inline info - if(rec_range.hdr.kind == CV_LeafKind_MFUNC_ID && - rec_range.hdr.size >= sizeof(CV_LeafMFuncId)) - { - CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId*)raw_leaf; - name = str8_cstring_capped(mfunc_id + 1, rec_data.str + rec_data.size); - type = p2r_type_ptr_from_itype(mfunc_id->itype); - owner = mfunc_id->owner_itype != 0 ? p2r_type_ptr_from_itype(mfunc_id->owner_itype) : 0; - } - - // rjf: extract non-method function inline info - else if(rec_range.hdr.kind == CV_LeafKind_FUNC_ID && - rec_range.hdr.size >= sizeof(CV_LeafFuncId)) - { - CV_LeafFuncId *func_id = (CV_LeafFuncId*)raw_leaf; - name = str8_cstring_capped(func_id + 1, rec_data.str + rec_data.size); - type = p2r_type_ptr_from_itype(func_id->itype); - owner = func_id->scope_string_id != 0 ? p2r_type_ptr_from_itype(func_id->scope_string_id) : 0; - } - } - - // rjf: build inline site - RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &sym_inline_sites, sym_inline_sites_chunk_cap); - inline_site->name = name; - inline_site->type = type; - inline_site->owner = owner; - inline_site->line_table = inline_site_line_table; - - // rjf: increment to next inline site line table in this unit - if(inline_site_line_table != 0 && inline_site_line_table->chunk != 0) - { - RDIM_LineTableChunkNode *chunk = inline_site_line_table->chunk; - U64 current_idx = (U64)(inline_site_line_table - chunk->v); - if(current_idx+1 < chunk->count) - { - inline_site_line_table += 1; - } - else - { - chunk = chunk->next; - inline_site_line_table = 0; - if(chunk != 0) - { - inline_site_line_table = chunk->v; - } - } - } - - // rjf: build scope - RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); - scope->inline_site = inline_site; - if(top_scope_node == 0) - { - // TODO(rjf): log - } - if(top_scope_node != 0) - { - RDIM_Scope *top_scope = top_scope_node->scope; - SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); - scope->parent_scope = top_scope; - scope->symbol = top_scope->symbol; - } - - // rjf: push this scope to scope stack - { - P2R_ScopeNode *node = free_scope_node; - if(node != 0) { SLLStackPop(free_scope_node); } - else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } - node->scope = scope; - SLLStackPush(top_scope_node, node); - } - - // rjf: parse offset ranges of this inline site - attach to scope - { - U32 code_length = 0; - U32 code_offset = 0; - U32 last_code_offset = code_offset; - U32 last_code_length = code_length; - U64 read_off = 0; - U64 read_off_opl = binary_annots.size; - for(B32 good = 1; read_off < read_off_opl && good;) - { - // rjf: decode next annotation op - U32 op = CV_InlineBinaryAnnotation_Null; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); - - // rjf: apply op - switch(op) - { - default:{good = 1;}break; - case CV_InlineBinaryAnnotation_Null: - { - good = 0; - }break; - case CV_InlineBinaryAnnotation_CodeOffset: - { - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: - { - good = 0; - // TODO(rjf): currently untested/unknown - first guess below: - // - // U32 delta = 0; - // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); - // code_offset_base = code_offset; - // code_offset_end = code_offset + delta; - // code_offset += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffset: - { - U32 delta = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); - code_offset += delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeLength: - { - code_length = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); - }break; - case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: - { - U32 code_offset_and_line_offset = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); - U32 code_delta = (code_offset_and_line_offset & 0xf); - code_offset += code_delta; - }break; - case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: - { - U32 offset_delta = 0; - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); - read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); - code_offset += offset_delta; - }break; - } - - // rjf: gather new ranges - if(last_code_length != code_length) - { - // rjf: convert current state machine state to [first_voff, opl_voff) range - RDIM_Rng1U64 voff_range = - { - procedure_base_voff + code_offset, - procedure_base_voff + code_offset + code_length, - }; - - // rjf: attempt to extend last-added range to cover this range, if possible - if(scope->voff_ranges.last != 0 && scope->voff_ranges.last->v.max == voff_range.min) - { - scope->voff_ranges.last->v.max = voff_range.max; - } - - // rjf: cannot add to previous range? -> build new range & add to scope - else - { - rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range); - } - - // rjf: advance - code_offset += code_length; - code_length = 0; - } - - // rjf: update prev/current states - last_code_offset = code_offset; - last_code_length = code_length; - } - } - }break; - - //- rjf: INLINESITE_END - case CV_SymKind_INLINESITE_END: - { - P2R_ScopeNode *n = top_scope_node; - if(n != 0) - { - SLLStackPop(top_scope_node); - SLLStackPush(free_scope_node, n); - } - defrange_target = 0; - defrange_target_is_param = 0; - }break; - } - } - } - - ////////////////////////// - //- rjf: allocate & fill output - // - P2R_SymbolStreamConvertOut *out = push_array(arena, P2R_SymbolStreamConvertOut, 1); - { - out->procedures = sym_procedures; - out->global_variables = sym_global_variables; - out->thread_variables = sym_thread_variables; - out->scopes = sym_scopes; - out->inline_sites = sym_inline_sites; - } - -#undef p2r_type_ptr_from_itype - scratch_end(scratch); - return out; -} -#endif - //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point @@ -6783,88 +4225,6 @@ ASYNC_WORK_DEF(p2r_bake_line_tables_work) return out; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_strings_task__entry_point) -{ - P2R_BakeSrcFilesStringsIn *in = (P2R_BakeSrcFilesStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake src file strings") rdim_bake_string_map_loose_push_src_files(arena, in->top, in->maps[thread_idx], in->list); - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_units_strings_task__entry_point) -{ - P2R_BakeUnitsStringsIn *in = (P2R_BakeUnitsStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake unit strings") rdim_bake_string_map_loose_push_units(arena, in->top, in->maps[thread_idx], in->list); - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_types_strings_task__entry_point) -{ - P2R_BakeTypesStringsIn *in = (P2R_BakeTypesStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake type strings") - { - for(P2R_BakeTypesStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_type_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_strings_task__entry_point) -{ - P2R_BakeUDTsStringsIn *in = (P2R_BakeUDTsStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake udt strings") - { - for(P2R_BakeUDTsStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_udt_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_symbols_strings_task__entry_point) -{ - P2R_BakeSymbolsStringsIn *in = (P2R_BakeSymbolsStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake symbol strings") - { - for(P2R_BakeSymbolsStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_symbol_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_strings_task__entry_point) -{ - P2R_BakeScopesStringsIn *in = (P2R_BakeScopesStringsIn *)p; - p2r_make_string_map_if_needed(); - ProfScope("bake scope strings") - { - for(P2R_BakeScopesStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_scope_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - return 0; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_line_tables_task__entry_point) -{ - P2R_BakeLineTablesIn *in = (P2R_BakeLineTablesIn *)p; - RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); - ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); - return out; -} -#endif - #undef p2r_make_string_map_if_needed //- rjf: bake string map joining @@ -6895,33 +4255,6 @@ ASYNC_WORK_DEF(p2r_bake_string_map_join_work) return 0; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_bake_string_map_join_task__entry_point) -{ - P2R_JoinBakeStringMapSlotsIn *in = (P2R_JoinBakeStringMapSlotsIn *)p; - ProfScope("join bake string maps") - { - for(U64 src_map_idx = 0; src_map_idx < in->src_maps_count; src_map_idx += 1) - { - for(U64 slot_idx = in->slot_idx_range.min; slot_idx < in->slot_idx_range.max; slot_idx += 1) - { - B32 src_slots_good = (in->src_maps[src_map_idx] != 0 && in->src_maps[src_map_idx]->slots != 0); - B32 dst_slot_is_zero = (in->dst_map->slots[slot_idx] == 0); - if(src_slots_good && dst_slot_is_zero) - { - in->dst_map->slots[slot_idx] = in->src_maps[src_map_idx]->slots[slot_idx]; - } - else if(src_slots_good && in->src_maps[src_map_idx]->slots[slot_idx] != 0) - { - rdim_bake_string_chunk_list_concat_in_place(in->dst_map->slots[slot_idx], in->src_maps[src_map_idx]->slots[slot_idx]); - } - } - } - } - return 0; -} -#endif - //- rjf: bake string map sorting ASYNC_WORK_DEF(p2r_bake_string_map_sort_work) @@ -6951,34 +4284,6 @@ ASYNC_WORK_DEF(p2r_bake_string_map_sort_work) return 0; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_bake_string_map_sort_task__entry_point) -{ - P2R_SortBakeStringMapSlotsIn *in = (P2R_SortBakeStringMapSlotsIn *)p; - ProfScope("sort bake string chunk list map range") - { - for(U64 slot_idx = in->slot_idx; - slot_idx < in->slot_idx+in->slot_count; - slot_idx += 1) - { - if(in->src_map->slots[slot_idx] != 0) - { - if(in->src_map->slots[slot_idx]->total_count > 1) - { - in->dst_map->slots[slot_idx] = push_array(arena, RDIM_BakeStringChunkList, 1); - *in->dst_map->slots[slot_idx] = rdim_bake_string_chunk_list_sorted_from_unsorted(arena, in->src_map->slots[slot_idx]); - } - else - { - in->dst_map->slots[slot_idx] = in->src_map->slots[slot_idx]; - } - } - } - } - return 0; -} -#endif - //- rjf: pass 1: interner/deduper map builds ASYNC_WORK_DEF(p2r_build_bake_name_map_work) @@ -6990,16 +4295,6 @@ ASYNC_WORK_DEF(p2r_build_bake_name_map_work) return name_map; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_build_bake_name_map_task__entry_point) -{ - P2R_BuildBakeNameMapIn *in = (P2R_BuildBakeNameMapIn *)p; - RDIM_BakeNameMap *name_map = 0; - ProfScope("build name map %i", in->k) name_map = rdim_bake_name_map_from_kind_params(arena, in->k, in->params); - return name_map; -} -#endif - //- rjf: pass 2: string-map-dependent debug info stream builds ASYNC_WORK_DEF(p2r_bake_units_work) @@ -7119,112 +4414,6 @@ ASYNC_WORK_DEF(p2r_bake_strings_work) return out; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_bake_units_task__entry_point) -{ - P2R_BakeUnitsIn *in = (P2R_BakeUnitsIn *)p; - RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); - ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_vmap_task__entry_point) -{ - P2R_BakeUnitVMapIn *in = (P2R_BakeUnitVMapIn *)p; - RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); - ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_task__entry_point) -{ - P2R_BakeSrcFilesIn *in = (P2R_BakeSrcFilesIn *)p; - RDIM_SrcFileBakeResult *out = push_array(arena, RDIM_SrcFileBakeResult, 1); - ProfScope("bake src files") *out = rdim_bake_src_files(arena, in->strings, in->path_tree, in->src_files); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_task__entry_point) -{ - P2R_BakeUDTsIn *in = (P2R_BakeUDTsIn *)p; - RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); - ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->udts); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_global_variables_task__entry_point) -{ - P2R_BakeGlobalVariablesIn *in = (P2R_BakeGlobalVariablesIn *)p; - RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); - ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->global_variables); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_global_vmap_task__entry_point) -{ - P2R_BakeGlobalVMapIn *in = (P2R_BakeGlobalVMapIn *)p; - RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); - ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_thread_variables_task__entry_point) -{ - P2R_BakeThreadVariablesIn *in = (P2R_BakeThreadVariablesIn *)p; - RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); - ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->thread_variables); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_procedures_task__entry_point) -{ - P2R_BakeProceduresIn *in = (P2R_BakeProceduresIn *)p; - RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); - ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->procedures); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_task__entry_point) -{ - P2R_BakeScopesIn *in = (P2R_BakeScopesIn *)p; - RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); - ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->scopes); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_scope_vmap_task__entry_point) -{ - P2R_BakeScopeVMapIn *in = (P2R_BakeScopeVMapIn *)p; - RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); - ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_inline_sites_task__entry_point) -{ - P2R_BakeInlineSitesIn *in = (P2R_BakeInlineSitesIn *)p; - RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); - ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->inline_sites); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_file_paths_task__entry_point) -{ - P2R_BakeFilePathsIn *in = (P2R_BakeFilePathsIn *)p; - RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); - ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_strings_task__entry_point) -{ - P2R_BakeStringsIn *in = (P2R_BakeStringsIn *)p; - RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); - ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); - return out; -} -#endif - //- rjf: pass 3: idx-run-map-dependent debug info stream builds ASYNC_WORK_DEF(p2r_bake_type_nodes_work) @@ -7254,32 +4443,6 @@ ASYNC_WORK_DEF(p2r_bake_idx_runs_work) return out; } -#if 0 -internal TS_TASK_FUNCTION_DEF(p2r_bake_type_nodes_task__entry_point) -{ - P2R_BakeTypeNodesIn *in = (P2R_BakeTypeNodesIn *)p; - RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); - ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->types); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_name_map_task__entry_point) -{ - P2R_BakeNameMapIn *in = (P2R_BakeNameMapIn *)p; - RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); - ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map); - return out; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_idx_runs_task__entry_point) -{ - P2R_BakeIdxRunsIn *in = (P2R_BakeIdxRunsIn *)p; - RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); - ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); - return out; -} -#endif - //////////////////////////////// //~ rjf: Top-Level Initialization diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c index 644e7d3f..a394f76a 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ b/src/rdi_from_pdb/rdi_from_pdb_main.c @@ -24,7 +24,6 @@ #include "base/base_inc.h" #include "os/os_inc.h" #include "async/async.h" -// #include "task_system/task_system.h" #include "rdi_make/rdi_make_local.h" #include "coff/coff.h" #include "codeview/codeview.h" @@ -40,7 +39,6 @@ #include "base/base_inc.c" #include "os/os_inc.c" #include "async/async.c" -//#include "task_system/task_system.c" #include "rdi_make/rdi_make_local.c" #include "coff/coff.c" #include "codeview/codeview.c" diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index cf9004f2..317413f3 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -19,7 +19,6 @@ //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" -#include "task_system/task_system.h" #include "rdi_make/rdi_make_local.h" #include "coff/coff.h" #include "codeview/codeview.h" @@ -33,7 +32,6 @@ //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" -#include "task_system/task_system.c" #include "rdi_make/rdi_make_local.c" #include "coff/coff.c" #include "codeview/codeview.c" diff --git a/src/task_system/task_system.c b/src/task_system/task_system.c deleted file mode 100644 index 26b2ee05..00000000 --- a/src/task_system/task_system.c +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Basic Type Functions - -internal TS_Ticket -ts_ticket_zero(void) -{ - TS_Ticket ticket = {0}; - return ticket; -} - -internal B32 -ts_ticket_match(TS_Ticket a, TS_Ticket b) -{ - B32 result = MemoryMatchStruct(&a, &b); - return result; -} - -internal void -ts_ticket_list_push(Arena *arena, TS_TicketList *list, TS_Ticket ticket) -{ - TS_TicketNode *n = push_array(arena, TS_TicketNode, 1); - n->v = ticket; - SLLQueuePush(list->first, list->last, n); - list->count += 1; -} - -//////////////////////////////// -//~ rjf: Top-Level Layer Initialization - -internal void -ts_init(void) -{ - Arena *arena = arena_alloc(); - ts_shared = push_array(arena, TS_Shared, 1); - ts_shared->arena = arena; - ts_shared->artifact_slots_count = 1024; - ts_shared->artifact_stripes_count = Min(ts_shared->artifact_slots_count, os_get_system_info()->logical_processor_count); - ts_shared->artifact_slots = push_array(arena, TS_TaskArtifactSlot, ts_shared->artifact_slots_count); - ts_shared->artifact_stripes = push_array(arena, TS_TaskArtifactStripe, ts_shared->artifact_stripes_count); - for(U64 idx = 0; idx < ts_shared->artifact_stripes_count; idx += 1) - { - ts_shared->artifact_stripes[idx].arena = arena_alloc(); - ts_shared->artifact_stripes[idx].cv = os_condition_variable_alloc(); - ts_shared->artifact_stripes[idx].rw_mutex = os_rw_mutex_alloc(); - } - ts_shared->u2t_ring_size = MB(1); - ts_shared->u2t_ring_base = push_array_no_zero(arena, U8, ts_shared->u2t_ring_size); - ts_shared->u2t_ring_mutex = os_mutex_alloc(); - ts_shared->u2t_ring_cv = os_condition_variable_alloc(); - ts_shared->task_threads_count = Max(1, os_get_system_info()->logical_processor_count-1); - ts_shared->task_threads = push_array(arena, TS_TaskThread, ts_shared->task_threads_count); - for(U64 idx = 0; idx < ts_shared->task_threads_count; idx += 1) - { - ts_shared->task_threads[idx].arena = arena_alloc(); - ts_shared->task_threads[idx].thread = os_thread_launch(ts_task_thread__entry_point, (void *)idx, 0); - } -} - -//////////////////////////////// -//~ rjf: Top-Level Accessors - -internal U64 -ts_thread_count(void) -{ - return ts_shared->task_threads_count; -} - -//////////////////////////////// -//~ rjf: High-Level Task Kickoff / Joining - -internal TS_Ticket -ts_kickoff_(TS_TaskFunctionType *entry_point, TS_KickoffParams *params) -{ - ProfBeginFunction(); - - // rjf: obtain number & slot/stripe for next artifact - U64 artifact_num = ins_atomic_u64_inc_eval(&ts_shared->artifact_num_gen); - U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; - U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count; - TS_TaskArtifactSlot *slot = &ts_shared->artifact_slots[slot_idx]; - TS_TaskArtifactStripe *stripe = &ts_shared->artifact_stripes[stripe_idx]; - - // rjf: allocate artifact - TS_TaskArtifact *artifact = 0; - ProfScope("allocate artifact") - { - OS_MutexScopeW(stripe->rw_mutex) - { - artifact = stripe->free_artifact; - if(artifact != 0) - { - SLLStackPop(stripe->free_artifact); - } - else - { - artifact = push_array_no_zero(stripe->arena, TS_TaskArtifact, 1); - } - artifact->num = artifact_num; - artifact->task_is_done = 0; - artifact->out = 0; - } - } - - // rjf: form ticket out of artifact info - TS_Ticket ticket = {artifact_num, (U64)artifact}; - - // rjf: push task info to task ring buffer - ProfScope("push task info to task ring buffer") - { - OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) - { - U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; - U64 available_size = ts_shared->u2t_ring_size-unconsumed_size; - if(available_size >= sizeof(entry_point) + sizeof(Arena *) + sizeof(params->in) + sizeof(ticket)) - { - Arena *task_arena = 0; - if(params->optional_arena_ptr != 0) - { - task_arena = *params->optional_arena_ptr; - } - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, ¶ms->in); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket); - if(params->optional_arena_ptr != 0) - { - *params->optional_arena_ptr = 0; - } - break; - } - os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); - } - os_condition_variable_signal(ts_shared->u2t_ring_cv); - } - - ProfEnd(); - return ticket; -} - -internal TS_JoinResult -ts_join(TS_Ticket ticket, U64 endt_us) -{ - TS_JoinResult result = {0}; - U64 artifact_num = ticket.u64[0]; - U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; - U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count; - TS_TaskArtifactSlot *slot = &ts_shared->artifact_slots[slot_idx]; - TS_TaskArtifactStripe *stripe = &ts_shared->artifact_stripes[stripe_idx]; - TS_TaskArtifact *artifact = (TS_TaskArtifact *)ticket.u64[1]; - if(artifact != 0) - { - OS_MutexScopeR(stripe->rw_mutex) for(;;) - { - B64 task_is_done = artifact->task_is_done; - if(task_is_done) - { - OS_MutexScopeRWPromote(stripe->rw_mutex) - { - result.good = 1; - result.out = artifact->out; - SLLStackPush(stripe->free_artifact, artifact); - } - break; - } - if(os_now_microseconds() >= endt_us) - { - break; - } - os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us); - } - } - return result; -} - -//////////////////////////////// -//~ rjf: Task Threads - -internal void -ts_u2t_dequeue_task(TS_TaskFunctionType **entry_point_out, Arena **arena_out, void **p_out, TS_Ticket *ticket_out) -{ - OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) - { - U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; - if(unconsumed_size >= sizeof(*entry_point_out) + sizeof(*p_out) + sizeof(*ticket_out)) - { - ts_shared->u2t_ring_read_pos += ring_read_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_read_pos, entry_point_out); - ts_shared->u2t_ring_read_pos += ring_read_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_read_pos, arena_out); - ts_shared->u2t_ring_read_pos += ring_read_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_read_pos, p_out); - ts_shared->u2t_ring_read_pos += ring_read_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_read_pos, ticket_out); - break; - } - os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); - } - os_condition_variable_broadcast(ts_shared->u2t_ring_cv); -} - -internal void -ts_task_thread__entry_point(void *p) -{ - U64 thread_idx = (U64)p; - ThreadNameF("[ts] task thread #%I64u", thread_idx); - TS_TaskThread *thread = &ts_shared->task_threads[thread_idx]; - for(;;) - { - //- rjf: grab next task - TS_TaskFunctionType *task_function = 0; - Arena *task_arena = 0; - void *task_params = 0; - TS_Ticket task_ticket = {0}; - ts_u2t_dequeue_task(&task_function, &task_arena, &task_params, &task_ticket); - - //- rjf: use task thread's arena if none specified - if(task_arena == 0) - { - task_arena = thread->arena; - } - - //- rjf: run task - void *task_out = task_function(task_arena, thread_idx, task_params); - - //- rjf: store into artifact - U64 artifact_num = task_ticket.u64[0]; - U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; - U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count; - TS_TaskArtifactSlot *slot = &ts_shared->artifact_slots[slot_idx]; - TS_TaskArtifactStripe *stripe = &ts_shared->artifact_stripes[stripe_idx]; - TS_TaskArtifact *artifact = (TS_TaskArtifact *)task_ticket.u64[1]; - OS_MutexScopeW(stripe->rw_mutex) - { - artifact->task_is_done = 1; - artifact->out = task_out; - } - os_condition_variable_broadcast(stripe->cv); - } -} diff --git a/src/task_system/task_system.h b/src/task_system/task_system.h deleted file mode 100644 index 7b17429e..00000000 --- a/src/task_system/task_system.h +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef TASK_SYSTEM_H -#define TASK_SYSTEM_H - -//////////////////////////////// -//~ rjf: Task "Ticket" Type -// -// "Tickets" are opaque handles, used to refer to submitted tasks. -// - -typedef struct TS_Ticket TS_Ticket; -struct TS_Ticket -{ - U64 u64[2]; -}; - -typedef struct TS_TicketNode TS_TicketNode; -struct TS_TicketNode -{ - TS_TicketNode *next; - TS_Ticket v; -}; - -typedef struct TS_TicketList TS_TicketList; -struct TS_TicketList -{ - TS_TicketNode *first; - TS_TicketNode *last; - U64 count; -}; - -//////////////////////////////// -//~ rjf: Task Request Types - -#define TS_TASK_FUNCTION_DEF(name) void *name(Arena *arena, U64 thread_idx, void *p) -typedef TS_TASK_FUNCTION_DEF(TS_TaskFunctionType); - -//////////////////////////////// -//~ rjf: Task Kickoff Parameters - -typedef struct TS_KickoffParams TS_KickoffParams; -struct TS_KickoffParams -{ - Arena **optional_arena_ptr; - void *in; -}; - -//////////////////////////////// -//~ rjf: Task Join Result - -typedef struct TS_JoinResult TS_JoinResult; -struct TS_JoinResult -{ - B32 good; - void *out; -}; - -//////////////////////////////// -//~ rjf: Task Artifact Cache Types - -typedef struct TS_TaskArtifact TS_TaskArtifact; -struct TS_TaskArtifact -{ - TS_TaskArtifact *next; - U64 num; - B64 task_is_done; - void *out; -}; - -typedef struct TS_TaskArtifactSlot TS_TaskArtifactSlot; -struct TS_TaskArtifactSlot -{ - TS_TaskArtifact *first; - TS_TaskArtifact *last; -}; - -typedef struct TS_TaskArtifactStripe TS_TaskArtifactStripe; -struct TS_TaskArtifactStripe -{ - Arena *arena; - OS_Handle cv; - OS_Handle rw_mutex; - TS_TaskArtifact *free_artifact; -}; - -//////////////////////////////// -//~ rjf: Per-Thread State - -typedef struct TS_TaskThread TS_TaskThread; -struct TS_TaskThread -{ - Arena *arena; - OS_Handle thread; -}; - -//////////////////////////////// -//~ rjf: Main Shared State - -typedef struct TS_Shared TS_Shared; -struct TS_Shared -{ - Arena *arena; - - // rjf: task artifact cache - U64 artifact_num_gen; - U64 artifact_slots_count; - U64 artifact_stripes_count; - TS_TaskArtifactSlot *artifact_slots; - TS_TaskArtifactStripe *artifact_stripes; - - // rjf: task ring buffer - U64 u2t_ring_size; - U8 *u2t_ring_base; - U64 u2t_ring_write_pos; - U64 u2t_ring_read_pos; - OS_Handle u2t_ring_mutex; - OS_Handle u2t_ring_cv; - - // rjf: task threads - TS_TaskThread *task_threads; - U64 task_threads_count; -}; - -//////////////////////////////// -//~ rjf: Globals - -global TS_Shared *ts_shared = 0; - -//////////////////////////////// -//~ rjf: Basic Type Functions - -internal TS_Ticket ts_ticket_zero(void); -internal B32 ts_ticket_match(TS_Ticket a, TS_Ticket b); -internal void ts_ticket_list_push(Arena *arena, TS_TicketList *list, TS_Ticket ticket); - -//////////////////////////////// -//~ rjf: Top-Level Layer Initialization - -internal void ts_init(void); - -//////////////////////////////// -//~ rjf: Top-Level Accessors - -internal U64 ts_thread_count(void); - -//////////////////////////////// -//~ rjf: High-Level Task Kickoff / Joining - -internal TS_Ticket ts_kickoff_(TS_TaskFunctionType *entry_point, TS_KickoffParams *params); -#define ts_kickoff(entry_point, input_ptr, ...) ts_kickoff_((entry_point), &(TS_KickoffParams){.in = (input_ptr), __VA_ARGS__}) -internal TS_JoinResult ts_join(TS_Ticket ticket, U64 endt_us); -#define ts_join_struct(ticket, endt_us, type) (type *)ts_join((ticket), (endt_us)).out - -//////////////////////////////// -//~ rjf: Task Threads - -internal void ts_u2t_dequeue_task(TS_TaskFunctionType **entry_point_out, Arena **arena_out, void **p_out, TS_Ticket *ticket_out); -internal void ts_task_thread__entry_point(void *p); - -#endif // TASK_SYSTEM_H