From 55f21018df612759de64c26d31e853d58e4ec519 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 18 Aug 2025 14:19:48 -0700 Subject: [PATCH] unit conversion, line info conversion --- src/rdi_from_pdb/rdi_from_pdb.c | 2 +- src/rdi_from_pdb/rdi_from_pdb_2.c | 470 ++++++++++++++++++++++++++---- src/rdi_from_pdb/rdi_from_pdb_2.h | 12 + 3 files changed, 430 insertions(+), 54 deletions(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 95b57049..0b29493b 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -3196,7 +3196,7 @@ p2r_convert(Arena *arena, ASYNC_Root *async_root, P2R_ConvertParams *in) //- rjf: parse PDB strtbl // PDB_Strtbl *strtbl = 0; - String8 raw_strtbl = str8_zero(); + String8 raw_strtbl = {0}; if(named_streams != 0) ProfScope("parse PDB strtbl") { MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable]; diff --git a/src/rdi_from_pdb/rdi_from_pdb_2.c b/src/rdi_from_pdb/rdi_from_pdb_2.c index 3be70c8b..215d15b2 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_2.c +++ b/src/rdi_from_pdb/rdi_from_pdb_2.c @@ -41,7 +41,7 @@ p2r2_convert_thread_entry_point(void *p) ////////////////////////////////////////////////////////////// //- rjf: do top-level MSF/PDB extraction // - if(lane_idx() == 0) ProfScope("do top-level MSF/PDB extraction") + ProfScope("do top-level MSF/PDB extraction") if(lane_idx() == 0) { ProfScope("parse PDB info") { @@ -64,6 +64,7 @@ p2r2_convert_thread_entry_point(void *p) ////////////////////////////////////////////////////////////// //- rjf: parse PDB strtbl & top-level streams // + ProfScope("parse PDB strtbl & top-level streams") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("parse PDB strtbl") { @@ -98,6 +99,7 @@ p2r2_convert_thread_entry_point(void *p) ////////////////////////////////////////////////////////////// //- rjf: unpack DBI // + ProfScope("unpack DBI") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("parse COFF sections") { @@ -125,6 +127,7 @@ p2r2_convert_thread_entry_point(void *p) ////////////////////////////////////////////////////////////// //- rjf: hash EXE, parse TPI/IPI hash/leaf & global symbol stream & comp units // + ProfScope("hash EXE, parse TPI/IPI hash/leaf & global symbol stream & comp units") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("hash EXE") { @@ -181,7 +184,7 @@ p2r2_convert_thread_entry_point(void *p) ////////////////////////////////////////////////////////////// //- rjf: bucket compilation unit contributions // - if(lane_idx() == 0) ProfScope("bucket compilation unit contributions") + ProfScope("bucket compilation unit contributions") if(lane_idx() == 0) { p2r2_shared->unit_ranges = push_array(arena, RDIM_Rng1U64ChunkList, comp_units->count); for(U64 idx = 0; idx < comp_unit_contributions->count; idx += 1) @@ -318,13 +321,15 @@ p2r2_convert_thread_entry_point(void *p) ProfScope("gather all source file paths; build nodes") { //- rjf: prep outputs - if(lane_idx() == 0) + ProfScope("prep outputs") if(lane_idx() == 0) { p2r2_shared->unit_src_file_paths = push_array(arena, String8Array, comp_units->count); + p2r2_shared->unit_src_file_paths_hashes = push_array(arena, U64Array, comp_units->count); } lane_sync(); //- rjf: do wide gather + ProfScope("do wide gather") { Rng1U64 range = lane_range(comp_units->count); for EachInRange(idx, range) @@ -565,68 +570,427 @@ p2r2_convert_thread_entry_point(void *p) } } } - scratch_end(scratch); } p2r2_shared->unit_src_file_paths[idx] = str8_array_from_list(arena, &src_file_paths); - } - } - -#if 0 // TODO(rjf): OLD - U64 tasks_count = comp_unit_count; - P2R_GatherUnitSrcFilesIn *tasks_inputs = push_array(scratch.arena, P2R_GatherUnitSrcFilesIn, tasks_count); - P2R_GatherUnitSrcFilesOut *tasks_outputs = push_array(scratch.arena, P2R_GatherUnitSrcFilesOut, tasks_count); - ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, tasks_count); - for EachIndex(idx, tasks_count) - { - tasks_inputs[idx].pdb_strtbl = strtbl; - tasks_inputs[idx].coff_sections = coff_sections; - tasks_inputs[idx].comp_unit = comp_units->units[idx]; - tasks_inputs[idx].comp_unit_syms = sym_for_unit[idx]; - tasks_inputs[idx].comp_unit_c13s = c13_for_unit[idx]; - tasks[idx] = async_task_launch(scratch.arena, p2r_gather_unit_src_file_work, .input = &tasks_inputs[idx]); - } - U64 total_path_count = 0; - for EachIndex(idx, tasks_count) - { - tasks_outputs[idx] = *async_task_join_struct(tasks[idx], P2R_GatherUnitSrcFilesOut); - total_path_count += tasks_outputs[idx].src_file_paths.count; - } - src_file_map.slots_count = total_path_count + total_path_count/2 + 1; - src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); -#endif - - //- rjf: build src file map -#if 0 - for EachIndex(idx, tasks_count) - { - for EachIndex(path_idx, tasks_outputs[idx].src_file_paths.count) - { - String8 file_path_sanitized = tasks_outputs[idx].src_file_paths.v[path_idx]; - U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); - U64 src_file_slot = file_path_sanitized_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) + ProfScope("hash all paths") { - if(str8_match(n->src_file->path, file_path_sanitized, 0)) + p2r2_shared->unit_src_file_paths_hashes[idx].count = p2r2_shared->unit_src_file_paths[idx].count; + p2r2_shared->unit_src_file_paths_hashes[idx].v = push_array(arena, U64, p2r2_shared->unit_src_file_paths[idx].count); + for EachIndex(path_idx, p2r2_shared->unit_src_file_paths_hashes[idx].count) { - src_file_node = n; - break; + p2r2_shared->unit_src_file_paths_hashes[idx].v[path_idx] = rdi_hash(p2r2_shared->unit_src_file_paths[idx].v[path_idx].str, p2r2_shared->unit_src_file_paths[idx].v[path_idx].size); } } - if(src_file_node == 0) + } + } + lane_sync(); + + //- rjf: set up table + ProfScope("set up table") if(lane_idx() == 0) + { + p2r2_shared->total_path_count = 0; + for EachIndex(idx, comp_units->count) + { + p2r2_shared->total_path_count += p2r2_shared->unit_src_file_paths[idx].count; + } + p2r2_shared->src_file_map.slots_count = p2r2_shared->total_path_count + p2r2_shared->total_path_count/2 + 1; + p2r2_shared->src_file_map.slots = push_array(arena, P2R_SrcFileNode *, p2r2_shared->src_file_map.slots_count); + } + lane_sync(); + + //- rjf: fill table + ProfScope("fill table") if(lane_idx() == 0) + { + for EachIndex(idx, comp_units->count) + { + for EachIndex(path_idx, p2r2_shared->unit_src_file_paths[idx].count) { - 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, &all_src_files__sequenceless, total_path_count); - src_file_node->src_file->path = push_str8_copy(arena, file_path_sanitized); + String8 file_path_sanitized = p2r2_shared->unit_src_file_paths[idx].v[path_idx]; + U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); + U64 src_file_slot = file_path_sanitized_hash%p2r2_shared->src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = p2r2_shared->src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->path, file_path_sanitized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(arena, P2R_SrcFileNode, 1); + SLLStackPush(p2r2_shared->src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &p2r2_shared->all_src_files__sequenceless, p2r2_shared->total_path_count); + src_file_node->src_file->path = push_str8_copy(arena, file_path_sanitized); + } } } } -#endif } - RDIM_SrcFileChunkList all_src_files__sequenceless = {0}; - P2R_SrcFileMap src_file_map = {0}; + lane_sync(); + RDIM_SrcFileChunkList all_src_files__sequenceless = p2r2_shared->all_src_files__sequenceless; + P2R_SrcFileMap src_file_map = p2r2_shared->src_file_map; + + ////////////////////////////////////////////////////////////// + //- rjf: convert unit info + // + ProfScope("convert unit info") + { + //- rjf: set up outputs + ProfScope("set up outputs") if(lane_idx() == 0) + { + for EachIndex(idx, comp_units->count) + { + rdim_unit_chunk_list_push(arena, &p2r2_shared->all_units, comp_units->count); + } + p2r2_shared->units_line_tables = push_array(arena, RDIM_LineTableChunkList, comp_units->count); + p2r2_shared->units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, comp_units->count); + } + lane_sync(); + RDIM_Unit *units = p2r2_shared->all_units.first->v; + RDIM_LineTableChunkList *units_line_tables = p2r2_shared->units_line_tables; + U64 units_count = p2r2_shared->all_units.first->count; + Assert(units_count == comp_units->count); + + //- rjf: wide conversion of units + ProfScope("wide conversion of units") + { + Rng1U64 range = lane_range(units_count); + for EachInRange(idx, range) + { + Temp scratch = scratch_begin(&arena, 1); + PDB_CompUnit *src_unit = comp_units->units[idx]; + CV_SymParsed *src_unit_sym = sym_for_unit[idx]; + CV_C13Parsed *src_unit_c13 = c13_for_unit[idx]; + RDIM_Unit *dst_unit = &units[idx]; + RDIM_LineTableChunkList *dst_line_tables = &p2r2_shared->units_line_tables[idx]; + RDIM_LineTable **dst_unit_first_inline_site_line_table = &p2r2_shared->units_first_inline_site_line_tables[idx]; + + //- rjf: produce unit name + String8 unit_name = src_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/path + String8 obj_name = src_unit->obj_name; + if(str8_match(obj_name, str8_lit("* Linker *"), 0) || + str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) + { + MemoryZeroStruct(&obj_name); + } + String8 obj_folder_path = backslashed_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); + + //- rjf: build this unit's line table, fill out primary line info (inline info added after) + RDIM_LineTable *line_table = 0; + ProfScope("build unit line table") + for(CV_C13SubSectionNode *node = src_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 -> sanitized file path + String8 file_path = lines->file_name; + String8 file_path_sanitized = str8_copy(scratch.arena, str8_skip_chop_whitespace(file_path)); + { + PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); + String8List file_path_sanitized_parts = str8_split_path(scratch.arena, file_path_sanitized); + if(file_path_sanitized_style == PathStyle_Relative) + { + String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); + str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); + file_path_sanitized_parts = obj_folder_path_parts; + file_path_sanitized_style = path_style_from_str8(obj_folder_path); + } + str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); + file_path_sanitized = str8_path_list_join_by_style(scratch.arena, &file_path_sanitized_parts, file_path_sanitized_style); + } + + // rjf: sanitized file path -> source file node + U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); + U64 src_file_slot = file_path_sanitized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + if(lines->line_count != 0) + { + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->path, file_path_sanitized, 0)) + { + src_file_node = n; + break; + } + } + } + + // rjf: push sequence into both line table & source file's line map + if(src_file_node != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, dst_line_tables, 256); + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, dst_line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + } + } + } + } + + //- rjf: build line tables for all inline sites + ProfScope("build line tables for all inline sites") + { + CV_RecRange *rec_ranges_first = src_unit_sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first + src_unit_sym->sym_ranges.count; + + //- rjf: parse inlinee line tables + 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 > src_unit_sym->data.size || sym_off_first > src_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 = src_unit_sym->data.str + sym_off_first; + void *sym_data_opl = src_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 <= coff_sections.count) ? &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%src_unit_c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = src_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 + if(inlinee_lines_parsed != 0) + { + // rjf: grab checksums sub-section + CV_C13SubSectionNode *file_chksms = src_unit_c13->file_chksms_sub_section; + + // 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; + U32 last_file_off = max_U32; + U32 curr_file_off = max_U32; + RDIM_LineTable* line_table = 0; + + CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); + for(;;) + { + // rjf: step & update + CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) + { + last_file_off = curr_file_off; + curr_file_off = step.file_off; + } + if(step.flags == 0 && total_line_chunk_line_count > 0) + { + last_file_off = curr_file_off; + curr_file_off = max_U32; + } + + // rjf: file updated -> push line chunks gathered for this file + if(last_file_off != max_U32 && last_file_off != curr_file_off) + { + String8 seq_file_name = {0}; + if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(src_unit_c13->data.str + file_chksms->off + last_file_off); + U32 name_off = checksum->name_off; + seq_file_name = pdb_strtbl_string_from_off(strtbl, name_off); + } + + // rjf: file name -> sanitized file path + String8 file_path = seq_file_name; + String8 file_path_sanitized = str8_copy(scratch.arena, str8_skip_chop_whitespace(file_path)); + { + PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); + String8List file_path_sanitized_parts = str8_split_path(scratch.arena, file_path_sanitized); + if(file_path_sanitized_style == PathStyle_Relative) + { + String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); + str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); + file_path_sanitized_parts = obj_folder_path_parts; + file_path_sanitized_style = path_style_from_str8(obj_folder_path); + } + str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); + file_path_sanitized = str8_path_list_join_by_style(scratch.arena, &file_path_sanitized_parts, file_path_sanitized_style); + } + + // rjf: sanitized file path -> source file node + U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); + U64 src_file_slot = file_path_sanitized_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->path, file_path_sanitized, 0)) + { + src_file_node = n; + break; + } + } + + // rjf: gather all lines + RDI_U64 *voffs = 0; + RDI_U32 *line_nums = 0; + RDI_U64 line_count = 0; + if(src_file_node != 0) + { + voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); + line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); + 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+1)); + MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); + dst_idx += chunk->count; + } + } + + // rjf: push + if(line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, dst_line_tables, 256); + if(dst_unit_first_inline_site_line_table[0] == 0) + { + dst_unit_first_inline_site_line_table[0] = line_table; + } + } + rdim_line_table_push_sequence(arena, dst_line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + } + + // rjf: clear line chunks for subsequent sequences + first_line_chunk = last_line_chunk = 0; + total_line_chunk_line_count = 0; + } + + // rjf: new line -> emit to chunk + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) + { + 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 = 8; + 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] = step.line_voff; + chunk->voffs[chunk->count+1] = step.line_voff_end; + chunk->line_nums[chunk->count] = step.ln; + chunk->count += 1; + total_line_chunk_line_count += 1; + } + + // rjf: no more flags -> done + if(step.flags == 0) + { + break; + } + } + } + }break; + } + } + } + scratch_end(scratch); + } + } + } + lane_sync(); + RDIM_UnitChunkList *units = &p2r2_shared->all_units; + RDIM_LineTableChunkList *units_line_tables = p2r2_shared->units_line_tables; + RDIM_LineTable **units_first_inline_site_line_tables = p2r2_shared->units_first_inline_site_line_tables; + + ////////////////////////////////////////////////////////////// + //- rjf: join all line tables + // + ProfScope("join all line tables") if(lane_idx() == 0) + { + for EachIndex(idx, units->total_count) + { + rdim_line_table_chunk_list_concat_in_place(&p2r2_shared->all_line_tables, &p2r2_shared->units_line_tables[idx]); + } + } + lane_sync(); + RDIM_LineTableChunkList all_line_tables = p2r2_shared->all_line_tables; } internal RDIM_BakeParams diff --git a/src/rdi_from_pdb/rdi_from_pdb_2.h b/src/rdi_from_pdb/rdi_from_pdb_2.h index f5c79085..bfc738e3 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_2.h +++ b/src/rdi_from_pdb/rdi_from_pdb_2.h @@ -21,6 +21,7 @@ struct P2R2_Shared { MSF_RawStreamTable *msf_raw_stream_table; MSF_Parsed *msf; + PDB_Info *pdb_info; PDB_NamedStreamTable *named_streams; @@ -51,6 +52,17 @@ struct P2R2_Shared RDI_Arch arch; String8Array *unit_src_file_paths; + U64Array *unit_src_file_paths_hashes; + U64 total_path_count; + + RDIM_SrcFileChunkList all_src_files__sequenceless; + P2R_SrcFileMap src_file_map; + + RDIM_UnitChunkList all_units; + RDIM_LineTableChunkList *units_line_tables; + RDIM_LineTable **units_first_inline_site_line_tables; + + RDIM_LineTableChunkList all_line_tables; }; global P2R2_Shared *p2r2_shared = 0;