diff --git a/src/lib_raddbgi_make/raddbgi_make.c b/src/lib_raddbgi_make/raddbgi_make.c index 2b1b7914..7ac16ff6 100644 --- a/src/lib_raddbgi_make/raddbgi_make.c +++ b/src/lib_raddbgi_make/raddbgi_make.c @@ -1971,7 +1971,131 @@ rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeSt //- rjf: units RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMap *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) +rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit) +{ + RDIM_BakeSectionList sections = {0}; + + //////////////////////// + //- rjf: produce combined unit line info + // + RDI_U64 *unit_voffs = 0; + RDI_Line *unit_lines = 0; + RDI_U16 *unit_cols = 0; + RDI_U32 unit_line_count = 0; + RDIM_ProfScope("produce combined unit line info") + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: gather up all line info into two arrays: + // + // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders + // [2] recs: contains all the source coordinates for a range of voffs + // + typedef struct RDIM_LineRec RDIM_LineRec; + struct RDIM_LineRec + { + RDI_U32 file_id; + RDI_U32 line_num; + RDI_U16 col_first; + RDI_U16 col_opl; + }; + RDI_U64 line_count = 0; + RDI_U64 seq_count = 0; + for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) + { + seq_count += 1; + line_count += seq_n->v.line_count; + } + RDI_U64 key_count = line_count + seq_count; + RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); + RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); + { + RDIM_SortKey *key_ptr = line_keys; + RDIM_LineRec *rec_ptr = line_recs; + for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) + { + RDIM_LineSequence *seq = &seq_n->v; + for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) + { + key_ptr->key = seq->voffs[line_idx]; + key_ptr->val = rec_ptr; + key_ptr += 1; + rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 + rec_ptr->line_num = seq->line_nums[line_idx]; + if(seq->col_nums != 0) + { + rec_ptr->col_first = seq->col_nums[line_idx*2]; + rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; + } + rec_ptr += 1; + } + key_ptr->key = seq->voffs[seq->line_count]; + key_ptr->val = 0; + key_ptr += 1; + } + } + + //- rjf: sort + RDIM_SortKey *sorted_line_keys = 0; + RDIM_ProfScope("sort") + { + sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); + } + + // TODO(rjf): do a pass over sorted keys to make sure duplicate keys + // are sorted with null record first, and no more than one null + // record and one non-null record + + //- rjf: arrange output + RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); + RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); + RDIM_ProfScope("arrange output") + { + for(RDI_U64 i = 0; i < key_count; i += 1) + { + arranged_voffs[i] = sorted_line_keys[i].key; + } + arranged_voffs[key_count] = ~0ull; + for(RDI_U64 i = 0; i < key_count; i += 1) + { + RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; + if(rec != 0) + { + arranged_lines[i].file_idx = rec->file_id; + arranged_lines[i].line_num = rec->line_num; + } + else + { + arranged_lines[i].file_idx = 0; + arranged_lines[i].line_num = 0; + } + } + } + + //- rjf: fill output + unit_voffs = arranged_voffs; + unit_lines = arranged_lines; + unit_cols = 0; + unit_line_count = key_count; + rdim_scratch_end(scratch); + } + + //////////////////////// + //- rjf: build line info sections + // + U64 unit_idx = rdim_idx_from_unit(unit); + rdim_bake_section_list_push_new(arena, §ions, unit_voffs, sizeof(RDI_U64)*(unit_line_count+1), RDI_DataSectionTag_LineInfoVoffs, unit_idx); + rdim_bake_section_list_push_new(arena, §ions, unit_lines, sizeof(RDI_Line)*unit_line_count, RDI_DataSectionTag_LineInfoData, unit_idx); + if(unit_cols != 0) + { + rdim_bake_section_list_push_new(arena, §ions, unit_cols, sizeof(RDI_Column)*unit_line_count, RDI_DataSectionTag_LineInfoColumns, unit_idx); + } + + return sections; +} + +RDI_PROC RDIM_BakeSectionList +rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMap *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) { RDIM_BakeSectionList sections = {0}; RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, params->units.total_count+1); diff --git a/src/lib_raddbgi_make/raddbgi_make.h b/src/lib_raddbgi_make/raddbgi_make.h index f412e9f3..eac2487a 100644 --- a/src/lib_raddbgi_make/raddbgi_make.h +++ b/src/lib_raddbgi_make/raddbgi_make.h @@ -1145,7 +1145,8 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_info_section_list_from_params( RDI_PROC RDIM_BakeSectionList rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMap *strings, RDIM_BakeParams *params); //- rjf: units -RDI_PROC RDIM_BakeSectionList rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMap *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); +RDI_PROC RDIM_BakeSectionList rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit); +RDI_PROC RDIM_BakeSectionList rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMap *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); //- rjf: unit vmap RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.c b/src/raddbgi_from_pdb/raddbgi_from_pdb.c index 8b25b47b..1a662e0b 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.c +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.c @@ -3579,11 +3579,20 @@ p2r_build_bake_name_map_task__entry_point(Arena *arena, void *p) //- rjf: pass 2: string-map-dependent debug info stream builds internal void * -p2r_bake_units_task__entry_point(Arena *arena, void *p) +p2r_bake_units_top_level_task__entry_point(Arena *arena, void *p) { - P2R_BakeUnitsIn *in = (P2R_BakeUnitsIn *)p; + P2R_BakeUnitsTopLevelIn *in = (P2R_BakeUnitsTopLevelIn *)p; RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake units") *s = rdim_bake_unit_section_list_from_params(arena, in->strings, in->path_tree, in->params); + ProfScope("bake units") *s = rdim_bake_unit_top_level_section_list_from_params(arena, in->strings, in->path_tree, in->params); + return s; +} + +internal void * +p2r_bake_unit_task__entry_point(Arena *arena, void *p) +{ + P2R_BakeUnitIn *in = (P2R_BakeUnitIn *)p; + RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); + ProfScope("bake unit") *s = rdim_bake_section_list_from_unit(arena, in->unit); return s; } @@ -3733,6 +3742,16 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } //- rjf: kick off pass 1 tasks + P2R_BakeUnitIn *bake_units_in = push_array(scratch.arena, P2R_BakeUnitIn, params->units.total_count); + TS_Ticket *bake_units_tickets = push_array(scratch.arena, TS_Ticket, params->units.total_count); + for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) + { + for(U64 idx = 0; idx < n->count; idx += 1) + { + bake_units_in[idx].unit = &n->v[idx]; + bake_units_tickets[idx] = ts_kickoff(p2r_bake_unit_task__entry_point, 0, &bake_units_in[idx]); + } + } P2R_BuildBakeStringMapIn build_bake_string_map_in = {path_tree, params}; TS_Ticket build_bake_string_map_ticket = ts_kickoff(p2r_build_bake_string_map_task__entry_point, 0, &build_bake_string_map_in); P2R_BuildBakeNameMapIn build_bake_name_map_in[RDI_NameMapKind_COUNT] = {0}; @@ -3754,8 +3773,8 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } //- rjf: kick off pass 2 tasks - P2R_BakeUnitsIn bake_units_in = {strings, path_tree, params}; - TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_in); + P2R_BakeUnitsTopLevelIn bake_units_top_level_in = {strings, path_tree, params}; + TS_Ticket bake_units_top_level_ticket = ts_kickoff(p2r_bake_units_top_level_task__entry_point, 0, &bake_units_top_level_in); P2R_BakeUnitVMapIn bake_unit_vmap_in = {params}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); P2R_BakeSrcFilesIn bake_src_files_in = {strings, path_tree, params}; @@ -3842,10 +3861,10 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) rdim_bake_section_list_concat_in_place(§ions, &s); } - //- rjf: join units - ProfScope("units") + //- rjf: join top-level units info + ProfScope("top-level units info") { - RDIM_BakeSectionList *s = ts_join_struct(bake_units_ticket, max_U64, RDIM_BakeSectionList); + RDIM_BakeSectionList *s = ts_join_struct(bake_units_top_level_ticket, max_U64, RDIM_BakeSectionList); rdim_bake_section_list_concat_in_place(§ions, s); } @@ -3950,6 +3969,16 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) rdim_bake_section_list_concat_in_place(§ions, s); } + //- rjf: join per-unit bakes + ProfScope("units") + { + for(U64 idx = 0; idx < params->units.total_count; idx += 1) + { + RDIM_BakeSectionList *s = ts_join_struct(bake_units_tickets[idx], max_U64, RDIM_BakeSectionList); + rdim_bake_section_list_concat_in_place(§ions, s); + } + } + //- rjf: fill & return P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); out->sections = sections; diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.h b/src/raddbgi_from_pdb/raddbgi_from_pdb.h index 86a9f9e2..9384bcb1 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.h +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.h @@ -266,14 +266,20 @@ struct P2R_BuildBakeNameMapIn RDIM_BakeParams *params; }; -typedef struct P2R_BakeUnitsIn P2R_BakeUnitsIn; -struct P2R_BakeUnitsIn +typedef struct P2R_BakeUnitsTopLevelIn P2R_BakeUnitsTopLevelIn; +struct P2R_BakeUnitsTopLevelIn { RDIM_BakeStringMap *strings; RDIM_BakePathTree *path_tree; RDIM_BakeParams *params; }; +typedef struct P2R_BakeUnitIn P2R_BakeUnitIn; +struct P2R_BakeUnitIn +{ + RDIM_Unit *unit; +}; + typedef struct P2R_BakeUnitVMapIn P2R_BakeUnitVMapIn; struct P2R_BakeUnitVMapIn { @@ -454,7 +460,8 @@ internal void *p2r_build_bake_string_map_task__entry_point(Arena *arena, void *p internal void *p2r_build_bake_name_map_task__entry_point(Arena *arena, void *p); //- rjf: pass 2: string-map-dependent debug info stream builds -internal void *p2r_bake_units_task__entry_point(Arena *arena, void *p); +internal void *p2r_bake_units_top_level_task__entry_point(Arena *arena, void *p); +internal void *p2r_bake_unit_task__entry_point(Arena *arena, void *p); internal void *p2r_bake_unit_vmap_task__entry_point(Arena *arena, void *p); internal void *p2r_bake_src_files_task__entry_point(Arena *arena, void *p); internal void *p2r_bake_udts_task__entry_point(Arena *arena, void *p);