diff --git a/src/rdi_from_pdb/rdi_from_pdb_2.c b/src/rdi_from_pdb/rdi_from_pdb_2.c index fa8a5068..89e1d325 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_2.c +++ b/src/rdi_from_pdb/rdi_from_pdb_2.c @@ -723,117 +723,133 @@ p2r2_convert_thread_entry_point(void *p) { 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); + p2r2_shared->lanes_line_tables = push_array(arena, RDIM_LineTableChunkList, lane_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; + RDIM_LineTableChunkList *lanes_line_tables = p2r2_shared->lanes_line_tables; Assert(units_count == comp_units->count); - //- rjf: wide conversion of units - ProfScope("wide conversion of units") + //- rjf: do per-lane work { - Rng1U64 range = lane_range(units_count); - for EachInRange(idx, range) + RDIM_LineTableChunkList *dst_line_tables = &lanes_line_tables[lane_idx()]; + + //- rjf: per-unit line table conversion + ProfScope("per-unit line table conversion") { - 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) + Rng1U64 range = lane_range(units_count); + for EachInRange(idx, range) { - String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); - if(unit_name_past_last_slash.size != 0) + 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]; + + // 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)) { - unit_name = unit_name_past_last_slash; + MemoryZeroStruct(&obj_name); } - } - - //- 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) + 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) { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) + if(node->kind == CV_C13SubSectionKind_Lines) { - 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)); + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) { - 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) + 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)); { - 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)) + 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) { - src_file_node = n; - break; + 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) + + // rjf: push sequence into both line table & source file's line map + if(src_file_node != 0) { - line_table = rdim_line_table_chunk_list_push(arena, dst_line_tables, 256); + 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); } - 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); } } } + scratch_end(scratch); } - - //- rjf: build line tables for all inline sites - ProfScope("build line tables for all inline sites") + } + + //- rjf: build per-inline-site line tables + ProfScope("build per-inline-site line tables") + { + U64 last_unit_num_started_by_this_lane = 0; + for(P2R2_UnitSymBlock *lane_block = lane_sym_blocks[lane_idx()].first; + lane_block != 0; + lane_block = lane_block->next) { - 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 + Temp scratch = scratch_begin(&arena, 1); + if(lane_block->unit_rec_range.min == 0) + { + last_unit_num_started_by_this_lane = lane_block->unit_idx+1; + } + else if(last_unit_num_started_by_this_lane-1 != lane_block->unit_idx) + { + last_unit_num_started_by_this_lane = 0; + } + PDB_CompUnit *src_unit = comp_units->units[lane_block->unit_idx]; + CV_SymParsed *src_unit_sym = sym_for_unit[lane_block->unit_idx]; + CV_C13Parsed *src_unit_c13 = c13_for_unit[lane_block->unit_idx]; + 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)); + CV_RecRange *rec_ranges_first = src_unit_sym->sym_ranges.ranges + lane_block->unit_rec_range.min; + CV_RecRange *rec_ranges_opl = src_unit_sym->sym_ranges.ranges + lane_block->unit_rec_range.max; U64 base_voff = 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; @@ -1005,9 +1021,12 @@ p2r2_convert_thread_entry_point(void *p) 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) + if(last_unit_num_started_by_this_lane != 0) { - dst_unit_first_inline_site_line_table[0] = line_table; + if(p2r2_shared->units_first_inline_site_line_tables[last_unit_num_started_by_this_lane-1] == 0) + { + p2r2_shared->units_first_inline_site_line_tables[last_unit_num_started_by_this_lane-1] = line_table; + } } } rdim_line_table_push_sequence(arena, dst_line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); @@ -1047,14 +1066,14 @@ p2r2_convert_thread_entry_point(void *p) }break; } } + scratch_end(scratch); } - scratch_end(scratch); } } } lane_sync(); - RDIM_UnitChunkList *units = &p2r2_shared->all_units; - RDIM_LineTableChunkList *units_line_tables = p2r2_shared->units_line_tables; + RDIM_UnitChunkList *all_units = &p2r2_shared->all_units; + RDIM_LineTableChunkList *lanes_line_tables = p2r2_shared->lanes_line_tables; RDIM_LineTable **units_first_inline_site_line_tables = p2r2_shared->units_first_inline_site_line_tables; ////////////////////////////////////////////////////////////// @@ -1062,14 +1081,1030 @@ p2r2_convert_thread_entry_point(void *p) // ProfScope("join all line tables") if(lane_idx() == 0) { - for EachIndex(idx, units->total_count) + for EachIndex(idx, lane_count()) { - rdim_line_table_chunk_list_concat_in_place(&p2r2_shared->all_line_tables, &p2r2_shared->units_line_tables[idx]); + rdim_line_table_chunk_list_concat_in_place(&p2r2_shared->all_line_tables, &p2r2_shared->lanes_line_tables[idx]); } } lane_sync(); RDIM_LineTableChunkList all_line_tables = p2r2_shared->all_line_tables; + ////////////////////////////////////////////////////////////// + //- rjf: types pass 1: produce type forward resolution map + // + // this map is used to resolve usage of "incomplete structs" in codeview's + // type info. this often happens when e.g. "struct Foo" is used to refer to + // a later-defined "Foo", which actually contains members and so on. we want + // to hook types up to their actual destination complete types wherever + // possible, and so this map can be used to do that in subsequent stages. + // + ProfScope("types pass 1: produce type forward resolution map") + { + //- rjf: allocate forward resolution map + if(lane_idx() == 0) + { + p2r2_shared->itype_first = tpi_leaf->itype_first; + p2r2_shared->itype_opl = tpi_leaf->itype_opl; + p2r2_shared->itype_fwd_map = push_array(arena, CV_TypeId, (U64)p2r2_shared->itype_opl); + } + lane_sync(); + + //- rjf: do wide fill + { + Rng1U64 range = lane_range(p2r2_shared->itype_opl); + for EachInRange(idx, range) + { + CV_TypeId itype = (CV_TypeId)idx; + if(itype < p2r2_shared->itype_first) { continue; } + + //- rjf: determine if this itype resolves to another + CV_TypeId itype_fwd = 0; + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-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 <= tpi_leaf->data.size && + range->off+2+header_struct_size <= tpi_leaf->data.size && + range->hdr.size >= 2) + { + U8 *itype_leaf_first = 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(tpi_hash, 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(tpi_hash, 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(tpi_hash, 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(tpi_hash, 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 < tpi_leaf->itype_opl) + { + p2r2_shared->itype_fwd_map[itype] = itype_fwd; + } + } + } + } + lane_sync(); + CV_TypeId *itype_fwd_map = p2r2_shared->itype_fwd_map; + CV_TypeId itype_first = p2r2_shared->itype_first; + CV_TypeId itype_opl = p2r2_shared->itype_opl; + + ////////////////////////////////////////////////////////////// + //- rjf: types pass 2: produce per-itype itype chain + // + // this pass is to ensure that subsequent passes always produce types for + // dependent itypes first - guaranteeing rdi's "only reference backward" + // rule (which eliminates cycles). each itype slot gets a list of itypes, + // starting with the deepest dependency - when types are produced per-itype, + // this chain is walked, so that deeper dependencies are built first, and + // as such, always show up *earlier* in the actually built types. + // + ProfScope("types pass 2: produce per-itype itype chain (for producing dependent types first)") + { + //- rjf: allocate itype chain table + if(lane_idx() == 0) + { + p2r2_shared->itype_chains = push_array(arena, P2R_TypeIdChain *, (U64)p2r2_shared->itype_opl); + } + lane_sync(); + + //- rjf: do wide fill + { + Rng1U64 range = lane_range(p2r2_shared->itype_opl); + for EachInRange(idx, range) + { + CV_TypeId itype = (CV_TypeId)idx; + if(itype < p2r2_shared->itype_first) { continue; } + + //- 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(p2r2_shared->itype_chains[itype], c); + } + + //- rjf: skip basic types for dependency walk + if(itype < tpi_leaf->itype_first) + { + continue; + } + + //- rjf: walk dependent types, push to chain + Temp scratch = scratch_begin(&arena, 1); + 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 = itype_fwd_map[walk_task->itype] ? itype_fwd_map[walk_task->itype] : walk_task->itype; + if(walk_itype < tpi_leaf->itype_first) + { + continue; + } + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[walk_itype-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 <= tpi_leaf->data.size && + range->off+2+header_struct_size <= tpi_leaf->data.size && + range->hdr.size >= 2) + { + U8 *itype_leaf_first = 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(p2r2_shared->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(p2r2_shared->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(p2r2_shared->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 = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-tpi_leaf->itype_first]; + if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || + arglist_range->hdr.size<2 || + arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = 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(p2r2_shared->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(p2r2_shared->itype_chains[itype], c); + } + { + P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); + c->itype = lf->arg_itype; + SLLStackPush(p2r2_shared->itype_chains[itype], c); + } + { + P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); + c->itype = lf->this_itype; + SLLStackPush(p2r2_shared->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 = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-tpi_leaf->itype_first]; + if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || + arglist_range->hdr.size<2 || + arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = 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(p2r2_shared->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(p2r2_shared->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(p2r2_shared->itype_chains[itype], c); + } + { + P2R_TypeIdChain *c = push_array(arena, P2R_TypeIdChain, 1); + c->itype = lf->index_itype; + SLLStackPush(p2r2_shared->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(p2r2_shared->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); + } + } + } + lane_sync(); + P2R_TypeIdChain **itype_chains = p2r2_shared->itype_chains; + + ////////////////////////////////////////////////////////////// + //- rjf: types pass 3: construct all types from TPI + // + // this doesn't gather struct/class/union/enum members, which is done by + // subsequent passes, to build RDI "UDT" information, which is distinct + // from regular type info. + // + ProfScope("types pass 3: construct all root/stub types from TPI") if(lane_idx() == 0) + { +#define p2r_builtin_type_ptr_from_kind(kind) ((basic_type_ptrs && RDI_TypeKind_FirstBuiltIn <= (kind) && (kind) <= RDI_TypeKind_LastBuiltIn) ? (basic_type_ptrs[(kind) - RDI_TypeKind_FirstBuiltIn]) : 0) +#define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0) + RDIM_Type **itype_type_ptrs = push_array(arena, RDIM_Type *, (U64)(itype_opl)); + RDIM_Type **basic_type_ptrs = push_array(arena, RDIM_Type *, (RDI_TypeKind_LastBuiltIn - RDI_TypeKind_FirstBuiltIn + 1)); + RDIM_TypeChunkList all_types = {0}; + + //////////////////////////// + //- rjf: build basic types + // + { + for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; + type_kind <= RDI_TypeKind_LastBuiltIn; + type_kind += 1) + { + RDIM_Type *type = rdim_type_chunk_list_push(arena, &all_types, 512); + type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size); + type->kind = type_kind; + type->byte_size = rdi_size_from_basic_type_kind(type_kind); + basic_type_ptrs[type_kind - RDI_TypeKind_FirstBuiltIn] = type; + } + } + + //////////////////////////// + //- rjf: build basic type aliases + // + { + RDIM_DataModel data_model = rdim_data_model_from_os_arch(OperatingSystem_Windows, arch); + RDI_TypeKind short_type = rdim_short_type_kind_from_data_model(data_model); + RDI_TypeKind ushort_type = rdim_unsigned_short_type_kind_from_data_model(data_model); + RDI_TypeKind long_type = rdim_long_type_kind_from_data_model(data_model); + RDI_TypeKind ulong_type = rdim_unsigned_long_type_kind_from_data_model(data_model); + RDI_TypeKind long_long_type = rdim_long_long_type_kind_from_data_model(data_model); + RDI_TypeKind ulong_long_type = rdim_unsigned_long_long_type_kind_from_data_model(data_model); + RDI_TypeKind ptr_type = rdim_pointer_size_t_type_kind_from_data_model(data_model); + struct + { + char * name; + RDI_TypeKind kind_rdi; + CV_LeafKind kind_cv; + } + table[] = + { + { "signed char" , RDI_TypeKind_Char8 , CV_BasicType_CHAR }, + { "short" , short_type , CV_BasicType_SHORT }, + { "long" , long_type , CV_BasicType_LONG }, + { "long long" , long_long_type , CV_BasicType_QUAD }, + { "__int128" , RDI_TypeKind_S128 , CV_BasicType_OCT }, // Clang type + { "unsigned char" , RDI_TypeKind_UChar8 , CV_BasicType_UCHAR }, + { "unsigned short" , ushort_type , CV_BasicType_USHORT }, + { "unsigned long" , ulong_type , CV_BasicType_ULONG }, + { "unsigned long long" , ulong_long_type , CV_BasicType_UQUAD }, + { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UOCT }, // Clang type + { "bool" , RDI_TypeKind_S8 , CV_BasicType_BOOL8 }, + { "__bool16" , RDI_TypeKind_S16 , CV_BasicType_BOOL16 }, // not real C type + { "__bool32" , RDI_TypeKind_S32 , CV_BasicType_BOOL32 }, // not real C type + { "float" , RDI_TypeKind_F32 , CV_BasicType_FLOAT32 }, + { "double" , RDI_TypeKind_F64 , CV_BasicType_FLOAT64 }, + { "long double" , RDI_TypeKind_F80 , CV_BasicType_FLOAT80 }, + { "__float128" , RDI_TypeKind_F128 , CV_BasicType_FLOAT128 }, // Clang type + { "__float48" , RDI_TypeKind_F48 , CV_BasicType_FLOAT48 }, // not real C type + { "__float32pp" , RDI_TypeKind_F32PP , CV_BasicType_FLOAT32PP }, // not real C type + { "__float16" , RDI_TypeKind_F16 , CV_BasicType_FLOAT16 }, + { "_Complex float" , RDI_TypeKind_ComplexF32 , CV_BasicType_COMPLEX32 }, + { "_Complex double" , RDI_TypeKind_ComplexF64 , CV_BasicType_COMPLEX64 }, + { "_Complex long double" , RDI_TypeKind_ComplexF80 , CV_BasicType_COMPLEX80 }, + { "_Complex __float128" , RDI_TypeKind_ComplexF128, CV_BasicType_COMPLEX128 }, + { "__int8" , RDI_TypeKind_S8 , CV_BasicType_INT8 }, + { "__uint8" , RDI_TypeKind_U8 , CV_BasicType_UINT8 }, + { "__int16" , RDI_TypeKind_S16 , CV_BasicType_INT16 }, + { "__uint16" , RDI_TypeKind_U16 , CV_BasicType_UINT16 }, + { "int" , RDI_TypeKind_S32 , CV_BasicType_INT32 }, + { "int32" , RDI_TypeKind_S32 , CV_BasicType_INT32 }, + { "uint32" , RDI_TypeKind_U32 , CV_BasicType_UINT32 }, + { "__int64" , RDI_TypeKind_S64 , CV_BasicType_INT64 }, + { "__uint64" , RDI_TypeKind_U64 , CV_BasicType_UINT64 }, + { "__int128" , RDI_TypeKind_S128 , CV_BasicType_INT128 }, + { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UINT128 }, + { "char" , RDI_TypeKind_Char8 , CV_BasicType_RCHAR }, // always ASCII + { "wchar_t" , RDI_TypeKind_UChar16 , CV_BasicType_WCHAR }, // on windows always UTF-16 + { "char8_t" , RDI_TypeKind_Char8 , CV_BasicType_CHAR8 }, // always UTF-8 + { "char16_t" , RDI_TypeKind_Char16 , CV_BasicType_CHAR16 }, // always UTF-16 + { "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 }, // always UTF-32 + { "__pointer" , ptr_type , CV_BasicType_PTR } + }; + for EachElement(idx, table) + { + RDIM_Type *builtin_alias = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); + builtin_alias->kind = RDI_TypeKind_Alias; + builtin_alias->name = str8_cstring(table[idx].name); + builtin_alias->direct_type = p2r_builtin_type_ptr_from_kind(table[idx].kind_rdi); + builtin_alias->byte_size = rdi_size_from_basic_type_kind(table[idx].kind_rdi); + itype_type_ptrs[table[idx].kind_cv] = builtin_alias; + } + itype_type_ptrs[CV_BasicType_HRESULT] = basic_type_ptrs[RDI_TypeKind_HResult - RDI_TypeKind_FirstBuiltIn]; + itype_type_ptrs[CV_BasicType_VOID] = basic_type_ptrs[RDI_TypeKind_Void - RDI_TypeKind_FirstBuiltIn]; + } + + //////////////////////////// + //- rjf: build types from TPI + // + for(CV_TypeId root_itype = 0; root_itype < itype_opl; root_itype += 1) + { + for(P2R_TypeIdChain *itype_chain = itype_chains[root_itype]; + itype_chain != 0; + itype_chain = itype_chain->next) + { + CV_TypeId itype = (root_itype != itype_chain->itype && itype_chain->itype < itype_opl && itype_fwd_map[itype_chain->itype]) ? itype_fwd_map[itype_chain->itype] : itype_chain->itype; + B32 itype_is_basic = (itype < tpi->itype_first); + + ////////////////////////// + //- rjf: skip forward-reference itypes - all future resolutions will + // reference whatever this itype resolves to, and so there is no point + // in filling out this slot + // + if(itype_fwd_map[root_itype] != 0) + { + continue; + } + + ////////////////////////// + //- rjf: skip already produced dependencies + // + if(itype_type_ptrs[itype] != 0) + { + continue; + } + + ////////////////////////// + //- rjf: build basic type + // + if(itype_is_basic) + { + RDIM_Type *dst_type = 0; + + // rjf: unpack itype + CV_BasicPointerKind cv_basic_ptr_kind = CV_BasicPointerKindFromTypeId(itype); + CV_BasicType cv_basic_type_code = CV_BasicTypeFromTypeId(itype); + + // rjf: get basic type slot, fill if unfilled + RDIM_Type *basic_type = itype_type_ptrs[cv_basic_type_code]; + if(basic_type == 0) + { + RDI_TypeKind type_kind = p2r_rdi_type_kind_from_cv_basic_type(cv_basic_type_code); + U32 byte_size = rdi_size_from_basic_type_kind(type_kind); + basic_type = dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + if(byte_size == 0xffffffff) + { + byte_size = arch_addr_size; + } + basic_type->kind = type_kind; + basic_type->name = cv_type_name_from_basic_type(cv_basic_type_code); + basic_type->byte_size = byte_size; + } + + // rjf: nonzero ptr kind -> form ptr type to basic tpye + if(cv_basic_ptr_kind != 0) + { + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Ptr; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = basic_type; + } + + // rjf: fill this itype's slot with the finished type + itype_type_ptrs[itype] = dst_type; + } + + ////////////////////////// + //- rjf: build non-basic type + // + if(!itype_is_basic && itype >= itype_first) + { + RDIM_Type *dst_type = 0; + CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-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 <= tpi_leaf->data.size && + range->off+2+header_struct_size <= tpi_leaf->data.size && + range->hdr.size >= 2) + { + U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; + U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; + switch(kind) + { + //- rjf: MODIFIER + case CV_LeafKind_MODIFIER: + { + // rjf: unpack leaf + CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; + + // rjf: cv -> rdi flags + RDI_TypeModifierFlags flags = 0; + if(lf->flags & CV_ModifierFlag_Const) {flags |= RDI_TypeModifierFlag_Const;} + if(lf->flags & CV_ModifierFlag_Volatile) {flags |= RDI_TypeModifierFlag_Volatile;} + + // rjf: fill type + if(flags == 0) + { + dst_type = p2r_type_ptr_from_itype(lf->itype); + } + else + { + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Modifier; + dst_type->flags = flags; + dst_type->direct_type = p2r_type_ptr_from_itype(lf->itype); + dst_type->byte_size = dst_type->direct_type ? dst_type->direct_type->byte_size : 0; + } + }break; + + //- rjf: POINTER + case CV_LeafKind_POINTER: + { + // TODO(rjf): if ptr_mode in {PtrMem, PtrMethod} then output a member pointer instead + + // rjf: unpack leaf + CV_LeafPointer *lf = (CV_LeafPointer *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->itype); + CV_PointerKind ptr_kind = CV_PointerAttribs_Extract_Kind(lf->attribs); + CV_PointerMode ptr_mode = CV_PointerAttribs_Extract_Mode(lf->attribs); + U32 ptr_size = CV_PointerAttribs_Extract_Size(lf->attribs); + + // rjf: cv -> rdi modifier flags + RDI_TypeModifierFlags modifier_flags = 0; + if(lf->attribs & CV_PointerAttrib_Const) {modifier_flags |= RDI_TypeModifierFlag_Const;} + if(lf->attribs & CV_PointerAttrib_Volatile) {modifier_flags |= RDI_TypeModifierFlag_Volatile;} + if(lf->attribs & CV_PointerAttrib_Restricted) {modifier_flags |= RDI_TypeModifierFlag_Restrict;} + + // rjf: cv info -> rdi pointer type kind + RDI_TypeKind type_kind = RDI_TypeKind_Ptr; + { + if(lf->attribs & CV_PointerAttrib_LRef) + { + type_kind = RDI_TypeKind_LRef; + } + else if(lf->attribs & CV_PointerAttrib_RRef) + { + type_kind = RDI_TypeKind_RRef; + } + if(ptr_mode == CV_PointerMode_LRef) + { + type_kind = RDI_TypeKind_LRef; + } + else if(ptr_mode == CV_PointerMode_RRef) + { + type_kind = RDI_TypeKind_RRef; + } + } + + // rjf: fill type + if(modifier_flags != 0) + { + RDIM_Type *pointer_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Modifier; + dst_type->flags = modifier_flags; + dst_type->direct_type = pointer_type; + dst_type->byte_size = arch_addr_size; + pointer_type->kind = type_kind; + pointer_type->byte_size = arch_addr_size; + pointer_type->direct_type = direct_type; + } + else + { + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = type_kind; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = direct_type; + } + }break; + + //- rjf: PROCEDURE + case CV_LeafKind_PROCEDURE: + { + // TODO(rjf): handle call_kind & attribs + + // rjf: unpack leaf + CV_LeafProcedure *lf = (CV_LeafProcedure *)itype_leaf_first; + RDIM_Type *ret_type = p2r_type_ptr_from_itype(lf->ret_itype); + + // rjf: fill type's basics + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Function; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = ret_type; + + // rjf: unpack arglist range + CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-itype_first]; + if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || + arglist_range->hdr.size<2 || + arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = 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: build param type array + RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count); + for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) + { + params[idx] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); + } + + // rjf: fill dst type + dst_type->count = arglist_itypes_count; + dst_type->param_types = params; + }break; + + //- rjf: MFUNCTION + case CV_LeafKind_MFUNCTION: + { + // TODO(rjf): handle call_kind & attribs + // TODO(rjf): preserve "this_adjust" + + // rjf: unpack leaf + CV_LeafMFunction *lf = (CV_LeafMFunction *)itype_leaf_first; + RDIM_Type *ret_type = p2r_type_ptr_from_itype(lf->ret_itype); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = (lf->this_itype != 0) ? RDI_TypeKind_Method : RDI_TypeKind_Function; + dst_type->byte_size = arch_addr_size; + dst_type->direct_type = ret_type; + + // rjf: unpack arglist range + CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-itype_first]; + if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || + arglist_range->hdr.size<2 || + arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) + { + break; + } + U8 *arglist_first = 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: build param type array + U64 num_this_extras = 1; + if(lf->this_itype == 0) + { + num_this_extras = 0; + } + RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count+num_this_extras); + for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) + { + params[idx+num_this_extras] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); + } + if(lf->this_itype != 0) + { + params[0] = p2r_type_ptr_from_itype(lf->this_itype); + } + + // rjf: fill dst type + dst_type->count = arglist_itypes_count+num_this_extras; + dst_type->param_types = params; + }break; + + //- rjf: BITFIELD + case CV_LeafKind_BITFIELD: + { + // rjf: unpack leaf + CV_LeafBitField *lf = (CV_LeafBitField *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->itype); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Bitfield; + dst_type->off = lf->pos; + dst_type->count = lf->len; + dst_type->byte_size = direct_type?direct_type->byte_size:0; + dst_type->direct_type = direct_type; + }break; + + //- rjf: ARRAY + case CV_LeafKind_ARRAY: + { + // rjf: unpack leaf + CV_LeafArray *lf = (CV_LeafArray *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->entry_itype); + U8 *numeric_ptr = (U8*)(lf + 1); + CV_NumericParsed array_count = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 full_size = cv_u64_from_numeric(&array_count); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + dst_type->kind = RDI_TypeKind_Array; + dst_type->direct_type = direct_type; + dst_type->byte_size = full_size; + dst_type->count = (direct_type && direct_type->byte_size) ? (dst_type->byte_size/direct_type->byte_size) : 0; + }break; + + //- rjf: CLASS/STRUCTURE + case CV_LeafKind_CLASS: + case CV_LeafKind_STRUCTURE: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafStruct *lf = (CV_LeafStruct *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + if(lf->props & CV_TypeProp_FwdRef) + { + dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); + dst_type->name = name; + } + else + { + dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct); + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + }break; + + //- rjf: CLASS2/STRUCT2 + case CV_LeafKind_CLASS2: + case CV_LeafKind_STRUCT2: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafStruct2 *lf = (CV_LeafStruct2 *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + if(lf->props & CV_TypeProp_FwdRef) + { + dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); + dst_type->name = name; + } + else + { + dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_Class : RDI_TypeKind_Struct); + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + }break; + + //- rjf: UNION + case CV_LeafKind_UNION: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafUnion *lf = (CV_LeafUnion *)itype_leaf_first; + U8 *numeric_ptr = (U8*)(lf + 1); + CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); + U64 size_u64 = cv_u64_from_numeric(&size); + U8 *name_ptr = numeric_ptr + size.encoded_size; + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + if(lf->props & CV_TypeProp_FwdRef) + { + dst_type->kind = RDI_TypeKind_IncompleteUnion; + dst_type->name = name; + } + else + { + dst_type->kind = RDI_TypeKind_Union; + dst_type->byte_size = (U32)size_u64; + dst_type->name = name; + } + }break; + + //- rjf: ENUM + case CV_LeafKind_ENUM: + { + // TODO(rjf): handle props + + // rjf: unpack leaf + CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; + RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->base_itype); + U8 *name_ptr = (U8 *)(lf + 1); + String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); + + // rjf: fill type + dst_type = rdim_type_chunk_list_push(arena, &all_types, (U64)itype_opl); + if(lf->props & CV_TypeProp_FwdRef) + { + dst_type->kind = RDI_TypeKind_IncompleteEnum; + dst_type->name = name; + } + else + { + dst_type->kind = RDI_TypeKind_Enum; + dst_type->direct_type = direct_type; + dst_type->byte_size = direct_type ? direct_type->byte_size : 0; + dst_type->name = name; + } + }break; + } + } + + //- rjf: store finalized type to this itype's slot + itype_type_ptrs[itype] = dst_type; + } + } + } + p2r2_shared->itype_type_ptrs = itype_type_ptrs; + p2r2_shared->basic_type_ptrs = basic_type_ptrs; + p2r2_shared->all_types = all_types; +#undef p2r_type_ptr_from_itype +#undef p2r_builtin_type_ptr_from_kind + } + lane_sync(); + RDIM_Type **itype_type_ptrs = p2r2_shared->itype_type_ptrs; + RDIM_Type **basic_type_ptrs = p2r2_shared->basic_type_ptrs; + RDIM_TypeChunkList all_types = p2r2_shared->all_types; + + //- //- //-- @@ -1110,4 +2145,5 @@ p2r2_convert_thread_entry_point(void *p) sec->foff_opl = coff_ptr->foff+coff_ptr->fsize; } } + } diff --git a/src/rdi_from_pdb/rdi_from_pdb_2.h b/src/rdi_from_pdb/rdi_from_pdb_2.h index 0b98c2e3..28bba102 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_2.h +++ b/src/rdi_from_pdb/rdi_from_pdb_2.h @@ -78,10 +78,20 @@ struct P2R2_Shared P2R_SrcFileMap src_file_map; RDIM_UnitChunkList all_units; - RDIM_LineTableChunkList *units_line_tables; RDIM_LineTable **units_first_inline_site_line_tables; + RDIM_LineTableChunkList *lanes_line_tables; RDIM_LineTableChunkList all_line_tables; + + CV_TypeId *itype_fwd_map; + CV_TypeId itype_first; + CV_TypeId itype_opl; + + P2R_TypeIdChain **itype_chains; + + RDIM_Type **itype_type_ptrs; + RDIM_Type **basic_type_ptrs; + RDIM_TypeChunkList all_types; }; global P2R2_Shared *p2r2_shared = 0;