diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 40a1bf0f..5fc16a59 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -438,153 +438,6 @@ rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r } } -//////////////////////////////// -//~ Data Model - -RDI_PROC RDI_TypeKind -rdim_short_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_S16; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_S16; - case RDIM_DataModel_LP64 : return RDI_TypeKind_S16; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_S16; - case RDIM_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_unsigned_short_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_U16; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_U16; - case RDIM_DataModel_LP64 : return RDI_TypeKind_U16; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_U16; - case RDIM_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_int_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_S32; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_S32; - case RDIM_DataModel_LP64 : return RDI_TypeKind_S32; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_U32; - case RDIM_DataModel_LP64 : return RDI_TypeKind_U32; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_long_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_S32; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_S32; - case RDIM_DataModel_LP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_unsigned_long_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_U32; - case RDIM_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_long_long_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_S64; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_LP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_unsigned_long_long_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_U64; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -RDI_PROC RDI_TypeKind -rdim_pointer_size_t_type_from_data_model(RDIM_DataModel data_model) -{ - switch(data_model) - { - case RDIM_DataModel_Null : break; - case RDIM_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIM_DataModel_LLP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIM_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - //////////////////////////////// //~ rjf: [Building] Binary Section List Building @@ -1216,10 +1069,9 @@ rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *ri } else { - left_dst->last_op->next = right_destroyed->first_op; - left_dst->last_op = right_destroyed->last_op; - left_dst->op_count += right_destroyed->op_count; - left_dst->encoded_size += right_destroyed->encoded_size; + left_dst->last_op = right_destroyed->last_op; + left_dst->op_count += right_destroyed->op_count; + left_dst->encoded_size += right_destroyed->encoded_size; } rdim_memzero_struct(right_destroyed); } @@ -1307,59 +1159,10 @@ rdim_count_from_location_block_chunk_list(RDIM_String8List *list) //////////////////////////////// -RDI_PROC RDIM_Type * -rdim_builtin_type_from_kind(RDIM_TypeChunkList list, RDI_TypeKind type_kind) -{ - RDI_U64 type_idx = 0; - if (type_kind != RDI_TypeKind_NULL) { - type_idx = (type_kind - RDI_TypeKind_FirstBuiltIn) + 1; - } - RDIM_Type *builtin = &list.first->v[type_idx]; - return builtin; -} - -RDI_PROC RDIM_TypeChunkList -rdim_init_type_chunk_list(RDIM_Arena *arena, RDI_Arch arch) -{ - RDIM_TypeChunkList list = {0}; - - RDI_U64 type_cap = (RDI_TypeKind_LastBuiltIn - RDI_TypeKind_FirstBuiltIn) + 2; - - RDIM_Type *null_type = rdim_type_chunk_list_push(arena, &list, type_cap); - - for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) - { - RDIM_String8 name = {0}; - name.str = rdi_string_from_type_kind(type_kind, &name.size); - - RDIM_Type *type = rdim_type_chunk_list_push(arena, &list, type_cap); - type->name = name; - type->kind = type_kind; - type->byte_size = rdi_size_from_basic_type_kind(type_kind); - } - - RDIM_Type *void_type = rdim_builtin_type_from_kind(list, RDI_TypeKind_Void); - void_type->byte_size = rdi_addr_size_from_arch(arch); - - RDIM_Type *handle_type = rdim_builtin_type_from_kind(list, RDI_TypeKind_Handle); - handle_type->byte_size = rdi_addr_size_from_arch(arch); - - return list; -} - -//////////////////////////////// - RDI_PROC void rdim_assign_type_index(RDIM_Type *type, U64 *type_indices, U64 *curr_type_idx) { RDI_U64 type_pos = rdim_idx_from_type(type); - - if(type->kind == RDI_TypeKind_NULL) - { - type_indices[type_pos] = 0; - return; - } - if(type_indices[type_pos] == 0) { if(type->param_types) @@ -1383,8 +1186,6 @@ rdim_assign_type_index(RDIM_Type *type, U64 *type_indices, U64 *curr_type_idx) RDI_PROC RDI_U64 * rdim_make_type_indices(RDIM_Arena *arena, RDIM_TypeChunkList *types) { - ProfBeginFunction(); - RDI_U64 *type_indices = rdim_push_array(arena, RDI_U64, types->total_count + 1); RDI_U64 type_indices_count = 1; @@ -1396,7 +1197,6 @@ rdim_make_type_indices(RDIM_Arena *arena, RDIM_TypeChunkList *types) } } - ProfEnd(); return type_indices; } @@ -2393,7 +2193,6 @@ rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDI for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDI_U32 type_idx = (RDI_U32)rdim_final_idx_from_type(type_indices, &n->v[idx]); // TODO(rjf): @u64_to_u32 - if(type_idx == 0) {continue;} rdim_bake_name_map_push(arena, map, n->v[idx].name, type_idx); } } @@ -3238,11 +3037,6 @@ rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeId RDIM_Type *src = &n->v[chunk_idx]; U64 dst_idx = rdim_final_idx_from_type(type_indices, src); RDI_TypeNode *dst = &type_nodes[dst_idx]; - - if(src->kind == RDI_TypeKind_NULL) - { - continue; - } //- rjf: fill shared type node info dst->kind = src->kind; @@ -3533,7 +3327,7 @@ rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, } RDI_PROC U64 -rdim_bake_location(RDIM_Arena *arena, RDIM_String8List *location_data_blobs, RDIM_Location *src_location) +rdim_bake_location(Arena *arena, RDIM_String8List *location_data_blobs, RDIM_Location *src_location) { U64 location_data_off = location_data_blobs->total_size; diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 43afb3c9..647f8cc4 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -595,17 +595,6 @@ struct RDIM_UnitChunkList //////////////////////////////// //~ rjf: Type System Node Types -typedef RDI_U32 RDIM_DataModel; -enum RDIM_DataModelEnum -{ - RDIM_DataModel_Null, - RDIM_DataModel_ILP32, - RDIM_DataModel_LLP64, - RDIM_DataModel_LP64, - RDIM_DataModel_ILP64, - RDIM_DataModel_SILP64 -}; - typedef struct RDIM_Type RDIM_Type; struct RDIM_Type { @@ -616,7 +605,6 @@ struct RDIM_Type RDI_U32 off; RDI_U32 count; RDIM_String8 name; - RDIM_String8 link_name; RDIM_Type *direct_type; RDIM_Type **param_types; struct RDIM_UDT *udt; @@ -1360,19 +1348,6 @@ RDI_PROC RDIM_SortKey *rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys //- rjf: rng1u64 list RDI_PROC void rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r); -//////////////////////////////// -//~ Data Model - -RDI_PROC RDI_TypeKind rdim_short_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_unsigned_short_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_int_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_long_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_unsigned_long_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_long_long_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_unsigned_long_long_type_from_data_model(RDIM_DataModel data_model); -RDI_PROC RDI_TypeKind rdim_pointer_size_t_type_from_data_model(RDIM_DataModel data_model); - //////////////////////////////// //~ rjf: [Building] Binary Section Info Building diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e84bb0eb..6d06f195 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -994,6 +994,439 @@ ASYNC_WORK_DEF(p2r_link_name_map_build_work) return 0; } +//////////////////////////////// +//~ rjf: Type Parsing/Conversion Tasks + +ASYNC_WORK_DEF(p2r_itype_fwd_map_fill_work) +{ + ProfBeginFunction(); + Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + P2R_ITypeFwdMapFillIn *in = (P2R_ITypeFwdMapFillIn *)input; + 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; + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(p2r_itype_chain_build_work) +{ + ProfBeginFunction(); + Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Temp scratch = scratch_begin(&arena, 1); + P2R_ITypeChainBuildIn *in = (P2R_ITypeChainBuildIn *)input; + 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); + ProfEnd(); + return 0; +} + //////////////////////////////// //~ rjf: UDT Conversion Tasks @@ -1002,7 +1435,7 @@ ASYNC_WORK_DEF(p2r_udt_convert_work) ProfBeginFunction(); Arena *arena = p2r_state->work_thread_arenas[thread_idx]; P2R_UDTConvertIn *in = (P2R_UDTConvertIn *)input; -#define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[itype]) : 0) +#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") @@ -1640,21 +2073,21 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) Arena *arena = p2r_state->work_thread_arenas[thread_idx]; Temp scratch = scratch_begin(&arena, 1); P2R_SymbolStreamConvertIn *in = (P2R_SymbolStreamConvertIn *)input; -#define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[itype]) : 0) +#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_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}; + 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) @@ -2865,9 +3298,9 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) //- rjf: join ipi/tpi hash/leaf parses // PDB_TpiHashParsed *tpi_hash = 0; - CV_LeafParsed *tpi_leaf = 0; + CV_LeafParsed *tpi_leaf = 0; PDB_TpiHashParsed *ipi_hash = 0; - CV_LeafParsed *ipi_leaf = 0; + CV_LeafParsed *ipi_leaf = 0; { tpi_hash = async_task_join_struct(tpi_hash_task, PDB_TpiHashParsed); tpi_leaf = async_task_join_struct(tpi_leaf_task, CV_LeafParsed); @@ -2876,551 +3309,546 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) } ////////////////////////////////////////////////////////////// - //- rjf: types pass 1: construct all types from TPI + //- 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. + // + CV_TypeId *itype_fwd_map = 0; + CV_TypeId itype_first = 0; + CV_TypeId itype_opl = 0; + if(tpi_leaf != 0 && in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 1: produce type forward resolution map") + { + //- rjf: allocate forward resolution map + itype_first = tpi_leaf->itype_first; + itype_opl = tpi_leaf->itype_opl; + itype_fwd_map = push_array(arena, CV_TypeId, (U64)itype_opl); + + //- rjf: kick off tasks to fill forward resolution map + U64 task_size_itypes = 1024; + U64 tasks_count = ((U64)itype_opl+(task_size_itypes-1))/task_size_itypes; + P2R_ITypeFwdMapFillIn *tasks_inputs = push_array(scratch.arena, P2R_ITypeFwdMapFillIn, tasks_count); + ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, tasks_count); + for(U64 idx = 0; idx < tasks_count; idx += 1) + { + tasks_inputs[idx].tpi_hash = tpi_hash; + tasks_inputs[idx].tpi_leaf = tpi_leaf; + tasks_inputs[idx].itype_first = idx*task_size_itypes; + tasks_inputs[idx].itype_opl = tasks_inputs[idx].itype_first + task_size_itypes; + tasks_inputs[idx].itype_opl = ClampTop(tasks_inputs[idx].itype_opl, itype_opl); + tasks_inputs[idx].itype_fwd_map = itype_fwd_map; + tasks[idx] = async_task_launch(scratch.arena, p2r_itype_fwd_map_fill_work, .input = &tasks_inputs[idx]); + } + + //- rjf: join all tasks + for(U64 idx = 0; idx < tasks_count; idx += 1) + { + async_task_join(tasks[idx]); + } + } + + ////////////////////////////////////////////////////////////// + //- 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. + // + P2R_TypeIdChain **itype_chains = 0; + if(tpi_leaf != 0 && in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 2: produce per-itype itype chain (for producing dependent types first)") + { + //- rjf: allocate itype chain table + itype_chains = push_array(arena, P2R_TypeIdChain *, (U64)itype_opl); + + //- rjf: kick off tasks to fill itype chain table + U64 task_size_itypes = 1024; + U64 tasks_count = ((U64)itype_opl+(task_size_itypes-1))/task_size_itypes; + P2R_ITypeChainBuildIn *tasks_inputs = push_array(scratch.arena, P2R_ITypeChainBuildIn, tasks_count); + ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, tasks_count); + for(U64 idx = 0; idx < tasks_count; idx += 1) + { + tasks_inputs[idx].tpi_leaf = tpi_leaf; + tasks_inputs[idx].itype_first = idx*task_size_itypes; + tasks_inputs[idx].itype_opl = tasks_inputs[idx].itype_first + task_size_itypes; + tasks_inputs[idx].itype_opl = ClampTop(tasks_inputs[idx].itype_opl, itype_opl); + tasks_inputs[idx].itype_chains = itype_chains; + tasks_inputs[idx].itype_fwd_map = itype_fwd_map; + tasks[idx] = async_task_launch(scratch.arena, p2r_itype_chain_build_work, .input = &tasks_inputs[idx]); + } + + //- rjf: join all tasks + for(U64 idx = 0; idx < tasks_count; idx += 1) + { + async_task_join(tasks[idx]); + } + } + + ////////////////////////////////////////////////////////////// + //- 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. // - RDIM_Type **itype_type_ptrs = 0; - RDIM_TypeChunkList all_types = {0}; -#define p2r_type_ptr_from_itype(itype) (((itype) < tpi_leaf->itype_opl) ? itype_type_ptrs[itype] : 0) - if(in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 1: construct all root/stub types from TPI") + RDIM_Type **itype_type_ptrs = 0; + RDIM_TypeChunkList all_types = {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) + if(in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 3: construct all root/stub types from TPI") { - itype_type_ptrs = push_array(arena, RDIM_Type *, tpi_leaf->itype_opl); - - ////////////////////////// - //- build basic type - // + itype_type_ptrs = push_array(arena, RDIM_Type *, (U64)(itype_opl)); + for(CV_TypeId root_itype = 0; root_itype < itype_opl; root_itype += 1) { - RDIM_DataModel data_model = rdim_infer_data_model(OperatingSystem_Windows, top_level_info.arch); - - RDI_TypeKind short_type = rdim_short_type_from_data_model(data_model); - RDI_TypeKind ushort_type = rdim_unsigned_short_type_from_data_model(data_model); - RDI_TypeKind int_type = rdim_int_type_from_data_model(data_model); - RDI_TypeKind uint_type = rdim_unsigned_int_type_from_data_model(data_model); - RDI_TypeKind long_type = rdim_long_type_from_data_model(data_model); - RDI_TypeKind ulong_type = rdim_unsigned_long_type_from_data_model(data_model); - RDI_TypeKind long_long_type = rdim_long_long_type_from_data_model(data_model); - RDI_TypeKind ulong_long_type = rdim_unsigned_long_long_type_from_data_model(data_model); - RDI_TypeKind ptr_type = rdim_pointer_size_t_type_from_data_model(data_model); - - struct + for(P2R_TypeIdChain *itype_chain = itype_chains[root_itype]; + itype_chain != 0; + itype_chain = itype_chain->next) { - char * name; - RDI_TypeKind kind_rdi; - CV_LeafKind kind_cv; - B32 make_pointer_near; - B32 make_pointer_32; - B32 make_pointer_64; - } - table[] = - { - { "" , RDI_TypeKind_NULL , CV_BasicType_NOTYPE , 0, 0, 0 }, - { "void" , RDI_TypeKind_Void , CV_BasicType_VOID , 1, 1, 1 }, - { "HRESULT" , RDI_TypeKind_Handle , CV_BasicType_HRESULT , 0, 1, 1 }, - { "signed char" , RDI_TypeKind_Char8 , CV_BasicType_CHAR , 1, 1, 1 }, - { "short" , short_type , CV_BasicType_SHORT , 1, 1, 1 }, - { "long" , long_type , CV_BasicType_LONG , 1, 1, 1 }, - { "long long" , long_long_type , CV_BasicType_QUAD , 1, 1, 1 }, - { "__int128" , RDI_TypeKind_S128 , CV_BasicType_OCT , 1, 1, 1 }, // Clang type - { "unsigned char" , RDI_TypeKind_UChar8 , CV_BasicType_UCHAR , 1, 1, 1 }, - { "unsigned short" , ushort_type , CV_BasicType_USHORT , 1, 1, 1 }, - { "unsigned long" , ulong_type , CV_BasicType_ULONG , 1, 1, 1 }, - { "unsigned long long" , ulong_long_type , CV_BasicType_UQUAD , 1, 1, 1 }, - { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UOCT , 1, 1, 1 }, // Clang type - { "bool" , RDI_TypeKind_S8 , CV_BasicType_BOOL8 , 1, 1, 1 }, - { "__bool16" , RDI_TypeKind_S16 , CV_BasicType_BOOL16 , 1, 1, 1 }, // not real C type - { "__bool32" , RDI_TypeKind_S32 , CV_BasicType_BOOL32 , 1, 1, 1 }, // not real C type - { "float" , RDI_TypeKind_F32 , CV_BasicType_FLOAT32 , 1, 1, 1 }, - { "double" , RDI_TypeKind_F64 , CV_BasicType_FLOAT64 , 1, 1, 1 }, - { "long double" , RDI_TypeKind_F80 , CV_BasicType_FLOAT80 , 1, 1, 1 }, - { "__float128" , RDI_TypeKind_F128 , CV_BasicType_FLOAT128 , 1, 1, 1 }, // Clang type - { "__float48" , RDI_TypeKind_F48 , CV_BasicType_FLOAT48 , 1, 1, 1 }, // not real C type - { "__float32pp" , RDI_TypeKind_F32PP , CV_BasicType_FLOAT32PP , 1, 1, 1 }, // not real C type - { "_Complex float" , RDI_TypeKind_ComplexF32 , CV_BasicType_COMPLEX32 , 0, 0, 0 }, - { "_Complex double" , RDI_TypeKind_ComplexF64 , CV_BasicType_COMPLEX64 , 0, 0, 0 }, - { "_Complex long double" , RDI_TypeKind_ComplexF80 , CV_BasicType_COMPLEX80 , 0, 0, 0 }, - { "_Complex __float128" , RDI_TypeKind_ComplexF128, CV_BasicType_COMPLEX128 , 0, 0, 0 }, - { "__int8" , RDI_TypeKind_S8 , CV_BasicType_INT8 , 1, 1, 1 }, - { "__uint8" , RDI_TypeKind_U8 , CV_BasicType_UINT8 , 1, 1, 1 }, - { "__int16" , RDI_TypeKind_S16 , CV_BasicType_INT16 , 1, 1, 1 }, - { "__uint16" , RDI_TypeKind_U16 , CV_BasicType_UINT16 , 1, 1, 1 }, - { "int" , int_type , CV_BasicType_INT32 , 1, 1, 1 }, - { "unsigned int" , uint_type , CV_BasicType_UINT32 , 1, 1, 1 }, - { "__int64" , RDI_TypeKind_S64 , CV_BasicType_INT64 , 1, 1, 1 }, - { "__uint64" , RDI_TypeKind_U64 , CV_BasicType_UINT64 , 1, 1, 1 }, - { "__int128" , RDI_TypeKind_S128 , CV_BasicType_INT128 , 1, 1, 1 }, - { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UINT128 , 1, 1, 1 }, - { "char" , RDI_TypeKind_Char8 , CV_BasicType_RCHAR , 1, 1, 1 }, // always ASCII - { "wchar_t" , RDI_TypeKind_UChar16 , CV_BasicType_WCHAR , 1, 1, 1 }, // on windows always UTF-16 - { "char8_t" , RDI_TypeKind_Char8 , CV_BasicType_CHAR8 , 1, 1, 1 }, // always UTF-8 - { "char16_t" , RDI_TypeKind_Char16 , CV_BasicType_CHAR16 , 1, 1, 1 }, // always UTF-16 - { "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 , 1, 1, 1 }, // always UTF-32 - { "__pointer" , ptr_type , CV_BasicType_PTR , 0, 0, 0 } - }; - - for(U64 i = 0; i < ArrayCount(table); i += 1) - { - U64 builtin_size; - if(table[i].kind_rdi == RDI_TypeKind_Void || table[i].kind_rdi == RDI_TypeKind_Handle) + 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 < 0x1000); + + ////////////////////////// + //- 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) { - builtin_size = arch_addr_size; + continue; } - else + + ////////////////////////// + //- rjf: skip already produced dependencies + // + if(itype_type_ptrs[itype] != 0) { - builtin_size = rdi_size_from_basic_type_kind(table[i].kind_rdi); + continue; } - - RDIM_Type *builtin = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); - builtin->kind = table[i].kind_rdi; - builtin->name = str8_cstring(table[i].name); - builtin->byte_size = builtin_size; - - itype_type_ptrs[table[i].kind_cv] = builtin; - - if(table[i].make_pointer_near) + + ////////////////////////// + //- rjf: build basic type + // + if(itype_is_basic) { - CV_TypeIndex near_ptr_itype = table[i].kind_cv | 0x100; - RDIM_Type *ptr_near = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); - ptr_near->kind = RDI_TypeKind_Ptr; - ptr_near->byte_size = 2; - ptr_near->direct_type = builtin; - - itype_type_ptrs[near_ptr_itype] = ptr_near; - } - if(table[i].make_pointer_32) - { - CV_TypeIndex ptr_32_itype = table[i].kind_cv | 0x400; - RDIM_Type *ptr_32 = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); - ptr_32->kind = RDI_TypeKind_Ptr; - ptr_32->byte_size = 4; - ptr_32->direct_type = builtin; - - itype_type_ptrs[ptr_32_itype] = ptr_32; - } - if(table[i].make_pointer_64) - { - CV_TypeIndex ptr_64_itype = table[i].kind_cv | 0x600; - RDIM_Type *ptr_64 = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); - ptr_64->kind = RDI_TypeKind_Ptr; - ptr_64->byte_size = 8; - ptr_64->direct_type = builtin; - - itype_type_ptrs[ptr_64_itype] = ptr_64; - } - } - } - - ////////////////////////// - //- rjf: build non-basic type - // - for(CV_TypeId itype = tpi_leaf->itype_first; itype < tpi_leaf->itype_opl; itype += 1) - { - RDIM_Type *dst_type = 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) - { - //- 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, tpi_leaf->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; + RDIM_Type *dst_type = 0; - //- 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, tpi_leaf->itype_opl); - dst_type = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->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, tpi_leaf->itype_opl); - dst_type->kind = type_kind; - dst_type->byte_size = arch_addr_size; - dst_type->direct_type = direct_type; - } - }break; + // rjf: unpack itype + CV_BasicPointerKind cv_basic_ptr_kind = CV_BasicPointerKindFromTypeId(itype); + CV_BasicType cv_basic_type_code = CV_BasicTypeFromTypeId(itype); - //- rjf: PROCEDURE - case CV_LeafKind_PROCEDURE: + // rjf: get basic type slot, fill if unfilled + RDIM_Type *basic_type = itype_type_ptrs[cv_basic_type_code]; + if(basic_type == 0) { - // 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, tpi_leaf->itype_opl); - dst_type->kind = RDI_TypeKind_Function; + 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 = ret_type; - - // 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: 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; + dst_type->direct_type = basic_type; + } - //- rjf: MFUNCTION - case CV_LeafKind_MFUNCTION: + // 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) { - // 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, tpi_leaf->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-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) + U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; + U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; + switch(kind) { - break; + //- 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; } - 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, tpi_leaf->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, tpi_leaf->itype_opl); - dst_type->kind = RDI_TypeKind_Array; - dst_type->direct_type = direct_type; - dst_type->byte_size = full_size; - }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, tpi_leaf->itype_opl); - if(lf->props & CV_TypeProp_FwdRef) - { - dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); - } - else - { - dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct); - } - - B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && - ((lf->props & CV_TypeProp_HasUniqueName) != 0)); - if(do_unique_name_lookup) - { - U8 *unique_name_ptr = name_ptr + name.size + 1; - dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - } - - dst_type->name = name; - dst_type->byte_size = safe_cast_u32(size_u64); - }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, tpi_leaf->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; - } - - B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && - ((lf->props & CV_TypeProp_HasUniqueName) != 0)); - if(do_unique_name_lookup) - { - U8 *unique_name_ptr = name_ptr + name.size + 1; - dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - } - }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, tpi_leaf->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; - } - - B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && - ((lf->props & CV_TypeProp_HasUniqueName) != 0)); - if(do_unique_name_lookup) - { - U8 *unique_name_ptr = name_ptr + name.size + 1; - dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - } - }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, tpi_leaf->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; - } - - B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && - ((lf->props & CV_TypeProp_HasUniqueName) != 0)); - if(do_unique_name_lookup) - { - U8 *unique_name_ptr = name_ptr + name.size + 1; - dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); - } - }break; + //- rjf: store finalized type to this itype's slot + itype_type_ptrs[itype] = dst_type; } } - - //- rjf: store finalized type to this itype's slot - itype_type_ptrs[itype] = dst_type; } } ////////////////////////////////////////////////////////////// - //- rjf: types pass 2: kick off UDT build + //- rjf: types pass 4: kick off UDT build // U64 udt_task_size_itypes = 4096; - U64 udt_tasks_count = (tpi_leaf->itype_opl+(udt_task_size_itypes-1))/udt_task_size_itypes; + U64 udt_tasks_count = ((U64)itype_opl+(udt_task_size_itypes-1))/udt_task_size_itypes; P2R_UDTConvertIn *udt_tasks_inputs = push_array(scratch.arena, P2R_UDTConvertIn, udt_tasks_count); ASYNC_Task **udt_tasks = push_array(scratch.arena, ASYNC_Task *, udt_tasks_count); - if(in->flags & P2R_ConvertFlag_UDTs) ProfScope("types pass 2: kick off UDT build") + if(in->flags & P2R_ConvertFlag_UDTs) ProfScope("types pass 4: kick off UDT build") { for(U64 idx = 0; idx < udt_tasks_count; idx += 1) { udt_tasks_inputs[idx].tpi_leaf = tpi_leaf; udt_tasks_inputs[idx].itype_first = idx*udt_task_size_itypes; udt_tasks_inputs[idx].itype_opl = udt_tasks_inputs[idx].itype_first + udt_task_size_itypes; - udt_tasks_inputs[idx].itype_opl = ClampTop(udt_tasks_inputs[idx].itype_opl, tpi_leaf->itype_opl); + udt_tasks_inputs[idx].itype_opl = ClampTop(udt_tasks_inputs[idx].itype_opl, itype_opl); + udt_tasks_inputs[idx].itype_fwd_map = itype_fwd_map; udt_tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; udt_tasks[idx] = async_task_launch(scratch.arena, p2r_udt_convert_work, .input = &udt_tasks_inputs[idx]); } @@ -3479,6 +3907,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].tpi_hash = tpi_hash; tasks_inputs[idx].tpi_leaf = tpi_leaf; tasks_inputs[idx].ipi_leaf = ipi_leaf; + tasks_inputs[idx].itype_fwd_map = itype_fwd_map; tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; tasks_inputs[idx].link_name_map = link_name_map; if(idx < global_stream_subdivision_tasks_count) diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index f9effda5..03cae2d2 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -201,6 +201,37 @@ struct P2R_LinkNameMapBuildIn P2R_LinkNameMap *link_name_map; }; +//- rjf: type forward resolution map build + +typedef struct P2R_ITypeFwdMapFillIn P2R_ITypeFwdMapFillIn; +struct P2R_ITypeFwdMapFillIn +{ + PDB_TpiHashParsed *tpi_hash; + CV_LeafParsed *tpi_leaf; + CV_TypeId itype_first; + CV_TypeId itype_opl; + CV_TypeId *itype_fwd_map; +}; + +//- rjf: itype chain build + +typedef struct P2R_TypeIdChain P2R_TypeIdChain; +struct P2R_TypeIdChain +{ + P2R_TypeIdChain *next; + CV_TypeId itype; +}; + +typedef struct P2R_ITypeChainBuildIn P2R_ITypeChainBuildIn; +struct P2R_ITypeChainBuildIn +{ + CV_LeafParsed *tpi_leaf; + CV_TypeId itype_first; + CV_TypeId itype_opl; + CV_TypeId *itype_fwd_map; + P2R_TypeIdChain **itype_chains; +}; + //- rjf: udt conversion typedef struct P2R_UDTConvertIn P2R_UDTConvertIn; @@ -209,6 +240,7 @@ struct P2R_UDTConvertIn CV_LeafParsed *tpi_leaf; CV_TypeId itype_first; CV_TypeId itype_opl; + CV_TypeId *itype_fwd_map; RDIM_Type **itype_type_ptrs; }; @@ -225,6 +257,7 @@ struct P2R_SymbolStreamConvertIn CV_SymParsed *sym; U64 sym_ranges_first; U64 sym_ranges_opl; + CV_TypeId *itype_fwd_map; RDIM_Type **itype_type_ptrs; P2R_LinkNameMap *link_name_map; RDIM_LineTable *first_inline_site_line_table; @@ -308,6 +341,12 @@ ASYNC_WORK_DEF(p2r_units_convert_work); ASYNC_WORK_DEF(p2r_link_name_map_build_work); +//////////////////////////////// +//~ rjf: Type Parsing/Conversion Tasks + +ASYNC_WORK_DEF(p2r_itype_fwd_map_fill_work); +ASYNC_WORK_DEF(p2r_itype_chain_build_work); + //////////////////////////////// //~ rjf: UDT Conversion Tasks diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c index 6ab7a29b..9b2e49b5 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ b/src/rdi_from_pdb/rdi_from_pdb_main.c @@ -15,9 +15,6 @@ #include "lib_rdi_format/rdi_format.c" #include "third_party/rad_lzb_simple/rad_lzb_simple.h" #include "third_party/rad_lzb_simple/rad_lzb_simple.c" -#define XXH_STATIC_LINKING_ONLY -#include "third_party/xxHash/xxhash.h" -#include "third_party/xxHash/xxhash.c" //- rjf: [h] #include "base/base_inc.h" diff --git a/src/rdi_make/rdi_make_help.c b/src/rdi_make/rdi_make_help.c new file mode 100644 index 00000000..28d27f22 --- /dev/null +++ b/src/rdi_make/rdi_make_help.c @@ -0,0 +1,925 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Baking Stage Tasks + +//- rjf: bake string map building + +#define rdim_make_string_map_if_needed() do {if(in->maps[thread_idx] == 0) ProfScope("make map") {in->maps[thread_idx] = rdim_bake_string_map_loose_make(arena, in->top);}} while(0) + +ASYNC_WORK_DEF(rdim_bake_src_files_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeSrcFilesStringsIn *in = (RDIM_BakeSrcFilesStringsIn *)input; + rdim_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); + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_units_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeUnitsStringsIn *in = (RDIM_BakeUnitsStringsIn *)input; + rdim_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); + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_types_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeTypesStringsIn *in = (RDIM_BakeTypesStringsIn *)input; + rdim_make_string_map_if_needed(); + ProfScope("bake type strings") + { + for(RDIM_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); + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_udts_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeUDTsStringsIn *in = (RDIM_BakeUDTsStringsIn *)input; + rdim_make_string_map_if_needed(); + ProfScope("bake udt strings") + { + for(RDIM_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); + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_symbols_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeSymbolsStringsIn *in = (RDIM_BakeSymbolsStringsIn *)input; + rdim_make_string_map_if_needed(); + ProfScope("bake symbol strings") + { + for(RDIM_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); + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_inline_site_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeInlineSiteStringsIn *in = input; + rdim_make_string_map_if_needed(); + ProfScope("bake inline site strings") + { + for(RDIM_BakeInlineSiteStringsInNode *n = in->first; n != 0; n = n->next) + { + rdim_bake_string_map_loose_push_inline_site_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_scopes_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeScopesStringsIn *in = (RDIM_BakeScopesStringsIn *)input; + rdim_make_string_map_if_needed(); + ProfScope("bake scope strings") + { + for(RDIM_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); + } + } + ProfEnd(); + return 0; +} + +ASYNC_WORK_DEF(rdim_bake_line_tables_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeLineTablesIn *in = (RDIM_BakeLineTablesIn *)input; + RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); + ProfEnd(); + return out; +} + +#undef rdim_make_string_map_if_needed + +//- rjf: bake string map joining + +ASYNC_WORK_DEF(rdim_bake_string_map_join_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_JoinBakeStringMapSlotsIn *in = (RDIM_JoinBakeStringMapSlotsIn *)input; + 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]); + } + } + } + } + ProfEnd(); + return 0; +} + +//- rjf: bake string map sorting + +ASYNC_WORK_DEF(rdim_bake_string_map_sort_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_SortBakeStringMapSlotsIn *in = (RDIM_SortBakeStringMapSlotsIn *)input; + 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]; + } + } + } + } + ProfEnd(); + return 0; +} + +//- rjf: pass 1: interner/deduper map builds + +ASYNC_WORK_DEF(rdim_build_bake_name_map_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BuildBakeNameMapIn *in = (RDIM_BuildBakeNameMapIn *)input; + 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->type_indices, in->params); + ProfEnd(); + return name_map; +} + +//- rjf: pass 2: string-map-dependent debug info stream builds + +ASYNC_WORK_DEF(rdim_bake_units_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeUnitsIn *in = (RDIM_BakeUnitsIn *)input; + RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); + ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_unit_vmap_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeUnitVMapIn *in = (RDIM_BakeUnitVMapIn *)input; + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_src_files_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeSrcFilesIn *in = (RDIM_BakeSrcFilesIn *)input; + 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); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_udts_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeUDTsIn *in = (RDIM_BakeUDTsIn *)input; + RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); + ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->type_indices, in->udts); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_global_variables_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeGlobalVariablesIn *in = (RDIM_BakeGlobalVariablesIn *)input; + RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); + ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->type_indices, in->global_variables); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_global_vmap_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeGlobalVMapIn *in = (RDIM_BakeGlobalVMapIn *)input; + RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); + ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_thread_variables_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeThreadVariablesIn *in = (RDIM_BakeThreadVariablesIn *)input; + RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); + ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->type_indices, in->thread_variables); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_procedures_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeProceduresIn *in = (RDIM_BakeProceduresIn *)input; + RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); + ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->type_indices, in->location_blocks, in->location_data_blobs, in->procedures); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_scopes_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeScopesIn *in = (RDIM_BakeScopesIn *)input; + RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); + ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->type_indices, in->location_blocks, in->location_data_blobs, in->scopes); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_scope_vmap_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeScopeVMapIn *in = (RDIM_BakeScopeVMapIn *)input; + RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); + ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_inline_sites_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeInlineSitesIn *in = (RDIM_BakeInlineSitesIn *)input; + RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); + ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->type_indices, in->inline_sites); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_file_paths_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeFilePathsIn *in = (RDIM_BakeFilePathsIn *)input; + RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); + ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_strings_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeStringsIn *in = (RDIM_BakeStringsIn *)input; + RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); + ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); + ProfEnd(); + return out; +} + +//- rjf: pass 3: idx-run-map-dependent debug info stream builds + +ASYNC_WORK_DEF(rdim_bake_type_nodes_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeTypeNodesIn *in = (RDIM_BakeTypeNodesIn *)input; + RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); + ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->type_indices, in->types); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_name_map_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeNameMapIn *in = (RDIM_BakeNameMapIn *)input; + 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); + ProfEnd(); + return out; +} + +ASYNC_WORK_DEF(rdim_bake_idx_runs_work) +{ + ProfBeginFunction(); + Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; + RDIM_BakeIdxRunsIn *in = (RDIM_BakeIdxRunsIn *)input; + RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); + ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); + ProfEnd(); + return out; +} + +internal RDIM_HelpState * +rdim_help_init(void) +{ + Arena *arena = arena_alloc(); + RDIM_HelpState *state = push_array(arena, RDIM_HelpState, 1); + state->arena = arena; + state->work_thread_arenas_count = async_thread_count(); + state->work_thread_arenas = push_array(arena, Arena *, state->work_thread_arenas_count); + for EachIndex(idx, state->work_thread_arenas_count) + { + state->work_thread_arenas[idx] = arena_alloc(); + } + return state; +} + +internal RDIM_BakeResults +rdim_bake(RDIM_HelpState *state, RDIM_BakeParams *in_params) +{ + Temp scratch = scratch_begin(0,0); + RDIM_BakeResults out = {0}; + + rdim_help_state = state; + + //////////////////////////////// + // compute type indices + + RDI_U64 *type_indices = rdim_make_type_indices(scratch.arena, &in_params->types); + + ////////////////////////////// + //- rjf: kick off line tables baking + // + ASYNC_Task *bake_line_tables_task = 0; + { + RDIM_BakeLineTablesIn *in = push_array(scratch.arena, RDIM_BakeLineTablesIn, 1); + in->line_tables = &in_params->line_tables; + bake_line_tables_task = async_task_launch(scratch.arena, rdim_bake_line_tables_work, .input = in); + } + + ////////////////////////////// + //- rjf: build interned path tree + // + RDIM_BakePathTree *path_tree = 0; + ProfScope("build interned path tree") + { + path_tree = rdim_bake_path_tree_from_params(state->work_thread_arenas[0], in_params); + } + + ////////////////////////////// + //- rjf: kick off string map building tasks + // + RDIM_BakeStringMapTopology bake_string_map_topology = {(64 + + in_params->procedures.total_count*1 + + in_params->global_variables.total_count*1 + + in_params->thread_variables.total_count*1 + + in_params->types.total_count/2)}; + RDIM_BakeStringMapLoose **bake_string_maps__in_progress = push_array(scratch.arena, RDIM_BakeStringMapLoose *, async_thread_count()); + ASYNC_TaskList bake_string_map_build_tasks = {0}; + { + // rjf: src files + ProfScope("kick off src files string map build task") + { + RDIM_BakeSrcFilesStringsIn *in = push_array(scratch.arena, RDIM_BakeSrcFilesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + in->list = &in_params->src_files; + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_src_files_strings_work, .input = in)); + } + + // rjf: units + ProfScope("kick off units string map build task") + { + RDIM_BakeUnitsStringsIn *in = push_array(scratch.arena, RDIM_BakeUnitsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + in->list = &in_params->units; + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_units_strings_work, .input = in)); + } + + // rjf: types + ProfScope("kick off types string map build tasks") + { + U64 items_per_task = 4096; + U64 num_tasks = (in_params->types.total_count+items_per_task-1)/items_per_task; + RDIM_TypeChunkNode *chunk = in_params->types.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_BakeTypesStringsIn *in = push_array(scratch.arena, RDIM_BakeTypesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) + { + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); + RDIM_BakeTypesStringsInNode *n = push_array(scratch.arena, RDIM_BakeTypesStringsInNode, 1); + SLLQueuePush(in->first, in->last, n); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } + } + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_types_strings_work, .input = in)); + } + } + + // rjf: UDTs + ProfScope("kick off udts string map build tasks") + { + U64 items_per_task = 4096; + U64 num_tasks = (in_params->udts.total_count+items_per_task-1)/items_per_task; + RDIM_UDTChunkNode *chunk = in_params->udts.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_BakeUDTsStringsIn *in = push_array(scratch.arena, RDIM_BakeUDTsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) + { + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); + RDIM_BakeUDTsStringsInNode *n = push_array(scratch.arena, RDIM_BakeUDTsStringsInNode, 1); + SLLQueuePush(in->first, in->last, n); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } + } + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_udts_strings_work, .input = in)); + } + } + + // rjf: symbols + ProfScope("kick off symbols string map build tasks") + { + RDIM_SymbolChunkList *symbol_lists[] = + { + &in_params->global_variables, + &in_params->thread_variables, + &in_params->procedures, + }; + for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) + { + U64 items_per_task = 4096; + U64 num_tasks = (symbol_lists[list_idx]->total_count+items_per_task-1)/items_per_task; + RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_BakeSymbolsStringsIn *in = push_array(scratch.arena, RDIM_BakeSymbolsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) + { + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); + RDIM_BakeSymbolsStringsInNode *n = push_array(scratch.arena, RDIM_BakeSymbolsStringsInNode, 1); + SLLQueuePush(in->first, in->last, n); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } + } + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_symbols_strings_work, .input = in)); + } + } + } + + ProfScope("kick off inline site string map build task") + { + U64 items_per_task = 4096; + U64 num_tasks = CeilIntegerDiv(in_params->inline_sites.total_count, items_per_task); + RDIM_InlineSiteChunkNode *chunk = in_params->inline_sites.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_BakeInlineSiteStringsIn *in = push_array(scratch.arena, RDIM_BakeInlineSiteStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) + { + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); + RDIM_BakeInlineSiteStringsInNode *n = push_array(scratch.arena, RDIM_BakeInlineSiteStringsInNode, 1); + SLLQueuePush(in->first, in->last, n); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } + } + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_inline_site_strings_work, .input = in)); + } + } + + // rjf: scope chunks + ProfScope("kick off scope chunks string map build tasks") + { + U64 items_per_task = 4096; + U64 num_tasks = (in_params->scopes.total_count+items_per_task-1)/items_per_task; + RDIM_ScopeChunkNode *chunk = in_params->scopes.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_BakeScopesStringsIn *in = push_array(scratch.arena, RDIM_BakeScopesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) + { + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); + RDIM_BakeScopesStringsInNode *n = push_array(scratch.arena, RDIM_BakeScopesStringsInNode, 1); + SLLQueuePush(in->first, in->last, n); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } + } + async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_scopes_strings_work, .input = in)); + } + } + } + + ////////////////////////////// + //- rjf: kick off name map building tasks + // + RDIM_BuildBakeNameMapIn build_bake_name_map_in[RDI_NameMapKind_COUNT] = {0}; + ASYNC_Task *build_bake_name_map_task[RDI_NameMapKind_COUNT] = {0}; + for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); + k < RDI_NameMapKind_COUNT; + k = (RDI_NameMapKind)(k+1)) + { + build_bake_name_map_in[k].k = k; + build_bake_name_map_in[k].type_indices = type_indices; + build_bake_name_map_in[k].params = in_params; + build_bake_name_map_task[k] = async_task_launch(scratch.arena, rdim_build_bake_name_map_work, .input = &build_bake_name_map_in[k]); + } + + ////////////////////////////// + //- rjf: join string map building tasks + // + ProfScope("join string map building tasks") + { + for(ASYNC_TaskNode *n = bake_string_map_build_tasks.first; n != 0; n = n->next) + { + async_task_join(n->v); + } + } + + ////////////////////////////// + //- rjf: produce joined string map + // + RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(state->work_thread_arenas[0], &bake_string_map_topology); + ProfScope("produce joined string map") + { + U64 slots_per_task = 16384; + U64 num_tasks = (bake_string_map_topology.slots_count+slots_per_task-1)/slots_per_task; + ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, num_tasks); + + // rjf: kickoff tasks + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_JoinBakeStringMapSlotsIn *in = push_array(scratch.arena, RDIM_JoinBakeStringMapSlotsIn, 1); + in->top = &bake_string_map_topology; + in->src_maps = bake_string_maps__in_progress; + in->src_maps_count = async_thread_count(); + in->dst_map = unsorted_bake_string_map; + in->slot_idx_range = r1u64(task_idx*slots_per_task, task_idx*slots_per_task + slots_per_task); + in->slot_idx_range.max = Min(in->slot_idx_range.max, in->top->slots_count); + tasks[task_idx] = async_task_launch(scratch.arena, rdim_bake_string_map_join_work, .input = in); + } + + // rjf: join tasks + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + async_task_join(tasks[task_idx]); + } + + // rjf: insert small top-level stuff + rdim_bake_string_map_loose_push_top_level_info(state->work_thread_arenas[0], &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); + rdim_bake_string_map_loose_push_binary_sections(state->work_thread_arenas[0], &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); + rdim_bake_string_map_loose_push_path_tree(state->work_thread_arenas[0], &bake_string_map_topology, unsorted_bake_string_map, path_tree); + } + + ////////////////////////////// + //- rjf: kick off string map sorting tasks + // + ASYNC_TaskList sort_bake_string_map_tasks = {0}; + RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(state->work_thread_arenas[0], &bake_string_map_topology); + { + U64 slots_per_task = 4096; + U64 num_tasks = (bake_string_map_topology.slots_count+slots_per_task-1)/slots_per_task; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) + { + RDIM_SortBakeStringMapSlotsIn *in = push_array(scratch.arena, RDIM_SortBakeStringMapSlotsIn, 1); + { + in->top = &bake_string_map_topology; + in->src_map = unsorted_bake_string_map; + in->dst_map = sorted_bake_string_map__in_progress; + in->slot_idx = task_idx*slots_per_task; + in->slot_count = slots_per_task; + if(in->slot_idx+in->slot_count > bake_string_map_topology.slots_count) + { + in->slot_count = bake_string_map_topology.slots_count - in->slot_idx; + } + } + async_task_list_push(scratch.arena, &sort_bake_string_map_tasks, async_task_launch(scratch.arena, rdim_bake_string_map_sort_work, .input = in)); + } + } + + ////////////////////////////// + //- rjf: join string map sorting tasks + // + ProfScope("join string map sorting tasks") + { + for(ASYNC_TaskNode *n = sort_bake_string_map_tasks.first; n != 0; n = n->next) + { + async_task_join(n->v); + } + } + RDIM_BakeStringMapLoose *sorted_bake_string_map = sorted_bake_string_map__in_progress; + + ////////////////////////////// + //- rjf: build finalized string map + // + ProfBegin("build finalized string map base indices"); + RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(state->work_thread_arenas[0], &bake_string_map_topology, sorted_bake_string_map); + ProfEnd(); + ProfBegin("build finalized string map"); + RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(state->work_thread_arenas[0], &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); + ProfEnd(); + + ////////////////////////////// + //- rjf: kick off pass 2 tasks + // + RDIM_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units}; + ASYNC_Task *bake_units_task = async_task_launch(scratch.arena, rdim_bake_units_work, .input = &bake_units_top_level_in); + RDIM_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units}; + ASYNC_Task *bake_unit_vmap_task = async_task_launch(scratch.arena, rdim_bake_unit_vmap_work, .input = &bake_unit_vmap_in); + RDIM_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, &in_params->src_files}; + ASYNC_Task *bake_src_files_task = async_task_launch(scratch.arena, rdim_bake_src_files_work, .input = &bake_src_files_in); + RDIM_BakeUDTsIn bake_udts_in = {&bake_strings, &in_params->udts, type_indices}; + ASYNC_Task *bake_udts_task = async_task_launch(scratch.arena, rdim_bake_udts_work, .input = &bake_udts_in); + RDIM_BakeGlobalVMapIn bake_global_vmap_in = {&in_params->global_variables}; + ASYNC_Task *bake_global_vmap_task = async_task_launch(scratch.arena, rdim_bake_global_vmap_work, .input = &bake_global_vmap_in); + RDIM_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes}; + ASYNC_Task *bake_scope_vmap_task = async_task_launch(scratch.arena, rdim_bake_scope_vmap_work, .input = &bake_scope_vmap_in); + RDIM_BakeInlineSitesIn bake_inline_sites_in = {&bake_strings, &in_params->inline_sites, type_indices}; + ASYNC_Task *bake_inline_sites_task = async_task_launch(scratch.arena, rdim_bake_inline_sites_work, .input = &bake_inline_sites_in); + RDIM_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; + ASYNC_Task *bake_file_paths_task = async_task_launch(scratch.arena, rdim_bake_file_paths_work, .input = &bake_file_paths_in); + RDIM_BakeStringsIn bake_strings_in = {&bake_strings}; + ASYNC_Task *bake_strings_task = async_task_launch(scratch.arena, rdim_bake_strings_work, .input = &bake_strings_in); + + RDIM_String8List location_blocks = {0}; + RDIM_String8List location_data_blobs = {0}; + + // reserve null location block for opl + rdim_location_block_chunk_list_push_array(state->work_thread_arenas[0], &location_blocks, 1); + + // TODO: export location instead of VOFF + RDIM_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables, type_indices}; + ASYNC_Task *bake_thread_variables_task = async_task_launch(scratch.arena, rdim_bake_thread_variables_work, .input = &bake_thread_variables_in); + ProfScope("thread variables") out.thread_variables = *async_task_join_struct(bake_thread_variables_task, RDIM_ThreadVariableBakeResult); + + // TODO: export location instead of VOFF + RDIM_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables, type_indices}; + ASYNC_Task *bake_global_variables_task = async_task_launch(scratch.arena, rdim_bake_global_variables_work, .input = &bake_global_variables_in); + ProfScope("global variables") out.global_variables = *async_task_join_struct(bake_global_variables_task, RDIM_GlobalVariableBakeResult); + + RDIM_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes, type_indices, &location_blocks, &location_data_blobs}; + ASYNC_Task *bake_scopes_task = async_task_launch(scratch.arena, rdim_bake_scopes_work, .input = &bake_scopes_in); + ProfScope("scopes") out.scopes = *async_task_join_struct(bake_scopes_task, RDIM_ScopeBakeResult); + + RDIM_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures, type_indices, &location_blocks, &location_data_blobs}; + ASYNC_Task *bake_procedures_task = async_task_launch(scratch.arena, rdim_bake_procedures_work, .input = &bake_procedures_in); + ProfScope("procedures") out.procedures = *async_task_join_struct(bake_procedures_task, RDIM_ProcedureBakeResult); + + ////////////////////////////// + //- rjf: join name map building tasks + // + RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT] = {0}; + ProfScope("join name map building tasks") + { + for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); + k < RDI_NameMapKind_COUNT; + k = (RDI_NameMapKind)(k+1)) + { + name_maps[k] = async_task_join_struct(build_bake_name_map_task[k], RDIM_BakeNameMap); + } + } + + ////////////////////////////// + //- rjf: build interned idx run map + // + RDIM_BakeIdxRunMap *idx_runs = 0; + ProfScope("build interned idx run map") + { + idx_runs = rdim_bake_idx_run_map_from_params(state->work_thread_arenas[0], name_maps, type_indices, in_params); + } + + ////////////////////////////// + //- rjf: do small top-level bakes + // + ProfScope("top level info") out.top_level_info = rdim_bake_top_level_info(state->work_thread_arenas[0], &bake_strings, &in_params->top_level_info); + ProfScope("binary sections") out.binary_sections = rdim_bake_binary_sections(state->work_thread_arenas[0], &bake_strings, &in_params->binary_sections); + ProfScope("top level name maps section") out.top_level_name_maps = rdim_bake_name_maps_top_level(state->work_thread_arenas[0], &bake_strings, idx_runs, name_maps); + + ////////////////////////////// + //- rjf: kick off pass 3 tasks + // + RDIM_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, &in_params->types, type_indices}; + ASYNC_Task *bake_type_nodes_task = async_task_launch(scratch.arena, rdim_bake_type_nodes_work, .input = &bake_type_nodes_in); + ASYNC_Task *bake_name_maps_tasks[RDI_NameMapKind_COUNT] = {0}; + { + for EachNonZeroEnumVal(RDI_NameMapKind, k) + { + if(name_maps[k] == 0 || name_maps[k]->name_count == 0) + { + continue; + } + RDIM_BakeNameMapIn *in = push_array(scratch.arena, RDIM_BakeNameMapIn, 1); + in->strings = &bake_strings; + in->idx_runs = idx_runs; + in->map = name_maps[k]; + in->kind = k; + bake_name_maps_tasks[k] = async_task_launch(scratch.arena, rdim_bake_name_map_work, .input = in); + } + } + RDIM_BakeIdxRunsIn bake_idx_runs_in = {idx_runs}; + ASYNC_Task *bake_idx_runs_task = async_task_launch(scratch.arena, rdim_bake_idx_runs_work, .input = &bake_idx_runs_in); + + ////////////////////////////// + //- rjf: join remaining completed bakes + // + ProfScope("top-level units info") out.units = *async_task_join_struct(bake_units_task, RDIM_UnitBakeResult); + ProfScope("unit vmap") out.unit_vmap = *async_task_join_struct(bake_unit_vmap_task, RDIM_UnitVMapBakeResult); + ProfScope("source files") out.src_files = *async_task_join_struct(bake_src_files_task, RDIM_SrcFileBakeResult); + ProfScope("UDTs") out.udts = *async_task_join_struct(bake_udts_task, RDIM_UDTBakeResult); + ProfScope("global vmap") out.global_vmap = *async_task_join_struct(bake_global_vmap_task, RDIM_GlobalVMapBakeResult); + ProfScope("scope vmap") out.scope_vmap = *async_task_join_struct(bake_scope_vmap_task, RDIM_ScopeVMapBakeResult); + ProfScope("inline sites") out.inline_sites = *async_task_join_struct(bake_inline_sites_task, RDIM_InlineSiteBakeResult); + ProfScope("file paths") out.file_paths = *async_task_join_struct(bake_file_paths_task, RDIM_FilePathBakeResult); + ProfScope("strings") out.strings = *async_task_join_struct(bake_strings_task, RDIM_StringBakeResult); + ProfScope("type nodes") out.type_nodes = *async_task_join_struct(bake_type_nodes_task, RDIM_TypeNodeBakeResult); + ProfScope("idx runs") out.idx_runs = *async_task_join_struct(bake_idx_runs_task, RDIM_IndexRunBakeResult); + ProfScope("line tables") out.line_tables = *async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); + + ////////////////////////////// + //- rjf: join individual name map bakes + // + RDIM_NameMapBakeResult name_map_bakes[RDI_NameMapKind_COUNT] = {0}; + ProfScope("name maps") + { + for EachNonZeroEnumVal(RDI_NameMapKind, k) + { + RDIM_NameMapBakeResult *bake = async_task_join_struct(bake_name_maps_tasks[k], RDIM_NameMapBakeResult); + if(bake != 0) + { + name_map_bakes[k] = *bake; + } + } + } + + ////////////////////////////// + //- rjf: join all individual name map bakes + // + ProfScope("join all name map bakes into final name map bake") + { + out.name_maps = rdim_name_map_bake_results_combine(state->work_thread_arenas[0], name_map_bakes, ArrayCount(name_map_bakes)); + } + + + //////////////////////////////// + + out.location_blocks = rdim_str8_list_join(state->work_thread_arenas[0], &location_blocks, rdim_str8(0,0)); + out.location_data = rdim_str8_list_join(state->work_thread_arenas[0], &location_data_blobs, rdim_str8(0,0)); + + rdim_help_state = 0; + + scratch_end(scratch); + return out; +} + +internal RDIM_SerializedSectionBundle +rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in) +{ + RDIM_SerializedSectionBundle out = {0}; + + //- rjf: set up compression context + rr_lzb_simple_context ctx = {0}; + ctx.m_tableSizeBits = 14; + ctx.m_hashTable = push_array(arena, U16, 1<sections[k]; + RDIM_SerializedSection *dst = &out.sections[k]; + MemoryCopyStruct(dst, src); + + // rjf: determine if this section should be compressed + B32 should_compress = 1; + + // rjf: compress if needed + if(should_compress) + { + MemoryZero(ctx.m_hashTable, sizeof(U16)*(1<data = push_array_no_zero(arena, U8, src->encoded_size); + dst->encoded_size = rr_lzb_simple_encode_veryfast(&ctx, src->data, src->encoded_size, dst->data); + dst->unpacked_size = src->encoded_size; + dst->encoding = RDI_SectionEncoding_LZB; + } + } + + return out; +} diff --git a/src/rdi_make/rdi_make_help.h b/src/rdi_make/rdi_make_help.h new file mode 100644 index 00000000..08c64391 --- /dev/null +++ b/src/rdi_make/rdi_make_help.h @@ -0,0 +1,342 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RDIM_MAKE_HELP +#define RDIM_MAKE_HELP + +//- rjf: line table baking task types + +typedef struct RDIM_BakeLineTablesIn RDIM_BakeLineTablesIn; +struct RDIM_BakeLineTablesIn +{ + RDIM_LineTableChunkList *line_tables; +}; + +//- rjf: string map baking task types + +typedef struct RDIM_BakeSrcFilesStringsIn RDIM_BakeSrcFilesStringsIn; +struct RDIM_BakeSrcFilesStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_SrcFileChunkList *list; +}; + +typedef struct RDIM_BakeUnitsStringsIn RDIM_BakeUnitsStringsIn; +struct RDIM_BakeUnitsStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_UnitChunkList *list; +}; + +typedef struct RDIM_BakeUDTsStringsInNode RDIM_BakeUDTsStringsInNode; +struct RDIM_BakeUDTsStringsInNode +{ + RDIM_BakeUDTsStringsInNode *next; + RDIM_UDT *v; + RDI_U64 count; +}; + +typedef struct RDIM_BakeTypesStringsInNode RDIM_BakeTypesStringsInNode; +struct RDIM_BakeTypesStringsInNode +{ + RDIM_BakeTypesStringsInNode *next; + RDIM_Type *v; + RDI_U64 count; +}; + +typedef struct RDIM_BakeTypesStringsIn RDIM_BakeTypesStringsIn; +struct RDIM_BakeTypesStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_BakeTypesStringsInNode *first; + RDIM_BakeTypesStringsInNode *last; +}; + +typedef struct RDIM_BakeUDTsStringsIn RDIM_BakeUDTsStringsIn; +struct RDIM_BakeUDTsStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_BakeUDTsStringsInNode *first; + RDIM_BakeUDTsStringsInNode *last; +}; + +typedef struct RDIM_BakeSymbolsStringsInNode RDIM_BakeSymbolsStringsInNode; +struct RDIM_BakeSymbolsStringsInNode +{ + RDIM_BakeSymbolsStringsInNode *next; + RDIM_Symbol *v; + RDI_U64 count; +}; + +typedef struct RDIM_BakeSymbolsStringsIn RDIM_BakeSymbolsStringsIn; +struct RDIM_BakeSymbolsStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_BakeSymbolsStringsInNode *first; + RDIM_BakeSymbolsStringsInNode *last; +}; + +typedef struct RDIM_BakeInlineSiteStringsInNode RDIM_BakeInlineSiteStringsInNode; +struct RDIM_BakeInlineSiteStringsInNode +{ + RDIM_BakeInlineSiteStringsInNode *next; + RDIM_InlineSite *v; + RDI_U64 count; +}; + +typedef struct RDIM_BakeInlineSiteStringsIn RDIM_BakeInlineSiteStringsIn; +struct RDIM_BakeInlineSiteStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_BakeInlineSiteStringsInNode *first; + RDIM_BakeInlineSiteStringsInNode *last; +}; + +typedef struct RDIM_BakeScopesStringsInNode RDIM_BakeScopesStringsInNode; +struct RDIM_BakeScopesStringsInNode +{ + RDIM_BakeScopesStringsInNode *next; + RDIM_Scope *v; + RDI_U64 count; +}; + +typedef struct RDIM_BakeScopesStringsIn RDIM_BakeScopesStringsIn; +struct RDIM_BakeScopesStringsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **maps; + RDIM_BakeScopesStringsInNode *first; + RDIM_BakeScopesStringsInNode *last; +}; + +//- rjf: OLD string map baking types + +typedef struct RDIM_BuildBakeStringMapIn RDIM_BuildBakeStringMapIn; +struct RDIM_BuildBakeStringMapIn +{ + RDIM_BakePathTree *path_tree; + RDIM_BakeParams *params; +}; + +typedef struct RDIM_BuildBakeNameMapIn RDIM_BuildBakeNameMapIn; +struct RDIM_BuildBakeNameMapIn +{ + RDI_NameMapKind k; + RDI_U64 *type_indices; + RDIM_BakeParams *params; +}; + +//- rjf: string map joining task types + +typedef struct RDIM_JoinBakeStringMapSlotsIn RDIM_JoinBakeStringMapSlotsIn; +struct RDIM_JoinBakeStringMapSlotsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose **src_maps; + U64 src_maps_count; + RDIM_BakeStringMapLoose *dst_map; + Rng1U64 slot_idx_range; +}; + +//- rjf: string map sorting task types + +typedef struct RDIM_SortBakeStringMapSlotsIn RDIM_SortBakeStringMapSlotsIn; +struct RDIM_SortBakeStringMapSlotsIn +{ + RDIM_BakeStringMapTopology *top; + RDIM_BakeStringMapLoose *src_map; + RDIM_BakeStringMapLoose *dst_map; + U64 slot_idx; + U64 slot_count; +}; + +//- rjf: debug info baking task types + +typedef struct RDIM_BakeUnitsIn RDIM_BakeUnitsIn; +struct RDIM_BakeUnitsIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_BakePathTree *path_tree; + RDIM_UnitChunkList *units; +}; + +typedef struct RDIM_BakeUnitVMapIn RDIM_BakeUnitVMapIn; +struct RDIM_BakeUnitVMapIn +{ + RDIM_UnitChunkList *units; +}; + +typedef struct RDIM_BakeSrcFilesIn RDIM_BakeSrcFilesIn; +struct RDIM_BakeSrcFilesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_BakePathTree *path_tree; + RDIM_SrcFileChunkList *src_files; +}; + +typedef struct RDIM_BakeUDTsIn RDIM_BakeUDTsIn; +struct RDIM_BakeUDTsIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_UDTChunkList *udts; + RDI_U64 *type_indices; +}; + +typedef struct RDIM_BakeGlobalVariablesIn RDIM_BakeGlobalVariablesIn; +struct RDIM_BakeGlobalVariablesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_SymbolChunkList *global_variables; + RDI_U64 *type_indices; +}; + +typedef struct RDIM_BakeGlobalVMapIn RDIM_BakeGlobalVMapIn; +struct RDIM_BakeGlobalVMapIn +{ + RDIM_SymbolChunkList *global_variables; +}; + +typedef struct RDIM_BakeThreadVariablesIn RDIM_BakeThreadVariablesIn; +struct RDIM_BakeThreadVariablesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_SymbolChunkList *thread_variables; + RDI_U64 *type_indices; +}; + +typedef struct RDIM_BakeProceduresIn RDIM_BakeProceduresIn; +struct RDIM_BakeProceduresIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_SymbolChunkList *procedures; + RDI_U64 *type_indices; + RDIM_String8List *location_blocks; + RDIM_String8List *location_data_blobs; +}; + +typedef struct RDIM_BakeScopesIn RDIM_BakeScopesIn; +struct RDIM_BakeScopesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_ScopeChunkList *scopes; + RDI_U64 *type_indices; + RDIM_String8List *location_blocks; + RDIM_String8List *location_data_blobs; +}; + +typedef struct RDIM_BakeScopeVMapIn RDIM_BakeScopeVMapIn; +struct RDIM_BakeScopeVMapIn +{ + RDIM_ScopeChunkList *scopes; +}; + +typedef struct RDIM_BakeInlineSitesIn RDIM_BakeInlineSitesIn; +struct RDIM_BakeInlineSitesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_InlineSiteChunkList *inline_sites; + RDI_U64 *type_indices; +}; + +typedef struct RDIM_BakeFilePathsIn RDIM_BakeFilePathsIn; +struct RDIM_BakeFilePathsIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_BakePathTree *path_tree; +}; + +typedef struct RDIM_BakeStringsIn RDIM_BakeStringsIn; +struct RDIM_BakeStringsIn +{ + RDIM_BakeStringMapTight *strings; +}; + +typedef struct RDIM_BakeTypeNodesIn RDIM_BakeTypeNodesIn; +struct RDIM_BakeTypeNodesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_BakeIdxRunMap *idx_runs; + RDIM_TypeChunkList *types; + RDI_U64 *type_indices; +}; + +typedef struct RDIM_BakeNameMapIn RDIM_BakeNameMapIn; +struct RDIM_BakeNameMapIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_BakeIdxRunMap *idx_runs; + RDIM_BakeNameMap *map; + RDI_NameMapKind kind; +}; + +typedef struct RDIM_BakeIdxRunsIn RDIM_BakeIdxRunsIn; +struct RDIM_BakeIdxRunsIn +{ + RDIM_BakeIdxRunMap *idx_runs; +}; + +//////////////////////////////// +//~ rjf: Baking Stage Tasks + +//- rjf: unsorted bake string map building +ASYNC_WORK_DEF(p2r_bake_src_files_strings_work); +ASYNC_WORK_DEF(p2r_bake_units_strings_work); +ASYNC_WORK_DEF(p2r_bake_types_strings_work); +ASYNC_WORK_DEF(p2r_bake_udts_strings_work); +ASYNC_WORK_DEF(p2r_bake_symbols_strings_work); +ASYNC_WORK_DEF(p2r_bake_scopes_strings_work); +ASYNC_WORK_DEF(p2r_bake_line_tables_work); + +//- rjf: bake string map joining +ASYNC_WORK_DEF(p2r_bake_string_map_join_work); + +//- rjf: bake string map sorting +ASYNC_WORK_DEF(p2r_bake_string_map_sort_work); + +//- rjf: pass 1: interner/deduper map builds +ASYNC_WORK_DEF(p2r_build_bake_name_map_work); + +//- rjf: pass 2: string-map-dependent debug info stream builds +ASYNC_WORK_DEF(p2r_bake_units_work); +ASYNC_WORK_DEF(p2r_bake_unit_vmap_work); +ASYNC_WORK_DEF(p2r_bake_src_files_work); +ASYNC_WORK_DEF(p2r_bake_udts_work); +ASYNC_WORK_DEF(p2r_bake_global_variables_work); +ASYNC_WORK_DEF(p2r_bake_global_vmap_work); +ASYNC_WORK_DEF(p2r_bake_thread_variables_work); +ASYNC_WORK_DEF(p2r_bake_procedures_work); +ASYNC_WORK_DEF(p2r_bake_scopes_work); +ASYNC_WORK_DEF(p2r_bake_scope_vmap_work); +ASYNC_WORK_DEF(p2r_bake_file_paths_work); +ASYNC_WORK_DEF(p2r_bake_strings_work); + +//- rjf: pass 3: idx-run-map-dependent debug info stream builds +ASYNC_WORK_DEF(p2r_bake_type_nodes_work); +ASYNC_WORK_DEF(p2r_bake_name_map_work); +ASYNC_WORK_DEF(p2r_bake_idx_runs_work); + +typedef struct RDIM_HelpState RDIM_HelpState; +struct RDIM_HelpState +{ + Arena *arena; + U64 work_thread_arenas_count; + Arena **work_thread_arenas; +}; + +//////////////////////////////// + +global RDIM_HelpState *rdim_help_state = 0; + +//////////////////////////////// + +internal RDIM_HelpState * rdim_help_init(void); +internal RDIM_BakeResults rdim_bake(RDIM_HelpState *state, RDIM_BakeParams *in); +internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in); + +#endif // RDIM_MAKE_HELP