diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 13fb8d1a..7054990c 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -58,13 +58,6 @@ #include "llvm/llvm.c" #include "dwarf/x64/dwarf_x64.c" -// --- RDI --------------------------------------------------------------------- - -#include "rdi/rdi_local.h" -#include "arch/arch_inc.h" -#include "rdi/rdi_local.c" -#include "arch/arch_inc.c" - // --- Code Base Extensions ---------------------------------------------------- #include "base_ext/base_inc.h" @@ -83,15 +76,21 @@ #include "pdb_ext/pdb_helpers.c" #include "pdb_ext/pdb_builder.c" -// --- RDI Builder ------------------------------------------------------------- +// --- RDI --------------------------------------------------------------------- -#include "rdi/rdi_builder.h" -#include "rdi/rdi_coff.h" -#include "rdi/rdi_cv.h" +#include "pdb/pdb_parse.h" +#include "rdi/rdi_local.h" +#include "rdi_make/rdi_make_local.h" +#include "rdi_from_coff/rdi_from_coff.h" +#include "rdi_from_pdb/rdi_from_pdb.h" +#include "arch/arch_inc.h" -#include "rdi/rdi_builder.c" -#include "rdi/rdi_coff.c" -#include "rdi/rdi_cv.c" +#include "pdb/pdb_parse.c" +#include "rdi/rdi_local.c" +#include "rdi_make/rdi_make_local.c" +#include "rdi_from_coff/rdi_from_coff.c" +#include "rdi_from_pdb/rdi_from_pdb.c" +#include "arch/arch_inc.c" // --- Linker ------------------------------------------------------------------ @@ -5259,6 +5258,40 @@ lnk_log_timers(void) scratch_end(scratch); } +internal +THREAD_POOL_TASK_FUNC(lnk_p2r_worker) +{ + Temp scratch = scratch_begin(&arena, 1); + + LNK_P2R *ctx = raw_task; + + P2R_ConvertParams p2r_params = {0}; + if (task_id == 0) { + p2r_params.input_pdb_name = lnk_get_pdb_name(ctx->config); + p2r_params.input_pdb_data = ctx->pdb_data; + p2r_params.input_exe_name = lnk_get_image_name(ctx->config); + p2r_params.input_exe_data = ctx->image_data; + p2r_params.subset_flags = max_U32; + } + tp_broadcast(&p2r_params); + + LaneCtx lctx = { .lane_idx = task_id, .lane_count = tp->worker_count, .barrier = tp->barrier, .broadcast_memory = tp->broadcast }; + lane_ctx(lctx); + + Arena *bake_arena = arena_alloc(); + RDIM_BakeParams bake_params = p2r_convert(bake_arena, &p2r_params); + barrier_wait(tp->barrier); + + RDIM_BakeResults bake_results = rdim_bake(arena, &bake_params); + barrier_wait(tp->barrier); + + if (task_id == 0) { + ctx->bake_results = bake_results; + } + + scratch_end(scratch); +} + internal void lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) { @@ -5349,51 +5382,45 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) LNK_MergedTypes cv_types = lnk_merge_types(tp, arena, &cv); // - // RDI - // - if (config->rad_debug == LNK_SwitchState_Yes) { - lnk_timer_begin(LNK_Timer_Rdi); - - String8List rdi_data = lnk_build_rad_debug_info(tp, - arena, - OperatingSystem_Windows, - rdi_arch_from_coff_machine(config->machine), - lnk_get_image_name(config), - image_ctx.image_data, - debug_info_objs_count, - debug_info_objs, - cv.debug_s_arr, - cv.symbol_input_count, - cv.symbol_inputs, - (CV_SymbolListArray[]){0}, - cv_types); - - lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_data); - - lnk_timer_end(LNK_Timer_Rdi); - } - - // - // PDB + // Debug Info // // TODO: Parallel debug info builds are currently blocked by the patch // strings in $$FILE_CHECKSUM step in `lnk_process_c13_data_task`. - if (config->debug_mode == LNK_DebugMode_Full) { - lnk_timer_begin(LNK_Timer_Pdb); + if (config->debug_mode == LNK_DebugMode_Full || config->rad_debug == LNK_SwitchState_Yes) { + Temp huge_arena_temp = temp_begin(lnk_get_huge_arena()); - if (config->pdb_hash_type_names != LNK_TypeNameHashMode_Null && config->pdb_hash_type_names != LNK_TypeNameHashMode_None) { - lnk_replace_type_names_with_hashes(tp, - arena, - cv_types.count[CV_TypeIndexSource_TPI], - cv_types.v [CV_TypeIndexSource_TPI], - config->pdb_hash_type_names, - config->pdb_hash_type_name_length, - config->pdb_hash_type_name_map); + String8List pdb_data = {0}; + { + lnk_timer_begin(LNK_Timer_Pdb); + if (config->pdb_hash_type_names != LNK_TypeNameHashMode_Null && config->pdb_hash_type_names != LNK_TypeNameHashMode_None) { + lnk_replace_type_names_with_hashes(tp, + arena, + cv_types.count[CV_TypeIndexSource_TPI], + cv_types.v [CV_TypeIndexSource_TPI], + config->pdb_hash_type_names, + config->pdb_hash_type_name_length, + config->pdb_hash_type_name_map); + } + pdb_data = lnk_build_pdb(tp, arena, image_ctx.image_data, config, symtab, &cv, cv_types); + if (config->debug_mode == LNK_DebugMode_Full) { + lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data); + } + lnk_timer_end(LNK_Timer_Pdb); } - String8List pdb_data = lnk_build_pdb(tp, arena, image_ctx.image_data, config, symtab, &cv, cv_types); - lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data); - lnk_timer_end(LNK_Timer_Pdb); + if (config->rad_debug == LNK_SwitchState_Yes) { + lnk_timer_begin(LNK_Timer_Rdi); + + LNK_P2R p2r = { .config = config, .pdb_data = str8_list_join(lnk_get_huge_arena(), &pdb_data, 0), .image_data = image_ctx.image_data }; + tp_for_parallel(tp, arena, tp->worker_count, lnk_p2r_worker, &p2r); + + String8List rdi_blobs = rdim_file_blobs_from_section_bundle(scratch.arena, &p2r.bake_results.section_bundle); + lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_blobs); + + lnk_timer_end(LNK_Timer_Rdi); + } + + temp_end(huge_arena_temp); } // diff --git a/src/linker/lnk.h b/src/linker/lnk.h index 95210356..5b2d20e3 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -309,6 +309,14 @@ typedef struct U128 *hashes; } LNK_Blake3Hasher; +typedef struct +{ + RDIM_BakeResults bake_results; + LNK_Config *config; + String8 pdb_data; + String8 image_data; +} LNK_P2R; + // --- Config ----------------------------------------------------------------- internal LNK_Config * lnk_config_from_argcv(Arena *arena, int argc, char **argv); diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index 9f92dfad..2e5a8f1a 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -753,11 +753,19 @@ lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_Me internal String8 lnk_get_image_name(LNK_Config *config) { - String8 image_name = config->image_alt_path.size ? config->image_alt_path : config->out_path; - image_name = str8_skip_last_slash(image_name); + String8 image_path = config->image_alt_path.size ? config->image_alt_path : config->out_path; + String8 image_name = str8_skip_last_slash(image_path); return image_name; } +internal String8 +lnk_get_pdb_name(LNK_Config *config) +{ + String8 pdb_path = config->pdb_alt_path.size ? config->pdb_alt_path : config->pdb_name; + String8 pdb_name = str8_skip_last_slash(pdb_path); + return pdb_name; +} + internal U64 lnk_get_default_function_pad_min(COFF_MachineType machine) { diff --git a/src/linker/lnk_config.h b/src/linker/lnk_config.h index 6e7e7951..2f0f34cf 100644 --- a/src/linker/lnk_config.h +++ b/src/linker/lnk_config.h @@ -542,6 +542,7 @@ internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LN // --- Getters ----------------------------------------------------------------- internal String8 lnk_get_image_name (LNK_Config *config); +internal String8 lnk_get_pdb_name (LNK_Config *config); internal U64 lnk_get_default_function_pad_min (COFF_MachineType machine); internal U64 lnk_get_base_addr (LNK_Config *config); internal Version lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine); diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 7176e96e..da6ab1bd 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -2464,15 +2464,13 @@ internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, LNK_CodeViewInput *cv, LNK_MergedTypes cv_types) { ProfBeginFunction(); - Temp scratch = scratch_begin(tp_arena->v, tp_arena->count); - Temp huge_arena_temp = temp_begin(lnk_get_huge_arena()); LNK_BuildPdb task = { .image_data = image_data, .symtab = symtab, .cv = cv, - .pdb = pdb_alloc_(huge_arena_temp.arena, config->pdb_page_size, config->machine, config->time_stamp, config->age, config->guid), + .pdb = pdb_alloc_(lnk_get_huge_arena(), config->pdb_page_size, config->machine, config->time_stamp, config->age, config->guid), .mod_arr = push_array(scratch.arena, PDB_DbiModule *, cv->obj_count), .pe = pe_bin_info_from_data(scratch.arena, image_data), .image_section_table = coff_section_table_from_data(scratch.arena, image_data, task.pe.section_table_range), @@ -2594,2266 +2592,8 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config ProfEnd(); #endif - temp_end(huge_arena_temp); scratch_end(scratch); ProfEnd(); return page_data_list; } -internal U64 -lnk_udt_name_hash_table_hash(String8 string) -{ - return XXH3_64bits(string.str, string.size); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_build_udt_name_hash_table_task) -{ - LNK_BuildUDTNameHashTableTask *task = raw_task; - - LNK_UDTNameBucket *new_bucket = 0; - for EachInRange(leaf_idx, task->ranges[task_id]) { - String8 leaf_data = str8(task->leaf_arr[leaf_idx], max_U64); - - CV_Leaf leaf; - cv_read_leaf(leaf_data, 0, 1, &leaf); - - // is this UDT? - if ( ! cv_is_udt(leaf.kind)) { continue; } - - // skip forward references - CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); - if (udt_info.props & CV_TypeProp_FwdRef) { continue; } - - // skip anon UDT - if (cv_is_udt_name_anon(udt_info.name)) { continue; } - - // UDT name -> bucket index - String8 name = cv_name_from_udt_info(udt_info); - U64 hash = lnk_udt_name_hash_table_hash(name); - U64 best_idx = hash % task->buckets_cap; - U64 bucket_idx = best_idx; - - // push and fill bucket - if (new_bucket == 0) { new_bucket = push_array(arena, LNK_UDTNameBucket, 1); } - new_bucket->name = name; - new_bucket->leaf_idx = leaf_idx; - - B32 is_inserted_or_updated = 0; - do { - retry:; - LNK_UDTNameBucket *curr_bucket = task->buckets[bucket_idx]; - - if (curr_bucket == 0) { - LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - // success, bucket was inserted - is_inserted_or_updated = 1; - break; - } - - // another thread took the bucket... - goto retry; - } else if (str8_match(curr_bucket->name, name, 0)) { - // there is more than one UDT with identical name, pick most recent and ignore others - - if (leaf_idx < curr_bucket->leaf_idx) { - LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket); - if (compare_bucket == curr_bucket) { - is_inserted_or_updated = 1; - break; - } - } else { - // don't need to update, more recent leaf is in the bucket - break; - } - - // another thread took the bucket... - goto retry; - } - - // advance - bucket_idx = (bucket_idx + 1) % task->buckets_cap; - } while (bucket_idx != best_idx); - - if (is_inserted_or_updated) { - new_bucket = 0; - } - } -} - - -internal LNK_UDTNameBucket ** -lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, - TP_Arena *arena, - U64 leaf_count, - U8 **leaf_arr, - U64 *buckets_cap_out) -{ - Temp scratch = scratch_begin(&arena->v[0], 1); - LNK_BuildUDTNameHashTableTask task = {0}; - task.leaf_count = leaf_count; - task.leaf_arr = leaf_arr; - task.buckets_cap = (leaf_count * 13) / 10; - task.buckets = push_array(arena->v[0], LNK_UDTNameBucket *, task.buckets_cap); - task.ranges = tp_divide_work(scratch.arena, leaf_count, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, lnk_build_udt_name_hash_table_task, &task); - *buckets_cap_out = task.buckets_cap; - scratch_end(scratch); - return task.buckets; -} - -internal LNK_UDTNameBucket * -lnk_udt_name_hash_table_lookup(LNK_UDTNameBucket **buckets, U64 cap, String8 name) -{ - U64 hash = lnk_udt_name_hash_table_hash(name); - U64 best_idx = hash % cap; - U64 bucket_idx = best_idx; - do { - if (buckets[bucket_idx] == 0) { - break; - } - if (str8_match(buckets[bucket_idx]->name, name, 0)) { - return buckets[bucket_idx]; - } - bucket_idx = (bucket_idx + 1) % cap; - } while (bucket_idx != best_idx); - return 0; -} - -internal CV_TypeIndex -lnk_udt_name_hash_table_lookup_itype(LNK_UDTNameBucket **buckets, U64 cap, String8 name) -{ - LNK_UDTNameBucket *bucket = lnk_udt_name_hash_table_lookup(buckets, cap, name); - if (bucket != 0) { - return CV_MinComplexTypeIndex + bucket->leaf_idx; - } - return 0; -} - -internal RDIB_Type * -lnk_push_converted_codeview_type(Arena *arena, RDIB_TypeChunkList *list, RDIB_Type **itype_map, CV_TypeIndex itype) -{ - RDIB_Type *type = rdib_type_chunk_list_push(arena, list, 8196); - type->final_idx = 0; - type->itype = itype; - - Assert(itype_map[itype] == 0); - itype_map[itype] = type; - - return type; -} - -internal void -lnk_push_basic_itypes(Arena *arena, RDIB_DataModel data_model, RDIB_Type **itype_map, RDIB_TypeChunkList *rdib_types_list) -{ - RDI_TypeKind short_type = rdib_short_type_from_data_model(data_model); - RDI_TypeKind ushort_type = rdib_unsigned_short_type_from_data_model(data_model); - RDI_TypeKind int_type = rdib_int_type_from_data_model(data_model); - RDI_TypeKind uint_type = rdib_unsigned_int_type_from_data_model(data_model); - RDI_TypeKind long_type = rdib_long_type_from_data_model(data_model); - RDI_TypeKind ulong_type = rdib_unsigned_long_type_from_data_model(data_model); - RDI_TypeKind long_long_type = rdib_long_long_type_from_data_model(data_model); - RDI_TypeKind ulong_long_type = rdib_unsigned_long_long_type_from_data_model(data_model); - RDI_TypeKind ptr_type = rdib_pointer_size_t_type_from_data_model(data_model); - - struct { - char * name; - RDI_TypeKind kind_rdi; - CV_LeafKind kind_cv; - B32 make_pointer_near; - B32 make_pointer_32; - B32 make_pointer_64; - } table[] = { - { "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 }, // TODO: we need Signed Char8 in RDI - { "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 }, // GCC/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 }, // GCC/Clang type - { "bool" , RDI_TypeKind_S8 , CV_BasicType_BOOL8 , 1, 1, 1 }, // TODO: we need a actual boolean type in RDI so we can format value as true/false. - { "__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 }, // GCC/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) { - U64 builtin_size; - if (table[i].kind_rdi == RDI_TypeKind_Void || table[i].kind_rdi == RDI_TypeKind_Handle) { - builtin_size = rdi_size_from_basic_type_kind(ptr_type); - } else { - builtin_size = rdi_size_from_basic_type_kind(table[i].kind_rdi); - } - - RDIB_Type *builtin = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv); - builtin->kind = table[i].kind_rdi; - builtin->builtin.name = str8_cstring(table[i].name); - builtin->builtin.size = builtin_size; - - RDIB_Type **wrapper = push_array(arena, RDIB_Type *, 1); - *wrapper = builtin; - - if (table[i].make_pointer_near) { - RDIB_Type *ptr_near = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x100); - ptr_near->kind = RDI_TypeKind_Ptr; - ptr_near->ptr.size = rdi_size_from_basic_type_kind(ptr_type); - ptr_near->ptr.type_ref = wrapper; - } - if (table[i].make_pointer_32) { - RDIB_Type *ptr_32 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x400); - ptr_32->kind = RDI_TypeKind_Ptr; - ptr_32->ptr.size = 4; - ptr_32->ptr.type_ref = wrapper; - } - if (table[i].make_pointer_64) { - RDIB_Type *ptr_64 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x600); - ptr_64->kind = RDI_TypeKind_Ptr; - ptr_64->ptr.size = 8; - ptr_64->ptr.type_ref = wrapper; - } - -#if 0 - RDIB_Type *ptr_far = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x200); - RDIB_Type *ptr_huge = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x300); - RDIB_Type *ptr_16_32 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x500); - - ptr_far->kind = RDI_TypeKind_Ptr; - ptr_far->ptr.size = rdi_size_from_basic_type_kind(ptr_type); - ptr_far->ptr.type_ref = wrapper; - - ptr_huge->kind = RDI_TypeKind_Ptr; - ptr_huge->ptr.size = 4; - ptr_huge->ptr.type_ref = wrapper; - - - ptr_16_32->kind = RDI_TypeKind_Ptr; - ptr_16_32->ptr.size = 6; - ptr_16_32->ptr.type_ref = wrapper; -#endif - } -} - -internal RDIB_TypeRef -lnk_rdib_type_from_itype(LNK_ConvertTypesToRDI *task, CV_TypeIndex itype) -{ - RDIB_TypeRef result = &task->tpi_itype_map[0]; - Rng1U64 tpi_range = task->itype_ranges[CV_TypeIndexSource_TPI]; - - if (itype < tpi_range.min) { - // check for supported CodeView pointer formats: - AssertAlways(BitExtract(itype, 8, 8) == /* near */ 0x1 || - BitExtract(itype, 8, 8) == /* 32 bit */ 0x4 || - BitExtract(itype, 8, 8) == /* 64 bit */ 0x6 || - BitExtract(itype, 8, 8) == /* regular */ 0x0); - } - - if (itype < tpi_range.max) { - CV_TypeIndex final_itype = itype; - - // try to resovle forward reference (defn might be missing) - if (itype >= tpi_range.min) { - CV_Leaf leaf; - cv_read_leaf(str8(task->leaf_arr[CV_TypeIndexSource_TPI][itype - tpi_range.min], max_U64), 0, 1, &leaf); - if (cv_is_udt(leaf.kind)) { - CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); - if (udt_info.props & CV_TypeProp_FwdRef) { - String8 name = cv_name_from_udt_info(udt_info); - CV_TypeIndex resolved_itype = lnk_udt_name_hash_table_lookup_itype(task->udt_name_buckets, task->udt_name_bucket_cap, name); - if (resolved_itype != 0) { - final_itype = resolved_itype; - } - } - } - } - - result = &task->tpi_itype_map[final_itype]; - } - - return result; -} - -internal RDI_MemberKind -lnk_rdib_method_kind_from_cv_prop(CV_MethodProp prop) -{ - switch (prop) { - case CV_MethodProp_Vanilla: return RDI_MemberKind_Method; - case CV_MethodProp_Virtual: return RDI_MemberKind_VirtualMethod; - case CV_MethodProp_Static: return RDI_MemberKind_StaticMethod; - case CV_MethodProp_Friend: NotImplemented; - case CV_MethodProp_Intro: return RDI_MemberKind_VirtualMethod; - case CV_MethodProp_PureVirtual: return RDI_MemberKind_VirtualMethod; - case CV_MethodProp_PureIntro: return RDI_MemberKind_VirtualMethod; - } - return RDI_MemberKind_NULL; -} - -internal -THREAD_POOL_TASK_FUNC(lnk_convert_types_to_rdi_task) -{ - ProfBeginFunction(); - LNK_ConvertTypesToRDI *task = raw_task; - - // upfront push output type array - U64 leaf_count = dim_1u64(task->ranges[task_id]); - rdib_type_chunk_list_reserve(arena, &task->rdib_types_lists[task_id], leaf_count); - - for(U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) { - U64 itype = task->itype_ranges[CV_TypeIndexSource_TPI].min + leaf_idx; - CV_Leaf src = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][leaf_idx]); - - switch (src.kind) { - case CV_LeafKind_MODIFIER: { - CV_LeafModifier *modifier = (CV_LeafModifier *) src.data.str; - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKind_Modifier; - dst->modifier.flags = rdi_type_modifier_flags_from_cv_modifier_flags(modifier->flags); - dst->modifier.type_ref = lnk_rdib_type_from_itype(task, modifier->itype); - } break; - case CV_LeafKind_POINTER: { - CV_LeafPointer *ptr = (CV_LeafPointer *) src.data.str; - CV_PointerKind ptr_kind = CV_PointerAttribs_Extract_Kind(ptr->attribs); - CV_PointerMode ptr_mode = CV_PointerAttribs_Extract_Mode(ptr->attribs); - U32 ptr_size = CV_PointerAttribs_Extract_Size(ptr->attribs); - (void)ptr_kind; - - // parse ahead type chain and squash modifiers - RDI_TypeModifierFlags modifier_flags = rdi_type_modifier_flags_from_cv_pointer_attribs(ptr->attribs); - CV_TypeIndex next_itype; - for (next_itype = ptr->itype; task->itype_ranges[CV_TypeIndexSource_TPI].min <= next_itype && next_itype < task->itype_ranges[CV_TypeIndexSource_TPI].max;) { - U64 next_leaf_idx = next_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min; - CV_Leaf next_leaf = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][next_leaf_idx]); - if (next_leaf.kind != CV_LeafKind_MODIFIER) { - break; - } - - // parse LF_MODIFIER - CV_LeafModifier *sym_modifier = (CV_LeafModifier *) next_leaf.data.str; - RDI_TypeModifierFlags flags = rdi_type_modifier_flags_from_cv_modifier_flags(sym_modifier->flags); - - // accumulate modifier flags - modifier_flags |= flags; - - // advance - next_itype = sym_modifier->itype; - } - - if (modifier_flags == 0) { - // No modifer just generate pointer type. - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = rdi_type_kind_from_pointer(ptr->attribs, ptr_mode); - dst->ptr.size = ptr_size; - dst->ptr.type_ref = lnk_rdib_type_from_itype(task, ptr->itype); - } else { - // CodeView embeds modifier in pointer struct, we don't have an equivalent - // so generate a modifier type in pointer slot and link with pointer type. - - RDIB_Type *ptr_type = rdib_type_chunk_list_push(arena, &task->rdib_types_lists[task_id], task->type_cap); - ptr_type->kind = rdi_type_kind_from_pointer(ptr->attribs, ptr_mode); - ptr_type->ptr.type_ref = lnk_rdib_type_from_itype(task, next_itype); - RDIB_Type **indirect_ptr_type = push_array(arena, RDIB_Type *, 1); - *indirect_ptr_type = ptr_type; - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKind_Modifier; - dst->modifier.flags = modifier_flags; - dst->modifier.type_ref = indirect_ptr_type; - } - } break; - case CV_LeafKind_PROCEDURE: { - CV_LeafProcedure *proc = (CV_LeafProcedure *) src.data.str; - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKind_Function; - dst->func.return_type = lnk_rdib_type_from_itype(task, proc->ret_itype); - dst->func.params_type = lnk_rdib_type_from_itype(task, proc->arg_itype); - } break; - case CV_LeafKind_MFUNCTION: { - CV_LeafMFunction *mfunc = (CV_LeafMFunction *) src.data.str; - B32 is_static_method = mfunc->this_itype == 0; - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - - if (is_static_method) { - dst->kind = RDI_TypeKindExt_StaticMethod; - dst->static_method.class_type = lnk_rdib_type_from_itype(task, mfunc->class_itype); - dst->static_method.return_type = lnk_rdib_type_from_itype(task, mfunc->ret_itype); - dst->static_method.params_type = lnk_rdib_type_from_itype(task, mfunc->arg_itype); - } else { - dst->kind = RDI_TypeKind_Method; - dst->method.class_type = lnk_rdib_type_from_itype(task, mfunc->class_itype); - dst->method.this_type = lnk_rdib_type_from_itype(task, mfunc->this_itype); - dst->method.return_type = lnk_rdib_type_from_itype(task, mfunc->ret_itype); - dst->method.params_type = lnk_rdib_type_from_itype(task, mfunc->arg_itype); - } - } break; - case CV_LeafKind_BITFIELD: { - CV_LeafBitField *bitfield = (CV_LeafBitField *) src.data.str; - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKind_Bitfield; - dst->bitfield.off = bitfield->pos; - dst->bitfield.count = bitfield->len; - dst->bitfield.value_type = lnk_rdib_type_from_itype(task, bitfield->itype); - } break; - case CV_LeafKind_ARRAY: { - CV_LeafArray *array = (CV_LeafArray *) src.data.str; - CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafArray), src.data.str + src.data.size); - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKind_Array; - dst->array.entry_type = lnk_rdib_type_from_itype(task, array->entry_itype); - dst->array.size = cv_u64_from_numeric(&size); - } break; - case CV_LeafKind_CLASS: - case CV_LeafKind_STRUCTURE: { - CV_LeafStruct *udt = (CV_LeafStruct *) src.data.str; - CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafStruct), src.data.str + src.data.size); - - String8 name; - String8 link_name; - if (udt->props & CV_TypeProp_HasUniqueName) { - name = str8_cstring_capped(src.data.str + sizeof(CV_LeafStruct) + size.encoded_size, src.data.str + src.data.size); - link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); - } else { - name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafStruct) + size.encoded_size, src.data.str + src.data.size); - link_name = name; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_struct_lists[task_id], task->tpi_itype_map, itype); - dst->udt.name = name; - dst->udt.link_name = link_name; - dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); - dst->udt.struct_type.size = cv_u64_from_numeric(&size); - dst->udt.struct_type.derived = lnk_rdib_type_from_itype(task, udt->derived_itype); - dst->udt.struct_type.vtshape = lnk_rdib_type_from_itype(task, udt->vshape_itype); - - if (udt->props & CV_TypeProp_FwdRef) { - dst->kind = src.kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct; - } else { - dst->kind = src.kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct; - } - } break; - case CV_LeafKind_CLASS2: - case CV_LeafKind_STRUCT2: { - CV_LeafStruct2 *udt = (CV_LeafStruct2 *) src.data.str; - CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafStruct2), src.data.str + src.data.size); - - String8 name; - String8 link_name; - if (udt->props & CV_TypeProp_HasUniqueName) { - name = str8_cstring_capped(src.data.str + sizeof(CV_LeafStruct2) + size.encoded_size, src.data.str + src.data.size); - link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); - } else { - name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafStruct2) + size.encoded_size, src.data.str + src.data.size); - link_name = name; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_struct_lists[task_id], task->tpi_itype_map, itype); - dst->udt.name = name; - dst->udt.link_name = link_name; - dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); - dst->udt.struct_type.size = cv_u64_from_numeric(&size); - dst->udt.struct_type.derived = lnk_rdib_type_from_itype(task, udt->derived_itype); - dst->udt.struct_type.vtshape = lnk_rdib_type_from_itype(task, udt->vshape_itype); - - if (udt->props & CV_TypeProp_FwdRef) { - dst->kind = src.kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct; - } else { - dst->kind = src.kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_Class : RDI_TypeKind_Struct; - } - } break; - case CV_LeafKind_UNION: { - CV_LeafUnion *udt = (CV_LeafUnion *) src.data.str; - CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafUnion), src.data.str + src.data.size); - - String8 name; - String8 link_name; - if (udt->props & CV_TypeProp_HasUniqueName) { - name = str8_cstring_capped(src.data.str + sizeof(CV_LeafUnion) + size.encoded_size, src.data.str + src.data.size); - link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); - } else { - name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafUnion) + size.encoded_size, src.data.str + src.data.size); - link_name = name; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_union_lists[task_id], task->tpi_itype_map, itype); - dst->udt.name = name; - dst->udt.link_name = link_name; - dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); - dst->udt.union_type.size = cv_u64_from_numeric(&size); - - if (udt->props & CV_TypeProp_FwdRef) { - dst->kind = RDI_TypeKind_IncompleteUnion; - } else { - dst->kind = RDI_TypeKind_Union; - } - } break; - case CV_LeafKind_ENUM: { - CV_LeafEnum *udt = (CV_LeafEnum *) src.data.str; - - String8 name; - String8 link_name; - if (udt->props & CV_TypeProp_HasUniqueName) { - name = str8_cstring_capped(src.data.str + sizeof(*udt), src.data.str + src.data.size); - link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); - } else { - name = str8_cstring_capped_reverse(src.data.str + sizeof(*udt), src.data.str + src.data.size); - link_name = name; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_enum_lists[task_id], task->tpi_itype_map, itype); - dst->kind = (RDI_TypeKindExt)RDI_TypeKind_Enum; - dst->udt.name = name; - dst->udt.link_name = link_name; - dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); - dst->udt.enum_type.base_type = lnk_rdib_type_from_itype(task, udt->base_itype); - - if (udt->props & CV_TypeProp_FwdRef) { - dst->kind = RDI_TypeKind_IncompleteEnum; - } else { - dst->kind = (RDI_TypeKindExt)RDI_TypeKind_Enum; - } - } break; - case CV_LeafKind_ARGLIST: { - CV_LeafArgList *arglist = (CV_LeafArgList *) src.data.str; - CV_TypeIndex *itypes = (CV_TypeIndex *) (arglist + 1); - - if (arglist->count * sizeof(CV_TypeIndex) + sizeof(CV_LeafArgList) > src.data.size) { - AssertAlways("error: ill-formed LF_ARGLIST"); - break; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_params_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKindExt_Params; // there is no Params kind in RDI - dst->params.count = arglist->count; - dst->params.types = push_array(arena, RDIB_TypeRef, arglist->count); - for (U64 param_idx = 0; param_idx < arglist->count; ++param_idx) { - // strange way to encode variadic params, when outside LF_ARGLIST LF_NOTYPE actually means null... - if (itypes[param_idx] == CV_LeafKind_NOTYPE) { - dst->params.types[param_idx] = task->variadic_type_ref; - } else { - dst->params.types[param_idx] = lnk_rdib_type_from_itype(task, itypes[param_idx]); - } - } - } break; - case CV_LeafKind_FIELDLIST: { - RDIB_UDTMemberChunkList *rdib_member_list; - RDIB_TypeChunkList *rdib_member_types; - B32 is_enum = sizeof(CV_LeafKind) <= src.data.size && (*(CV_LeafKind *)src.data.str == CV_LeafKind_ENUMERATE); - if (is_enum) { - rdib_member_list = &task->rdib_enum_members_lists[worker_id]; - rdib_member_types = &task->rdib_types_enum_members_lists[worker_id]; - } else { - rdib_member_list = &task->rdib_udt_members_lists[worker_id]; - rdib_member_types = &task->rdib_types_udt_members_lists[worker_id]; - } - - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, rdib_member_types, task->tpi_itype_map, itype); - dst->kind = RDI_TypeKindExt_Members; - - for (U64 cursor = 0; cursor + sizeof(CV_LeafKind) <= src.data.size; ) { - CV_LeafKind field_kind = *(CV_LeafKind *) (src.data.str + cursor); - cursor += sizeof(field_kind); - - // do we have bytes to read? - U64 header_size = cv_header_struct_size_from_leaf_kind(field_kind); - if (cursor + header_size > src.data.size) { - break; - } - - switch (field_kind) { - case CV_LeafKind_INDEX: { - CV_LeafIndex *index = (CV_LeafIndex *) (src.data.str + cursor); - cursor += sizeof(*index); - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB member list pointer - member->kind = RDI_MemberKindExt_MemberListPointer; - member->member_list_pointer = lnk_rdib_type_from_itype(task, index->itype); - } break; - case CV_LeafKind_MEMBER: { - // prase CodeView struct/class/union data member - CV_LeafMember *leaf_member = (CV_LeafMember *) (src.data.str + cursor); - CV_NumericParsed offset = cv_numeric_from_data_range((U8 *)(leaf_member + 1), src.data.str + src.data.size); - String8 name = str8_cstring_capped(src.data.str + cursor + sizeof(CV_LeafMember) + offset.encoded_size, src.data.str + src.data.size); - cursor += sizeof(CV_LeafMember); - cursor += offset.encoded_size; - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB data member - member->kind = RDI_MemberKind_DataField; - member->data_field.name = name; - member->data_field.type_ref = lnk_rdib_type_from_itype(task, leaf_member->itype); - member->data_field.offset = cv_u64_from_numeric(&offset); - } break; - case CV_LeafKind_STMEMBER: { - // parse CodeView static member - CV_LeafStMember *st_member = (CV_LeafStMember *) (src.data.str + cursor); - String8 name = str8_cstring_capped(st_member + 1, src.data.str + src.data.size); - cursor += sizeof(CV_LeafStMember); - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB static member - member->kind = RDI_MemberKind_StaticData; - member->static_data.name = name; - member->static_data.type_ref = lnk_rdib_type_from_itype(task, st_member->itype); - } break; - case CV_LeafKind_METHOD: { - // parse CodeView over-loaded method - CV_LeafMethod *method = (CV_LeafMethod *) (src.data.str + cursor); - String8 name = str8_cstring_capped(method + 1, src.data.str + src.data.size); - cursor += sizeof(CV_LeafMethod); - cursor += name.size + 1; - - if (contains_1u64(task->itype_ranges[CV_TypeIndexSource_TPI], method->list_itype)) { - U64 method_list_leaf_idx = method->list_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min; - CV_Leaf method_list_leaf = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][method_list_leaf_idx]); - if (method_list_leaf.kind == CV_LeafKind_METHODLIST) { - for (U64 cursor = 0; cursor + sizeof(CV_LeafMethodListMember) <= method_list_leaf.data.size; ) { - // parse CodeView method overload info - CV_LeafMethodListMember *list_member = (CV_LeafMethodListMember *) (method_list_leaf.data.str + cursor); - CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(list_member->attribs); - cursor += sizeof(CV_LeafMethodListMember); - U32 vftable_offset = 0; - if (prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { - str8_deserial_read_struct(src.data, cursor, &vftable_offset); - cursor += sizeof(vftable_offset); - } - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB method - member->kind = RDI_MemberKind_Method; - member->method.kind = lnk_rdib_method_kind_from_cv_prop(prop); - member->method.name = name; - member->method.type_ref = lnk_rdib_type_from_itype(task, list_member->itype); - member->method.vftable_offset = vftable_offset; - } - } else { - Assert(!"error: expected LF_METHODLIST"); - } - } - } break; - case CV_LeafKind_ONEMETHOD: { - // parse CodeView method - CV_LeafOneMethod *one_method = (CV_LeafOneMethod *) (src.data.str + cursor); - CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(one_method->attribs); - cursor += sizeof(CV_LeafOneMethod); - U32 vftable_offset = 0; - if (prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { - str8_deserial_read_struct(src.data, cursor, &vftable_offset); - cursor += sizeof(vftable_offset); - } - String8 name = str8_cstring_capped(src.data.str + cursor, src.data.str + src.data.size); - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB member - member->kind = RDI_MemberKind_Method; - member->method.kind = lnk_rdib_method_kind_from_cv_prop(prop); - member->method.name = name; - member->method.type_ref = lnk_rdib_type_from_itype(task, one_method->itype); - member->method.vftable_offset = vftable_offset; - } break; - case CV_LeafKind_NESTTYPE: { - // parse CodeView nested type - CV_LeafNestType *nest_type = (CV_LeafNestType *) (src.data.str + cursor); - String8 name = str8_cstring_capped(nest_type + 1, src.data.str + src.data.size); - cursor += sizeof(CV_LeafNestType); - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB nested type member - member->kind = RDI_MemberKind_NestedType; - member->nested_type.name = name; - member->nested_type.type_ref = lnk_rdib_type_from_itype(task, nest_type->itype); - } break; - case CV_LeafKind_NESTTYPEEX: { - // parse CodeView nested type extended - CV_LeafNestTypeEx *nest_type_ex = (CV_LeafNestTypeEx *) (src.data.str + cursor); - String8 name = str8_cstring_capped(nest_type_ex + 1, src.data.str + src.data.size); - cursor += sizeof(CV_LeafNestTypeEx); - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB nested type member - member->kind = RDI_MemberKind_NestedType; - member->nested_type.name = name; - member->nested_type.type_ref = lnk_rdib_type_from_itype(task, nest_type_ex->itype); - } break; - case CV_LeafKind_BCLASS: { - // parse CodeView base class member - CV_LeafBClass *bclass = (CV_LeafBClass *) (src.data.str + cursor); - CV_NumericParsed offset = cv_numeric_from_data_range((U8 *)(bclass + 1), src.data.str + src.data.size); - cursor += sizeof(CV_LeafBClass); - cursor += offset.encoded_size; - - U64 offset64 = cv_u64_from_numeric(&offset); - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB base class member - member->kind = RDI_MemberKind_Base; - member->base_class.type_ref = lnk_rdib_type_from_itype(task, bclass->itype); - member->base_class.offset = offset64; - } break; - case CV_LeafKind_VBCLASS: - case CV_LeafKind_IVBCLASS: { - // parse CodeView virtual base class - CV_LeafVBClass *vbclass = (CV_LeafVBClass *) (src.data.str + cursor); - CV_NumericParsed vbptr_off = cv_numeric_from_data_range(src.data.str + cursor + sizeof(*vbclass), src.data.str + src.data.size); - CV_NumericParsed vtable_off = cv_numeric_from_data_range(src.data.str + cursor + sizeof(*vbclass) + vbptr_off.encoded_size, src.data.str + src.data.size); - cursor += sizeof(CV_LeafVBClass); - cursor += vbptr_off.encoded_size; - cursor += vtable_off.encoded_size; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB virtual base class member - member->kind = RDI_MemberKind_VirtualBase; - member->virtual_base_class.type_ref = lnk_rdib_type_from_itype(task, vbclass->itype); - member->virtual_base_class.vbptr_off = cv_u64_from_numeric(&vbptr_off); - member->virtual_base_class.vtable_off = cv_u64_from_numeric(&vtable_off); - } break; - case CV_LeafKind_VFUNCTAB: { - // parse CodeView virtual function table - CV_LeafVFuncTab *vfunc_tab = (CV_LeafVFuncTab *) (src.data.str + cursor); - cursor += sizeof(*vfunc_tab); - - // TODO: we don't have an equivalent in RDI - } break; - case CV_LeafKind_ENUMERATE: { - // parse CodeView enum member - CV_LeafEnumerate *enumerate = (CV_LeafEnumerate *) (src.data.str + cursor); - CV_NumericParsed value = cv_numeric_from_data_range((U8 *) (enumerate + 1), src.data.str + src.data.size); - String8 name = str8_cstring_capped(src.data.str + cursor + sizeof(CV_LeafEnumerate) + value.encoded_size, src.data.str + src.data.size); - cursor += sizeof(CV_LeafEnumerate); - cursor += value.encoded_size; - cursor += name.size + 1; - - // push new node - RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); - rdib_udt_member_list_push_node(&dst->members.list, member); - - // fill out RDIB enum member - member->kind = RDI_MemberKind_NULL; - member->enumerate.name = name; - member->enumerate.value = cv_u64_from_numeric(&value); - } break; - default: InvalidPath; - } - - cursor = AlignPow2(cursor, 4); - } - } break; - case CV_LeafKind_METHODLIST: { - // see CV_LeafKind_METHOD - } break; - case CV_LeafKind_LABEL: { - // ??? - } break; - case CV_LeafKind_VTSHAPE: { - RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); - dst->kind = RDI_TypeKindExt_VirtualTable; - // ??? - } break; - case CV_LeafKind_VFTABLE: { - // ??? - } break; - default: InvalidPath; break; - } - -#undef push_converted_type - } - ProfEnd(); -} - -internal U64 -lnk_src_file_hash_cv(String8 normal_full_path, CV_C13ChecksumKind checksum_kind, String8 checksum) -{ - XXH3_state_t state; - XXH3_INITSTATE(&state); - XXH3_64bits_reset(&state); - XXH3_64bits_update(&state, normal_full_path.str, normal_full_path.size); - XXH3_64bits_update(&state, &checksum_kind, sizeof(checksum_kind)); - XXH3_64bits_update(&state, checksum.str, checksum.size); - XXH64_hash_t result = XXH3_64bits_digest(&state); - return result; -} - -internal String8 -lnk_normalize_src_file_path(Arena *arena, String8 file_path) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 result = file_path; - result = lower_from_str8(scratch.arena, result); - result = path_convert_slashes(scratch.arena, result, PathStyle_UnixAbsolute); - result = push_str8_copy(arena, result); - scratch_end(scratch); - return result; -} - -internal LNK_SourceFileBucket * -lnk_src_file_hash_table_lookup_slot(LNK_SourceFileBucket **buckets, - U64 cap, - U64 hash, - String8 normal_path, - CV_C13ChecksumKind checksum_kind, - String8 checksum) -{ - U64 best_idx = hash % cap; - U64 bucket_idx = best_idx; - - RDIB_SourceFile temp = {0}; - temp.normal_full_path = normal_path; - temp.checksum_kind = checksum_kind; - temp.checksum = checksum; - - do { - if (buckets[bucket_idx] == 0) { - break; - } - if (rdib_source_file_match(buckets[bucket_idx]->src_file, &temp, OperatingSystem_CURRENT)) { - return buckets[bucket_idx]; - } - bucket_idx = (bucket_idx + 1) % cap; - } while (bucket_idx != best_idx); - - return 0; -} - - -internal LNK_SourceFileBucket * -lnk_src_file_insert_or_update(LNK_SourceFileBucket **buckets, U64 cap, U64 hash, LNK_SourceFileBucket *new_bucket) -{ - LNK_SourceFileBucket *result = 0; - - U64 best_idx = hash % cap; - U64 idx = best_idx; - do { - retry:; - LNK_SourceFileBucket *curr_bucket = buckets[idx]; - - if (curr_bucket == 0) { - LNK_SourceFileBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - // success, bucket was inserted - result = curr_bucket; - break; - } - - // another thread took the bucket... - goto retry; - } else if (rdib_source_file_match(curr_bucket->src_file, new_bucket->src_file, OperatingSystem_CURRENT)) { - // do we need to update value in the bucket? - int cmp = u64_compar(&curr_bucket->obj_idx, &new_bucket->obj_idx); - if (cmp <= 0) { - // are we inserting bucket that was already inserterd? - Assert(cmp < 0); - - // don't need to update, more recent value is in the bucket - break; - } - - LNK_SourceFileBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - // success, bucket was inserted - result = compare_bucket; - break; - } - - // another thread took the bucket... - goto retry; - } - - // advance - idx = (idx + 1); - idx = idx == cap ? 0 : idx; - } while (idx != best_idx); - - return result; -} - -internal -THREAD_POOL_TASK_FUNC(lnk_count_source_files_task) -{ - U64 unit_idx = task_id; - LNK_ConvertSourceFilesToRDITask *task = raw_task; - CV_DebugS debug_s = task->debug_s_arr[unit_idx]; - String8List raw_chksms_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); - - U64 count = 0; - - for (String8Node *raw_chksms_n = raw_chksms_list.first; raw_chksms_n != 0; raw_chksms_n = raw_chksms_n->next) { - for(U64 cursor = 0; cursor + sizeof(CV_C13Checksum) <= raw_chksms_n->string.size; ) { - // parse header - CV_C13Checksum *header = (CV_C13Checksum *) (raw_chksms_n->string.str + cursor); - - // update count - ++count; - - // advance cursor - cursor += sizeof(*header); - cursor += header->len; - cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); - } - } - - // update total count - ins_atomic_u64_add_eval(&task->total_src_file_count, count); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_insert_src_files_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - U64 obj_idx = task_id; - LNK_ConvertSourceFilesToRDITask *task = raw_task; - CV_DebugS debug_s = task->debug_s_arr[obj_idx]; - String8List raw_chksms_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); - String8List raw_strtab_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_StringTable); - - if (raw_strtab_list.node_count > 1) { - lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Multiple string table sub-sections, picking first one."); - } - if (raw_chksms_list.node_count > 1) { - lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Multiple file checksum sub-sections, picking first one."); - } - - String8 string_table = cv_string_table_from_debug_s(debug_s); - LNK_SourceFileBucket *curr_bucket = 0; - - for (String8Node *raw_chksms_n = raw_chksms_list.first; raw_chksms_n != 0; raw_chksms_n = raw_chksms_n->next) { - for (U64 cursor = 0; cursor + sizeof(CV_C13Checksum) <= raw_chksms_n->string.size; ) { - // parse header - CV_C13Checksum *header = (CV_C13Checksum *) (raw_chksms_n->string.str + cursor); - - // grab checksum - String8 checksum = str8_substr(raw_chksms_n->string, rng_1u64(cursor + sizeof(CV_C13Checksum), - cursor + sizeof(CV_C13Checksum) + header->len)); - - // grab file path - Assert(header->name_off < string_table.size); - String8 file_path = str8_cstring_capped(string_table.str + header->name_off, string_table.str + string_table.size); - - // normalize file path - String8 normal_path = lnk_normalize_src_file_path(arena, file_path); - - // push new bucket - if (curr_bucket == 0) { - curr_bucket = push_array(arena, LNK_SourceFileBucket, 1); - curr_bucket->src_file = push_array(arena, RDIB_SourceFile, 1); - } - - // fill out obj idx so we can decide which source file to keep in the hash table - curr_bucket->obj_idx = obj_idx; - - // fill out part with source file info - curr_bucket->src_file->file_path = file_path; - curr_bucket->src_file->normal_full_path = normal_path; - curr_bucket->src_file->checksum_kind = rdi_checksum_from_cv_c13(header->kind); - curr_bucket->src_file->checksum = checksum; - curr_bucket->src_file->line_table_frags = 0; - - // insert bucket - U64 normal_path_hash = lnk_src_file_hash_cv(normal_path, header->kind, checksum); - LNK_SourceFileBucket *insert_result = lnk_src_file_insert_or_update(task->src_file_buckets, task->src_file_buckets_cap, normal_path_hash, curr_bucket); - - if (curr_bucket == insert_result) { - // bucket was inserted into empty slot, reset current bucket - curr_bucket = 0; - } else if (curr_bucket != insert_result) { - // reuse evicted bucket - curr_bucket = insert_result; - } - - // advance cursor - cursor += sizeof(*header); - cursor += header->len; - cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); - } - } - - scratch_end(scratch); - ProfEnd(); -} - -internal RDIB_Type * -lnk_find_container_type(String8 name, Rng1U64 tpi_itype_range, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap, RDIB_Type **tpi_itype_map) -{ - CV_TypeIndex container_itype = 0; - - String8 delim = str8_lit("::"); - U64 delim_pos = str8_find_needle_reverse(name, 0, delim, 0); - if (delim_pos > 0) { - U64 container_name_size = delim_pos - delim.size; - String8 container_name = str8_prefix(name, container_name_size); - container_itype = lnk_udt_name_hash_table_lookup_itype(udt_name_buckets, udt_name_buckets_cap, container_name); - } - - RDIB_Type *container = 0; - if (container_itype > 0) { - Assert(container_itype < tpi_itype_range.max); - container = tpi_itype_map[container_itype]; - } - - return container; -} - -internal RDIB_Type * -lnk_type_from_itype(CV_TypeIndex itype, Rng1U64 tpi_itype_range, RDIB_Type **tpi_itype_map, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) -{ - RDIB_Type *type = 0; - if (itype < tpi_itype_range.max) { - type = tpi_itype_map[itype]; - } else { - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds type index 0x%x in S_%S @ 0x%llx.", - itype, cv_string_from_sym_kind(symbol_kind), symbol_offset); - } - return type; -} - -internal U64 -lnk_voff_from_sect_off(U64 sect_idx, U64 sect_off, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) -{ - U64 voff = 0; - if (sect_idx < image_sects.count) { - voff = image_sects.v[sect_idx].voff + sect_off; - } else { - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", - sect_idx, cv_string_from_sym_kind(symbol_kind), symbol_offset); - } - return voff; -} - -internal Rng1U64 -lnk_virt_range_from_sect_off_size(U64 sect_idx, U64 sect_off, U64 size, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) -{ - Rng1U64 virt_range = {0}; - if (sect_idx < image_sects.count) { - U64 voff = image_sects.v[sect_idx].voff + sect_off; - virt_range = rng_1u64(voff, voff + size); - } else { - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", - sect_idx, cv_string_from_sym_kind(symbol_kind), symbol_offset); - } - return virt_range; -} - -internal void -lnk_error_on_invalid_defrange_symbol(LNK_Obj *obj, CV_Symbol symbol) -{ - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Unable to parse symbol stream, unexpected S_%S without preceding S_LOCAL @ 0x%llx.", - cv_string_from_sym_kind(symbol.kind), symbol.offset); -} - -internal void -lnk_error_on_missing_cv_frameproc(LNK_Obj *obj, CV_Symbol symbol) -{ - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Missing S_FRAMEPROC, unable to parse S_%S @ 0x%llx.", - cv_string_from_sym_kind(symbol.kind), symbol.offset); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_find_obj_compiler_info_task) -{ - ProfBeginFunction(); - - LNK_ConvertUnitToRDITask *task = raw_task; - LNK_CodeViewCompilerInfo *comp_info = &task->comp_info_arr[task_id]; - - comp_info->arch = (CV_Arch)~0u; - comp_info->language = (CV_Language)~0u; - comp_info->compiler_name = str8_zero(); - - String8List symbols = cv_sub_section_from_debug_s(task->debug_s_arr[task_id], CV_C13SubSectionKind_Symbols); - - // infer unit compiler data from S_COMPILE* which always follows S_OBJ - for EachNode(n, String8Node, symbols.first) { - for (U64 cursor = 0; cursor < n->string.size; ) { - CV_Symbol symbol = {0}; NotImplemented; // TODO: @symbol_pass - if (symbol.kind == CV_SymKind_COMPILE) { - AssertAlways(sizeof(CV_SymCompile) <= symbol.data.size); - CV_SymCompile *compile = (CV_SymCompile *)symbol.data.str; - comp_info->arch = compile->machine; - comp_info->language = CV_CompileFlags_Extract_Language(compile->flags); - comp_info->compiler_name = str8_cstring_capped(compile + 1, symbol.data.str + symbol.data.size); - goto exit; - } else if (symbol.kind == CV_SymKind_COMPILE2) { - AssertAlways(sizeof(CV_SymCompile2) <= symbol.data.size); - CV_SymCompile2 *compile2 = (CV_SymCompile2 *)symbol.data.str; - comp_info->arch = compile2->machine; - comp_info->language = CV_Compile2Flags_Extract_Language(compile2->flags); - comp_info->compiler_name = str8_cstring_capped(compile2 + 1, symbol.data.str + symbol.data.size); - goto exit; - } else if (symbol.kind == CV_SymKind_COMPILE3) { - AssertAlways(sizeof(CV_SymCompile3) <= symbol.data.size); - CV_SymCompile3 *compile3 = (CV_SymCompile3 *)symbol.data.str; - comp_info->arch = compile3->machine; - comp_info->language = CV_Compile3Flags_Extract_Language(compile3->flags); - comp_info->compiler_name = str8_cstring_capped(compile3 + 1, symbol.data.str + symbol.data.size); - goto exit; - } - } - } - exit:; - - LNK_Obj *obj = task->obj_arr[task_id]; - - // fill out unit info - U64 unit_chunk_idx = task_id / task->unit_chunk_cap; - U64 local_unit_idx = task_id - unit_chunk_idx * task->unit_chunk_cap; - - RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; - dst->arch = rdi_arch_from_cv_arch(comp_info->arch); - dst->unit_name = str8_skip_last_slash(obj->path); - dst->compiler_name = comp_info->compiler_name; - dst->source_file = str8_zero(); - dst->object_file = push_str8_copy(arena, obj->path); - dst->archive_file = lnk_obj_get_lib_path(obj); - dst->build_path = str8_zero(); - dst->language = rdi_language_from_cv_language(comp_info->language); - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_convert_line_tables_to_rdi_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - U64 unit_idx = task_id; - LNK_ConvertUnitToRDITask *task = raw_task; - LNK_Obj *obj = task->obj_arr[unit_idx]; - CV_DebugS debug_s = task->debug_s_arr[unit_idx]; - - U64 unit_chunk_idx = unit_idx / task->unit_chunk_cap; - U64 local_unit_idx = unit_idx - unit_chunk_idx * task->unit_chunk_cap; - RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; - - // find sub sections - String8 raw_string_table = cv_string_table_from_debug_s(debug_s); - String8 raw_file_chksms = cv_file_chksms_from_debug_s(debug_s); - String8List raw_lines_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); - - // emit line table fragments for each source file from C13 line info - dst->line_table = rdib_line_table_chunk_list_push(arena, &task->line_tables[worker_id], task->line_table_cap); - - for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { - String8 raw_lines = raw_lines_node->string; - CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(scratch.arena, raw_lines, rng_1u64(0, raw_lines.size)); - for (CV_C13LinesHeaderNode *lines_node = parsed_list.first; lines_node != 0; lines_node = lines_node->next) { - CV_C13LinesHeader parsed_lines = lines_node->v; - - // parse checksum header - if (parsed_lines.file_off + sizeof(CV_C13Checksum) > raw_file_chksms.size) { - lnk_error_obj(LNK_Warning_IllData, obj, "Out of bounds $$FILE_CHECKSUM offset (0x%llx) in line table header.", parsed_lines.file_off); - continue; - } - CV_C13Checksum *checksum_header = (CV_C13Checksum *) (raw_file_chksms.str + parsed_lines.file_off); - if (parsed_lines.file_off + sizeof(CV_C13Checksum) + checksum_header->len > raw_file_chksms.size) { - lnk_error_obj(LNK_Warning_IllData, obj, "Not enough bytes to read file checksum @ 0x%llx.", parsed_lines.file_off); - continue; - } - String8 file_path = str8_cstring_capped(raw_string_table.str + checksum_header->name_off, raw_string_table.str + raw_string_table.size); - String8 checksum_bytes = str8((U8 *) (checksum_header + 1), checksum_header->len); - - // read out lines - if (0 == parsed_lines.sec_idx || parsed_lines.sec_idx > task->image_sects.count) { - lnk_error_obj(LNK_Warning_IllData, obj, "Out of bounds section index (%u) in $$LINES; skip line info for \"%S\".", parsed_lines.sec_idx, file_path); - continue; - } - COFF_SectionHeader *sect = &task->image_sects.v[parsed_lines.sec_idx]; - CV_LineArray lines = cv_c13_line_array_from_data(arena, raw_lines, sect->voff, parsed_lines); - - // find source file for this line table - String8 normal_path = lnk_normalize_src_file_path(scratch.arena, file_path); - U64 src_file_hash = lnk_src_file_hash_cv(normal_path, checksum_header->kind, checksum_bytes); - LNK_SourceFileBucket *src_file_bucket = lnk_src_file_hash_table_lookup_slot(task->src_file_buckets, task->src_file_buckets_cap, src_file_hash, normal_path, checksum_header->kind, checksum_bytes); - if (src_file_bucket == 0) { - lnk_error_obj(LNK_Error_UnexpectedCodePath, obj, "Unable to find source file in the hash table: \"%S\".", file_path); - continue; - } - RDIB_SourceFile *src_file = src_file_bucket->src_file; - - // fill out line table fragment and atomically insert - RDIB_LineTableFragment *frag = rdib_line_table_push(arena, dst->line_table); - frag->src_file = src_file; - frag->voffs = lines.voffs; - frag->line_nums = lines.line_nums; - frag->col_nums = lines.col_nums; - frag->line_count = lines.line_count; - frag->col_count = lines.col_count; - - // build list of line table fragments per file - frag->next_src_file = ins_atomic_ptr_eval_assign(&src_file->line_table_frags, frag); - } - } - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_build_inlinee_lines_accels_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - LNK_ConvertUnitToRDITask *task = raw_task; - CV_DebugS debug_s = task->debug_s_arr[task_id]; - - String8List raw_inlinee_lines = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_InlineeLines); - CV_C13InlineeLinesParsedList inlinee_lines = cv_c13_inlinee_lines_from_sub_sections(arena, raw_inlinee_lines); - CV_InlineeLinesAccel *inlinee_lines_accel = cv_c13_make_inlinee_lines_accel(arena, inlinee_lines); - - task->inlinee_lines_accel_arr[task_id] = inlinee_lines_accel; - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_convert_symbols_to_rdi_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - LNK_ConvertUnitToRDITask *task = raw_task; - LNK_SymbolInput symbols_input = task->symbol_inputs[task_id]; - LNK_Obj *obj = task->obj_arr[symbols_input.obj_idx]; - LNK_CodeViewCompilerInfo comp_info = task->comp_info_arr[symbols_input.obj_idx]; - CV_InlineeLinesAccel *inlinee_lines_accel = task->inlinee_lines_accel_arr[symbols_input.obj_idx]; - - RDI_Arch arch_rdi = rdi_arch_from_cv_arch(comp_info.arch); - - struct ScopeFrame { - struct ScopeFrame *prev; - RDIB_Scope *scope; - RDIB_Procedure *proc; - CV_ProcFlags proc_flags; - CV_SymFrameproc *frameproc; - U64 param_count; - U64 regrel32_idx; - RDIB_Variable *defrange_target; - }; -#define push_scope_frame() do { \ - struct ScopeFrame *frame; \ - if (free_scope_stack != 0) { \ - frame = free_scope_stack; \ - SLLStackPop_N(free_scope_stack, prev); \ - } else { \ - frame = push_array(scratch.arena, struct ScopeFrame, 1); \ - } \ - SLLStackPush_N(scope_stack, frame, prev); \ -} while (0) - - struct ScopeFrame *scope_stack = 0; - struct ScopeFrame *free_scope_stack = 0; - - // root frame - push_scope_frame(); - - for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= symbols_input.raw_symbols.size; ) { - CV_Symbol symbol = {0}; - TryReadBreak(cv_read_symbol(symbols_input.raw_symbols, cursor, CV_SymbolAlign, &symbol), cursor); - - switch (symbol.kind) { - case CV_SymKind_COMPILE: - case CV_SymKind_COMPILE2: - case CV_SymKind_COMPILE3: { - // handled above - } break; - case CV_SymKind_INLINESITE_END: - case CV_SymKind_END: { - if (scope_stack != 0) { - // move top frame to free stack - struct ScopeFrame *free_frame = scope_stack; - SLLStackPop_N(scope_stack, prev); - SLLStackPush_N(free_scope_stack, free_frame, prev); - } else { - lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Encountered unbalanced blocks. Unable to finish symbol parse."); - goto exit; - } - } break; - case CV_SymKind_BLOCK32: { - CV_SymBlock32 *block32 = (CV_SymBlock32 *) symbol.data.str; - Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(block32->sec, block32->off, block32->len, task->image_sects, obj, symbol.kind, symbol.offset); - - // push new scope node - RDIB_Scope *scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); - - // fill out scope - scope->container_proc = scope_stack->proc; - scope->parent = scope_stack->scope; - SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, scope, next_sibling); - rng1u64_list_push(arena, &scope->ranges, virt_range); - -#if 0 - if (scope->parent) { - Assert(virt_range.min >= scope->parent->ranges.first->v.min); - Assert(virt_range.max <= scope->parent->ranges.first->v.max); - } -#endif - - // push new scope stack frame - push_scope_frame(); - scope_stack->scope = scope; - scope_stack->proc = scope->container_proc; - scope_stack->proc_flags = scope_stack->proc_flags; - scope_stack->frameproc = scope_stack->prev->frameproc; - } break; - case CV_SymKind_GDATA32: - case CV_SymKind_LDATA32: { - CV_SymData32 *data32 = (CV_SymData32 *) symbol.data.str; - String8 name = str8_cstring_capped(data32 + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(data32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - RDIB_Type *container_type = lnk_find_container_type(name, task->tpi_itype_range, task->udt_name_buckets, task->udt_name_buckets_cap, task->tpi_itype_map); - U64 data_voff = lnk_voff_from_sect_off(data32->sec, data32->off, task->image_sects, obj, symbol.kind, symbol.offset); - - B32 is_comp_gen = symbol.kind == CV_SymKind_LDATA32 && name.size == 0 && type == 0; - if (!is_comp_gen) { - - // get link name through virtual offset look up - String8 link_name = {0}; - if (symbol.kind == CV_SymKind_GDATA32) { - BucketNode *pair = hash_table_search_u64(task->extern_symbol_voff_ht, data_voff); - if (pair != 0) { - LNK_Symbol *link_symbol = pair->v.value_raw; - link_name = link_symbol->name; - } - } - - // make module relative location - RDIB_LocationList locations = {0}; - { - RDIB_EvalBytecode bytecode = {0}; - rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_ModuleOff, data_voff); - - U64 data_size = rdib_size_from_type(type); - if (data_size == 0) { - data_size = max_U64; - } - - Rng1U64List ranges = {0}; - rng1u64_list_push(arena, &ranges, rng_1u64(data_voff, data_voff + data_size)); - - RDIB_Location location = rdib_make_location_addr_byte_stream(ranges, bytecode); - rdib_location_list_push(arena, &locations, location); - } - - RDIB_VariableChunkList *var_chunk_list = symbol.kind == CV_SymKind_GDATA32 ? - &task->extern_gvars[worker_id] : &task->static_gvars[worker_id]; - - // push new node - RDIB_Variable *gvar = rdib_variable_chunk_list_push(arena, var_chunk_list, task->symbol_chunk_cap); - gvar->name = name; - gvar->link_name = link_name; - gvar->type = type; - gvar->container_type = container_type; - gvar->container_proc = scope_stack->proc; - gvar->locations = locations; - } - } break; - case CV_SymKind_LTHREAD32: - case CV_SymKind_GTHREAD32: { - CV_SymThread32 *thread32 = (CV_SymThread32 *) symbol.data.str; - String8 name = str8_cstring_capped(thread32 + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(thread32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - RDIB_Type *container_type = lnk_find_container_type(name, task->tpi_itype_range, task->udt_name_buckets, task->udt_name_buckets_cap, task->tpi_itype_map); - - // make TLS offset location - RDIB_LocationList locations = {0}; - { - RDIB_EvalBytecode bytecode = {0}; - rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_TLSOff, thread32->tls_off); - - Rng1U64List ranges = {0}; - rng1u64_list_push(arena, &ranges, rng_1u64(0, max_U64)); - - RDIB_Location location = rdib_make_location_addr_byte_stream(ranges, bytecode); - rdib_location_list_push(arena, &locations, location); - } - - // push new node - RDIB_VariableChunkList *tvar_list = symbol.kind == CV_SymKind_GTHREAD32 ? &task->extern_tvars[worker_id] : &task->static_tvars[worker_id]; - RDIB_Variable *tvar = rdib_variable_chunk_list_push(arena, tvar_list, task->symbol_chunk_cap); - - // fill out thread variable - tvar->name = name; - tvar->link_name = str8(0,0); - tvar->type = type; - tvar->container_type = container_type; - tvar->container_proc = scope_stack->proc; - tvar->locations = locations; - } break; - case CV_SymKind_LPROC32_ID: - case CV_SymKind_GPROC32_ID: { - AssertAlways(!"linker converts *_ID symbols in post-process step, if we ever get to this case then we have a bug in post-process step"); - } break; - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: { - CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol.data.str; - String8 name = str8_cstring_capped(proc32 + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(proc32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(proc32->sec, proc32->off, proc32->len, task->image_sects, obj, symbol.kind, symbol.offset); - - // infer container type for method - RDIB_Type *container_type = 0; - if (type != 0) { - if (type->kind == RDI_TypeKind_Method) { - container_type = (RDIB_Type *) type->method.class_type; - } else if (type->kind == RDI_TypeKindExt_StaticMethod) { - container_type = (RDIB_Type *) type->static_method.class_type; - } - } - - // get link name through virtual offset look up - String8 link_name = str8(0,0); - if (symbol.kind == CV_SymKind_GPROC32) { - LNK_Symbol *link_symbol = hash_table_search_u64_raw(task->extern_symbol_voff_ht, virt_range.min); - if (link_symbol) { - link_name = link_symbol->name; - } - } - - // scan ahead for context S_FRAMEPROC (must be defined in scope of PROC symbol) - CV_SymFrameproc *frameproc = 0; - { - U64 depth = 1; - for (U64 lookahead_off = cursor; lookahead_off + sizeof(CV_SymbolHeader) <= symbols_input.raw_symbols.size; ) { - CV_Symbol lookahead = {0}; - TryReadBreak(cv_read_symbol(symbols_input.raw_symbols, lookahead_off, CV_SymbolAlign, &lookahead), lookahead_off); - - if (lookahead.kind == CV_SymKind_FRAMEPROC) { - frameproc = str8_deserial_get_raw_ptr(lookahead.data, 0, sizeof(*frameproc)); - break; - } - if (cv_is_scope_symbol(lookahead.kind)) { - ++depth; - } else if (cv_is_end_symbol(lookahead.kind)) { - --depth; - if (depth == 0) { - break; - } - } - } - } - - // push new procedure node - RDIB_ProcedureChunkList *proc_list = symbol.kind == CV_SymKind_GPROC32 ? &task->extern_procs[worker_id] : &task->static_procs[worker_id]; - RDIB_Procedure *proc = rdib_procedure_chunk_list_push(arena, proc_list, task->symbol_chunk_cap); - - // push new scope node - RDIB_Scope *root_scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); - root_scope->container_proc = proc; - root_scope->parent = scope_stack->scope; - if (scope_stack->scope != 0) { - SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, root_scope, next_sibling); - } - rng1u64_list_push(arena, &root_scope->ranges, virt_range); - - // fill out procedure - proc->name = name; - proc->link_name = link_name; - proc->type = type; - proc->container_type = container_type; - proc->container_proc = scope_stack->proc; - proc->scope = root_scope; - - // push scope frame - push_scope_frame(); - scope_stack->scope = root_scope; - scope_stack->proc = proc; - scope_stack->proc_flags = proc32->flags; - scope_stack->frameproc = frameproc; - - // set number of params for procedure on scope so we can figure out which S_REGREL32 is param - { - B32 is_proc_scope = (scope_stack->proc->scope == scope_stack->scope); - if (is_proc_scope) { - RDIB_Type *params = 0; - if (scope_stack->proc != 0) { - RDIB_Type *proc_type = scope_stack->proc->type; - if (proc_type != 0) { - if (proc_type->kind == RDI_TypeKind_NULL) { - // compiler generates procedures with no type for __try/__except, lambdas, and etc. - } else if (proc_type->kind == RDI_TypeKind_Function) { - params = (RDIB_Type *)proc_type->func.params_type; - } else if (proc_type->kind == RDI_TypeKind_Method) { - params = (RDIB_Type *)proc_type->method.params_type; - } else if (proc_type->kind == RDI_TypeKindExt_StaticMethod) { - params = (RDIB_Type *)proc_type->static_method.params_type; - } else { - InvalidPath; - } - } - } - if (params != 0) { - AssertAlways(params->kind == RDI_TypeKindExt_Params); - scope_stack->param_count = params->params.count; - scope_stack->regrel32_idx = 0; - } - } - } - } break; - case CV_SymKind_THUNK32: { - CV_SymThunk32 *thunk32 = (CV_SymThunk32 *) symbol.data.str; - String8 name = str8_cstring_capped(thunk32 + 1, symbol.data.str + symbol.data.size); - Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(thunk32->sec, thunk32->off, thunk32->len, task->image_sects, obj, symbol.kind, symbol.offset); - - // scan ahead for context S_FRAMEPROC (must be defined in scope of PROC symbol) - CV_SymFrameproc *frameproc = 0; - { - U64 depth = 1; - for (U64 lookahead_off = cursor; lookahead_off + sizeof(CV_SymbolHeader) <= symbols_input.raw_symbols.size; ) { - CV_Symbol lookahead = {0}; - TryReadBreak(cv_read_symbol(symbols_input.raw_symbols, lookahead_off, CV_SymbolAlign, &lookahead), lookahead_off); - - if (lookahead.kind == CV_SymKind_FRAMEPROC) { - frameproc = str8_deserial_get_raw_ptr(lookahead.data, 0, sizeof(*frameproc)); - break; - } - if (cv_is_scope_symbol(lookahead.kind)) { - ++depth; - } else if (cv_is_end_symbol(lookahead.kind)) { - --depth; - if (depth == 0) { - break; - } - } - } - } - - // push new procedure node - RDIB_ProcedureChunkList *proc_list = &task->static_procs[worker_id]; - RDIB_Procedure *thunk = rdib_procedure_chunk_list_push(arena, proc_list, task->symbol_chunk_cap); - - // push new scope node - RDIB_Scope *root_scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); - root_scope->container_proc = thunk; - root_scope->parent = scope_stack->scope; - if (scope_stack->scope != 0) { - SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, root_scope, next_sibling); - } - rng1u64_list_push(arena, &root_scope->ranges, virt_range); - - // fill out procedure - thunk->name = name; - thunk->type = 0; - thunk->scope = root_scope; - - // push scope frame - push_scope_frame(); - scope_stack->scope = root_scope; - scope_stack->proc = thunk; - scope_stack->proc_flags = 0; - scope_stack->frameproc = frameproc; - } break; - case CV_SymKind_REGREL32: { - if (~scope_stack->proc_flags & CV_ProcFlag_OptDbgInfo) { - CV_SymRegrel32 *regrel32 = (CV_SymRegrel32 *) symbol.data.str; - String8 name = str8_cstring_capped(regrel32 + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(regrel32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - - B32 is_ref = 0; - if (scope_stack->regrel32_idx < scope_stack->param_count) { - if (type != 0) { - U64 byte_size = rdib_size_from_type(type); - switch (comp_info.arch) { - case CV_Arch_8086: is_ref = byte_size > 4 || !IsPow2OrZero(byte_size); break; - case CV_Arch_X64: is_ref = byte_size > 8 || !IsPow2OrZero(byte_size); break; - default: NotImplemented; - } - } - } - - // push node - RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); - SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); - ++scope_stack->scope->local_count; - - // fill out local - local->name = name; - local->type = type; - - // encode location - RDI_RegCode reg_code = rdi_reg_code_from_cv(comp_info.arch, regrel32->reg); - U32 value_size = 8; - U32 value_pos = 0; - rdib_push_location_addr_reg_off(arena, &local->locations, arch_rdi, reg_code, value_size, value_pos, (S64)regrel32->reg_off, is_ref, scope_stack->scope->ranges); - - // advance reg rel index - ++scope_stack->regrel32_idx; - } - } break; - case CV_SymKind_LOCAL: { - CV_SymLocal *sym_local = (CV_SymLocal *) symbol.data.str; - String8 name = str8_cstring_capped(sym_local + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(sym_local->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - - // reset defrange target - scope_stack->defrange_target = 0; - - if (sym_local->flags & CV_LocalFlag_Global) { - // TODO: apply global modifications - } else if (sym_local->flags & CV_LocalFlag_Static) { - // TODO: apply local modifications - } - - // push New node - RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); - SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); - ++scope_stack->scope->local_count; - - // fill out local - local->name = name; - local->type = type; - - scope_stack->defrange_target = local; - } break; - case CV_SymKind_FILESTATIC: { - CV_SymFileStatic *file_static = (CV_SymFileStatic *) symbol.data.str; - String8 name = str8_cstring_capped(file_static + 1, symbol.data.str + symbol.data.size); - RDIB_Type *type = lnk_type_from_itype(file_static->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - - // push New node - RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); - SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); - ++scope_stack->scope->local_count; - - // fill out local - local->name = name; - local->type = type; - - // set target for following defrange modifications - scope_stack->defrange_target = local; - } break; - case CV_SymKind_DEFRANGE_REGISTER: { - if (scope_stack->defrange_target == 0) { - lnk_error_on_invalid_defrange_symbol(obj, symbol); - break; - } - - CV_SymDefrangeRegister *defrange_reg = (CV_SymDefrangeRegister *) symbol.data.str; - RDI_RegCode reg_code = rdi_reg_code_from_cv(comp_info.arch, defrange_reg->reg); - CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_reg + 1); - U64 gap_count = (symbol.data.size - sizeof(*defrange_reg)) / sizeof(*gaps); - - Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_reg->range.sec, defrange_reg->range.off, defrange_reg->range.len, task->image_sects, obj, symbol.kind, symbol.offset); - Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); - RDIB_Location location = rdib_make_location_val_reg(ranges, reg_code); - - rdib_location_list_push(arena, &scope_stack->defrange_target->locations, location); - } break; - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: { - if (scope_stack->defrange_target == 0) { - lnk_error_on_invalid_defrange_symbol(obj, symbol); - break; - } - if (scope_stack->frameproc == 0) { - lnk_error_on_missing_cv_frameproc(obj, symbol); - break; - } - - CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel *)symbol.data.str; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_fprel + 1); - U64 gap_count = (symbol.data.size - sizeof(*defrange_fprel)) / sizeof(gaps[0]); - - B32 is_local_param = 0; - CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(scope_stack->frameproc, is_local_param); - CV_Reg fp_reg = cv_decode_fp_reg(comp_info.arch, encoded_fp_reg); - RDI_RegCode fp_reg_rdi = rdi_reg_code_from_cv(comp_info.arch, fp_reg); - Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_fprel->range.sec, defrange_fprel->range.off, defrange_fprel->range.len, task->image_sects, obj, symbol.kind, symbol.offset); - Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); - U32 value_pos = 0; - U32 value_size = rdi_addr_size_from_arch(arch_rdi); - - rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, fp_reg_rdi, value_size, value_pos, (S64)defrange_fprel->off, 0, ranges); - } break; - case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: { - if (scope_stack->defrange_target == 0) { - lnk_error_on_invalid_defrange_symbol(obj, symbol); - break; - } - - CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister *) symbol.data.str; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_subfield_register + 1); - U64 gap_count = (symbol.data.size - sizeof(*defrange_subfield_register)) / sizeof(gaps[0]); - RDI_RegCode reg_rdi = rdi_reg_code_from_cv(comp_info.arch, defrange_subfield_register->reg); - U32 value_pos = CV_DefrangeSubfieldRegister_Extract_ParentOffset(defrange_subfield_register->field_offset); - U32 value_size = cv_size_from_reg(comp_info.arch, defrange_subfield_register->reg) - value_pos; - Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_subfield_register->range.sec, defrange_subfield_register->range.off, defrange_subfield_register->range.len, task->image_sects, obj, symbol.kind, symbol.offset); - Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); - - rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, reg_rdi, value_size, value_pos, 0, 0, ranges); - } break; - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { - if (scope_stack->defrange_target == 0) { - lnk_error_on_invalid_defrange_symbol(obj, symbol); - break; - } - if (scope_stack->frameproc == 0) { - lnk_error_on_missing_cv_frameproc(obj, symbol); - break; - } - - CV_SymDefrangeFramepointerRelFullScope *defrange_fprelfs = (CV_SymDefrangeFramepointerRelFullScope *) symbol.data.str; - B32 is_local_param = 0; //scope_stack->defrange_target->kind == RDI_LocalKind_Parameter; - CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(scope_stack->frameproc, is_local_param); - CV_Reg fp_reg = cv_decode_fp_reg(comp_info.arch, encoded_fp_reg); - RDI_RegCode fp_reg_rdi = rdi_reg_code_from_cv(comp_info.arch, fp_reg); - U32 value_size = cv_size_from_reg(comp_info.arch, fp_reg); - U32 value_pos = 0; - Rng1U64List ranges = scope_stack->scope->ranges; // variable is available everywhere in the scope - - rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, fp_reg_rdi, value_size, value_pos, (S64)defrange_fprelfs->off, 0, ranges); - } break; - case CV_SymKind_DEFRANGE_REGISTER_REL: { - if (scope_stack->defrange_target == 0) { - lnk_error_on_invalid_defrange_symbol(obj, symbol); - break; - } - - CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel *) symbol.data.str; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_register_rel + 1); - U64 gap_count = (symbol.data.size - sizeof(*defrange_register_rel)) / sizeof(gaps[0]); - RDI_RegCode reg_rdi = rdi_reg_code_from_cv(comp_info.arch, defrange_register_rel->reg); - U64 value_size = cv_size_from_reg(comp_info.arch, defrange_register_rel->reg); - U64 value_pos = 0; - Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_register_rel->range.sec, defrange_register_rel->range.off, defrange_register_rel->range.len, task->image_sects, obj, symbol.kind, symbol.offset); - Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); - - rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, reg_rdi, value_size, value_pos, (S64)defrange_register_rel->reg_off, 0, ranges); - } break; - case CV_SymKind_INLINESITE: { - CV_SymInlineSite *sym_inline_site = (CV_SymInlineSite *) symbol.data.str; - String8 binary_annots = str8_skip(symbol.data, sizeof(*sym_inline_site)); - - U64 parent_voff = 0; - if (scope_stack != 0) { - RDIB_Scope *proc_scope = scope_stack->proc->scope; - Assert(proc_scope->ranges.count == 1); - Rng1U64 scope_vrange = proc_scope->ranges.first->v; - parent_voff = scope_vrange.min; - } else { - Assert(!"S_INLINESITE doesn't have a parent procedure symbol"); - } - - // parse binary annots - CV_C13InlineeLinesParsed *inlinee_parsed = cv_c13_inlinee_lines_accel_find(inlinee_lines_accel, sym_inline_site->inlinee); - CV_InlineBinaryAnnotsParsed binary_annots_parsed = cv_c13_parse_inline_binary_annots(arena, parent_voff, inlinee_parsed, binary_annots); - - String8 name = str8_zero(); - RDIB_Type *type = 0; - RDIB_Type *owner = 0; - if (task->ipi_itype_range.min <= sym_inline_site->inlinee && sym_inline_site->inlinee < task->ipi_itype_range.max) { - U64 leaf_idx = sym_inline_site->inlinee - task->tpi_itype_range.min; - CV_Leaf leaf = cv_leaf_from_ptr(task->leaf_arr_ipi[leaf_idx]); - if (leaf.kind == CV_LeafKind_MFUNC_ID) { - if (sizeof(CV_LeafMFuncId) <= leaf.data.size) { - CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId *) leaf.data.str; - name = str8_cstring_capped_reverse(mfunc_id + 1, leaf.data.str + leaf.data.size); - type = lnk_type_from_itype(mfunc_id->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - owner = lnk_type_from_itype(mfunc_id->owner_itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - } else { - Assert(!"invalid leaf size"); - } - } else if (leaf.kind == CV_LeafKind_FUNC_ID) { - if (sizeof(CV_LeafFuncId) <= leaf.data.size) { - CV_LeafFuncId *func_id = (CV_LeafFuncId *) leaf.data.str; - name = str8_cstring_capped_reverse(func_id + 1, leaf.data.str + leaf.data.size); - type = lnk_type_from_itype(func_id->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - owner = lnk_type_from_itype(func_id->scope_string_id, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); - } else { - Assert(!"invalid leaf size"); - } - } else { - Assert(!"inlinee must pointer to LF_FUNC_ID or LF_MFUNC_ID"); - } - } else { - Assert(!"out of bounds inlinee"); - } - - // fill out inline site - RDIB_InlineSite *inline_site = rdib_inline_site_chunk_list_push(arena, &task->inline_sites[worker_id], task->inline_site_cap); - inline_site->name = name; - inline_site->type = type; - inline_site->owner = owner; - - inline_site->convert_ref.ud0 = binary_annots_parsed.lines; - inline_site->convert_ref.ud1 = binary_annots_parsed.lines_count; - inline_site->convert_ref.ud2 = symbols_input.obj_idx; - - // fill out scope - RDIB_Scope *scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); - scope->container_proc = scope_stack->proc; - scope->parent = scope_stack->scope; - scope->inline_site = inline_site; - scope->ranges = binary_annots_parsed.code_ranges; - - // push new scope stack frame - push_scope_frame(); - scope_stack->scope = scope; - scope_stack->proc = scope->container_proc; - scope_stack->proc_flags = scope_stack->proc_flags; - scope_stack->frameproc = scope_stack->prev->frameproc; - } break; - default: break; - } - } - exit:; - -#undef push_scope_frame - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_convert_inline_site_line_tables_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - LNK_ConvertUnitToRDITask *task = raw_task; - RDIB_InlineSiteChunk *chunk = task->inline_site_chunks[task_id]; - - RDIB_LineTableFragmentChunkList frag_chunk_list = {0}; - - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_InlineSite *inline_site = &chunk->v[i]; - - CV_LineArray *lines_arr = inline_site->convert_ref.ud0; - U64 lines_count = inline_site->convert_ref.ud1; - U64 obj_idx = inline_site->convert_ref.ud2; - - CV_DebugS debug_s = task->debug_s_arr[obj_idx]; - String8 raw_string_table = cv_string_table_from_debug_s(debug_s); - String8 raw_file_chksms = cv_file_chksms_from_debug_s(debug_s); - - if (lines_count > 0) { - inline_site->line_table = rdib_line_table_chunk_list_push(arena, &task->line_tables[worker_id], task->line_table_cap); - } else { - inline_site->line_table = task->null_line_table; - } - - // emit line tables for each file (yes, it is possbile to split inline site among two or more files via #include) - for (U64 file_idx = 0; file_idx < lines_count; ++file_idx) { - CV_LineArray lines = lines_arr[file_idx]; - - // prase checksum header - CV_C13Checksum *checksum_header = (CV_C13Checksum *) (raw_file_chksms.str + lines.file_off); - if (lines.file_off + sizeof(CV_C13Checksum) + checksum_header->len > raw_file_chksms.size) { - lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Not enough bytes to read file checksum @ 0x%llx.", lines.file_off); - continue; - } - String8 file_path = str8_cstring_capped(raw_string_table.str + checksum_header->name_off, raw_string_table.str + raw_string_table.size); - String8 checksum_bytes = str8((U8 *) (checksum_header + 1), checksum_header->len); - - // find source file for this line table - String8 normal_path = lnk_normalize_src_file_path(scratch.arena, file_path); - U64 src_file_hash = lnk_src_file_hash_cv(normal_path, checksum_header->kind, checksum_bytes); - LNK_SourceFileBucket *src_file_bucket = lnk_src_file_hash_table_lookup_slot(task->src_file_buckets, task->src_file_buckets_cap, src_file_hash, normal_path, checksum_header->kind, checksum_bytes); - if (src_file_bucket == 0) { - lnk_error_obj(LNK_Error_UnexpectedCodePath, task->obj_arr[obj_idx], "Unable to find source file in the hash table: \"%S\".", file_path); - continue; - } - RDIB_SourceFile *src_file = src_file_bucket->src_file; - - // fill out line table fragment - RDIB_LineTableFragment *frag = rdib_line_table_fragment_chunk_list_push(arena, &frag_chunk_list, chunk->count); - frag->src_file = src_file; - frag->voffs = lines.voffs; - frag->line_nums = lines.line_nums; - frag->col_nums = lines.col_nums; - frag->line_count = lines.line_count; - frag->col_count = lines.col_count; - - // build list of fragments per line table - rdib_line_table_push_fragment_node(inline_site->line_table, frag); - - // build list of line table fragments per file - frag->next_src_file = ins_atomic_ptr_eval_assign(&src_file->line_table_frags, frag); - } - } - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_collect_obj_virtual_ranges_task) -{ - ProfBeginFunction(); - - LNK_ConvertUnitToRDITask *task = raw_task; - - U64 unit_idx = task_id; - LNK_Obj *obj = task->obj_arr[unit_idx]; - - U64 unit_chunk_idx = unit_idx / task->unit_chunk_cap; - U64 local_unit_idx = unit_idx - unit_chunk_idx * task->unit_chunk_cap; - - RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; - dst->virt_range_count = 0; - dst->virt_ranges = push_array_no_zero(arena, Rng1U64, obj->header.section_count_no_null); - - COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; - - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { - COFF_SectionHeader *sect_header = §ion_table[sect_idx]; - - if (sect_header->flags & COFF_SectionFlag_LnkRemove) { - continue; - } - if (sect_header->vsize == 0) { - continue; - } - - dst->virt_ranges[dst->virt_range_count] = rng_1u64(sect_header->voff, sect_header->voff + sect_header->vsize); - ++dst->virt_range_count; - } - - // free unused memory - arena_pop(arena, sizeof(dst->virt_ranges[0]) * (obj->header.section_count_no_null - dst->virt_range_count)); - - ProfEnd(); -} - -internal String8List -lnk_build_rad_debug_info(TP_Context *tp, - TP_Arena *tp_arena, - OperatingSystem os, - RDI_Arch arch, - String8 image_name, - String8 image_data, - U64 obj_count, - LNK_Obj **obj_arr, - CV_DebugS *debug_s_arr, - U64 symbol_input_count, - LNK_SymbolInput *symbol_inputs, - CV_SymbolListArray *parsed_symbols, - LNK_MergedTypes types) -{ - ProfBegin("RDI"); - Temp scratch = scratch_begin(tp_arena->v,tp_arena->count); - - RDIB_Input input = rdib_init_input(scratch.arena); - - COFF_SectionHeaderArray image_sects; - String8 image_strtab; - { - PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); - image_sects.count = pe.section_count; - image_sects.v = (COFF_SectionHeader *)str8_substr(image_data, pe.section_table_range).str; - image_strtab = str8_substr(image_data, pe.string_table_range); - } - - ProfBegin("Top Level Info"); - { - U64 image_vsize = 0; - for (U64 sect_idx = 0; sect_idx < image_sects.count; sect_idx++) { - COFF_SectionHeader *sect = &image_sects.v[sect_idx]; - image_vsize = Max(image_vsize, sect->voff + sect->vsize); - } - - input.top_level_info.arch = arch; - input.top_level_info.exe_name = image_name; - input.top_level_info.exe_hash = rdi_hash(image_data.str, image_data.size); - input.top_level_info.voff_max = image_vsize; - input.top_level_info.producer_string = push_str8f(scratch.arena, "%s [Debug Info: CodeView]", BUILD_VERSION_STRING_LITERAL); - } - ProfEnd(); - - ProfBegin("Sections"); - { - input.sect_count = image_sects.count; - input.sections = push_array(scratch.arena, RDIB_BinarySection, image_sects.count); - for (U64 sect_idx = 0; sect_idx < image_sects.count; ++sect_idx) { - COFF_SectionHeader *src = &image_sects.v[sect_idx]; - RDIB_BinarySection *dst = &input.sections[sect_idx]; - String8 sect_name = coff_name_from_section_header(image_strtab, src); - - dst->name = push_str8_copy(scratch.arena, sect_name); - dst->flags = rdi_binary_section_flags_from_coff_section_flags(src->flags); - dst->voff_first = src->voff; - dst->voff_opl = src->voff + src->vsize; - dst->foff_first = src->foff; - dst->foff_opl = src->foff + src->fsize; - } - } - ProfEnd(); - - // assing low and high type indices per source - Rng1U64 itype_ranges[CV_TypeIndexSource_COUNT]; - for (U64 i = 0; i < ArrayCount(itype_ranges); ++i) { - itype_ranges[i] = rng_1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + types.count[i]); - } - - ProfBegin("Convert Types"); - U64 udt_name_buckets_cap; - LNK_UDTNameBucket **udt_name_buckets; - RDIB_Type **tpi_itype_map; - { - ProfBegin("Push TPI itype -> RDIB Type map"); - tpi_itype_map = push_array(scratch.arena, RDIB_Type *, itype_ranges[CV_TypeIndexSource_TPI].max); - ProfEnd(); - - ProfBegin("Push Built-in Types"); - RDIB_DataModel data_model = rdib_infer_data_model(os, arch); - lnk_push_basic_itypes(scratch.arena, data_model, tpi_itype_map, &input.types); - ProfEnd(); - - Assert(tpi_itype_map[0] == 0); - tpi_itype_map[0] = input.null_type; - - ProfBegin("Build UDT Name Hash Table"); - // TODO: fix memory life-time - udt_name_buckets_cap = 0; - udt_name_buckets = lnk_udt_name_hash_table_from_leaf_arr(tp, tp_arena, types.count[CV_TypeIndexSource_TPI], types.v[CV_TypeIndexSource_TPI], &udt_name_buckets_cap); - ProfEnd(); - - - ProfBegin("Convert CodeView types to RDIB Types"); - LNK_ConvertTypesToRDI task = {0}; - MemoryCopyTyped(task.leaf_count, types.count, CV_TypeIndexSource_COUNT); - MemoryCopyTyped(task.leaf_arr, types.v, CV_TypeIndexSource_COUNT); - task.type_cap = input.type_cap; - task.udt_cap = input.udt_cap; - task.variadic_type_ref = rdib_make_type_ref(scratch.arena, input.variadic_type); - task.itype_ranges = itype_ranges; - task.tpi_itype_map = tpi_itype_map; - task.udt_name_bucket_cap = udt_name_buckets_cap; - task.udt_name_buckets = udt_name_buckets; - task.rdib_types_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_struct_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_union_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_enum_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_udt_members_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_enum_members_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_types_params_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); - task.rdib_udt_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count); - task.rdib_enum_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, types.count[CV_TypeIndexSource_TPI], tp->worker_count); - tp_for_parallel(tp, tp_arena, tp->worker_count, lnk_convert_types_to_rdi_task, &task); - ProfEnd(); - - ProfBegin("Concat converted types"); - rdib_type_chunk_list_concat_in_place_many (&input.types, task.rdib_types_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.struct_list, task.rdib_types_struct_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.union_list, task.rdib_types_union_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.enum_list, task.rdib_types_enum_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.param_types, task.rdib_types_params_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.member_types, task.rdib_types_udt_members_lists, tp->worker_count); - rdib_type_chunk_list_concat_in_place_many (&input.enum_types, task.rdib_types_enum_members_lists, tp->worker_count); - rdib_udt_member_chunk_list_concat_in_place_many(&input.udt_members, task.rdib_udt_members_lists, tp->worker_count); - rdib_udt_member_chunk_list_concat_in_place_many(&input.enum_members, task.rdib_enum_members_lists, tp->worker_count); - ProfEnd(); - - // types are converted and we can remove indirection and release 'itype_map' - ProfBegin("Deref Type Refs"); - rdib_deref_type_refs(tp, &input.types); - rdib_deref_type_refs(tp, &input.struct_list); - rdib_deref_type_refs(tp, &input.union_list); - rdib_deref_type_refs(tp, &input.enum_list); - rdib_deref_type_refs(tp, &input.param_types); - rdib_deref_type_refs(tp, &input.member_types); - rdib_deref_type_refs(tp, &input.enum_types); - ProfEnd(); - } - ProfEnd(); - - // Loop over source files in objs and build a hash table - // for path -> source file maps. During symbol conversion - // we use the hash table to lookup source files and append - // inline site line tables. - U64 src_file_buckets_cap; - LNK_SourceFileBucket **src_file_buckets; - { - ProfBegin("Build Source File Hash Table"); - - LNK_ConvertSourceFilesToRDITask task = {0}; - task.obj_arr = obj_arr; - task.debug_s_arr = debug_s_arr; - - ProfBegin("Count Source Files"); - tp_for_parallel(tp, 0, obj_count, lnk_count_source_files_task, &task); - ProfEnd(); - - ProfBeginDynamic("Insert Source Files [Count %llu]", task.total_src_file_count); - task.src_file_buckets_cap = (U64)(task.total_src_file_count * 1.3); - task.src_file_buckets = push_array(tp_arena->v[0], LNK_SourceFileBucket*, task.src_file_buckets_cap); - tp_for_parallel(tp, tp_arena, obj_count, lnk_insert_src_files_task, &task); - ProfEnd(); - - src_file_buckets_cap = task.src_file_buckets_cap; - src_file_buckets = task.src_file_buckets; - - ProfEnd(); - } - - // Copy source files to a contiguous array and update source file pointers - // in buckets so we can do lookup and compute source file index in output array - // with a pointer subtraction. - ProfBegin("Source Files"); - for (U64 bucket_idx = 0; bucket_idx < src_file_buckets_cap; ++bucket_idx) { - LNK_SourceFileBucket *bucket = src_file_buckets[bucket_idx]; - if (bucket != 0) { - RDIB_SourceFile *new_src_file = rdib_source_file_chunk_list_push(scratch.arena, &input.src_files, input.src_file_chunk_cap); - - // restore chunk pointer after copy - RDIB_SourceFileChunk *new_src_file_chunk = new_src_file->chunk; - *new_src_file = *bucket->src_file; - new_src_file->chunk = new_src_file_chunk; - - bucket->src_file = new_src_file; - } - } - ProfEnd(); - - ProfBegin("Units"); - { - LNK_ConvertUnitToRDITask task = {0}; - task.image_sects = image_sects; - task.obj_arr = obj_arr; - task.debug_s_arr = debug_s_arr; - task.leaf_arr_count_ipi = types.count[CV_TypeIndexSource_IPI]; - task.leaf_arr_ipi = types.v[CV_TypeIndexSource_IPI]; - task.symbol_inputs = symbol_inputs; - task.ipi_itype_range = itype_ranges[CV_TypeIndexSource_IPI]; - task.tpi_itype_range = itype_ranges[CV_TypeIndexSource_TPI]; - task.tpi_itype_map = tpi_itype_map; - task.src_file_buckets_cap = src_file_buckets_cap; - task.src_file_buckets = src_file_buckets; - task.udt_name_buckets = udt_name_buckets; - task.udt_name_buckets_cap = udt_name_buckets_cap; - task.src_file_chunk_cap = input.src_file_chunk_cap; - task.line_table_cap = input.line_table_cap; - task.symbol_chunk_cap = input.symbol_chunk_cap; - task.unit_chunk_cap = input.unit_chunk_cap; - task.inline_site_cap = input.inline_site_cap; - task.null_line_table = input.null_line_table; - task.extern_symbol_voff_ht = hash_table_init(scratch.arena, 256); - task.units = rdib_unit_chunk_list_reserve_ex(scratch.arena, &input.units, input.unit_chunk_cap, obj_count); - task.scopes = push_array(scratch.arena, RDIB_ScopeChunkList, tp->worker_count); - task.locals = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); - task.extern_gvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); - task.static_gvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); - task.extern_tvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); - task.static_tvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); - task.extern_procs = push_array(scratch.arena, RDIB_ProcedureChunkList, tp->worker_count); - task.static_procs = push_array(scratch.arena, RDIB_ProcedureChunkList, tp->worker_count); - task.inline_sites = push_array(scratch.arena, RDIB_InlineSiteChunkList, tp->worker_count); - task.line_tables = push_array(scratch.arena, RDIB_LineTableChunkList, tp->worker_count); - - ProfBegin("Gather Compiler Info"); - task.comp_info_arr = push_array(scratch.arena, LNK_CodeViewCompilerInfo, obj_count); - tp_for_parallel(tp, tp_arena, obj_count, lnk_find_obj_compiler_info_task, &task); - ProfEnd(); - - ProfBegin("Convert Line Tables"); - tp_for_parallel(tp, tp_arena, obj_count, lnk_convert_line_tables_to_rdi_task, &task); - ProfEnd(); - - ProfBegin("Build Inlinee Lines Accels"); - task.inlinee_lines_accel_arr = push_array(scratch.arena, CV_InlineeLinesAccel *, obj_count); - tp_for_parallel(tp, tp_arena, obj_count, lnk_build_inlinee_lines_accels_task, &task); - ProfEnd(); - - ProfBegin("Convert Symbols"); - tp_for_parallel(tp, tp_arena, symbol_input_count, lnk_convert_symbols_to_rdi_task, &task); - ProfEnd(); - - ProfBegin("Convert Inline Sites Line Tables"); - rdib_inline_site_chunk_list_concat_in_place_many(&input.inline_sites, task.inline_sites, tp->worker_count); - task.inline_site_chunks = rdib_array_from_inline_site_chunk_list(scratch.arena, input.inline_sites); - tp_for_parallel(tp, tp_arena, input.inline_sites.count, lnk_convert_inline_site_line_tables_task, &task); - ProfEnd(); - - ProfBegin("Collect Units Virtual Ranges"); - tp_for_parallel(tp, tp_arena, obj_count, lnk_collect_obj_virtual_ranges_task, &task); - ProfEnd(); - - rdib_line_table_chunk_list_concat_in_place_many(&input.line_tables, task.line_tables, tp->worker_count); - rdib_scope_chunk_list_concat_in_place_many(&input.scopes, task.scopes, tp->worker_count); - rdib_variable_chunk_list_concat_in_place_many(&input.locals, task.locals, tp->worker_count); - rdib_variable_chunk_list_concat_in_place_many(&input.extern_gvars, task.extern_gvars, tp->worker_count); - rdib_variable_chunk_list_concat_in_place_many(&input.static_gvars, task.static_gvars, tp->worker_count); - rdib_variable_chunk_list_concat_in_place_many(&input.extern_tvars, task.extern_tvars, tp->worker_count); - rdib_variable_chunk_list_concat_in_place_many(&input.static_tvars, task.static_tvars, tp->worker_count); - rdib_procedure_chunk_list_concat_in_place_many(&input.extern_procs, task.extern_procs, tp->worker_count); - rdib_procedure_chunk_list_concat_in_place_many(&input.static_procs, task.static_procs, tp->worker_count); - } - ProfEnd(); - - String8List rdi_data = rdib_finish(tp, tp_arena, &input); - - scratch_end(scratch); - ProfEnd(); - return rdi_data; -} - diff --git a/src/linker/lnk_debug_info.h b/src/linker/lnk_debug_info.h index 1f97fa23..d93c66eb 100644 --- a/src/linker/lnk_debug_info.h +++ b/src/linker/lnk_debug_info.h @@ -162,120 +162,6 @@ typedef struct String8List *maps; } LNK_TypeNameReplacer; -//////////////////////////////// -// RDI - -typedef struct -{ - String8 name; - U64 leaf_idx; -} LNK_UDTNameBucket; - -typedef struct -{ - U64 leaf_count; - U8 **leaf_arr; - Rng1U64 *ranges; - U64 buckets_cap; - LNK_UDTNameBucket **buckets; -} LNK_BuildUDTNameHashTableTask; - -typedef struct -{ - CV_DebugT debug_t; - CV_TypeIndex ti_lo; - Rng1U64 *ranges; - U64 udt_name_buckets_cap; - LNK_UDTNameBucket **udt_name_buckets; - CV_TypeIndex *fwdmap; -} LNK_BuildUDTFwdMapTask; - -typedef struct -{ - U64 leaf_count[CV_TypeIndexSource_COUNT]; - U8 **leaf_arr[CV_TypeIndexSource_COUNT]; - U64 type_cap; - U64 udt_cap; - RDIB_TypeRef variadic_type_ref; - Rng1U64 *itype_ranges; - U64 udt_name_bucket_cap; - LNK_UDTNameBucket **udt_name_buckets; - RDIB_Type **tpi_itype_map; - RDIB_TypeChunkList *rdib_types_lists; - RDIB_TypeChunkList *rdib_types_struct_lists; - RDIB_TypeChunkList *rdib_types_union_lists; - RDIB_TypeChunkList *rdib_types_enum_lists; - RDIB_TypeChunkList *rdib_types_params_lists; - RDIB_TypeChunkList *rdib_types_udt_members_lists; - RDIB_TypeChunkList *rdib_types_enum_members_lists; - RDIB_UDTMemberChunkList *rdib_udt_members_lists; - RDIB_UDTMemberChunkList *rdib_enum_members_lists; - Rng1U64 *ranges; -} LNK_ConvertTypesToRDI; - -typedef struct -{ - U64 obj_idx; - RDIB_SourceFile *src_file; -} LNK_SourceFileBucket; - -typedef struct -{ - LNK_Obj **obj_arr; - CV_DebugS *debug_s_arr; - U64 total_src_file_count; - LNK_SourceFileBucket **src_file_buckets; - U64 src_file_buckets_cap; -} LNK_ConvertSourceFilesToRDITask; - -typedef struct -{ - CV_Arch arch; - CV_Language language; - String8 compiler_name; -} LNK_CodeViewCompilerInfo; - -typedef struct -{ - COFF_SectionHeaderArray image_sects; - LNK_Obj **obj_arr; - CV_DebugS *debug_s_arr; - U64 leaf_arr_count_ipi; - U8 **leaf_arr_ipi; - LNK_SymbolInput *symbol_inputs; - Rng1U64 ipi_itype_range; - Rng1U64 tpi_itype_range; - RDIB_Type **tpi_itype_map; - U64 src_file_buckets_cap; - LNK_SourceFileBucket **src_file_buckets; - LNK_UDTNameBucket **udt_name_buckets; - U64 line_table_cap; - U64 udt_name_buckets_cap; - U64 src_file_chunk_cap; - U64 symbol_chunk_cap; - U64 unit_chunk_cap; - U64 inline_site_cap; - RDIB_LineTable *null_line_table; - HashTable *extern_symbol_voff_ht; - LNK_CodeViewCompilerInfo *comp_info_arr; - CV_InlineeLinesAccel **inlinee_lines_accel_arr; - - RDIB_InlineSiteChunk **inline_site_chunks; - - // output - RDIB_UnitChunk *units; - RDIB_VariableChunkList *locals; - RDIB_ScopeChunkList *scopes; - RDIB_VariableChunkList *extern_gvars; - RDIB_VariableChunkList *static_gvars; - RDIB_VariableChunkList *extern_tvars; - RDIB_VariableChunkList *static_tvars; - RDIB_ProcedureChunkList *extern_procs; - RDIB_ProcedureChunkList *static_procs; - RDIB_InlineSiteChunkList *inline_sites; - RDIB_LineTableChunkList *line_tables; -} LNK_ConvertUnitToRDITask; - //////////////////////////////// // CodeView @@ -296,46 +182,3 @@ internal void lnk_replace_type_names_with_hashes (TP_Context *tp, TP internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, LNK_CodeViewInput *cv, LNK_MergedTypes cv_types); -//////////////////////////////// -// RDI - -internal U64 lnk_udt_name_hash_table_hash (String8 string); -internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out); -internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name); -internal CV_TypeIndex * lnk_build_udt_fwdmap (TP_Context *tp, Arena *arena, CV_DebugT debug_t, CV_TypeIndex ti_lo, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap); - -internal RDIB_TypeRef lnk_rdib_type_from_itype (LNK_ConvertTypesToRDI *task, CV_TypeIndex itype); -internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop (CV_MethodProp prop); -internal LNK_SourceFileBucket * lnk_src_file_hash_table_hash (String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes); -internal LNK_SourceFileBucket * lnk_src_file_hash_table_lookup_slot(LNK_SourceFileBucket **src_file_buckets, U64 src_file_buckets_cap, U64 hash, String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes); - -internal String8List -lnk_build_rad_debug_info(TP_Context *tp, - TP_Arena *tp_arena, - OperatingSystem os, - RDI_Arch arch, - String8 image_name, - String8 image_data, - U64 obj_count, - LNK_Obj **obj_arr, - CV_DebugS *debug_s_arr, - U64 symbol_input_count, - LNK_SymbolInput *symbol_inputs, - CV_SymbolListArray *parsed_symbols, - LNK_MergedTypes types); - -internal U64 lnk_udt_name_hash_table_hash (String8 string); -internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out); -internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name); - -internal CV_TypeIndex * lnk_build_udt_fwdmap(TP_Context *tp, - Arena *arena, - CV_DebugT debug_t, - CV_TypeIndex ti_lo, - LNK_UDTNameBucket **udt_name_buckets, - U64 udt_name_buckets_cap); - -internal void lnk_init_rdib_itype_map (Arena *arena, RDI_Arch arch, RDIB_Type **itype_map, RDIB_TypeChunkList *rdib_types_list); -internal RDIB_TypeRef lnk_rdib_type_from_itype (LNK_ConvertTypesToRDI *task, CV_TypeIndex itype); -internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop(CV_MethodProp prop); - diff --git a/src/linker/rdi/rdi_builder.c b/src/linker/rdi/rdi_builder.c deleted file mode 100644 index 710bfa19..00000000 --- a/src/linker/rdi/rdi_builder.c +++ /dev/null @@ -1,5584 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -internal RDIB_DataModel -rdib_infer_data_model(OperatingSystem os, RDI_Arch arch) -{ - RDIB_DataModel data_model = RDIB_DataModel_Null; - switch (os) { - case OperatingSystem_Null: break; - case OperatingSystem_Windows: { - switch (arch) { - case RDI_Arch_X64: - data_model = RDIB_DataModel_LLP64; break; - default: NotImplemented; - } - } break; - case OperatingSystem_Linux: { - switch (arch) { - case RDI_Arch_X64: data_model = RDIB_DataModel_LLP64; break; - default: NotImplemented; - } - } break; - case OperatingSystem_Mac: { - switch (arch) { - case RDI_Arch_X64: data_model = RDIB_DataModel_LP64; break; - } - } break; - default: InvalidPath; - } - return data_model; -} - -internal RDI_TypeKind -rdib_short_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_S16; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_S16; - case RDIB_DataModel_LP64 : return RDI_TypeKind_S16; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_S16; - case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_unsigned_short_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_U16; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_U16; - case RDIB_DataModel_LP64 : return RDI_TypeKind_U16; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_U16; - case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_int_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_S32; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_S32; - case RDIB_DataModel_LP64 : return RDI_TypeKind_S32; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_unsigned_int_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_U32; - case RDIB_DataModel_LP64 : return RDI_TypeKind_U32; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_long_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_S32; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_S32; - case RDIB_DataModel_LP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_unsigned_long_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_U32; - case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_long_long_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_S64; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_LP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_unsigned_long_long_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_U64; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -internal RDI_TypeKind -rdib_pointer_size_t_type_from_data_model(RDIB_DataModel data_model) -{ - switch (data_model) { - case RDIB_DataModel_Null : break; - case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; - case RDIB_DataModel_LLP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; - case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; - default: InvalidPath; - } - return RDI_TypeKind_NULL; -} - -//////////////////////////////// - -internal void -rdib_udt_member_list_push_node(RDIB_UDTMemberList *list, RDIB_UDTMember *node) -{ - SLLQueuePushCount(list, node); -} - -internal void -rdib_udt_member_list_concat_in_place(RDIB_UDTMemberList *list, RDIB_UDTMemberList *to_concat) -{ - SLLConcatInPlace(list, to_concat); -} - -internal void -rdib_line_table_push_fragment_node(RDIB_LineTable *list, RDIB_LineTableFragment *n) -{ - SLLQueuePush_N(list->first, list->last, n, next_line_table); - ++list->count; -} - -internal RDIB_LineTableFragment * -rdib_line_table_push(Arena *arena, RDIB_LineTable *list) -{ - RDIB_LineTableFragment *n = push_array(arena, RDIB_LineTableFragment, 1); - rdib_line_table_push_fragment_node(list, n); - return n; -} - -//////////////////////////////// - -internal RDIB_LineTableFragment * -rdib_line_table_fragment_chunk_list_push(Arena *arena, RDIB_LineTableFragmentChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_LineTableFragment); - return SLLChunkListLastItem(list); -} - -internal RDIB_Unit * -rdib_unit_chunk_list_push(Arena *arena, RDIB_UnitChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_Unit); - return SLLChunkListLastItem(list); -} - -internal RDIB_Scope * -rdib_scope_chunk_list_push(Arena *arena, RDIB_ScopeChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_Scope); - return SLLChunkListLastItem(list); -} - -internal RDIB_Procedure * -rdib_procedure_chunk_list_push(Arena *arena, RDIB_ProcedureChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_Procedure); - return SLLChunkListLastItem(list); -} - -internal RDIB_Variable * -rdib_variable_chunk_list_push(Arena *arena, RDIB_VariableChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_Variable); - return SLLChunkListLastItem(list); -} - -internal RDIB_LineTable * -rdib_line_table_chunk_list_push(Arena *arena, RDIB_LineTableChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_LineTable); - return SLLChunkListLastItem(list); -} - -internal RDIB_Type * -rdib_type_chunk_list_push(Arena *arena, RDIB_TypeChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_Type); - RDIB_Type *type = SLLChunkListLastItem(list); - type->final_idx = 0; - return type; -} - -internal RDIB_UDTMember * -rdib_udt_member_chunk_list_push(Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_UDTMember); - return SLLChunkListLastItem(list); -} - -internal RDIB_SourceFile * -rdib_source_file_chunk_list_push(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_SourceFile); - return SLLChunkListLastItem(list); -} - -internal RDIB_InlineSite * -rdib_inline_site_chunk_list_push(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap) -{ - SLLChunkListPush(arena, list, cap, RDIB_InlineSite); - return SLLChunkListLastItem(list); -} - -internal RDIB_Unit * -rdib_unit_chunk_list_push_zero(Arena *arena, RDIB_UnitChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_Unit); - return SLLChunkListLastItem(list); -} - -internal RDIB_Scope * -rdib_scope_chunk_list_push_zero(Arena *arena, RDIB_ScopeChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_Scope); - return SLLChunkListLastItem(list); -} - -internal RDIB_Procedure * -rdib_procedure_chunk_list_push_zero(Arena *arena, RDIB_ProcedureChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_Procedure); - return SLLChunkListLastItem(list); -} - -internal RDIB_Variable * -rdib_variable_chunk_list_push_zero(Arena *arena, RDIB_VariableChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_Variable); - return SLLChunkListLastItem(list); -} - -internal RDIB_LineTable * -rdib_line_table_chunk_list_push_zero(Arena *arena, RDIB_LineTableChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_LineTable); - return SLLChunkListLastItem(list); -} - -internal RDIB_Type * -rdib_type_chunk_list_push_zero(Arena *arena, RDIB_TypeChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_Type); - return SLLChunkListLastItem(list); -} - -internal RDIB_UDTMember * -rdib_udt_member_chunk_list_push_zero(Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_UDTMember); - return SLLChunkListLastItem(list); -} - -internal RDIB_SourceFile * -rdib_source_file_chunk_list_push_zero(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_SourceFile); - return SLLChunkListLastItem(list); -} - -internal RDIB_InlineSite * -rdib_inline_site_chunk_list_push_zero(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap) -{ - SLLChunkListPushZero(arena, list, cap, RDIB_InlineSite); - return SLLChunkListLastItem(list); -} - -internal RDIB_UnitChunk * -rdib_unit_chunk_list_reserve_ex(Arena *arena, RDIB_UnitChunkList *list, U64 count_per_chunk, U64 item_count) -{ - U64 chunk_count = CeilIntegerDiv(item_count, count_per_chunk); - RDIB_UnitChunk *chunks = push_array(arena, RDIB_UnitChunk, chunk_count); - U64 base = list->last ? list->last->base : 0; - - for (U64 i = 0; i+1 < chunk_count; i += 1, item_count -= count_per_chunk, base += count_per_chunk) { - chunks[i].base = base; - chunks[i].count = count_per_chunk; - chunks[i].cap = count_per_chunk; - chunks[i].v = push_array(arena, RDIB_Unit, count_per_chunk); - SLLQueuePush(list->first, list->last, &chunks[i]); - - for (U64 k = 0; k < count_per_chunk; ++k) { - chunks[i].v[k].chunk = &chunks[i]; - } - } - - chunks[chunk_count-1].base = base; - chunks[chunk_count-1].count = item_count; - chunks[chunk_count-1].cap = item_count; - chunks[chunk_count-1].v = push_array(arena, RDIB_Unit, item_count); - for (U64 k = 0; k < item_count; ++k) { - chunks[chunk_count-1].v[k].chunk = &chunks[chunk_count-1]; - } - - SLLQueuePush(list->first, list->last, &chunks[chunk_count-1]); - list->count += chunk_count; - - return chunks; -} - -internal void -rdib_unit_chunk_list_reserve(Arena *arena, RDIB_UnitChunkList *list, U64 cap) -{ - // fill out node - RDIB_UnitChunk *chunk = push_array(arena, RDIB_UnitChunk, 1); - chunk->cap = cap; - chunk->v = push_array(arena, RDIB_Unit, cap); - - // push node to list - SLLQueuePush(list->first, list->last, chunk); - list->count += 1; -} - -internal void -rdib_type_chunk_list_reserve(Arena *arena, RDIB_TypeChunkList *list, U64 cap) -{ - // fill out node - RDIB_TypeChunk *chunk = push_array(arena, RDIB_TypeChunk, 1); - chunk->cap = cap; - chunk->v = push_array(arena, RDIB_Type, cap); - - // push node to list - SLLQueuePush(list->first, list->last, chunk); - list->count += 1; -} - -internal void -rdib_source_file_list_reserve(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) -{ - // fill out node - RDIB_SourceFileChunk *chunk = push_array(arena, RDIB_SourceFileChunk, 1); - chunk->cap = cap; - chunk->v = push_array(arena, RDIB_SourceFile, cap); - - // push node to list - SLLQueuePush(list->first, list->last, chunk); - list->count += 1; -} - -internal void -rdib_unit_chunk_list_concat_in_place(RDIB_UnitChunkList *list, RDIB_UnitChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_UnitChunk); -} - -internal void -rdib_scope_chunk_list_concat_in_place(RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_ScopeChunk); -} - -internal void -rdib_udt_member_chunk_list_concat_in_place(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_UDTMemberChunk); -} - -internal void -rdib_procedure_chunk_list_concat_in_place(RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_ProcedureChunk); -} - -internal void -rdib_variable_chunk_list_concat_in_place(RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_VariableChunk); -} - -internal void -rdib_line_table_chunk_list_concat_in_place(RDIB_LineTableChunkList *list, RDIB_LineTableChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_LineTableChunk); -} - -internal void -rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_InlineSiteChunk); -} - -internal void -rdib_type_chunk_list_concat_in_place(RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_TypeChunk); -} - -internal void -rdib_source_file_chunk_list_concat_in_place(RDIB_SourceFileChunkList *list, RDIB_SourceFileChunkList *to_concat) -{ - SLLConcatInPlaceChunkList(list, to_concat, RDIB_SourceFileChunk); -} - -internal void -rdib_line_table_chunk_list_concat_in_place_many(RDIB_LineTableChunkList *list, RDIB_LineTableChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_LineTableChunk, count); -} - -internal void -rdib_scope_chunk_list_concat_in_place_many(RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_ScopeChunk, count); -} - -internal void -rdib_variable_chunk_list_concat_in_place_many(RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_VariableChunk, count); -} - -internal void -rdib_procedure_chunk_list_concat_in_place_many(RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_ProcedureChunk, count); -} - -internal void -rdib_inline_site_chunk_list_concat_in_place_many(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_InlineSiteChunk, count); -} - -internal void -rdib_type_chunk_list_concat_in_place_many(RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_TypeChunk, count); -} - -internal void -rdib_udt_member_chunk_list_concat_in_place_many(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat, U64 count) -{ - SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_UDTMemberChunk, count); -} - -internal RDIB_UnitChunk ** -rdib_array_from_unit_chunk_list(Arena *arena, RDIB_UnitChunkList list) -{ - ProfBeginFunction(); - RDIB_UnitChunk **result = push_array_no_zero(arena, RDIB_UnitChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_UnitChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_ScopeChunk ** -rdib_array_from_scope_chunk_list(Arena *arena, RDIB_ScopeChunkList list) -{ - ProfBeginFunction(); - RDIB_ScopeChunk **result = push_array_no_zero(arena, RDIB_ScopeChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_ScopeChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_VariableChunk ** -rdib_array_from_variable_chunk_list(Arena *arena, RDIB_VariableChunkList list) -{ - ProfBeginFunction(); - RDIB_VariableChunk **result = push_array_no_zero(arena, RDIB_VariableChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_VariableChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_LineTableChunk ** -rdib_array_from_line_table_chunk_list(Arena *arena, RDIB_LineTableChunkList list) -{ - ProfBeginFunction(); - RDIB_LineTableChunk **result = push_array_no_zero(arena, RDIB_LineTableChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_LineTableChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_ProcedureChunk ** -rdib_array_from_procedure_chunk_list(Arena *arena, RDIB_ProcedureChunkList list) -{ - ProfBeginFunction(); - RDIB_ProcedureChunk **result = push_array_no_zero(arena, RDIB_ProcedureChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_ProcedureChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_InlineSiteChunk ** -rdib_array_from_inline_site_chunk_list(Arena *arena, RDIB_InlineSiteChunkList list) -{ - ProfBeginFunction(); - RDIB_InlineSiteChunk **result = push_array_no_zero(arena, RDIB_InlineSiteChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_InlineSiteChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_UDTMemberChunk ** -rdib_array_from_udt_member_chunk_list(Arena *arena, RDIB_UDTMemberChunkList list) -{ - ProfBeginFunction(); - RDIB_UDTMemberChunk **result = push_array_no_zero(arena, RDIB_UDTMemberChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_UDTMemberChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_TypeChunk ** -rdib_array_from_type_chunk_list(Arena *arena, RDIB_TypeChunkList list) -{ - ProfBeginFunction(); - RDIB_TypeChunk **result = push_array_no_zero(arena, RDIB_TypeChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_TypeChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { - result[chunk_idx] = chunk; - } - ProfEnd(); - return result; -} - -internal RDIB_SourceFileChunk ** -rdib_array_from_source_file_chunk_list(Arena *arena, RDIB_SourceFileChunkList list) -{ - ProfBeginFunction(); - RDIB_SourceFileChunk **result = push_array_no_zero(arena, RDIB_SourceFileChunk *, list.count); - U64 chunk_idx = 0; - for (RDIB_SourceFileChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - result[chunk_idx++] = chunk; - } - ProfEnd(); - return result; -} - -internal U64 -rdib_unit_chunk_list_total_count(RDIB_UnitChunkList list) -{ - U64 total_count = 0; - for (RDIB_UnitChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_scope_chunk_list_total_count(RDIB_ScopeChunkList list) -{ - U64 total_count = 0; - for (RDIB_ScopeChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_variable_chunk_list_total_count(RDIB_VariableChunkList list) -{ - U64 total_count = 0; - for (RDIB_VariableChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_line_table_chunk_list_total_count(RDIB_LineTableChunkList list) -{ - U64 total_count = 0; - for (RDIB_LineTableChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_procedure_chunk_list_total_count(RDIB_ProcedureChunkList list) -{ - U64 total_count = 0; - for (RDIB_ProcedureChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_inline_site_chunk_list_total_count(RDIB_InlineSiteChunkList list) -{ - U64 total_count = 0; - for (RDIB_InlineSiteChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_udt_member_chunk_list_total_count(RDIB_UDTMemberChunkList list) -{ - U64 total_count = 0; - for (RDIB_UDTMemberChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_type_chunk_list_total_count(RDIB_TypeChunkList list) -{ - U64 total_count = 0; - for (RDIB_TypeChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U64 -rdib_source_file_chunk_list_total_count(RDIB_SourceFileChunkList list) -{ - U64 total_count = 0; - for (RDIB_SourceFileChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { - total_count += chunk->count; - } - return total_count; -} - -internal U32 -rdib_idx_from_unit(RDIB_Unit *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_scope(RDIB_Scope *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_inline_site(RDIB_InlineSite *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_variable(RDIB_Variable *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_procedure(RDIB_Procedure *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_source_file(RDIB_SourceFile *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_line_table(RDIB_LineTable *n) -{ - U32 idx = 0; - if (n) { - Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); - idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); - Assert(idx - n->chunk->base < n->chunk->count); - } - return idx; -} - -internal U32 -rdib_idx_from_type(RDIB_Type *n) -{ - U32 idx = 0; - if (n) { - idx = safe_cast_u32(n->final_idx); - } - return idx; -} - -internal U32 -rdib_idx_from_udt_type(RDIB_Type *n) -{ - U32 idx = 0; - if (n && RDI_IsUserDefinedType(n->kind)) { - idx = safe_cast_u32(n->udt.udt_idx); - } - return idx; -} - -//////////////////////////////// -// Source File - -internal B32 -rdib_source_file_match(RDIB_SourceFile *a, RDIB_SourceFile *b, OperatingSystem os) -{ - StringMatchFlags match_flags = path_match_flags_from_os(os); - if (str8_match(a->normal_full_path, b->normal_full_path, match_flags)) { - if (a->checksum_kind == b->checksum_kind) { - if (str8_match(a->checksum, b->checksum, 0)) { - return 1; - } - } - } - return 0; -} - -//////////////////////////////// -// Eval Ops - -internal RDIB_EvalBytecodeOp * -rdib_bytecode_push_op(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) -{ - RDIB_EvalBytecodeOp *node = push_array(arena, RDIB_EvalBytecodeOp, 1); - node->op = op; - node->p_size = RDI_DECODEN_FROM_CTRLBITS(rdi_eval_op_ctrlbits_table[op]); - node->p = p; - - SLLQueuePush(bytecode->first, bytecode->last, node); - bytecode->count += 1; - bytecode->size += 1 + node->p_size; - - return node; -} - -internal void -rdib_bytecode_push_ucsont(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_U64 uconst) -{ - if (uconst <= max_U8) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, uconst); - } else if (uconst <= max_U16) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, uconst); - } else if (uconst <= max_U32) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, uconst); - } else { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, uconst); - } -} - -internal void -rdib_bytecode_push_sconst(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_S64 sconst) -{ - if (min_S8 <= sconst && sconst <= max_S8) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)sconst); - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); - } else if (min_S16 <= sconst && sconst <= max_S16) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)sconst); - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); - } else if (min_S32 <= sconst && sconst <= max_S32) { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)sconst); - } else { - rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)sconst); - } -} - -//////////////////////////////// -// Location - -internal RDIB_Location -rdib_make_location_addr_byte_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) -{ - RDIB_Location loc = {0}; - loc.ranges = ranges; - loc.kind = RDI_LocationKind_AddrBytecodeStream; - loc.bytecode = bytecode; - return loc; -} - -internal RDIB_Location -rdib_make_location_addr_bytecode_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) -{ - RDIB_Location loc = {0}; - loc.ranges = ranges; - loc.kind = RDI_LocationKind_AddrBytecodeStream; - loc.bytecode = bytecode; - return loc; -} - -internal RDIB_Location -rdib_make_location_val_bytecode_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) -{ - RDIB_Location loc = {0}; - loc.ranges = ranges; - loc.kind = RDI_LocationKind_ValBytecodeStream; - loc.bytecode = bytecode; - return loc; -} - -internal RDIB_Location -rdib_make_location_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset) -{ - RDIB_Location loc = {0}; - loc.ranges = ranges; - loc.kind = RDI_LocationKind_AddrRegPlusOff; - loc.reg_code = reg_code; - loc.offset = offset; - return loc; -} - -internal RDIB_Location -rdib_make_location_addr_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset) -{ - RDIB_Location loc = {0}; - loc.kind = RDI_LocationKind_AddrAddrRegPlusOff; - loc.ranges = ranges; - loc.reg_code = reg_code; - loc.offset = offset; - return loc; -} - -internal RDIB_Location -rdib_make_location_val_reg(Rng1U64List ranges, RDI_RegCode reg_code) -{ - RDIB_Location loc = {0}; - loc.kind = RDI_LocationKind_ValReg; - loc.ranges = ranges; - loc.reg_code = reg_code; - return loc; -} - -internal RDIB_LocationNode * -rdib_location_list_push(Arena *arena, RDIB_LocationList *list, RDIB_Location v) -{ - RDIB_LocationNode *node = push_array(arena, RDIB_LocationNode, 1); - node->v = v; - SLLQueuePush(list->first, list->last, node); - ++list->count; - return node; -} - -internal RDIB_LocationNode * -rdib_push_location_addr_reg_off(Arena *arena, RDIB_LocationList *list, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 is_reference, Rng1U64List ranges) -{ - RDIB_Location loc; - - if (0 <= offset && offset <= (S64)max_U16) { - if (is_reference) { - loc = rdib_make_location_addr_addr_reg_plus_u16(ranges, reg_code, (U16)offset); - } else { - loc = rdib_make_location_addr_reg_plus_u16(ranges, reg_code, (U16)offset); - } - } - - // long offset, emit byte code - else { - RDIB_EvalBytecode bytecode = {0}; - U32 reg_read_param = RDI_EncodeRegReadParam(reg_code, reg_byte_size, reg_byte_pos); - rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_RegRead, reg_read_param); - rdib_bytecode_push_sconst(arena, &bytecode, offset); - rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_Add, 0); - - if (is_reference) { - U64 addr_size = rdi_addr_size_from_arch(arch); - rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_MemRead, addr_size); - } - - loc = rdib_make_location_addr_bytecode_stream(ranges, bytecode); - } - - RDIB_LocationNode *node = rdib_location_list_push(arena, list, loc); - return node; -} - -internal void -rdib_variable_list_push_node(RDIB_VariableList *list, RDIB_VariableNode *node) -{ - SLLQueuePush(list->first, list->last, node); - ++list->count; -} - -internal RDIB_VariableNode * -rdib_variable_list_push(Arena *arena, RDIB_VariableList *list) -{ - RDIB_VariableNode *node = push_array(arena, RDIB_VariableNode, 1); - rdib_variable_list_push_node(list, node); - return node; -} - -//////////////////////////////// -// Types - -internal U64 -rdib_size_from_type(RDIB_Type *type) -{ - if (type) { - switch (type->kind) { - case RDI_TypeKind_Void: - case RDI_TypeKind_Char8: - case RDI_TypeKind_Char16: - case RDI_TypeKind_Char32: - case RDI_TypeKind_UChar8: - case RDI_TypeKind_UChar16: - case RDI_TypeKind_UChar32: - case RDI_TypeKind_U8: - case RDI_TypeKind_U16: - case RDI_TypeKind_U32: - case RDI_TypeKind_U64: - case RDI_TypeKind_U128: - case RDI_TypeKind_U256: - case RDI_TypeKind_U512: - case RDI_TypeKind_S8: - case RDI_TypeKind_S16: - case RDI_TypeKind_S32: - case RDI_TypeKind_S64: - case RDI_TypeKind_S128: - case RDI_TypeKind_S256: - case RDI_TypeKind_S512: - case RDI_TypeKind_Bool: - case RDI_TypeKind_F16: - case RDI_TypeKind_F32: - case RDI_TypeKind_F32PP: - case RDI_TypeKind_F48: - case RDI_TypeKind_F64: - case RDI_TypeKind_F80: - case RDI_TypeKind_F128: - case RDI_TypeKind_ComplexF32: - case RDI_TypeKind_ComplexF64: - case RDI_TypeKind_ComplexF80: - case RDI_TypeKind_ComplexF128: - case RDI_TypeKind_Handle: - return type->builtin.size; - case RDI_TypeKind_Modifier: - return rdib_size_from_type((RDIB_Type *)type->modifier.type_ref); - case RDI_TypeKind_Ptr: - case RDI_TypeKind_LRef: - case RDI_TypeKind_RRef: - return type->ptr.size; - case RDI_TypeKind_Array: - return type->array.size; - - case RDI_TypeKind_Function: - case RDI_TypeKind_Method: - case RDI_TypeKindExt_StaticMethod: { - Assert(!"check"); - return 0; - } - case RDI_TypeKind_Struct: - case RDI_TypeKind_Class: - case RDI_TypeKind_IncompleteStruct: - case RDI_TypeKind_IncompleteClass: - return type->udt.struct_type.size; - - case RDI_TypeKind_Union: - case RDI_TypeKind_IncompleteUnion: - return type->udt.union_type.size; - - case RDI_TypeKind_Alias: - Assert(!"check"); - - case RDI_TypeKind_Enum: - case RDI_TypeKind_IncompleteEnum: - return rdib_size_from_type(type->udt.enum_type.base_type); - - case RDI_TypeKind_MemberPtr: - case RDI_TypeKind_Bitfield: - case RDI_TypeKind_Variadic: - case RDI_TypeKindExt_Members: - case RDI_TypeKindExt_Params: - InvalidPath; // no size - } - } - return 0; -} - -internal RDIB_TypeRef -rdib_make_type_ref(Arena *arena, RDIB_Type *type) -{ - RDIB_Type **ref = push_array(arena, RDIB_Type *, 1); - ref[0] = type; - return ref; -} - -internal void -rdib_deref_type_refs(TP_Context *tp, RDIB_TypeChunkList *list) -{ - for (RDIB_TypeChunk *chunk = list->first; chunk != 0; chunk = chunk->next) { - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - if (type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Class || - type->kind == RDI_TypeKind_IncompleteStruct || type->kind == RDI_TypeKind_IncompleteClass) { - type->udt.members = *(RDIB_Type **)type->udt.members; - type->udt.struct_type.derived = *(RDIB_Type **)type->udt.struct_type.derived; - type->udt.struct_type.vtshape = *(RDIB_Type **)type->udt.struct_type.vtshape; - } else if (type->kind == RDI_TypeKind_Enum || type->kind == RDI_TypeKind_IncompleteEnum) { - type->udt.members = *(RDIB_Type **)type->udt.members; - type->udt.enum_type.base_type = *(RDIB_Type **)type->udt.enum_type.base_type; - } else if (type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_IncompleteUnion) { - type->udt.members = *(RDIB_Type **)type->udt.members; - } else if (type->kind == RDI_TypeKind_Array) { - type->array.entry_type = *(RDIB_Type **)type->array.entry_type; - } else if (type->kind == RDI_TypeKind_Function) { - type->func.return_type = *(RDIB_Type **)type->func.return_type; - type->func.params_type = *(RDIB_Type **)type->func.params_type; - } else if (type->kind == RDI_TypeKind_Method) { - type->method.class_type = *(RDIB_Type **)type->method.class_type; - type->method.this_type = *(RDIB_Type **)type->method.this_type; - type->method.return_type = *(RDIB_Type **)type->method.return_type; - type->method.params_type = *(RDIB_Type **)type->method.params_type; - } else if (type->kind == RDI_TypeKindExt_StaticMethod) { - type->static_method.class_type = *(RDIB_Type **)type->static_method.class_type; - type->static_method.return_type = *(RDIB_Type **)type->static_method.return_type; - type->static_method.params_type = *(RDIB_Type **)type->static_method.params_type; - } else if (type->kind == RDI_TypeKind_Ptr || type->kind == RDI_TypeKind_LRef || type->kind == RDI_TypeKind_RRef) { - type->ptr.type_ref = *(RDIB_Type **)type->ptr.type_ref; - } else if (type->kind == RDI_TypeKind_Modifier) { - type->modifier.type_ref = *(RDIB_Type **)type->modifier.type_ref; - } else if (type->kind == RDI_TypeKind_Bitfield) { - type->bitfield.value_type = *(RDIB_Type **)type->bitfield.value_type; - } else if (type->kind == RDI_TypeKindExt_Params) { - for (U64 i = 0; i < type->params.count; ++i) { - type->params.types[i] = *(RDIB_Type **)type->params.types[i]; - } - } else if (type->kind == RDI_TypeKindExt_Members) { - for (RDIB_UDTMember *member = type->members.list.first; member != 0; member = member->next) { - switch (member->kind) { - case RDI_MemberKind_NULL: break; - case RDI_MemberKind_DataField: { - member->data_field.type_ref = *(RDIB_Type **)member->data_field.type_ref; - } break; - case RDI_MemberKind_StaticData: { - member->static_data.type_ref = *(RDIB_Type **)member->static_data.type_ref; - } break; - case RDI_MemberKind_Method: { - member->method.type_ref = *(RDIB_Type **)member->method.type_ref; - } break; - case RDI_MemberKind_NestedType: { - member->nested_type.type_ref = *(RDIB_Type **)member->nested_type.type_ref; - } break; - case RDI_MemberKind_Base: { - member->base_class.type_ref = *(RDIB_Type **)member->base_class.type_ref; - } break; - case RDI_MemberKind_VirtualBase: { - member->virtual_base_class.type_ref = *(RDIB_Type **)member->virtual_base_class.type_ref; - } break; - case RDI_MemberKindExt_MemberListPointer: { - member->member_list_pointer = *(RDIB_Type **)member->member_list_pointer; - } break; -#if 0 - case RDI_MemberKind_Enumerate: { - // no types - } break; -#endif - default: InvalidPath; - } - } - } - } - } -} - -internal U64 -rdib_sizeof_type(RDIB_Type *type) -{ - U64 size = 0; - if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind < RDI_TypeKind_LastBuiltIn) { - size = type->builtin.size; - } else if (type->kind == RDI_TypeKind_Modifier) { - size = rdib_sizeof_type(type->modifier.type_ref); - } else if (type->kind == RDI_TypeKind_Ptr || type->kind == RDI_TypeKind_LRef || type->kind == RDI_TypeKind_RRef) { - size = type->ptr.size; - } else if (type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Class || - type->kind == RDI_TypeKind_IncompleteStruct || type->kind == RDI_TypeKind_IncompleteClass) { - size = type->udt.struct_type.size; - } else if (type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_IncompleteUnion) { - size = type->udt.union_type.size; - } else if (type->kind == RDI_TypeKind_Enum || type->kind == RDI_TypeKind_IncompleteEnum) { - size = rdib_sizeof_type(type->udt.enum_type.base_type); - } else if (type->kind == RDI_TypeKind_Bitfield) { - size = rdib_sizeof_type(type->bitfield.value_type); - } else if (type->kind == RDI_TypeKind_Array) { - size = type->array.size; - } else { - Assert(!"error: type doens't have a size"); - } - return size; -} - -internal U64 -rdib_count_members_deep(RDIB_Type *type) -{ - U64 member_count = 0; - for (RDIB_UDTMember *member = type->members.list.first; member != 0; member = member->next) { - if (member->kind == RDI_MemberKindExt_MemberListPointer) { - member_count += rdib_count_members_deep(member->member_list_pointer); - } else { - member_count += 1; - } - } - return member_count; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_type_stats_task) -{ - ProfBeginFunction(); - - RDIB_TypeStatsTask *task = raw_task; - RDIB_TypeChunk *chunk = task->chunks[task_id]; - - for (U64 itype = 0; itype < chunk->count; ++itype) { - RDIB_Type *type = chunk->v + itype; - - if (type->kind == RDI_TypeKind_Class || type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_Enum) { - task->type_stats->udt_counts[task_id] += 1; - } - } - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_concat_members_task) -{ - ProfBeginFunction(); - RDIB_MembersTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - RDIB_UDTMemberList acc = {0}; - - for (RDIB_Type *curr = type; ;) { - // concat members - rdib_udt_member_list_concat_in_place(&acc, &curr->members.list); - - // does this type continue member list? - if (acc.count == 0 || acc.last->kind != RDI_MemberKindExt_MemberListPointer) { - break; - } - - // remove member list pointer - RDIB_UDTMember *continuation = acc.last; - SLLQueuePop(acc.first, acc.last); - --acc.count; - - // advance to next type - curr = continuation->member_list_pointer; - - // other types should not reference any part of member list except for head type. - Assert(curr->kind == RDI_TypeKindExt_Members); - curr->kind = RDI_TypeKind_NULL; - } - - // update member list - type->members.list = acc; - } - } - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_count_head_members_task) -{ - ProfBeginFunction(); - RDIB_MembersTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - if (type->kind == RDI_TypeKindExt_Members) { - task->counts[task_id] += type->members.list.count; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_assign_head_member_indices_task) -{ - ProfBeginFunction(); - RDIB_MembersTask *task = raw_task; - U64 cursor = task->offsets[task_id]; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - if (type->kind == RDI_TypeKindExt_Members) { - type->members.first_member_idx = cursor; - cursor += type->members.list.count; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_udt_members_task) -{ - ProfBeginFunction(); - RDIB_MembersTask *task = raw_task; - RDIB_TypeChunk *chunk = task->type_chunks[task_id]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = chunk->v + i; - Assert(type->kind == RDI_TypeKindExt_Members); - - U64 member_idx = 0; - for (RDIB_UDTMember *src = type->members.list.first; src != 0; src = src->next, ++member_idx) { - U64 idx = type->members.first_member_idx + member_idx; - RDI_Member *dst = &task->udt_members_rdi[idx]; - - switch (src->kind) { - case RDI_MemberKind_NULL: { - MemoryZeroStruct(dst); - } break; - case RDI_MemberKind_DataField: { - dst->kind = RDI_MemberKind_DataField; - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->data_field.name); - dst->type_idx = rdib_idx_from_type(src->data_field.type_ref); - dst->off = src->data_field.offset; - } break; - case RDI_MemberKind_StaticData: { - dst->kind = RDI_MemberKind_StaticData; - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->static_data.name); - dst->type_idx = rdib_idx_from_type(src->static_data.type_ref); - } break; - case RDI_MemberKind_Method: - case RDI_MemberKind_StaticMethod: - case RDI_MemberKind_VirtualMethod: { - dst->kind = src->kind; - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->method.name); - dst->type_idx = rdib_idx_from_type(src->method.type_ref); - dst->off = src->method.vftable_offset; - } break; - case RDI_MemberKind_Base: { - dst->kind = RDI_MemberKind_Base; - dst->name_string_idx = 0; - dst->type_idx = rdib_idx_from_type(src->base_class.type_ref); - dst->off = src->base_class.offset; - } break; - case RDI_MemberKind_VirtualBase: { - dst->kind = RDI_MemberKind_VirtualBase; - dst->name_string_idx = 0; - dst->type_idx = rdib_idx_from_type(src->virtual_base_class.type_ref); - dst->off = 0; // TODO: ??? - } break; - case RDI_MemberKind_NestedType: { - dst->kind = RDI_MemberKind_NestedType; - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->nested_type.name); - dst->type_idx = rdib_idx_from_type(src->nested_type.type_ref); - dst->off = 0; - } break; - case RDI_MemberKindExt_MemberListPointer: { - InvalidPath; - } break; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_enum_members_task) -{ - ProfBeginFunction(); - RDIB_MembersTask *task = raw_task; - RDIB_TypeChunk *chunk = task->type_chunks[task_id]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = chunk->v + i; - - if (type->kind != RDI_TypeKindExt_Members) continue; - - U64 member_idx = 0; - for (RDIB_UDTMember *src = type->members.list.first; src != 0; src = src->next, ++member_idx) { - U64 idx = type->members.first_member_idx + member_idx; - RDI_EnumMember *dst = &task->enum_members_rdi[idx]; - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->enumerate.name); - dst->val = src->enumerate.value; - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_udts_task) -{ - ProfBeginFunction(); - RDIB_UserDefinesTask *task = raw_task; - - U64 ichunk = task_id; - RDIB_TypeChunk *chunk = task->type_chunks[ichunk]; - U64 udt_cursor = task->udt_base_idx[ichunk]; - U64 udt_cap = task->type_stats.udt_counts[ichunk]; - - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - - if (RDI_IsCompleteUserDefinedTypeKind(type->kind)) { - RDIB_Type *members_type = type->udt.members; - - // assign UDT idx - type->udt.udt_idx = udt_cursor; - - // fill out struct/class UDT - Assert(udt_cursor < task->udt_base_idx[ichunk] + udt_cap); - RDI_UDT *udt = &task->udts[udt_cursor++]; - udt->self_type_idx = rdib_idx_from_type(type); - udt->flags = type->kind == RDI_TypeKind_Enum ? RDI_UDTFlag_EnumMembers : 0; - if (members_type->members.list.count > 0) { - udt->member_first = members_type->members.first_member_idx; - udt->member_count = members_type->members.list.count; - } else { - udt->member_first = 0; - udt->member_count = 0; - } - udt->file_idx = 0; - udt->line = 0; - udt->col = 0; - } - } - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_type_nodes_task) -{ - Temp scratch = scratch_begin(0, 0); - - U64 ichunk = task_id; - RDIB_TypeNodesTask *task = raw_task; - RDIB_TypeChunk *chunk = task->type_chunks[ichunk]; - - for (U64 itype = 0; itype < chunk->count; ++itype) { - RDIB_Type *src = &chunk->v[itype]; - U64 dst_idx = rdib_idx_from_type(src); - RDI_TypeNode *dst = &task->type_nodes[dst_idx]; - - if (src->kind == RDI_TypeKind_NULL) { - MemoryZeroStruct(dst); - dst->kind = RDI_TypeKind_NULL; - } else if (RDI_TypeKind_FirstBuiltIn <= src->kind && src->kind <= RDI_TypeKind_LastBuiltIn) { - dst->kind = src->kind; - dst->flags = 0; - dst->byte_size = src->builtin.size; - dst->built_in.name_string_idx = rdib_idx_from_string_map(task->string_map, src->builtin.name); - } else if (src->kind == RDI_TypeKind_Modifier) { - dst->kind = RDI_TypeKind_Modifier; - dst->byte_size = rdib_sizeof_type(src->modifier.type_ref); - dst->flags = src->modifier.flags; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->modifier.type_ref); - } else if (src->kind == RDI_TypeKind_Ptr || src->kind == RDI_TypeKind_LRef || src->kind == RDI_TypeKind_RRef) { - dst->kind = src->kind; - dst->byte_size = src->ptr.size; - dst->flags = 0; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->ptr.type_ref); - } else if (src->kind == RDI_TypeKind_Method) { - RDIB_Type *params_type = src->method.params_type; - Assert(params_type->kind == RDI_TypeKindExt_Params); - RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->method.param_idx_run_bucket_idx]; - - dst->kind = RDI_TypeKind_Method; - dst->flags = 0; - dst->byte_size = 0; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->method.return_type); - dst->constructed.count = param_idx_run->indices.count; - dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; - } else if (src->kind == RDI_TypeKindExt_StaticMethod) { - RDIB_Type *params_type = src->static_method.params_type; - Assert(params_type->kind == RDI_TypeKindExt_Params); - RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->static_method.param_idx_run_bucket_idx]; - - dst->kind = RDI_TypeKind_Method; - dst->flags = 0; - dst->byte_size = 0; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->static_method.return_type); - dst->constructed.count = param_idx_run->indices.count; - dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; - } else if (src->kind == RDI_TypeKind_Function) { - RDIB_Type *params_type = src->func.params_type; - Assert(params_type->kind == RDI_TypeKindExt_Params); - RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->func.param_idx_run_bucket_idx]; - - dst->kind = RDI_TypeKind_Function; - dst->flags = 0; - dst->byte_size = 0; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->func.return_type); - dst->constructed.count = param_idx_run->indices.count; - dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; - } else if (src->kind == RDI_TypeKind_Array) { - U64 entry_size = rdib_size_from_type(src->array.entry_type); - U64 array_size = src->array.size; - U64 array_count = entry_size > 0 ? array_size / entry_size : 0; - - dst->kind = src->kind; - dst->flags = 0; - dst->byte_size = array_size; - dst->constructed.direct_type_idx = rdib_idx_from_type(src->array.entry_type); - dst->constructed.count = array_count; - } else if (src->kind == RDI_TypeKind_Bitfield) { - dst->kind = RDI_TypeKind_Bitfield; - dst->flags = 0; - dst->byte_size = rdib_sizeof_type(src->bitfield.value_type); - dst->bitfield.direct_type_idx = rdib_idx_from_type(src->bitfield.value_type); - dst->bitfield.off = src->bitfield.off; - dst->bitfield.size = src->bitfield.count; - } else if (src->kind == RDI_TypeKind_Struct || src->kind == RDI_TypeKind_Class || - src->kind == RDI_TypeKind_IncompleteStruct || src->kind == RDI_TypeKind_IncompleteClass) { - dst->kind = src->kind; - dst->flags = 0; - dst->byte_size = src->udt.struct_type.size; - dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); - dst->user_defined.udt_idx = src->udt.udt_idx; - dst->user_defined.direct_type_idx = 0; - } else if (src->kind == RDI_TypeKind_Union || src->kind == RDI_TypeKind_IncompleteUnion) { - dst->kind = src->kind; - dst->flags = 0; - dst->byte_size = src->udt.union_type.size; - dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); - dst->user_defined.udt_idx = src->udt.udt_idx; - dst->user_defined.direct_type_idx = 0; - } else if (src->kind == RDI_TypeKind_Enum || src->kind == RDI_TypeKind_IncompleteEnum) { - dst->kind = RDI_TypeKind_Enum; - dst->flags = 0; - dst->byte_size = rdib_size_from_type(src->udt.enum_type.base_type); - dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); - dst->user_defined.udt_idx = src->udt.udt_idx; - dst->user_defined.direct_type_idx = rdib_idx_from_type(src->udt.enum_type.base_type); - } else if (src->kind == RDI_TypeKind_Alias) { - // TODO - NotImplemented; - } else if (src->kind == RDI_TypeKind_MemberPtr) { - // TODO - NotImplemented; - } else if (src->kind == RDI_TypeKind_Variadic) { - MemoryZeroStruct(dst); - dst->kind = RDI_TypeKind_Variadic; - } else if (src->kind == RDI_TypeKindExt_VirtualTable) { - // TODO - MemoryZeroStruct(dst); - dst->kind = RDI_TypeKind_NULL; - } else { - InvalidPath; - } - } - - scratch_end(scratch); -} - -internal void -rdib_data_sections_from_types(TP_Context *tp, - Arena *arena, - RDIB_DataSectionList *sect_list, - RDI_Arch arch, - RDIB_StringMap *string_map, - RDIB_IndexRunMap *idx_run_map, - U64 udt_member_chunk_count, - RDIB_TypeChunk **udt_member_type_chunks, - U64 enum_member_chunk_count, - RDIB_TypeChunk **enum_member_type_chunks, - U64 total_type_node_count, - U64 type_chunk_count, - RDIB_TypeChunk **type_chunks, - RDIB_TypeStats type_stats) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - ProfBegin("UDT Members"); - U64 udt_member_count_rdi; - RDI_Member *udt_members_rdi; - { - RDIB_MembersTask task = {0}; - - ProfBegin("Concat"); - task.ranges = tp_divide_work(scratch.arena, udt_member_chunk_count, tp->worker_count); - task.type_chunks = udt_member_type_chunks; - tp_for_parallel(tp, 0, tp->worker_count, rdib_concat_members_task, &task); - ProfEnd(); - - ProfBegin("Count"); - task.counts = push_array(scratch.arena, U64, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_count_head_members_task, &task); - ProfEnd(); - - ProfBegin("Assign Indices"); - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_assign_head_member_indices_task, &task); - ProfEnd(); - - udt_member_count_rdi = sum_array_u64(tp->worker_count, task.counts); - udt_members_rdi = push_array_no_zero(arena, RDI_Member, udt_member_count_rdi); - - ProfBegin("Fill"); - task.string_map = string_map; - task.udt_members_rdi = udt_members_rdi; - tp_for_parallel(tp, 0, udt_member_chunk_count, rdib_fill_udt_members_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Enum Members"); - U64 enum_member_count_rdi; - RDI_EnumMember *enum_members_rdi; - { - RDIB_MembersTask task = {0}; - - ProfBegin("Concat"); - task.ranges = tp_divide_work(scratch.arena, enum_member_chunk_count, tp->worker_count); - task.type_chunks = enum_member_type_chunks; - tp_for_parallel(tp, 0, tp->worker_count, rdib_concat_members_task, &task); - ProfEnd(); - - ProfBegin("Count"); - task.counts = push_array(scratch.arena, U64, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_count_head_members_task, &task); - ProfEnd(); - - ProfBegin("Assign Indices"); - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_assign_head_member_indices_task, &task); - ProfEnd(); - - enum_member_count_rdi = sum_array_u64(tp->worker_count, task.counts); - enum_members_rdi = push_array_no_zero(arena, RDI_EnumMember, enum_member_count_rdi); - - ProfBegin("Fill"); - task.string_map = string_map; - task.enum_members_rdi = enum_members_rdi; - tp_for_parallel(tp, 0, enum_member_chunk_count, rdib_fill_enum_members_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Sum type stats"); - U64 total_udt_count = sum_array_u64(type_chunk_count, type_stats.udt_counts); - ProfEnd(); - - ProfBegin("Up front pushes"); - RDI_UDT *udts = push_array_no_zero(arena, RDI_UDT, total_udt_count ); - RDI_TypeNode *type_nodes = push_array_no_zero(arena, RDI_TypeNode, total_type_node_count); - ProfEnd(); - - ProfBegin("Fill out UDTs"); - RDIB_UserDefinesTask udts_task = {0}; - udts_task.type_chunks = type_chunks; - udts_task.type_stats = type_stats; - udts_task.udt_base_idx = offsets_from_counts_array_u64(scratch.arena, type_stats.udt_counts, type_chunk_count); - udts_task.udts = udts; - tp_for_parallel(tp, 0, type_chunk_count, rdib_fill_udts_task, &udts_task); - ProfEnd(); - - ProfBegin("Fill out type nodes"); - RDIB_TypeNodesTask type_nodes_task = {0}; - type_nodes_task.addr_size = rdi_addr_size_from_arch(arch); - type_nodes_task.string_map = string_map; - type_nodes_task.idx_run_map = idx_run_map; - type_nodes_task.type_chunks = type_chunks; - type_nodes_task.type_stats = type_stats; - type_nodes_task.type_nodes = type_nodes; - tp_for_parallel(tp, 0, type_chunk_count, rdib_type_nodes_task, &type_nodes_task); - ProfEnd(); - - RDIB_DataSection udt_member_sect = { .tag = RDI_SectionKind_Members }; - RDIB_DataSection enum_member_sect = { .tag = RDI_SectionKind_EnumMembers }; - RDIB_DataSection udt_sect = { .tag = RDI_SectionKind_UDTs }; - RDIB_DataSection type_nodes_sect = { .tag = RDI_SectionKind_TypeNodes }; - - str8_list_push(arena, &udt_member_sect.data, str8_array(udt_members_rdi, udt_member_count_rdi )); - str8_list_push(arena, &enum_member_sect.data, str8_array(enum_members_rdi, enum_member_count_rdi)); - str8_list_push(arena, &udt_sect.data, str8_array(udts, total_udt_count )); - str8_list_push(arena, &type_nodes_sect.data, str8_array(type_nodes, total_type_node_count)); - - rdib_data_section_list_push(arena, sect_list, enum_member_sect); - rdib_data_section_list_push(arena, sect_list, udt_member_sect ); - rdib_data_section_list_push(arena, sect_list, udt_sect ); - rdib_data_section_list_push(arena, sect_list, type_nodes_sect ); - - scratch_end(scratch); - ProfEnd(); -} - -//////////////////////////////// - -internal RDIB_PathTree * -rdib_path_tree_init(Arena *arena, U64 list_count) -{ - RDIB_PathTree *tree = push_array(arena, RDIB_PathTree, 1); - tree->root = push_array(arena, RDIB_PathTreeNode, 1); - tree->list_count = list_count; - tree->node_lists = push_array(arena, RDIB_PathTreeNodeList, list_count); - return tree; -} - -internal void -rdib_path_tree_insert(Arena *arena, RDIB_PathTree *tree, String8 path, RDIB_SourceFile *src_file) -{ - Temp scratch = scratch_begin(&arena, 1); - - RDIB_PathTreeNode *curr_sub_path = tree->root; - String8List sub_paths = str8_split_path(scratch.arena, path); - str8_path_list_resolve_dots_in_place(&sub_paths, path_style_from_str8(path)); - - for (String8Node *n = sub_paths.first; n != 0; n = n->next) { - RDIB_PathTreeNode *sub_child; - - // is there directory or file defined on this level? - for (sub_child = curr_sub_path->first_child; sub_child != 0; sub_child = sub_child->next_sibling) { - if (str8_match(sub_child->sub_path, n->string, 0)) { - break; - } - } - - // new directory/file - if (sub_child == 0) { - sub_child = push_array(arena, RDIB_PathTreeNode, 1); - sub_child->node_idx = tree->node_count; - sub_child->parent = curr_sub_path; - sub_child->sub_path = n->string; - sub_child->src_file = 0; - SLLQueuePush_N(curr_sub_path->first_child, curr_sub_path->last_child, sub_child, next_sibling); - ++tree->node_count; - - // last node, insert file - if (n->next == 0) { - sub_child->src_file = src_file; - } - - // HACK: setup node list per thread for serialization step - U64 list_idx = tree->next_list_idx % tree->list_count; - SLLQueuePush_N(tree->node_lists[list_idx].first, tree->node_lists[list_idx].last, sub_child, next_order); - ++tree->next_list_idx; - } - - // descend to sub node - curr_sub_path = sub_child; - } - - scratch_end(scratch); -} - -internal U32 -rdib_idx_from_path_tree(RDIB_PathTree *tree, String8 path) -{ - Temp scratch = scratch_begin(0,0); - - // redirect to special nil string - if (path.size == 0) { - path = RDIB_PATH_TREE_NIL_STRING; - } - - // begin traverse from tree root - RDIB_PathTreeNode *curr_sub_path = tree->root; - - // split path & resolve dots - String8List sub_paths = str8_split_path(scratch.arena, path); - str8_path_list_resolve_dots_in_place(&sub_paths, path_style_from_str8(path)); - - for (String8Node *n = sub_paths.first; n != 0; n = n->next) { - // scan children sub-path match - RDIB_PathTreeNode *sub_child; - for (sub_child = curr_sub_path->first_child; sub_child != 0; sub_child = sub_child->next_sibling) { - if (str8_match(sub_child->sub_path, n->string, 0)) { - break; - } - } - - // found match? - if (sub_child == 0) { - break; - } - - // descend to sub directory - curr_sub_path = sub_child; - } - - // did we find source file? - U64 idx = 0; - if (curr_sub_path != 0 && curr_sub_path->src_file != 0) { - idx = curr_sub_path->node_idx; - } else { - Assert(!"unable to find source file path"); - } - - scratch_end(scratch); - return safe_cast_u32(idx); -} - - -//////////////////////////////// - -internal U64 -rdib_string_map_hash(String8 string) -{ - XXH64_hash_t hash64 = XXH3_64bits(string.str, string.size); - return hash64; -} - -internal RDIB_StringMap * -rdib_init_string_map(Arena *arena, U64 cap) -{ - RDIB_StringMap *string_map = push_array(arena, RDIB_StringMap, 1); - string_map->cap = (U64)((F64)cap * 1.3); - string_map->buckets = push_array(arena, RDIB_StringMapBucket *, string_map->cap); - return string_map; -} - -internal U32 -rdib_idx_from_string_map(RDIB_StringMap *string_map, String8 string) -{ - U64 hash = rdib_string_map_hash(string); - U64 best_idx = hash % string_map->cap; - U64 idx = best_idx; - - do { - RDIB_StringMapBucket *bucket = string_map->buckets[idx]; - - if (bucket == 0) { - break; - } - - if (str8_match(bucket->string, string, 0)) { - return safe_cast_u32(bucket->idx); - } - - idx = (idx + 1) % string_map->cap; - } while (idx != best_idx); - - Assert(!"incomplete string map"); - return max_U32; -} - -internal RDIB_StringMapBucket * -rdib_string_map_insert_or_update(RDIB_StringMapBucket **buckets, U64 cap, U64 hash, RDIB_StringMapBucket *new_bucket, RDIB_StringMapUpdateFunc *update_func) -{ - RDIB_StringMapBucket *result = 0; - B32 was_bucket_inserted_or_updated = 0; - - U64 best_idx = hash % cap; - U64 idx = best_idx; - - do { - retry:; - RDIB_StringMapBucket *curr_bucket = buckets[idx]; - - if (curr_bucket == 0) { - RDIB_StringMapBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - // success, bucket was inserted - was_bucket_inserted_or_updated = 1; - break; - } - - // another thread took the bucket... - goto retry; - } else if (str8_match(curr_bucket->string, new_bucket->string, 0)) { - if (curr_bucket->sorter.v <= new_bucket->sorter.v) { - if (new_bucket->raw_values != 0) { - void_node_concat_atomic(&curr_bucket->raw_values, new_bucket->raw_values); - new_bucket->raw_values = 0; - } - - // recycle bucket - result = new_bucket; - - // don't need to update, more recent leaf is in the bucket - was_bucket_inserted_or_updated = 1; - - break; - } - - if (new_bucket->raw_values) { - new_bucket->raw_values->next = buckets[idx]->raw_values; - } - - RDIB_StringMapBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - - // recycle bucket - result = compare_bucket; - - // new bucket is in the hash table, exit - was_bucket_inserted_or_updated = 1; - break; - } - - if (new_bucket->raw_values) { - new_bucket->raw_values->next = 0; - } - - // another thread took the bucket... - goto retry; - } - - // advance - idx = (idx + 1) % cap; - } while (idx != best_idx); - - // are there enough free buckets? - Assert(was_bucket_inserted_or_updated); - - return result; -} - -internal void -rdib_string_map_insert_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, void *value) -{ - // do we have a free bucket? - RDIB_StringMapBucket **bucket = &task->free_buckets[task_id]; - if (*bucket == 0) { - *bucket = push_array(arena, RDIB_StringMapBucket, 1); - } - - // fill out bucket - (*bucket)->string = string; - (*bucket)->raw_values = value; - (*bucket)->sorter.hi = safe_cast_u32(task_id); - (*bucket)->sorter.lo = safe_cast_u32(task->element_indices[task_id]); - - // insert bucket into string map - U64 hash = rdib_string_map_hash(string); - RDIB_StringMapBucket *insert_or_update = rdib_string_map_insert_or_update(task->string_map->buckets, task->string_map->cap, hash, *bucket, task->string_map_update_func); - - // advance element index - if (insert_or_update != *bucket) { - ++task->element_indices[task_id]; - } - - // recycle bucket - *bucket = insert_or_update; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_count_extant_buckets_string_map_task) -{ - ProfBeginFunction(); - RDIB_GetExtantBucketsStringMapTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - if (task->string_map->buckets[bucket_idx] != 0) { - task->counts[task_id] += 1; - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_get_extant_buckets_string_map_task) -{ - ProfBeginFunction(); - RDIB_GetExtantBucketsStringMapTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min, cursor = task->offsets[task_id]; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_StringMapBucket *bucket = task->string_map->buckets[bucket_idx]; - if (bucket != 0) { - task->result[cursor] = bucket; - ++cursor; - } - } - ProfEnd(); -} - -internal RDIB_StringMapBucket ** -rdib_extant_buckets_from_string_map(TP_Context *tp, Arena *arena, RDIB_StringMap *string_map, U64 *bucket_count_out) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - RDIB_GetExtantBucketsStringMapTask task = {0}; - task.string_map = string_map; - - ProfBegin("Count Extant Buckets"); - task.counts = push_array(scratch.arena, U64, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, string_map->cap, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_count_extant_buckets_string_map_task, &task); - ProfEnd(); - - *bucket_count_out = sum_array_u64(tp->worker_count, task.counts); - - ProfBegin("Copy Extant Buckets"); - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - task.result = push_array(arena, RDIB_StringMapBucket *, *bucket_count_out); - tp_for_parallel(tp, 0, tp->worker_count, rdib_get_extant_buckets_string_map_task, &task); - ProfEnd(); - - scratch_end(scratch); - ProfEnd(); - return task.result; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_string_map_bucket_chunk_idx_histo_task) -{ - ProfBeginFunction(); - RDIB_StringMapRadixSort *task = raw_task; - Temp scratch = scratch_begin(0,0); - - U32 *range_histo = push_array(scratch.arena, U32, task->chunk_idx_opl); - - // count items per sorter - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_StringMapBucket *bucket = task->src[bucket_idx]; - U64 chunk_idx = bucket->sorter.hi; - Assert(chunk_idx < task->chunk_idx_opl); - ++range_histo[chunk_idx]; - } - - // add in per thread sorter counts - for (U64 i = 0; i < task->chunk_idx_opl; ++i) { - ins_atomic_u32_add_eval(&task->chunk_histo[i], range_histo[i]); - } - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_string_map_radix_sort_chunk_idx_task) -{ - ProfBeginFunction(); - RDIB_StringMapRadixSort *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_StringMapBucket *bucket = task->src[bucket_idx]; - U32 chunk_idx = bucket->sorter.hi; - U32 dst_idx = ins_atomic_u32_inc_eval(&task->chunk_offsets[chunk_idx]) - 1; - task->dst[dst_idx] = bucket; - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_string_map_radix_sort_element_idx_task) -{ - ProfBeginFunction(); - RDIB_StringMapRadixSort *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - U64 range_lo = task->chunk_offsets[chunk_idx]; - U64 range_hi = task->chunk_offsets[chunk_idx] + task->chunk_histo[chunk_idx]; - - ProfBegin("Zero out Histogram"); - U32 histo_bot[1 << 10]; MemoryZeroArray(histo_bot); - U32 histo_mid[1 << 11]; MemoryZeroArray(histo_mid); - U32 histo_top[1 << 11]; MemoryZeroArray(histo_top); - ProfEnd(); - - ProfBegin("Element Histogram"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_StringMapBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit_bot = (elem_idx >> 0) % ArrayCount(histo_bot); - U32 digit_mid = (elem_idx >> 10) % ArrayCount(histo_mid); - U32 digit_top = (elem_idx >> 21) % ArrayCount(histo_top); - histo_bot[digit_bot] += 1; - histo_mid[digit_mid] += 1; - histo_top[digit_top] += 1; - } - ProfEnd(); - - ProfBegin("Histogram Counts -> Offsets"); - u32_array_counts_to_offsets(ArrayCount(histo_bot), &histo_bot[0]); - u32_array_counts_to_offsets(ArrayCount(histo_mid), &histo_mid[0]); - u32_array_counts_to_offsets(ArrayCount(histo_top), &histo_top[0]); - ProfEnd(); - - ProfBegin("Sort Bot"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_StringMapBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 0) % ArrayCount(histo_bot); - U32 src_idx = range_lo + histo_bot[digit]++; - task->src[src_idx] = elem; - } - ProfEnd(); - - ProfBegin("Sort Mid"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_StringMapBucket *elem = task->src[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 10) % ArrayCount(histo_mid); - U32 dst_idx = range_lo + histo_mid[digit]++; - task->dst[dst_idx] = elem; - } - ProfEnd(); - - ProfBegin("Sort Top"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_StringMapBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 21) % ArrayCount(histo_top); - U32 src_idx = range_lo + histo_top[digit]++; - task->src[src_idx] = elem; - } - ProfEnd(); - } - - ProfEnd(); -} - -internal void -rdib_string_map_sort_buckets(TP_Context *tp, RDIB_StringMapBucket **buckets, U64 bucket_count, U64 chunk_idx_opl) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0,0); - - RDIB_StringMapRadixSort task = {0}; - task.chunk_idx_opl = chunk_idx_opl; - task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); - task.src = buckets; - task.dst = push_array_no_zero(scratch.arena, RDIB_StringMapBucket *, bucket_count); - - ProfBegin("Chunk Index Histogram"); - task.chunk_histo = push_array(scratch.arena, U32, chunk_idx_opl); - tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_bucket_chunk_idx_histo_task, &task); - ProfEnd(); - - // sort correctness check on chunk index -#if 0 - for (U64 i = 1; i < bucket_count; ++i) { - RDIB_StringMapBucket *prev = buckets[i - 1]; - RDIB_StringMapBucket *curr = buckets[i + 0]; - U32 prev_chunk_idx = prev->sorter.hi; - U32 curr_chunk_idx = curr->sorter.hi; - AssertAlways(prev_chunk_idx <= curr_chunk_idx); - } -#endif - - ProfBegin("Chunk Histo -> Offsets"); - task.chunk_offsets = u32_array_offsets_from_counts(scratch.arena, task.chunk_histo, chunk_idx_opl); - ProfEnd(); - - ProfBegin("Sort on chunk index"); - tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_radix_sort_chunk_idx_task, &task); - ProfEnd(); - - ProfBegin("Sort on element index"); - task.chunk_offsets = u32_array_offsets_from_counts(scratch.arena, task.chunk_histo, chunk_idx_opl); - task.ranges = tp_divide_work(scratch.arena, chunk_idx_opl, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_radix_sort_element_idx_task, &task); - ProfEnd(); - - // sort correctness check on element index -#if 0 - { - for (U64 i = 1; i < bucket_count; ++i) { - RDIB_StringMapBucket *prev = buckets[i - 1]; - RDIB_StringMapBucket *curr = buckets[i + 0]; - U32 prev_chunk_idx = prev->sorter.hi; - U32 curr_chunk_idx = curr->sorter.hi; - if (prev_chunk_idx == curr_chunk_idx) { - U32 prev_elem_idx = prev->sorter.lo; - U32 curr_elem_idx = curr->sorter.lo; - AssertAlways(prev_elem_idx < curr_elem_idx); - } - } - } -#endif - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_string_map_assign_indices(RDIB_StringMapBucket **buckets, U64 bucket_count) -{ - ProfBeginFunction(); - for (U64 idx = 0; idx < bucket_count; ++idx) { - buckets[idx]->idx = idx; - } - ProfEnd(); -} - -// Specialized Inserts - -internal void -rdib_string_map_insert_string_table_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string) -{ - rdib_string_map_insert_item(arena, task, task_id, string, 0); -} - -internal void -rdib_string_map_insert_name_map_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, VoidNode *node) -{ - rdib_string_map_insert_item(arena, task, task_id, string, node); -} - -internal -RDIB_STRING_MAP_UPDATE_FUNC(rdib_string_map_update_null) -{ - // null update -} - -internal -RDIB_STRING_MAP_UPDATE_FUNC(rdib_string_map_update_concat_void_list_atomic) -{ - node->next = ins_atomic_ptr_eval_assign(head, node); -} - -//////////////////////////////// -// String Table Tasks - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_sects_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 sect_idx = task->ranges[task_id].min; sect_idx < task->ranges[task_id].max; ++sect_idx) { - RDIB_BinarySection *sect = &task->sects[sect_idx]; - rdib_string_map_insert_string_table_item(arena, task, task_id, sect->name); - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_units_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_UnitChunk *chunk = task->units[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Unit *unit = &chunk->v[i]; - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->unit_name); - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->compiler_name); - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->source_file); - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->object_file); - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->archive_file); - rdib_string_map_insert_string_table_item(arena, task, task_id, unit->build_path); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_source_files_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_SourceFile *src_file = chunk->v + i; - rdib_string_map_insert_string_table_item(arena, task, task_id, src_file->normal_full_path); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_vars_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->vars[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Variable *var = &chunk->v[i]; - rdib_string_map_insert_string_table_item(arena, task, task_id, var->name); - rdib_string_map_insert_string_table_item(arena, task, task_id, var->link_name); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_procs_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Procedure *proc = &chunk->v[i]; - rdib_string_map_insert_string_table_item(arena, task, task_id, proc->name); - rdib_string_map_insert_string_table_item(arena, task, task_id, proc->link_name); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_inline_sites_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_InlineSiteChunk *chunk = task->inline_sites[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_InlineSite *inline_site = &chunk->v[i]; - rdib_string_map_insert_string_table_item(arena, task, task_id, inline_site->name); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_udt_members_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_UDTMemberChunk *chunk = task->udt_members[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_UDTMember *udt_member = &chunk->v[i]; - switch (udt_member->kind) { - case RDI_MemberKind_NULL : break; - case RDI_MemberKind_DataField : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->data_field.name ); break; - case RDI_MemberKind_StaticData : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->static_data.name); break; - case RDI_MemberKind_Method : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->method.name ); break; - case RDI_MemberKind_NestedType : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->nested_type.name); break; - case RDI_MemberKind_Base : break; - case RDI_MemberKind_VirtualBase : break; - //case RDI_MemberKind_Enumerate : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->enumerate.name); break; - case RDI_MemberKindExt_MemberListPointer: break; - default: InvalidPath; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_enum_members_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_UDTMemberChunk *chunk = task->enum_members[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - rdib_string_map_insert_string_table_item(arena, task, task_id, chunk->v[i].enumerate.name); - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_types_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_TypeChunk *chunk = task->types[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Type *type = &chunk->v[i]; - if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) { - rdib_string_map_insert_string_table_item(arena, task, task_id, type->builtin.name); - } else if (RDI_IsUserDefinedType(type->kind)) { - rdib_string_map_insert_string_table_item(arena, task, task_id, type->udt.name); - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_collect_strings_path_nodes_task) -{ - ProfBeginFunction(); - RDIB_CollectStringsTask *task = raw_task; - for (RDIB_PathTreeNode *n = task->path_node_lists[task_id].first; n != 0; n = n->next_order) { - rdib_string_map_insert_string_table_item(arena, task, task_id, n->sub_path); - } - ProfEnd(); -} - -//////////////////////////////// -// Name Map Tasks - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_var_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->vars[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { - RDIB_Variable *n = &chunk->v[var_idx]; - nodes[var_idx].v = n; - rdib_string_map_insert_name_map_item(arena, task, task_id, n->name, &nodes[var_idx]); - } - } -} - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_var_link_name_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->vars[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { - RDIB_Variable *n = &chunk->v[var_idx]; - nodes[var_idx].v = n; - rdib_string_map_insert_name_map_item(arena, task, task_id, n->link_name, &nodes[var_idx]); - } - } -} - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_procedure_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - for (U64 proc_idx = 0; proc_idx < chunk->count; ++proc_idx) { - RDIB_Procedure *n = &chunk->v[proc_idx]; - nodes[proc_idx].v = n; - rdib_string_map_insert_name_map_item(arena, task, task_id, n->name, &nodes[proc_idx]); - } - } -} - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_procedures_link_name_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - for (U64 proc_idx = 0; proc_idx < chunk->count; ++proc_idx) { - RDIB_Procedure *n = &chunk->v[proc_idx]; - nodes[proc_idx].v = n; - rdib_string_map_insert_name_map_item(arena, task, task_id, n->link_name, &nodes[proc_idx]); - } - } -} - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_types_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_TypeChunk *chunk = task->types[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - VoidNode *node_cursor = nodes; - for (U64 type_idx = 0; type_idx < chunk->count; ++type_idx) { - RDIB_Type *type = &chunk->v[type_idx]; - node_cursor->v = type; - - if (RDI_IsUserDefinedType(type->kind)) { - rdib_string_map_insert_name_map_item(arena, task, task_id, type->udt.name, node_cursor); - ++node_cursor; - } - } - } -} - -internal -THREAD_POOL_TASK_FUNC(rdib_name_map_normal_paths_task) -{ - RDIB_CollectStringsTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; - VoidNode *nodes = push_array(arena, VoidNode, chunk->count); - VoidNode *node_cursor = nodes; - for (U64 i = 0; i < chunk->count; ++i, ++node_cursor) { - node_cursor->v = &chunk->v[i]; - rdib_string_map_insert_name_map_item(arena, task, task_id, chunk->v[i].normal_full_path, node_cursor); - } - } -} - -//////////////////////////////// -// Index Run Map - -internal U64 -rdib_index_run_hash(U32 count, U32 *idxs) -{ - XXH64_hash_t hash64 = XXH3_64bits(idxs, count * sizeof(idxs[0])); - return hash64; -} - -internal RDIB_IndexRunMap * -rdib_init_index_run_map(Arena *arena, U64 cap) -{ - ProfBeginFunction(); - RDIB_IndexRunMap *map = push_array(arena, RDIB_IndexRunMap, 1); - map->cap = cap; - map->buckets = push_array(arena, RDIB_IndexRunBucket *, cap); - ProfEnd(); - return map; -} - -internal RDIB_IndexRunBucket * -rdib_index_run_map_insert_or_update(Arena *arena, RDIB_IndexRunBucket **buckets, U64 cap, U64 hash, RDIB_IndexRunBucket *new_bucket, U64 *bucket_idx_out) -{ - B32 was_bucket_inserted_or_updated = 0; - - RDIB_IndexRunBucket *result = 0; - - U64 best_idx = hash % cap; - U64 idx = best_idx; - - do { - retry:; - RDIB_IndexRunBucket *curr_bucket = buckets[idx]; - - if (curr_bucket == 0) { - RDIB_IndexRunBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - - if (compare_bucket == curr_bucket) { - // success, bucket was inserted - was_bucket_inserted_or_updated = 1; - break; - } - - // another thread took the bucket... - goto retry; - } else if (u32_array_compare(curr_bucket->indices, new_bucket->indices)) { - if (curr_bucket->sorter.v <= new_bucket->sorter.v) { - // recycle bucket - result = new_bucket; - - // don't need to update, more recent leaf is in the bucket - was_bucket_inserted_or_updated = 1; - break; - } - - RDIB_IndexRunBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); - if (compare_bucket == curr_bucket) { - // recycle bucket - result = compare_bucket; - - // new bucket is in the hash table, exit - was_bucket_inserted_or_updated = 1; - break; - } - - // another thread took the bucket... - goto retry; - } - - // advance - idx = (idx + 1) % cap; - } while (idx != best_idx); - - // are there enough free buckets? - Assert(was_bucket_inserted_or_updated); - - // output bucket index - *bucket_idx_out = idx; - - return result; -} - -internal U32 -rdib_idx_run_from_bucket_idx(RDIB_IndexRunMap *map, U64 bucket_idx) -{ - RDIB_IndexRunBucket *bucket = map->buckets[bucket_idx]; - U32 idx_run32 = safe_cast_u32(bucket->index_in_output_array); - return idx_run32; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_count_extant_buckets_index_run_map_task) -{ - ProfBeginFunction(); - RDIB_GetExtantBucketsIndexRunMapTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - if (task->idx_run_map->buckets[bucket_idx] != 0) { - task->counts[task_id] += 1; - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_get_extant_buckets_index_run_map_task) -{ - ProfBeginFunction(); - RDIB_GetExtantBucketsIndexRunMapTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min, cursor = task->offsets[task_id]; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_IndexRunBucket *bucket = task->idx_run_map->buckets[bucket_idx]; - if (bucket != 0) { - task->result[cursor] = bucket; - ++cursor; - } - } - ProfEnd(); -} - -internal RDIB_IndexRunBucket ** -rdib_extant_buckets_from_index_run_map(TP_Context *tp, Arena *arena, RDIB_IndexRunMap *idx_run_map, U64 *bucket_count_out) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - RDIB_GetExtantBucketsIndexRunMapTask task = {0}; - task.idx_run_map = idx_run_map; - - ProfBegin("Count Extant Buckets"); - task.counts = push_array(scratch.arena, U64, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, idx_run_map->cap, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_count_extant_buckets_index_run_map_task, &task); - ProfEnd(); - - *bucket_count_out = sum_array_u64(tp->worker_count, task.counts); - - ProfBegin("Copy Extant Buckets"); - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - task.result = push_array(arena, RDIB_IndexRunBucket *, *bucket_count_out); - tp_for_parallel(tp, 0, tp->worker_count, rdib_get_extant_buckets_index_run_map_task, &task); - ProfEnd(); - - scratch_end(scratch); - ProfEnd(); - return task.result; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_index_run_map_bucket_chunk_idx_histo_task) -{ - ProfBeginFunction(); - RDIB_IndexRunMapRadixSort *task = raw_task; - Temp scratch = scratch_begin(0,0); - - U32 *range_histo = push_array(scratch.arena, U32, task->chunk_idx_opl); - - // count items per sorter - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_IndexRunBucket *bucket = task->src[bucket_idx]; - U32 chunk_idx = bucket->sorter.hi; - Assert(chunk_idx < task->chunk_idx_opl); - ++range_histo[chunk_idx]; - } - - // add in per thread sorter counts - for (U64 i = 0; i < task->chunk_idx_opl; ++i) { - ins_atomic_u32_add_eval(&task->chunk_histo[i], range_histo[i]); - } - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_index_run_map_radix_sort_chunk_idx_task) -{ - ProfBeginFunction(); - RDIB_IndexRunMapRadixSort *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_IndexRunBucket *bucket = task->src[bucket_idx]; - U32 chunk_idx = bucket->sorter.hi; - U32 dst_idx = ins_atomic_u32_inc_eval(&task->chunk_offsets[chunk_idx]) - 1; - task->dst[dst_idx] = bucket; - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_index_run_map_radix_sort_element_idx_task) -{ - ProfBeginFunction(); - RDIB_IndexRunMapRadixSort *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - U64 range_lo = task->chunk_offsets[chunk_idx]; - U64 range_hi = task->chunk_offsets[chunk_idx] + task->chunk_histo[chunk_idx]; - - ProfBegin("Zero out Histogram"); - U32 histo_bot[1 << 10]; MemoryZeroArray(histo_bot); - U32 histo_mid[1 << 11]; MemoryZeroArray(histo_mid); - U32 histo_top[1 << 11]; MemoryZeroArray(histo_top); - ProfEnd(); - - ProfBegin("Element Histogram"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_IndexRunBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit_bot = (elem_idx >> 0) % ArrayCount(histo_bot); - U32 digit_mid = (elem_idx >> 10) % ArrayCount(histo_mid); - U32 digit_top = (elem_idx >> 21) % ArrayCount(histo_top); - histo_bot[digit_bot] += 1; - histo_mid[digit_mid] += 1; - histo_top[digit_top] += 1; - } - ProfEnd(); - - ProfBegin("Histogram Counts -> Offsets"); - u32_array_counts_to_offsets(ArrayCount(histo_bot), &histo_bot[0]); - u32_array_counts_to_offsets(ArrayCount(histo_mid), &histo_mid[0]); - u32_array_counts_to_offsets(ArrayCount(histo_top), &histo_top[0]); - ProfEnd(); - - ProfBegin("Sort Bot"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_IndexRunBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 0) % ArrayCount(histo_bot); - U32 src_idx = range_lo + histo_bot[digit]++; - task->src[src_idx] = elem; - } - ProfEnd(); - - ProfBegin("Sort Mid"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_IndexRunBucket *elem = task->src[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 10) % ArrayCount(histo_mid); - U32 dst_idx = range_lo + histo_mid[digit]++; - task->dst[dst_idx] = elem; - } - ProfEnd(); - - ProfBegin("Sort Top"); - for (U64 i = range_lo; i < range_hi; ++i) { - RDIB_IndexRunBucket *elem = task->dst[i]; - U32 elem_idx = elem->sorter.lo; - U32 digit = (elem_idx >> 21) % ArrayCount(histo_top); - U32 src_idx = range_lo + histo_top[digit]++; - task->src[src_idx] = elem; - } - ProfEnd(); - } - - ProfEnd(); -} - -internal void -rdib_index_run_map_sort_buckets(TP_Context *tp, RDIB_IndexRunBucket **buckets, U64 bucket_count, U64 chunk_idx_opl) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0,0); - - RDIB_IndexRunMapRadixSort task = {0}; - task.chunk_idx_opl = chunk_idx_opl; - task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); - task.src = buckets; - task.dst = push_array_no_zero(scratch.arena, RDIB_IndexRunBucket *, bucket_count); - - ProfBegin("Chunk Index Histogram"); - task.chunk_histo = push_array(scratch.arena, U32, chunk_idx_opl); - tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_bucket_chunk_idx_histo_task, &task); - ProfEnd(); - - // sort correctness check on chunk index -#if 0 - for (U64 i = 1; i < bucket_count; ++i) { - RDIB_StringMapBucket *prev = buckets[i - 1]; - RDIB_StringMapBucket *curr = buckets[i + 0]; - U32 prev_chunk_idx = RDIB_StringMap_ChunkIdx32FromSorter(prev->sorter); - U32 curr_chunk_idx = RDIB_StringMap_ChunkIdx32FromSorter(curr->sorter); - AssertAlways(prev_chunk_idx <= curr_chunk_idx); - } -#endif - - ProfBegin("Chunk Histo -> Offsets"); - task.chunk_offsets = u32_array_offsets_from_counts(scratch.arena, task.chunk_histo, chunk_idx_opl); - ProfEnd(); - - ProfBegin("Sort on chunk index"); - tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_radix_sort_chunk_idx_task, &task); - ProfEnd(); - - ProfBegin("Sort on element index"); - task.chunk_offsets = u32_array_offsets_from_counts(scratch.arena, task.chunk_histo, chunk_idx_opl); - task.ranges = tp_divide_work(scratch.arena, chunk_idx_opl, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_radix_sort_element_idx_task, &task); - ProfEnd(); - - // sort correctness check on element index -#if 0 - { - for (U64 i = 1; i < bucket_count; ++i) { - RDIB_IndexRunBucket *prev = buckets[i - 1]; - RDIB_IndexRunBucket *curr = buckets[i + 0]; - U32 prev_chunk_idx = prev->sorter.hi; - U32 curr_chunk_idx = curr->sorter.hi; - if (prev_chunk_idx == curr_chunk_idx) { - U32 prev_elem_idx = prev->sorter.lo; - U32 curr_elem_idx = curr->sorter.lo; - AssertAlways(prev_elem_idx < curr_elem_idx); - } - } - } -#endif - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_index_run_map_assign_indices(RDIB_IndexRunBucket **buckets, U64 bucket_count) -{ - ProfBeginFunction(); - for (U64 bucket_idx = 0, cursor = 0; bucket_idx < bucket_count; ++bucket_idx) { - buckets[bucket_idx]->index_in_output_array = cursor; - cursor += buckets[bucket_idx]->indices.count; - } - ProfEnd(); -} - -// index run map specialization - -internal U64 -rdib_index_run_map_insert_item(Arena *arena, RDIB_BuildIndexRunsTask *task, U64 worker_id, U64 item_idx, U64 count, U32 *idxs) -{ - Assert(item_idx < max_U32); - - // do we have a free bucket? - RDIB_IndexRunBucket *bucket = task->free_buckets[worker_id]; - if (bucket == 0) { - bucket = push_array(arena, RDIB_IndexRunBucket, 1); - } - - // fill out bucket - bucket->indices.count = count; - bucket->indices.v = idxs; - bucket->sorter.v = task->sorter_idx << 32 | (U32)item_idx; - - // insert bucket - U64 hash = rdib_index_run_hash(count, idxs); - U64 bucket_idx = max_U64; - RDIB_IndexRunBucket *free_bucket = rdib_index_run_map_insert_or_update(arena, - task->idx_run_map->buckets, - task->idx_run_map->cap, - hash, - bucket, - &bucket_idx); - Assert(bucket_idx != max_U64); - - // recycle bucket - task->free_buckets[worker_id] = free_bucket; - - return bucket_idx; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_idx_runs_params_task) -{ - ProfBeginFunction(); - - RDIB_BuildIndexRunsTask *task = raw_task; - RDIB_TypeChunk *chunk = task->type_chunks[task_id]; - - for (RDIB_Type *type = &chunk->v[0], *opl = chunk->v + chunk->count; type < opl; ++type) { - if (type->kind == RDI_TypeKind_Function) { - RDIB_Type *params = type->func.params_type; - - // pack params - U64 type_index_count = params->params.count; - U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); - for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { - type_indices[param_idx] = rdib_idx_from_type(params->params.types[param_idx]); - } - - // insert type indices - U32 func_type_idx = rdib_idx_from_type(type); - type->func.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, func_type_idx, type_index_count, type_indices); - } else if (type->kind == RDI_TypeKind_Method) { - RDIB_Type *params = type->method.params_type; - - U64 type_index_count = params->params.count + 1; - U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); - U64 type_idx_cursor = 0; - - // pack 'this' type - type_indices[type_idx_cursor++] = rdib_idx_from_type(type->method.this_type); - - // pack params - for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { - type_indices[type_idx_cursor++] = rdib_idx_from_type(params->params.types[param_idx]); - } - - // insert type indices - U32 method_type_idx = rdib_idx_from_type(type); - type->method.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, method_type_idx, type_index_count, type_indices); - } else if (type->kind == RDI_TypeKindExt_StaticMethod) { - RDIB_Type *params = type->static_method.params_type; - - U64 type_index_count = params->params.count + 1; - U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); - U64 type_idx_cursor = 0; - - // static methods don't have 'this' - type_indices[type_idx_cursor++] = 0; - - // pack params - for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { - type_indices[type_idx_cursor++] = rdib_idx_from_type(params->params.types[param_idx]); - } - - // insert type indices - U32 static_method_type_idx = rdib_idx_from_type(type); - type->static_method.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, static_method_type_idx, type_index_count, type_indices); - } - } - - ProfEnd(); -} - -internal U32 -rdib_idx_from_name_map_void_node(RDIB_BuildIndexRunsTask *task, VoidNode *node) -{ - U64 idx = 0; - switch (task->name_map_kind) { - case RDI_NameMapKind_NULL : break; - case RDI_NameMapKind_GlobalVariables : idx = rdib_idx_from_variable ((RDIB_Variable* ) node); break; - case RDI_NameMapKind_ThreadVariables : idx = rdib_idx_from_variable ((RDIB_Variable * ) node); break; - case RDI_NameMapKind_Procedures : idx = rdib_idx_from_procedure ((RDIB_Procedure * ) node); break; - case RDI_NameMapKind_Types : idx = rdib_idx_from_type ((RDIB_Type * ) node); break; - case RDI_NameMapKind_LinkNameProcedures: idx = rdib_idx_from_procedure ((RDIB_Procedure * ) node); break; - case RDI_NameMapKind_NormalSourcePaths : idx = rdib_idx_from_source_file((RDIB_SourceFile *) node); break; - default: InvalidPath; - } - U32 idx32 = safe_cast_u32(idx); - return idx32; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_idx_runs_name_map_buckets_task) -{ - ProfBeginFunction(); - - RDIB_BuildIndexRunsTask *task = raw_task; - - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_StringMapBucket *bucket = task->name_map_buckets[bucket_idx]; - U64 count = void_list_count_nodes(bucket->raw_values); - - if (count > 1) { - // build array of indices that point to name map respective arrays - U32 *idxs = push_array_no_zero(arena, U32, count); - { - U64 curr_idx = 0; - for (VoidNode *curr = bucket->raw_values; curr != 0; curr = curr->next, ++curr_idx) { - idxs[curr_idx] = rdib_idx_from_name_map_void_node(task, curr->v); - } - } - - // make index array deterministic - u32_array_sort(count, idxs); // TODO: we don't need to sort with one worker thread - - // :string_map_bucket_sorter_copy - U64 idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, bucket_idx, count, idxs); // TODO: fix `idx` leak when we insert same runs - - // fill out bucket - bucket->count = count; - bucket->idx_run_bucket_idx = idx_run_bucket_idx; - } if (count == 1) { - U32 match_idx = rdib_idx_from_name_map_void_node(task, bucket->raw_values->v); - - // fill out bucket - bucket->count = 1; - bucket->match_idx = match_idx; - } - } - - ProfEnd(); -} - -//////////////////////////////// - -#if 0 -internal U32 -rdib_idx_from_params(RDIB_IndexRunMap *map, RDIB_Type *params) -{ - Assert(params->kind == RDI_TypeKindExt_Params); - U32 idx = params->params.idx_run_bucket->index_in_output_array; - return idx; -} -#endif - -//////////////////////////////// -// Data Sections - -internal void -rdib_data_section_list_push_node(RDIB_DataSectionList *list, RDIB_DataSectionNode *node) -{ - SLLQueuePushCount(list, node); -} - -internal RDIB_DataSectionNode * -rdib_data_section_list_push(Arena *arena, RDIB_DataSectionList *list, RDIB_DataSection v) -{ - RDIB_DataSectionNode *node = push_array(arena, RDIB_DataSectionNode, 1); - node->v = v; - rdib_data_section_list_push_node(list, node); - return node; -} - -internal void -rdib_data_section_list_concat_in_place(RDIB_DataSectionList *list, RDIB_DataSectionList *to_concat) -{ - SLLConcatInPlace(list, to_concat); -} - -internal void -rdib_data_sections_from_top_level_info(Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_TopLevelInfo *src) -{ - ProfBeginFunction(); - - RDI_TopLevelInfo *dst = push_array(arena, RDI_TopLevelInfo, 1); - dst->arch = src->arch; - dst->exe_name_string_idx = rdib_idx_from_string_map(string_map, src->exe_name); - dst->exe_hash = src->exe_hash; - dst->voff_max = src->voff_max; - dst->producer_name_string_idx = rdib_idx_from_string_map(string_map, src->producer_string); - - RDIB_DataSection sect = { .tag = RDI_SectionKind_TopLevelInfo }; - str8_list_push(arena, §.data, str8_struct(dst)); - rdib_data_section_list_push(arena, sect_list, sect); - - ProfEnd(); -} - -internal void -rdib_data_sections_from_binary_sections(Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_BinarySection *binary_sects, U64 binary_sects_count) -{ - ProfBeginFunction(); - - RDI_BinarySection *dst_arr = push_array(arena, RDI_BinarySection, binary_sects_count); - - for (U64 sect_idx = 0; sect_idx < binary_sects_count; ++sect_idx) { - RDIB_BinarySection *src = &binary_sects[sect_idx]; - RDI_BinarySection *dst = &dst_arr[sect_idx]; - - dst->name_string_idx = rdib_idx_from_string_map(string_map, src->name); - dst->flags = src->flags; - dst->voff_first = src->voff_first; - dst->voff_opl = src->voff_opl; - dst->foff_first = src->foff_first; - dst->foff_opl = src->foff_opl; - } - - RDIB_DataSection sect = { .tag = RDI_SectionKind_BinarySections }; - str8_list_push(arena, §.data, str8_array(dst_arr, binary_sects_count)); - rdib_data_section_list_push(arena, sect_list, sect); - - ProfEnd(); -} - -internal void -rdib_data_sections_from_units(Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - RDIB_PathTree *path_tree, - U64 total_unit_count, - U64 unit_chunk_count, - RDIB_UnitChunk **unit_chunks) -{ - ProfBeginFunction(); - - RDI_Unit *dst_arr = push_array(arena, RDI_Unit, total_unit_count); - for (U64 chunk_idx = 0; chunk_idx < unit_chunk_count; chunk_idx += 1) { - RDIB_UnitChunk *chunk = unit_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; i += 1) { - RDIB_Unit *src = &chunk->v[i]; - U64 unit_idx = rdib_idx_from_unit(src); - RDI_Unit *dst = &dst_arr[unit_idx]; - dst->unit_name_string_idx = rdib_idx_from_string_map(string_map, src->unit_name); - dst->compiler_name_string_idx = rdib_idx_from_string_map(string_map, src->compiler_name); - dst->source_file_path_node = rdib_idx_from_path_tree(path_tree, src->source_file); - dst->object_file_path_node = rdib_idx_from_path_tree(path_tree, src->object_file); - dst->archive_file_path_node = rdib_idx_from_path_tree(path_tree, src->archive_file); - dst->build_path_node = rdib_idx_from_path_tree(path_tree, src->build_path); - dst->language = src->language; - dst->line_table_idx = src->line_table->output_array_idx; - } - } - - RDIB_DataSection sect = { .tag = RDI_SectionKind_Units }; - str8_list_push(arena, §.data, str8_array(dst_arr, total_unit_count)); - rdib_data_section_list_push(arena, sect_list, sect); - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_unit_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_UnitChunk *chunk = task->unit_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Unit *unit = &chunk->v[i]; - task->counts[task_id] += unit->virt_range_count; - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_gvar_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->gvar_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Variable *var = &chunk->v[i]; - for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { - task->counts[task_id] += loc_n->v.ranges.count; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_scope_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ScopeChunk *chunk = task->scope_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - task->counts[task_id] += chunk->v[i].ranges.count; - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_unit_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - U64 range_cursor = task->offsets[task_id]; - U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_UnitChunk *chunk = task->unit_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Unit *unit = &chunk->v[i]; - for (Rng1U64 *range_ptr = unit->virt_ranges, *range_opl = unit->virt_ranges + unit->virt_range_count; - range_ptr < range_opl; ++range_ptr) { - Assert(range_cursor < range_cursor_opl); - Assert(range_ptr->min <= range_ptr->max); - - RDIB_VMapRange *vmap_range = task->vmap + range_cursor; - vmap_range->voff = range_ptr->min; - vmap_range->size = range_ptr->max - range_ptr->min; - vmap_range->idx = rdib_idx_from_unit(unit); - range_cursor += 1; - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_gvar_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - - U64 range_cursor = task->offsets[task_id]; - U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->gvar_chunks[chunk_idx]; - for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { - RDIB_Variable *var = &chunk->v[var_idx]; - for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { - for (Rng1U64Node *range_n = loc_n->v.ranges.first; range_n != 0; range_n = range_n->next) { - Assert(range_cursor < range_cursor_opl); - Assert(range_n->v.min <= range_n->v.max); - U64 size = range_n->v.max - range_n->v.min; - - RDIB_VMapRange *vmap_range = task->vmap + range_cursor; - vmap_range->voff = range_n->v.min; - vmap_range->size = size; - vmap_range->idx = rdib_idx_from_variable(var); - range_cursor += 1; - } - } - } - } - - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_scope_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - - U64 range_cursor = task->offsets[task_id]; - U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ScopeChunk *chunk = task->scope_chunks[chunk_idx]; - for (U64 scope_idx = 0; scope_idx < chunk->count; ++scope_idx) { - RDIB_Scope *scope = &chunk->v[scope_idx]; - for (Rng1U64Node *range_n = scope->ranges.first; range_n != 0; range_n = range_n->next) { - Assert(range_cursor < range_cursor_opl); - Assert(range_n->v.min <= range_n->v.max); - - RDIB_VMapRange *vmap_range = task->vmap + range_cursor; - vmap_range->voff = range_n->v.min; - vmap_range->size = range_n->v.max - range_n->v.min; - vmap_range->idx = rdib_idx_from_scope(scope); - range_cursor += 1; - } - } - } - - ProfEnd(); -} - -internal void -rdib_sort_procs_radix_32(RDIB_Procedure **v, U64 count) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0,0); - - RDIB_Procedure **temp = push_array_no_zero(scratch.arena, RDIB_Procedure *, count); - RDIB_Procedure **src = v; - RDIB_Procedure **dst = temp; - - ProfBegin("Count Memzero"); - U32 count_8lo[256]; MemoryZeroArray(count_8lo); - U32 count_8hi[256]; MemoryZeroArray(count_8hi); - U32 count_16[1 << 16]; MemoryZeroArray(count_16); - ProfEnd(); - - ProfBegin("Histogram"); - for (U64 i = 0; i < count; i += 1) { - RDIB_Procedure *p = src[i]; - - U64 digit_8lo = (p->scope->ranges.first->v.min >> 0) % ArrayCount(count_8lo); - U64 digit_8hi = (p->scope->ranges.first->v.min >> 8) % ArrayCount(count_8hi); - U64 digit_16 = (p->scope->ranges.first->v.min >> 16) % ArrayCount(count_16); - - count_8lo[digit_8lo] += 1; - count_8hi[digit_8hi] += 1; - count_16[digit_16] += 1; - } - ProfEnd(); - - ProfBegin("Counts -> Offsets"); - u32_array_counts_to_offsets(ArrayCount(count_8lo), count_8lo); - u32_array_counts_to_offsets(ArrayCount(count_8hi), count_8hi); - u32_array_counts_to_offsets(ArrayCount(count_16), count_16 ); - ProfEnd(); - - ProfBegin("Order 8 Lo"); - for (U64 i = 0; i < count; i += 1) { - RDIB_Procedure *p = src[i]; - U64 digit = (p->scope->ranges.first->v.min >> 0) % ArrayCount(count_8lo); - dst[count_8lo[digit]++] = p; - } - ProfEnd(); - - ProfBegin("Order 8 Hi"); - for (U64 i = 0; i < count; i += 1) { - RDIB_Procedure *p = dst[i]; - U64 digit = (p->scope->ranges.first->v.min >> 8) % ArrayCount(count_8hi); - src[count_8hi[digit]++] = p; - } - ProfEnd(); - - ProfBegin("Order 16"); - for (U64 i = 0; i < count; i += 1) { - RDIB_Procedure *p = src[i]; - U64 digit = (p->scope->ranges.first->v.min >> 16) % ArrayCount(count_16); - dst[count_16[digit]++] = p; - } - ProfEnd(); - - MemoryCopyTyped(src, dst, count); - - scratch_end(scratch); - ProfEnd(); -} - -internal String8List -rdib_data_from_vmap(Arena *arena, U64 range_count, RDIB_VMapRange *ranges) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - const U64 size_bit_count0 = 8; - const U64 size_bit_count1 = 8; - const U64 size_bit_count2 = 16; - - const U64 voff_bit_count0 = 11; - const U64 voff_bit_count1 = 11; - const U64 voff_bit_count2 = 10; - - ProfBegin("Push shared buffer"); - U64 radix_memory_size = sizeof(RDIB_VMapRange) * range_count + - sizeof(U32) * ((1 << size_bit_count0) + (1 << size_bit_count1) + (1 << size_bit_count2)) + - sizeof(U32) * ((1 << voff_bit_count0) + (1 << voff_bit_count1) + (1 << voff_bit_count2)); - U8 *radix_memory = push_array_no_zero(arena, U8, radix_memory_size); - ProfEnd(); - - // TODO: windows caps images at 4GiB so we use 32-bit radix sort, but on linux - // images can have > 4GiB and we need to detect when vmap uses upper 32bits - // in voffs do a 64-bit radix sort. - ProfBegin("Sort"); - { - RDIB_VMapRange *src = ranges; - RDIB_VMapRange *dst = (RDIB_VMapRange *)radix_memory; - - U32 *size_count0 = (U32 *)(dst + range_count); - U32 *size_count1 = size_count0 + (1 << size_bit_count0); - U32 *size_count2 = size_count1 + (1 << size_bit_count1); - - U32 *voff_count0 = size_count2 + (1 << size_bit_count2); - U32 *voff_count1 = voff_count0 + (1 << voff_bit_count0); - U32 *voff_count2 = voff_count1 + (1 << voff_bit_count1); - - // - // Build histogram - // - - MemoryZeroTyped(size_count0, 1 << size_bit_count0); - MemoryZeroTyped(size_count1, 1 << size_bit_count1); - MemoryZeroTyped(size_count2, 1 << size_bit_count2); - - MemoryZeroTyped(voff_count0, 1 << voff_bit_count0); - MemoryZeroTyped(voff_count1, 1 << voff_bit_count1); - MemoryZeroTyped(voff_count2, 1 << voff_bit_count2); - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange *r = src+i; - - U32 size_digit0 = (-r->size >> 0) % (1 << size_bit_count0); - U32 size_digit1 = (-r->size >> size_bit_count0) % (1 << size_bit_count1); - U32 size_digit2 = (-r->size >> (size_bit_count0 + size_bit_count1)) % (1 << size_bit_count2); - - U64 voff_digit0 = (r->voff >> 0) % (1 << voff_bit_count0); - U64 voff_digit1 = (r->voff >> voff_bit_count0) % (1 << voff_bit_count1); - U64 voff_digit2 = (r->voff >> (voff_bit_count0 + voff_bit_count1)) % (1 << voff_bit_count2); - - ++size_count0[size_digit0]; - ++size_count1[size_digit1]; - ++size_count2[size_digit2]; - - ++voff_count0[voff_digit0]; - ++voff_count1[voff_digit1]; - ++voff_count2[voff_digit2]; - } - - u32_array_counts_to_offsets((1 << size_bit_count0), size_count0); - u32_array_counts_to_offsets((1 << size_bit_count1), size_count1); - u32_array_counts_to_offsets((1 << size_bit_count2), size_count2); - - u32_array_counts_to_offsets((1 << voff_bit_count0), voff_count0); - u32_array_counts_to_offsets((1 << voff_bit_count1), voff_count1); - u32_array_counts_to_offsets((1 << voff_bit_count2), voff_count2); - - // - // Sort on range size (high to low) - // - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = src[i]; - U32 digit = (-r.size >> 0) % (1 << size_bit_count0); - dst[size_count0[digit]++] = r; - } - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = dst[i]; - U32 digit = (-r.size >> size_bit_count0) % (1 << size_bit_count1); - src[size_count1[digit]++] = r; - } - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = src[i]; - U32 digit = (-r.size >> (size_bit_count0 + size_bit_count1)) % (1 << size_bit_count2); - dst[size_count2[digit]++] = r; - } - - // - // Sort on range voff (low to high) - // - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = dst[i]; - U32 digit = (r.voff >> 0) % (1 << voff_bit_count0); - src[voff_count0[digit]++] = r; - } - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = src[i]; - U32 digit = (r.voff >> voff_bit_count0) % (1 << voff_bit_count1); - dst[voff_count1[digit]++] = r; - } - - for (U64 i = 0; i < range_count; ++i) { - RDIB_VMapRange r = dst[i]; - U32 digit = (r.voff >> (voff_bit_count0 + voff_bit_count1)) % (1 << voff_bit_count2); - src[voff_count2[digit]++] = r; - } - } - ProfEnd(); - - ProfBegin("Layout virtual map"); - String8List raw_vmap = {0}; - { - U64 default_vme_cap = 4096; - U64 vme_block_cap = radix_memory_size / sizeof(RDI_VMapEntry); - U64 vme_block_size = 0; - RDI_VMapEntry *vme_block = (RDI_VMapEntry *)radix_memory; - - // Recycle radix sort memory - str8_list_push(arena, &raw_vmap, str8_array(vme_block, vme_block_cap)); - -#define push_vme() (vme_block_size < raw_vmap.last->string.size/sizeof(vme_block[0])) ? &vme_block[vme_block_size++] : \ - (vme_block = push_array(arena, RDI_VMapEntry, vme_block_cap), \ - vme_block_cap = default_vme_cap, \ - vme_block_size = 0, \ - str8_list_push(arena, &raw_vmap, str8_array(vme_block, vme_block_cap)), \ - &vme_block[vme_block_size++]) - - struct Stack { - RDIB_VMapRange *range; - struct Stack *next; - }; - struct Stack *stack = 0; - struct Stack *free_stack = 0; - stack = push_array(scratch.arena, struct Stack, 1); - stack->range = &ranges[0]; - - for (U64 range_idx = 1; range_idx < range_count; ++range_idx) { - RDIB_VMapRange *r = ranges+range_idx; - RDIB_VMapRange *last_bot_range = stack->range; - RDIB_VMapRange *last_pop_range = 0; - while (stack->range->idx != 0) { - if (r->voff < stack->range->voff + stack->range->size) { - // Current range is a subset, keep building stack - break; - } - - struct Stack *frame = stack; - SLLStackPop(stack); - - // Did we reach bottom most range? - if (last_pop_range == 0) { - // Don't push VME for index with adjacent ranges - if (vme_block_size > 0 && vme_block[vme_block_size-1].idx != frame->range->idx) { - RDI_VMapEntry *vme = push_vme(); - vme->voff = frame->range->voff; - vme->idx = frame->range->idx; - } - } - - // Reopen parent range - // - // Does parent range extend past child range? - if (stack->range->voff + stack->range->size != frame->range->voff + frame->range->size && - // Does next range open on where stack range ends? - r->voff != frame->range->voff + frame->range->size) { - RDI_VMapEntry *vme = push_vme(); - vme->idx = stack->range->idx; - vme->voff = frame->range->voff + frame->range->size; - } - - last_pop_range = stack->range; - - // Recycle stack frame - SLLStackPush(free_stack, frame); - } - - // Prefix - if (last_pop_range == 0 && last_bot_range->voff != r->voff) { - RDI_VMapEntry* vme = push_vme(); - vme->voff = last_bot_range->voff; - vme->idx = last_bot_range->idx; - } - - struct Stack *frame; - if (free_stack == 0) { - frame = push_array(scratch.arena, struct Stack, 1); - } else { - frame = free_stack; - SLLStackPop(free_stack); - } - frame->range = r; - SLLStackPush(stack, frame); - } - - // Empty stack - { - RDIB_VMapRange *last_pop_range = 0; - while (stack->range->idx != 0) { - struct Stack *frame = stack; - SLLStackPop(stack); - - if (last_pop_range == 0) { - if (vme_block_size > 0 && vme_block[vme_block_size-1].idx != frame->range->idx) { - RDI_VMapEntry *vme = push_vme(); - vme->voff = frame->range->voff; - vme->idx = frame->range->idx; - } - } - - if (stack->range->voff + stack->range->size != frame->range->voff + frame->range->size) { - RDI_VMapEntry *vme = push_vme(); - vme->voff = frame->range->voff + frame->range->size; - vme->idx = stack->range->idx; - } - - last_pop_range = stack->range; - } - } - - // Subtract unsued vmap entries - U64 last_vme_unused = raw_vmap.last->string.size - sizeof(vme_block[0]) * vme_block_size; - raw_vmap.last->string.size -= last_vme_unused; - raw_vmap.total_size -= last_vme_unused; - -#undef push_vme - } - ProfEnd(); - - - // duplicate voff check -#if 0 - U64 prev = max_U64; - for (String8Node *node = raw_vmap.first; node != 0; node = node->next) { - RDI_VMapEntry *e = (RDI_VMapEntry*)node->string.str; - for (U64 i = 0, c = node->string.size / sizeof(RDI_VMapEntry); i < c; ++i) { - Assert(e[i].voff != prev); - prev = e[i].voff; - } - } -#endif - - scratch_end(scratch); - ProfEnd(); - return raw_vmap; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_scope_vmaps_task) -{ - ProfBeginFunction(); - RDIB_VMapBuilderTask *task = raw_task; - task->raw_vmaps[task_id] = rdib_data_from_vmap(arena, task->vmap_counts[task_id], task->vmaps[task_id]); - ProfEnd(); -} - -internal void -rdib_data_sections_from_unit_gvar_scope_vmaps(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks, - U64 gvar_chunk_count, RDIB_VariableChunk **gvar_chunks, - U64 scope_chunk_count, RDIB_ScopeChunk **scope_chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - RDIB_VMapBuilderTask task = {0}; - task.counts = push_array(scratch.arena, U64, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, unit_chunk_count, tp->worker_count); - - ProfBegin("Unit VMap"); - U64 unit_vmap_count; - RDIB_VMapRange *unit_vmaps; - { - ProfBegin("Count Ranges"); - MemoryZeroTyped(task.counts, tp->worker_count); - task.unit_chunks = unit_chunks; - task.ranges = tp_divide_work(scratch.arena, unit_chunk_count, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_unit_task, &task); - ProfEnd(); - - ProfBegin("Push"); - unit_vmap_count = sum_array_u64(tp->worker_count, task.counts); - unit_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, unit_vmap_count); - ProfEnd(); - - ProfBegin("Fill"); - task.vmap = unit_vmaps; - task.unit_chunks = unit_chunks; - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_unit_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Global Variables"); - U64 gvar_vmap_count; - RDIB_VMapRange *gvar_vmaps; - { - ProfBegin("Count"); - MemoryZeroTyped(task.counts, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, gvar_chunk_count, tp->worker_count); - task.gvar_chunks = gvar_chunks; - tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_gvar_task, &task); - ProfEnd(); - - ProfBegin("Push"); - gvar_vmap_count = sum_array_u64(tp->worker_count, task.counts); - gvar_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, gvar_vmap_count); - ProfEnd(); - - ProfBegin("Fill"); - task.vmap = gvar_vmaps; - task.gvar_chunks = gvar_chunks; - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_gvar_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Scopes"); - U64 scope_vmap_count; - RDIB_VMapRange *scope_vmaps; - { - ProfBegin("Count"); - MemoryZeroTyped(task.counts, tp->worker_count); - task.ranges = tp_divide_work(scratch.arena, scope_chunk_count, tp->worker_count); - task.scope_chunks = scope_chunks; - tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_scope_task, &task); - ProfEnd(); - - ProfBegin("Push"); - scope_vmap_count = sum_array_u64(tp->worker_count, task.counts); - scope_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, scope_vmap_count); - ProfEnd(); - - ProfBegin("Fill"); - task.vmap = scope_vmaps; - task.scope_chunks = scope_chunks; - task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_scope_task, &task); - ProfEnd(); - } - ProfEnd(); - - task.vmap_counts[0] = unit_vmap_count; - task.vmap_counts[1] = gvar_vmap_count; - task.vmap_counts[2] = scope_vmap_count; - task.vmaps[0] = unit_vmaps; - task.vmaps[1] = gvar_vmaps; - task.vmaps[2] = scope_vmaps; - - ProfBegin("Fill RDI VMaps"); - MemoryZeroArray(task.raw_vmaps); - tp_for_parallel(tp, arena, 3, rdib_fill_scope_vmaps_task, &task); - ProfEnd(); - - RDIB_DataSection unit_vmap_sect = { .tag = RDI_SectionKind_UnitVMap, .data = task.raw_vmaps[0] }; - RDIB_DataSection gvar_vmap_sect = { .tag = RDI_SectionKind_GlobalVMap, .data = task.raw_vmaps[1] }; - RDIB_DataSection scope_vmap_sect = { .tag = RDI_SectionKind_ScopeVMap, .data = task.raw_vmaps[2] }; - rdib_data_section_list_push(arena->v[0], sect_list, unit_vmap_sect ); - rdib_data_section_list_push(arena->v[0], sect_list, gvar_vmap_sect ); - rdib_data_section_list_push(arena->v[0], sect_list, scope_vmap_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_copy_string_data_task) -{ - RDIB_CopyStringDataTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_StringMapBucket *bucket = task->buckets[bucket_idx]; - U64 string_table_offset = task->string_table[bucket_idx]; - Assert(string_table_offset + bucket->string.size <= task->string_data_size); - MemoryCopy(task->string_data + string_table_offset, bucket->string.str, bucket->string.size); - } -} - -internal void -rdib_data_sections_from_string_map(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - // assign string table offset for each bucket - U64 cursor = 0; - U32 *string_table = push_array_no_zero(arena, U32, bucket_count); - for (U64 bucket_idx = 0; bucket_idx < bucket_count; ++bucket_idx) { - string_table[bucket_idx] = cursor; - cursor += buckets[bucket_idx]->string.size; - } - - // populate string data buffer with bucket strings - RDIB_CopyStringDataTask task = {0}; - task.string_table = string_table; - task.string_data_size = cursor; - task.string_data = push_array_no_zero(arena, U8, task.string_data_size); - task.buckets = buckets; - task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_copy_string_data_task, &task); - - // fill out string table section - RDIB_DataSection string_table_sect = {0}; - string_table_sect.tag = RDI_SectionKind_StringTable; - str8_list_push(arena, &string_table_sect.data, str8((U8 *)task.string_table, sizeof(task.string_table[0]) * bucket_count)); - - // fill out string data section - RDIB_DataSection string_data_sect = { .tag = RDI_SectionKind_StringData }; - str8_list_push(arena, &string_data_sect.data, str8(task.string_data, task.string_data_size)); - - // push sections to list - rdib_data_section_list_push(arena, sect_list, string_table_sect); - rdib_data_section_list_push(arena, sect_list, string_data_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_idx_run_copy_task) -{ - RDIB_IdxRunCopyTask *task = raw_task; - for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { - RDIB_IndexRunBucket *bucket = task->buckets[bucket_idx]; - MemoryCopyTyped(&task->output_array[bucket->index_in_output_array], bucket->indices.v, bucket->indices.count); - } -} - -internal void -rdib_data_sections_from_index_runs(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_IndexRunBucket **buckets, U64 bucket_count) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - ProfBegin("Count Indices"); - U64 total_index_count = 0; - for (U64 bucket_idx = 0; bucket_idx < bucket_count; ++bucket_idx) { - total_index_count += buckets[bucket_idx]->indices.count; - } - ProfEnd(); - - U32 *output_array = push_array_no_zero(arena, U32, total_index_count); - - RDIB_IdxRunCopyTask task = {0}; - task.buckets = buckets; - task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); - task.output_array = output_array; - tp_for_parallel(tp, 0, tp->worker_count, rdib_idx_run_copy_task, &task); - - RDIB_DataSection data_sect = { .tag = RDI_SectionKind_IndexRuns }; - str8_list_push(arena, &data_sect.data, str8_array(output_array, total_index_count)); - - rdib_data_section_list_push(arena, sect_list, data_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_file_path_nodes_task) -{ - ProfBeginFunction(); - RDIB_BuildFilePathNodesTask *task = raw_task; - RDIB_StringMap *string_map = task->string_map; - RDIB_PathTree *path_tree = task->path_tree; - for (RDIB_PathTreeNode *n = path_tree->node_lists[task_id].first; n != 0; n = n->next_order) { - RDI_FilePathNode *dst = task->nodes_dst + n->node_idx; - dst->name_string_idx = rdib_idx_from_string_map(string_map, n->sub_path); - - B32 is_source_file_node = (n->first_child == 0); - if (is_source_file_node) { - dst->source_file_idx = rdib_idx_from_source_file(n->src_file); - } else { - // directories don't have a source file - Assert(n->src_file == 0); - dst->source_file_idx = 0; - } - - if(n->parent) { - dst->parent_path_node = n->parent->node_idx; - } - if (n->first_child) { - dst->first_child = n->first_child->node_idx; - } - if (n->next_sibling) { - dst->next_sibling = n->next_sibling->node_idx; - } - } - ProfEnd(); -} - -internal void -rdib_data_sections_from_path_tree(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree) -{ - ProfBeginFunction(); - RDI_FilePathNode *nodes_dst = push_array_no_zero(arena, RDI_FilePathNode, path_tree->node_count); - - RDIB_BuildFilePathNodesTask task = {0}; - task.path_tree = path_tree; - task.string_map = string_map; - task.nodes_dst = nodes_dst; - tp_for_parallel(tp, 0, path_tree->list_count, rdib_build_file_path_nodes_task, &task); - - RDIB_DataSection data_sect = { .tag = RDI_SectionKind_FilePathNodes }; - str8_list_push(arena, &data_sect.data, str8_array(nodes_dst, path_tree->node_count)); - - rdib_data_section_list_push(arena, sect_list, data_sect); - - ProfEnd(); -} - -internal RDIB_PathTree * -rdib_build_path_tree(Arena *arena, - U64 worker_count, - RDIB_SourceFile *null_src_file, - U64 unit_chunk_count, - RDIB_UnitChunk **unit_chunks, - U64 src_file_chunk_count, - RDIB_SourceFileChunk **src_file_chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - RDIB_PathTree *tree = rdib_path_tree_init(arena, worker_count); - rdib_path_tree_insert(arena, tree, RDIB_PATH_TREE_NIL_STRING, null_src_file); - - ProfBegin("Units"); - for (U64 ichunk = 0; ichunk < unit_chunk_count; ++ichunk) { - RDIB_UnitChunk *chunk = unit_chunks[ichunk]; - for (U64 iunit = 0; iunit < chunk->count; ++iunit) { - RDIB_Unit *unit = &chunk->v[iunit]; - rdib_path_tree_insert(arena, tree, unit->source_file, null_src_file); - rdib_path_tree_insert(arena, tree, unit->object_file, null_src_file); - rdib_path_tree_insert(arena, tree, unit->archive_file, null_src_file); - rdib_path_tree_insert(arena, tree, unit->build_path, null_src_file); - } - } - ProfEnd(); - - ProfBegin("Source Files"); - for (U64 chunk_idx = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_SourceFile *src_file = chunk->v + i; - rdib_path_tree_insert(arena, tree, src_file->file_path, src_file); - } - } - ProfEnd(); - - scratch_end(scratch); - ProfEnd(); - return tree; -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_var_section_task) -{ - ProfBeginDynamic("Global Variables Task %llu", task_id); - RDIB_BuildSymbolSectionTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->gvars_rdib[chunk_idx]; - RDI_Symbol *vars = push_array_no_zero(arena, RDI_Symbol, chunk->count); - - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Variable *src = &chunk->v[i]; - RDI_Symbol *dst = &vars[i]; - - // TODO: temporary hack while we don't have bytecode eval in RDI_GlobalVariable - U64 voff = 0; - if (src->locations.first != 0) { - if (src->locations.first->v.kind == RDI_LocationKind_AddrBytecodeStream && src->locations.first->v.bytecode.first->op == RDI_EvalOp_ModuleOff) { - voff = src->locations.first->v.bytecode.first->p; - } - } - - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); - dst->type_idx = rdib_idx_from_type(src->type); - - if (src->container_type != 0) { - Assert(!src->container_proc); - dst->container_idx = rdib_idx_from_udt_type(src->container_type); - } - if (src->container_proc != 0) { - Assert(!src->container_type); - dst->container_idx = rdib_idx_from_procedure(src->container_proc); - } - } - - str8_list_push(arena, &task->gvars_out[task_id], str8_array(vars, chunk->count)); - } - - ProfEnd(); -} - -internal void -rdib_data_sections_from_global_variables(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - U64 total_count, - U64 chunk_count, - RDIB_VariableChunk **chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - ProfBegin("Build"); - RDIB_BuildSymbolSectionTask task = {0}; - task.string_map = string_map; - task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); - task.gvars_rdib = chunks; - task.gvars_out = push_array(scratch.arena, String8List, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, rdib_build_var_section_task, &task); - ProfEnd(); - - RDIB_DataSection gvars_sect = { .tag = RDI_SectionKind_GlobalVariables }; - str8_list_concat_in_place_array(&gvars_sect.data, task.gvars_out, tp->worker_count); - rdib_data_section_list_push(arena->v[0], sect_list, gvars_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_tvar_section_task) -{ - RDIB_BuildSymbolSectionTask *task = raw_task; - ProfBeginDynamic("Thread Variables Task [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_VariableChunk *chunk = task->tvars_rdib[chunk_idx]; - RDI_Symbol *vars = push_array_no_zero(arena, RDI_Symbol, chunk->count); - - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Variable *src = &chunk->v[i]; - RDI_Symbol *dst = &vars[i]; - - U32 tls_off = 0; - if (src->locations.first != 0) { - if (src->locations.first->v.kind == RDI_LocationKind_AddrBytecodeStream && src->locations.first->v.bytecode.first->op == RDI_EvalOp_TLSOff) { - tls_off = src->locations.first->v.bytecode.first->p; - } - } - - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); - dst->type_idx = rdib_idx_from_type(src->type); - - if (src->container_type != 0) { - Assert(!src->container_proc); - dst->container_idx = rdib_idx_from_udt_type(src->container_type); - } - if (src->container_proc != 0) { - Assert(!src->container_type); - dst->container_idx = rdib_idx_from_procedure(src->container_proc); - } - } - - str8_list_push(arena, &task->tvars_out[task_id], str8_array(vars, chunk->count)); - } - - ProfEnd(); -} - -internal void -rdib_data_sections_from_thread_variables(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - U64 total_count, - U64 chunk_count, - RDIB_VariableChunk **chunks) -{ - ProfBeginDynamic("Thread Variables [Chunk Count: %llu, Total Count %llu]", total_count, chunk_count); - Temp scratch = scratch_begin(arena->v, arena->count); - - ProfBegin("Build"); - RDIB_BuildSymbolSectionTask task = {0}; - task.string_map = string_map; - task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); - task.tvars_rdib = chunks; - task.tvars_out = push_array(scratch.arena, String8List, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, rdib_build_tvar_section_task, &task); - ProfEnd(); - - RDIB_DataSection tvars_sect = { .tag = RDI_SectionKind_ThreadVariables }; - str8_list_concat_in_place_array(&tvars_sect.data, task.tvars_out, tp->worker_count); - rdib_data_section_list_push(arena->v[0], sect_list, tvars_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_procs_section_task) -{ - RDIB_BuildSymbolSectionTask *task = raw_task; - ProfBeginDynamic("Procedures Task [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ProcedureChunk *chunk = task->procs_rdib[chunk_idx]; - RDI_Symbol *procs = push_array_no_zero(arena, RDI_Symbol, chunk->count); - - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_Procedure *src = &chunk->v[i]; - RDI_Symbol *dst = &procs[i]; - - dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); - dst->link_name_string_idx = rdib_idx_from_string_map(task->string_map, src->link_name); - dst->type_idx = rdib_idx_from_type(src->type); - dst->root_scope_idx = rdib_idx_from_scope(src->scope); - - if (src->container_type != 0) { - AssertAlways(!src->container_proc); - dst->container_idx = rdib_idx_from_udt_type(src->container_type); - } - - if (src->container_proc != 0) { - AssertAlways(!src->container_type); - dst->container_idx = rdib_idx_from_procedure(0); Assert(!"TODO"); // src->container_proc - } - } - - str8_list_push(arena, &task->procs_out[task_id], str8_array(procs, chunk->count)); - } - - ProfEnd(); -} - -internal void -rdib_data_sections_from_procedures(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - U64 total_count, - U64 chunk_count, - RDIB_ProcedureChunk **chunks) -{ - ProfBeginDynamic("Procedures [Total Count: %llu, Chunk Count: %llu]", total_count, chunk_count); - Temp scratch = scratch_begin(arena->v, arena->count); - - ProfBegin("Build"); - RDIB_BuildSymbolSectionTask task = {0}; - task.string_map = string_map; - task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); - task.procs_rdib = chunks; - task.procs_out = push_array(scratch.arena, String8List, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, rdib_build_procs_section_task, &task); - ProfEnd(); - - RDIB_DataSection procs_sect = { .tag = RDI_SectionKind_Procedures }; - str8_list_concat_in_place_array(&procs_sect.data, task.procs_out, tp->worker_count); - rdib_data_section_list_push(arena->v[0], sect_list, procs_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_count_scopes_task) -{ - ProfBeginFunction(); - RDIB_BuildSymbolSectionTask *task = raw_task; - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_ScopeChunk *chunk = task->scopes_rdib[chunk_idx]; - for (U64 scope_i = 0; scope_i < chunk->count; ++scope_i) { - RDIB_Scope *scope = &chunk->v[scope_i]; - - task->scope_voff_counts[task_id] += scope->ranges.count * 2; - task->local_counts[task_id] += scope->local_count; - - for (RDIB_Variable *var = scope->local_first; var != 0; var = var->next) { - for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { - switch (loc_n->v.kind) { - case RDI_LocationKind_NULL: break; - case RDI_LocationKind_AddrBytecodeStream: - case RDI_LocationKind_ValBytecodeStream: { - task->loc_data_sizes[task_id] += loc_n->v.bytecode.size + /* stream ender: */ 1; - } break; - case RDI_LocationKind_ValReg: { - //task->loc_data_sizes[task_id] += sizeof(RDI_LocationReg); - } break; - case RDI_LocationKind_AddrRegPlusOff: - case RDI_LocationKind_AddrAddrRegPlusOff: { - //task->loc_data_sizes[task_id] += sizeof(RDI_LocationRegPlusU16); - } break; - default: InvalidPath; - } - - task->loc_block_counts[task_id] += loc_n->v.ranges.count; - task->loc_data_sizes[task_id] += AlignPadPow2(task->loc_data_sizes[task_id], 8); - } - } - } - } - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_scopes_task) -{ -#if 0 - RDIB_BuildSymbolSectionTask *task = raw_task; - ProfBeginDynamic("Scopes [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); - - // scope voff fill info - U64 scope_voff_cursor = task->scope_voff_offsets[task_id]; - U64 scope_voff_max = task->scope_voff_offsets[task_id] + task->scope_voff_counts[task_id]; - U64 *scope_voff_ptr = task->scope_voffs_rdi; - - // local fill info - U64 local_cursor = task->local_offsets[task_id]; - U64 local_max = task->local_offsets[task_id] + task->local_counts[task_id]; - RDI_Symbol *locals = task->locals_rdi; - - // location data fill info - U64 loc_data_max = task->loc_data_offsets[task_id] + task->loc_data_sizes[task_id]; - U64 loc_data_cursor = task->loc_data_offsets[task_id]; - U8 *loc_data = task->loc_data_rdi; - - // location block fill info - U64 loc_block_cursor = task->loc_block_offsets[task_id]; - U64 loc_block_max = task->loc_block_offsets[task_id] + task->loc_block_counts[task_id]; - void *loc_blocks = task->loc_blocks_rdi; - - for (U64 ichunk = task->ranges[task_id].min; ichunk < task->ranges[task_id].max; ++ichunk) { - RDIB_ScopeChunk *chunk = task->scopes_rdib[ichunk]; - for (U64 iscope = 0; iscope < chunk->count; ++iscope) { - RDIB_Scope *scope_src = &chunk->v[iscope]; - U64 scope_idx = rdib_idx_from_scope(scope_src); - RDI_Scope *scope_dst = &task->scopes_rdi[scope_idx]; - - scope_dst->proc_idx = rdib_idx_from_procedure(scope_src->container_proc); - scope_dst->parent_scope_idx = rdib_idx_from_scope(scope_src->parent); - scope_dst->first_child_scope_idx = rdib_idx_from_scope(scope_src->first_child); - scope_dst->next_sibling_scope_idx = rdib_idx_from_scope(scope_src->next_sibling); - scope_dst->voff_range_first = scope_voff_cursor; - scope_dst->voff_range_opl = scope_voff_cursor + scope_src->ranges.count * 2; - scope_dst->local_count = scope_src->local_count; - if (scope_src->local_count > 0) { - scope_dst->local_first = local_cursor; - } else { - scope_dst->local_first = 0; - } - // TODO: static locals can be exported as local variables - //scope_dst->static_local_idx_run_first = ???; - //scope_dst->static_local_count = ???; - scope_dst->inline_site_idx = rdib_idx_from_inline_site(scope_src->inline_site); - - // fill out scope voffs - for (Rng1U64Node *range_n = scope_src->ranges.first; range_n != 0; range_n = range_n->next) { - Assert(scope_voff_cursor + 2 <= scope_voff_max); - scope_voff_ptr[scope_voff_cursor + 0] = range_n->v.min; - scope_voff_ptr[scope_voff_cursor + 1] = range_n->v.max; - scope_voff_cursor += 2; - } - - // fill out locals & locations - for (RDIB_Variable *local_src = scope_src->local_first; local_src != 0; local_src = local_src->next, ++local_cursor) { - U64 loc_block_first = loc_block_cursor; - - for (RDIB_LocationNode *loc_n = local_src->locations.first; loc_n != 0; loc_n = loc_n->next) { - RDIB_Location *loc = &loc_n->v; - - // fill out location data - U64 location_data_off = loc_data_cursor; - switch (loc->kind) { - case RDI_LocationKind_NULL: break; - case RDI_LocationKind_AddrBytecodeStream: - case RDI_LocationKind_ValBytecodeStream: { - // write opcodes & operands - for (RDIB_EvalBytecodeOp *op_node = loc->bytecode.first; op_node != 0; op_node = op_node->next) { - // opcode - Assert(loc_data_cursor + sizeof(op_node->op) <= loc_data_max); - MemoryCopy(loc_data + loc_data_cursor, &op_node->op, sizeof(op_node->op)); - loc_data_cursor += sizeof(op_node->op); - - // operand - Assert(loc_data_cursor + op_node->p_size <= loc_data_max); - MemoryCopy(loc_data + loc_data_cursor, &op_node->p, op_node->p_size); - loc_data_cursor += op_node->p_size; - } - - // stream ender - Assert(loc_data_cursor + 1 <= loc_data_max); - loc_data[loc_data_cursor] = 0; - loc_data_cursor += 1; - } break; - case RDI_LocationKind_AddrRegPlusOff: - case RDI_LocationKind_AddrAddrRegPlusOff: { - Assert(loc_data_cursor + sizeof(RDI_LocationRegPlusOff) <= loc_data_max); - RDI_LocationRegPlusU16 *dst = (RDI_LocationRegPlusOff *) (loc_data + loc_data_cursor); - dst->kind = loc->kind; - dst->reg_code = loc->reg_code; - dst->offset = loc->offset; - - loc_data_cursor += sizeof(*dst); - } break; - case RDI_LocationKind_ValReg: { - Assert(loc_data_cursor + sizeof(RDI_LocationReg) <= loc_data_max); - RDI_LocationReg *dst = (RDI_LocationReg *) (loc_data + loc_data_cursor); - dst->kind = loc->kind; - dst->reg_code = loc->reg_code; - loc_data_cursor += sizeof(*dst); - } break; - default: InvalidPath; - } - - // zero out align bytes - U64 align_size = AlignPadPow2(loc_data_cursor, 8); - Assert(loc_data_cursor + align_size <= loc_data_max); - MemorySet(loc_data + loc_data_cursor, 0, align_size); - loc_data_cursor += align_size; - - // fill out location block - for (Rng1U64Node *range_n = loc->ranges.first; range_n != 0; range_n = range_n->next, ++loc_block_cursor) { - Assert(loc_block_cursor < loc_block_max); - RDI_LocationBlock *loc_block_dst = &loc_blocks[loc_block_cursor]; - loc_block_dst->scope_off_first = range_n->v.min; - loc_block_dst->scope_off_opl = range_n->v.max; - loc_block_dst->location_data_off = location_data_off; - } - } - - Assert(local_cursor <= local_max); - RDI_Local *local_dst = &locals[local_cursor]; - local_dst->kind = local_src->kind; - local_dst->name_string_idx = rdib_idx_from_string_map(task->string_map, local_src->name); - local_dst->type_idx = rdib_idx_from_type(local_src->type); - if (local_src->locations.count > 0) { - local_dst->location_first = loc_block_first; - local_dst->location_opl = loc_block_cursor; - } else { - local_dst->location_first = 0; - local_dst->location_opl = 0; - } - } - } - } - - Assert(scope_voff_cursor == scope_voff_max); - Assert(local_cursor == local_max); - Assert(loc_data_cursor == loc_data_max); - - ProfEnd(); -#endif -} - -internal void -rdib_data_sections_from_scopes(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - U64 total_scope_count, - U64 chunk_count, - RDIB_ScopeChunk **scopes) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - RDIB_BuildSymbolSectionTask task = {0}; - task.string_map = string_map; - task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); - task.scopes_rdib = scopes; - - ProfBegin("Count Locals & Locations"); - task.scope_voff_counts = push_array(scratch.arena, U64, tp->worker_count); - task.local_counts = push_array(scratch.arena, U64, tp->worker_count); - task.loc_block_counts = push_array(scratch.arena, U64, tp->worker_count); - task.loc_data_sizes = push_array(scratch.arena, U64, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_count_scopes_task, &task); - ProfEnd(); - - U64 total_scope_voff_count = sum_array_u64(tp->worker_count, task.scope_voff_counts); - U64 total_local_count = sum_array_u64(tp->worker_count, task.local_counts ); - U64 total_loc_block_count = sum_array_u64(tp->worker_count, task.loc_block_counts ); - U64 total_loc_data_size = sum_array_u64(tp->worker_count, task.loc_data_sizes ); - - ProfBegin("Fill out scopes, locals, location blocks, and location data"); - task.scope_voff_offsets = offsets_from_counts_array_u64(scratch.arena, task.scope_voff_counts, tp->worker_count); - task.local_offsets = offsets_from_counts_array_u64(scratch.arena, task.local_counts, tp->worker_count); - task.loc_block_offsets = offsets_from_counts_array_u64(scratch.arena, task.loc_block_counts, tp->worker_count); - task.loc_data_offsets = offsets_from_counts_array_u64(scratch.arena, task.loc_data_sizes, tp->worker_count); - - ProfBegin("Push"); - task.scope_voffs_rdi = push_array_no_zero(arena->v[0], U64, total_scope_voff_count); - task.scopes_rdi = push_array_no_zero(arena->v[0], RDI_Scope, total_scope_count ); - //task.locals_rdi = push_array_no_zero(arena->v[0], RDI_Local, total_local_count ); - //task.loc_blocks_rdi = push_array_no_zero(arena->v[0], RDI_LocationBlock, total_loc_block_count ); - task.loc_data_rdi = push_array_no_zero(arena->v[0], U8, total_loc_data_size ); - ProfEnd(); - - tp_for_parallel(tp, 0, tp->worker_count, rdib_build_scopes_task, &task); - ProfEnd(); - - RDIB_DataSection scopes_sect = { .tag = RDI_SectionKind_Scopes }; - RDIB_DataSection scope_voffs_sect = { .tag = RDI_SectionKind_ScopeVOffData }; - RDIB_DataSection locals_sect = { .tag = RDI_SectionKind_NULL }; - RDIB_DataSection loc_blocks_sect = { .tag = RDI_SectionKind_NULL }; - RDIB_DataSection loc_data_sect = { .tag = RDI_SectionKind_NULL }; - - str8_list_push(arena->v[0], &scopes_sect.data, str8_array(task.scopes_rdi, total_scope_count )); - str8_list_push(arena->v[0], &scope_voffs_sect.data, str8_array(task.scope_voffs_rdi, total_scope_voff_count)); - str8_list_push(arena->v[0], &locals_sect.data, str8_array(task.locals_rdi, total_local_count )); - //str8_list_push(arena->v[0], &loc_blocks_sect.data, str8_array(task.loc_blocks_rdi, total_loc_block_count )); - str8_list_push(arena->v[0], &loc_data_sect.data, str8_array(task.loc_data_rdi, total_loc_data_size )); - - rdib_data_section_list_push(arena->v[0], sect_list, scopes_sect ); - rdib_data_section_list_push(arena->v[0], sect_list, scope_voffs_sect); - rdib_data_section_list_push(arena->v[0], sect_list, locals_sect ); - rdib_data_section_list_push(arena->v[0], sect_list, loc_blocks_sect ); - rdib_data_section_list_push(arena->v[0], sect_list, loc_data_sect ); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_name_map_task) -{ - ProfBeginFunction("Build Name Map"); - Temp scratch = scratch_begin(&arena, 1); - - RDIB_NameMapBuilderTask *task = raw_task; - RDI_NameMapKind name_map_idx = (RDI_NameMapKind)task_id; - - U64 out_node_count = task->in_bucket_counts[name_map_idx]; - U64 load_factor = 4; - U64 out_bucket_count = CeilIntegerDiv(out_node_count, load_factor); - - ProfBegin("Build temp hash map"); - struct Node { - struct Node *next; - RDIB_StringMapBucket *name; - }; - struct NodeList { - struct Node *first; - struct Node *last; - U64 node_count; - }; - struct NodeList *temp_map = push_array(scratch.arena, struct NodeList, out_bucket_count); - struct Node *temp_nodes = push_array_no_zero(scratch.arena, struct Node, out_node_count); - for (U64 i = 0; i < task->in_bucket_counts[name_map_idx]; ++i) { - RDIB_StringMapBucket *src_bucket = task->in_buckets[name_map_idx][i]; - - U64 hash = rdi_hash(src_bucket->string.str, src_bucket->string.size); - U64 bucket_idx = hash % out_bucket_count; - - struct Node *node = temp_nodes + i; - node->next = 0; - node->name = src_bucket; - - SLLQueuePush(temp_map[bucket_idx].first, temp_map[bucket_idx].last, node); - ++temp_map[bucket_idx].node_count; - } - ProfEnd(); - - ProfBegin("Push buckets and nodes"); - RDI_NameMapBucket *out_buckets = push_array_no_zero(arena, RDI_NameMapBucket, out_bucket_count); - RDI_NameMapNode *out_nodes = push_array_no_zero(arena, RDI_NameMapNode, out_node_count); - ProfEnd(); - - ProfBegin("Fill out buckets"); - for (U64 bucket_idx = 0, node_cursor = 0; bucket_idx < out_bucket_count; ++bucket_idx) { - struct NodeList *src_bucket = &temp_map[bucket_idx]; - RDI_NameMapBucket *dst_bucket = &out_buckets[bucket_idx]; - - if (src_bucket->node_count == 0) { - dst_bucket->first_node = 0; - dst_bucket->node_count = 0; - continue; - } - - dst_bucket->first_node = safe_cast_u32(node_cursor); - dst_bucket->node_count = src_bucket->node_count; - - for (struct Node *n = src_bucket->first; n != 0; n = n->next, ++node_cursor) { - RDIB_StringMapBucket *src_name = n->name; - - RDI_NameMapNode *dst_node = &out_nodes[node_cursor]; - dst_node->string_idx = rdib_idx_from_string_map(task->string_map, src_name->string); - dst_node->match_count = src_name->count; - if (src_name->count > 1) { - dst_node->match_idx_or_idx_run_first = task->idx_run_map->buckets[src_name->idx_run_bucket_idx]->index_in_output_array; - } else { - dst_node->match_idx_or_idx_run_first = src_name->match_idx; - } - } - } - ProfEnd(); - - // fill out output - task->out_buckets[name_map_idx] = out_buckets; - task->out_nodes[name_map_idx] = out_nodes; - task->out_bucket_counts[name_map_idx] = out_bucket_count; - task->out_node_counts[name_map_idx] = out_node_count; - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_data_sections_from_name_maps(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - RDIB_IndexRunMap *idx_run_map, - RDIB_StringMapBucket **src_name_maps[RDI_NameMapKind_COUNT], - U64 src_name_map_counts[RDI_NameMapKind_COUNT]) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - ProfBegin("Build Name Maps"); - RDIB_NameMapBuilderTask task = {0}; - task.string_map = string_map; - task.idx_run_map = idx_run_map; - task.in_bucket_counts = src_name_map_counts; - task.in_buckets = src_name_maps; - task.out_buckets = push_array(scratch.arena, RDI_NameMapBucket *, RDI_NameMapKind_COUNT); - task.out_nodes = push_array(scratch.arena, RDI_NameMapNode *, RDI_NameMapKind_COUNT); - task.out_bucket_counts = push_array(scratch.arena, U64, RDI_NameMapKind_COUNT); - task.out_node_counts = push_array(scratch.arena, U64, RDI_NameMapKind_COUNT); - tp_for_parallel(tp, arena, RDI_NameMapKind_COUNT, rdib_build_name_map_task, &task); - ProfEnd(); - - U64 *bucket_offsets = offsets_from_counts_array_u64(scratch.arena, task.out_bucket_counts, RDI_NameMapKind_COUNT); - U64 *node_offsets = offsets_from_counts_array_u64(scratch.arena, task.out_node_counts, RDI_NameMapKind_COUNT); - - String8List raw_name_maps = {0}, raw_name_map_buckets = {0}, raw_name_map_nodes = {0}; - for (U64 i = 0; i < RDI_NameMapKind_COUNT; ++i) { - RDI_NameMap *dst_name_map = push_array(arena->v[0], RDI_NameMap, 1); - dst_name_map->bucket_base_idx = bucket_offsets[i]; - dst_name_map->node_base_idx = node_offsets[i]; - dst_name_map->bucket_count = task.out_bucket_counts[i]; - dst_name_map->node_count = task.out_node_counts[i]; - - str8_list_push(arena->v[0], &raw_name_maps, str8_struct(dst_name_map)); - str8_list_push(arena->v[0], &raw_name_map_buckets, str8_array(task.out_buckets[i], task.out_bucket_counts[i])); - str8_list_push(arena->v[0], &raw_name_map_nodes, str8_array(task.out_nodes[i], task.out_node_counts[i])); - } - - RDIB_DataSection name_maps_sect = { .tag = RDI_SectionKind_NameMaps, .data = raw_name_maps }; - RDIB_DataSection name_map_buckets_sect = { .tag = RDI_SectionKind_NameMapBuckets, .data = raw_name_map_buckets }; - RDIB_DataSection name_map_nodes_sect = { .tag = RDI_SectionKind_NameMapNodes, .data = raw_name_map_nodes }; - rdib_data_section_list_push(arena->v[0], sect_list, name_maps_sect); - rdib_data_section_list_push(arena->v[0], sect_list, name_map_buckets_sect); - rdib_data_section_list_push(arena->v[0], sect_list, name_map_nodes_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_src_line_map_task) -{ - // Line tables are ordered to perform 'virtual offset -> line number' maps, - // and thus we potentially can have multiple virtual offsets map to same line number. - // (e.g. in C/C++ if for-loop declaration site is on one line, intial-statment-condition - // and expression parts map to same line number). And so to make things easy on debugger - // we remove duplicates from source line map and reorient mapping to 'line number -> virtual offset' - // this way debugger can quickly compute virtual offsets when placing a breakpoint on a source line. - - Temp scratch = scratch_begin(&arena, 1); - RDIB_SrcLineMapsTask *task = raw_task; - - RDIB_SourceFile *src_file = task->src_file_arr[task_id]; - U64 src_file_idx = rdib_idx_from_source_file(src_file); - - //ProfBeginDynamic("Build Source Line Map [%.*s]", str8_varg(src_file->file_path)); - ProfBegin("Build Source Line Map"); - - ProfBegin("Count lines/virt offsets"); - U64 ln_voff_count = 0; - for (RDIB_LineTableFragment *frag = src_file->line_table_frags; frag != 0; frag = frag->next_src_file) { - ln_voff_count += frag->line_count; - } - ProfEnd(); - - ProfBegin("Push ln_voff_arr"); - PairU32 *ln_voff_arr = push_array_no_zero(scratch.arena, PairU32, ln_voff_count); - ProfEnd(); - - ProfBegin("Fill out ln_voff_arr"); - { - U64 cursor = 0; - for (RDIB_LineTableFragment *frag = src_file->line_table_frags; frag != 0; frag = frag->next_src_file) { - for (U64 line_idx = 0; line_idx < frag->line_count; ++line_idx) { - ln_voff_arr[cursor].v0 = frag->line_nums[line_idx]; - ln_voff_arr[cursor].v1 = frag->voffs[line_idx]; - ++cursor; - } - } - } - ProfEnd(); - - // sort on line number - ProfBegin("Sort"); - if (ln_voff_count < 512) { - // TODO: Radsort is buggy and inifte loops if we sort pair of u64. - // Check-in with Jeff on Monday about bugfix. For now workaround - // the bug wiht pair of u32s. There is no virtual offset larger - // than 4GiB in line table anyway. - radsort(ln_voff_arr, ln_voff_count, pair_u32_is_before_v0); - } else { - u32_pair_sort_radix(ln_voff_count, ln_voff_arr); - } - ProfEnd(); - - // TODO: leak, precompute unique line number count and push exact array lengths - U32 *line_nums = push_array_no_zero(arena, U32, ln_voff_count); - U32 *line_ranges = push_array_no_zero(arena, U32, ln_voff_count + 1); - U64 *voffs = push_array_no_zero(arena, U64, ln_voff_count); - - U64 voff_cursor = 0; - U64 line_num_cursor = 0; - if (ln_voff_count > 0) { - line_nums[line_num_cursor] = ln_voff_arr[0].v0; - voffs[voff_cursor] = ln_voff_arr[0].v1; - line_ranges[line_num_cursor] = voff_cursor; - - ++voff_cursor; - ++line_num_cursor; - - ProfBegin("Fill out output array"); - for (U64 i = 1; i < ln_voff_count; ++i) { - // does this voff belong to next line number? - if (ln_voff_arr[i].v0 != line_nums[line_num_cursor-1]) { - line_nums[line_num_cursor] = ln_voff_arr[i].v0; - line_ranges[line_num_cursor] = (U32)voff_cursor; - ++line_num_cursor; - } - voffs[voff_cursor++] = ln_voff_arr[i].v1; - } - ProfEnd(); - - // did we fill out voff array correctly? - Assert(voff_cursor == ln_voff_count); - - // close last line range - line_ranges[line_num_cursor] = voff_cursor; - } - - // fill out result - task->out_line_counts[src_file_idx] = line_num_cursor; - task->out_voff_counts[src_file_idx] = safe_cast_u32(voff_cursor); - task->out_line_nums[src_file_idx] = line_nums; - task->out_line_ranges[src_file_idx] = line_ranges; - task->out_voffs[src_file_idx] = voffs; - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_data_sections_from_source_line_maps(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - U64 total_src_file_count, - U64 src_file_chunk_count, - RDIB_SourceFileChunk **src_file_chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - ProfBegin("Prepare Source File Array"); - RDIB_SourceFile **src_file_arr = push_array_no_zero(scratch.arena, RDIB_SourceFile *, total_src_file_count); - for (U64 chunk_idx = 0, cursor = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - src_file_arr[cursor++] = &chunk->v[i]; - } - } - ProfEnd(); - - ProfBegin("Init Task Context"); - RDIB_SrcLineMapsTask task = {0}; - task.src_file_arr = src_file_arr; - task.out_line_counts = push_array_no_zero(scratch.arena, U32, total_src_file_count); - task.out_voff_counts = push_array_no_zero(scratch.arena, U32, total_src_file_count); - task.out_line_nums = push_array_no_zero(scratch.arena, U32 *, total_src_file_count); - task.out_line_ranges = push_array_no_zero(scratch.arena, U32 *, total_src_file_count); - task.out_voffs = push_array_no_zero(scratch.arena, U64 *, total_src_file_count); - ProfEnd(); - - ProfBegin("Build Source Line Maps"); - tp_for_parallel(tp, arena, total_src_file_count, rdib_build_src_line_map_task, &task); - ProfEnd(); - - ProfBegin("Fill out Source Line Maps"); - RDIB_DataSection src_line_maps_sect = { .tag = RDI_SectionKind_SourceLineMaps }; - RDIB_DataSection src_line_nums_sect = { .tag = RDI_SectionKind_SourceLineMapNumbers }; - RDIB_DataSection src_line_ranges_sect = { .tag = RDI_SectionKind_SourceLineMapRanges }; - RDIB_DataSection src_line_voffs_sect = { .tag = RDI_SectionKind_SourceLineMapVOffs }; - - ProfBegin("Push"); - RDI_SourceLineMap *src_line_maps = push_array_no_zero(arena->v[0], RDI_SourceLineMap, total_src_file_count + 1); - ProfEnd(); - - U64 src_line_map_cursor = 0; - U64 line_num_cursor = 0; - U64 line_range_cursor = 0; - U64 voff_cursor = 0; - - // zero-out null source line map - MemoryZeroStruct(&src_line_maps[src_line_map_cursor]); - ++src_line_map_cursor; - - for (U64 chunk_idx = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_SourceFile *src_file = chunk->v + i; - U64 src_file_idx = rdib_idx_from_source_file(src_file); - - if (task.out_line_counts[src_file_idx] > 0) { - src_file->src_line_map_idx = src_line_map_cursor; - - RDI_SourceLineMap *sm = src_line_maps + src_line_map_cursor++; - sm->line_count = task.out_line_counts[src_file_idx]; - sm->voff_count = task.out_voff_counts[src_file_idx]; - sm->line_map_nums_base_idx = line_num_cursor; - sm->line_map_range_base_idx = line_range_cursor; - sm->line_map_voff_base_idx = voff_cursor; - - str8_list_push(arena->v[0], &src_line_nums_sect.data, str8_array(task.out_line_nums[src_file_idx], task.out_line_counts[src_file_idx])); - str8_list_push(arena->v[0], &src_line_ranges_sect.data, str8_array(task.out_line_ranges[src_file_idx], task.out_line_counts[src_file_idx] + 1)); - str8_list_push(arena->v[0], &src_line_voffs_sect.data, str8_array(task.out_voffs[src_file_idx], task.out_voff_counts[src_file_idx])); - - line_num_cursor += task.out_line_counts[src_file_idx]; - line_range_cursor += task.out_line_counts[src_file_idx] + 1; - voff_cursor += task.out_voff_counts[src_file_idx]; - } else { - src_file->src_line_map_idx = 0; - } - } - } - ProfEnd(); - - str8_list_push(arena->v[0], &src_line_maps_sect.data, str8_array(src_line_maps, src_line_map_cursor)); - - rdib_data_section_list_push(arena->v[0], sect_list, src_line_maps_sect); - rdib_data_section_list_push(arena->v[0], sect_list, src_line_nums_sect); - rdib_data_section_list_push(arena->v[0], sect_list, src_line_ranges_sect); - rdib_data_section_list_push(arena->v[0], sect_list, src_line_voffs_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_build_line_tables_task) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - RDIB_BuildLineTablesTask *task = raw_task; - Rng1U64 range = task->ranges[task_id]; - - for (U64 chunk_idx = range.min; chunk_idx < range.max; ++chunk_idx) { - RDIB_LineTableChunk *chunk = task->chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_LineTable *line_table = &chunk->v[i]; - U64 line_table_idx = chunk->base + i; - - U64 total_line_count = 0; - for (RDIB_LineTableFragment *frag = line_table->first; frag != 0; frag = frag->next_line_table) { - total_line_count += frag->line_count + /* range terminator */ 1; - } - - if (total_line_count > 0) { - struct Value { - U32 src_file_idx; - U32 line_num; - U16 col_first; - U16 col_opl; - }; - KeyValuePair *pairs = push_array_no_zero(scratch.arena, KeyValuePair, total_line_count); - struct Value *values = push_array_no_zero(scratch.arena, struct Value, total_line_count); - U64 pair_cursor = 0; - - for (RDIB_LineTableFragment *frag = line_table->first; frag != 0; frag = frag->next_line_table) { - for (U64 line_idx = 0; line_idx < frag->line_count; ++line_idx, ++pair_cursor) { - struct Value *value = &values[pair_cursor]; - KeyValuePair *pair = &pairs[pair_cursor]; - - value->src_file_idx = rdib_idx_from_source_file(frag->src_file); - value->line_num = frag->line_nums[line_idx]; - if (frag->col_count > 0) { - value->col_first = frag->col_nums[line_idx*2]; - value->col_opl = frag->col_nums[line_idx*2 + 1]; - } else { - value->col_first = 0; - value->col_opl = 0; - } - - pair->key_u64 = frag->voffs[line_idx]; - pair->value_raw = value; - } - - // emit terminator - { - KeyValuePair *pair = &pairs[pair_cursor]; - struct Value *value = &values[pair_cursor]; - pair_cursor += 1; - - value->src_file_idx = 0; - value->line_num = 0; - value->col_first = 0; - value->col_opl = 0; - - pair->key_u64 = frag->voffs[frag->line_count]; - pair->value_raw = value; - } - } - - // sort on virtual offset - sort_key_value_pairs_as_u64(pairs, pair_cursor); - - // fill out RDI_Line output - U64 line_count = pair_cursor + 1; - U64 *voffs = push_array_no_zero(arena, U64, line_count); - RDI_Line *lines = push_array_no_zero(arena, RDI_Line, line_count); - - U64 line_cursor = 0; - for (U64 line_idx = 0; line_idx < pair_cursor; ++line_idx) { - // remove terminator if there is a real line number - if (line_idx + 1 < pair_cursor && pairs[line_idx].key_u64 == pairs[line_idx+1].key_u64) { - continue; - } - struct Value *value = pairs[line_idx].value_raw; - voffs[line_cursor] = pairs[line_idx].key_u64; - lines[line_cursor].file_idx = value->src_file_idx; - lines[line_cursor].line_num = value->line_num; - line_cursor += 1; - } - - // fill out terminators - voffs[line_cursor] = ~0llu; - MemoryZeroStruct(&lines[line_cursor]); - line_cursor += 1; - - // fill out line table output - task->out_line_table_counts[line_table_idx] = line_cursor; - task->out_line_table_voffs[line_table_idx] = voffs; - task->out_line_table_lines[line_table_idx] = lines; - } else { - task->out_line_table_counts[line_table_idx] = 0; - task->out_line_table_voffs[line_table_idx] = 0; - task->out_line_table_lines[line_table_idx] = 0; - } - } - } - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_data_sections_from_line_tables(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - U64 total_line_table_count, - U64 chunk_count, - RDIB_LineTableChunk **chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0,0); - - ProfBegin("Build Line Tables"); - RDIB_BuildLineTablesTask task = {0}; - task.chunks = chunks; - task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); - task.out_line_table_counts = push_array_no_zero(scratch.arena, U64, total_line_table_count); - task.out_line_table_voffs = push_array_no_zero(scratch.arena, U64 *, total_line_table_count); - task.out_line_table_lines = push_array_no_zero(scratch.arena, RDI_Line *, total_line_table_count); - tp_for_parallel(tp, arena, tp->worker_count, rdib_build_line_tables_task, &task); - ProfEnd(); - - RDIB_DataSection line_tables_sect = { .tag = RDI_SectionKind_LineTables }; - RDIB_DataSection line_table_voffs_sect = { .tag = RDI_SectionKind_LineInfoVOffs }; - RDIB_DataSection line_table_lines_sect = { .tag = RDI_SectionKind_LineInfoLines }; - RDIB_DataSection line_table_cols_sect = { .tag = RDI_SectionKind_LineInfoColumns }; - - ProfBegin("Fill out Line Tables"); - - ProfBegin("Push"); - RDI_LineTable *line_tables_rdi = push_array_no_zero(arena->v[0], RDI_LineTable, total_line_table_count); - ProfEnd(); - - U64 line_table_cursor = 0; - U64 line_table_voff_cursor = 0; - U64 line_table_line_cursor = 0; - - for (U64 chunk_idx = 0; chunk_idx < chunk_count; ++chunk_idx) { - RDIB_LineTableChunk *chunk = chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_LineTable *src = &chunk->v[i]; - U64 src_idx = rdib_idx_from_line_table(src); - if (task.out_line_table_counts[src_idx] > 0) { - RDI_LineTable *dst = &line_tables_rdi[line_table_cursor]; - - src->output_array_idx = line_table_cursor; - - dst->voffs_base_idx = line_table_voff_cursor; - dst->lines_base_idx = line_table_line_cursor; - dst->cols_base_idx = 0; - dst->lines_count = task.out_line_table_counts[src_idx] - 1; - dst->cols_count = 0; - - str8_list_push(arena->v[0], &line_table_voffs_sect.data, str8_array(task.out_line_table_voffs[src_idx], task.out_line_table_counts[src_idx])); - str8_list_push(arena->v[0], &line_table_lines_sect.data, str8_array(task.out_line_table_lines[src_idx], task.out_line_table_counts[src_idx])); - - line_table_voff_cursor += task.out_line_table_counts[src_idx]; - line_table_line_cursor += task.out_line_table_counts[src_idx]; - - line_table_cursor += 1; - } else { - src->output_array_idx = 0; - } - } - } - - str8_list_push(arena->v[0], &line_tables_sect.data, str8_array(line_tables_rdi, line_table_cursor)); - - ProfEnd(); - - rdib_data_section_list_push(arena->v[0], sect_list, line_tables_sect); - rdib_data_section_list_push(arena->v[0], sect_list, line_table_voffs_sect); - rdib_data_section_list_push(arena->v[0], sect_list, line_table_lines_sect); - rdib_data_section_list_push(arena->v[0], sect_list, line_table_cols_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal -THREAD_POOL_TASK_FUNC(rdib_fill_src_files_task) -{ - RDIB_FillSourceFilesTask *task = raw_task; - - for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { - RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_SourceFile *src = chunk->v + i; - U32 src_file_idx = rdib_idx_from_source_file(src); - RDI_SourceFile *dst = task->src_files_dst + src_file_idx; - - dst->file_path_node_idx = rdib_idx_from_path_tree(task->path_tree, src->file_path); - dst->normal_full_path_string_idx = rdib_idx_from_string_map(task->string_map, src->normal_full_path); - dst->source_line_map_idx = src->src_line_map_idx; - } - } -} - -internal void -rdib_data_sections_from_source_files(TP_Context *tp, - TP_Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - RDIB_PathTree *path_tree, - U64 total_src_file_count, - U64 src_file_chunk_count, - RDIB_SourceFileChunk **src_file_chunks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - RDIB_FillSourceFilesTask task = {0}; - task.ranges = tp_divide_work(scratch.arena, src_file_chunk_count, tp->worker_count); - task.string_map = string_map; - task.path_tree = path_tree; - task.src_file_chunks = src_file_chunks; - task.src_files_dst = push_array_no_zero(arena->v[0], RDI_SourceFile, total_src_file_count); - tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_src_files_task, &task); - - RDIB_DataSection src_files_sect = { .tag = RDI_SectionKind_SourceFiles }; - str8_list_push(arena->v[0], &src_files_sect.data, str8_array(task.src_files_dst, total_src_file_count)); - rdib_data_section_list_push(arena->v[0], sect_list, src_files_sect); - - scratch_end(scratch); - ProfEnd(); -} - -internal void -rdib_data_sections_from_inline_sites(TP_Context *tp, - Arena *arena, - RDIB_DataSectionList *sect_list, - RDIB_StringMap *string_map, - U64 total_inline_site_count, - U64 inline_site_chunk_count, - RDIB_InlineSiteChunk **inline_site_chunks) -{ - ProfBeginFunction(); - - RDI_InlineSite *dst_arr = push_array(arena, RDI_InlineSite, total_inline_site_count); - - for (U64 chunk_idx = 0; chunk_idx < inline_site_chunk_count; ++chunk_idx) { - RDIB_InlineSiteChunk *chunk = inline_site_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - RDIB_InlineSite *src = &chunk->v[i]; - U64 idx = rdib_idx_from_inline_site(src); - RDI_InlineSite *dst = &dst_arr[idx]; - - dst->name_string_idx = rdib_idx_from_string_map(string_map, src->name); - dst->type_idx = rdib_idx_from_type(src->type); - dst->owner_type_idx = rdib_idx_from_type(src->owner); - dst->line_table_idx = src->line_table->output_array_idx; - } - } - - RDIB_DataSection inline_site_sect = { .tag = RDI_SectionKind_InlineSites }; - str8_list_push(arena, &inline_site_sect.data, str8_array(dst_arr, total_inline_site_count)); - rdib_data_section_list_push(arena, sect_list, inline_site_sect); - - ProfEnd(); -} - -internal void -rdib_data_sections_from_checksums(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list) -{ - NotImplemented; -} - -//////////////////////////////// - -internal RDIB_Input -rdib_init_input(Arena *arena) -{ - ProfBeginFunction(); - - RDIB_Input input = {0}; - input.unit_chunk_cap = 128; - input.src_file_chunk_cap = 4096; - input.symbol_chunk_cap = 4096; - input.line_table_cap = 4096; - input.inline_site_cap = 4096; - input.type_cap = 1024; - input.udt_cap = 4096; - - RDIB_SourceFile *null_src_file = rdib_source_file_chunk_list_push_zero(arena, &input.src_files, 1); - RDIB_LineTable *null_line_table = rdib_line_table_chunk_list_push_zero (arena, &input.line_tables, 1); - RDIB_LineTableFragment *null_frag = rdib_line_table_push (arena, null_line_table); - RDIB_Type *null_type = rdib_type_chunk_list_push_zero (arena, &input.types, 1); - RDIB_Scope *null_scope = rdib_scope_chunk_list_push_zero (arena, &input.scopes, 1); - RDIB_Unit *null_unit = rdib_unit_chunk_list_push_zero (arena, &input.units, 1); - RDIB_Procedure *null_proc = rdib_procedure_chunk_list_push_zero (arena, &input.procs, 1); - RDIB_Variable *null_local = rdib_variable_chunk_list_push_zero (arena, &input.locals, 1); - RDIB_Variable *null_gvar = rdib_variable_chunk_list_push_zero (arena, &input.gvars, 1); - RDIB_Variable *null_tvar = rdib_variable_chunk_list_push_zero (arena, &input.tvars, 1); - RDIB_UDTMember *null_udt_member = rdib_udt_member_chunk_list_push_zero (arena, &input.udt_members, 1); - RDIB_UDTMember *null_enum_member = rdib_udt_member_chunk_list_push_zero (arena, &input.enum_members, 1); - RDIB_InlineSite *null_inline_site = rdib_inline_site_chunk_list_push_zero(arena, &input.inline_sites, 1); - { - // Line Table Fragment - null_frag->src_file = null_src_file; - null_frag->voffs = push_array(arena, U64, 1); - - // Source File - null_src_file->line_table_frags = null_frag; - - // Unit - null_unit->arch = RDI_Arch_NULL; - null_unit->unit_name = str8_zero(); - null_unit->compiler_name = str8_zero(); - null_unit->source_file = str8_zero(); - null_unit->object_file = str8_zero(); - null_unit->archive_file = str8_zero(); - null_unit->build_path = str8_zero(); - null_unit->virt_range_count = 1; - null_unit->virt_ranges = push_array(arena, Rng1U64, 1); - null_unit->virt_ranges[0] = rng_1u64(0,0); - null_unit->line_table = null_line_table; - - // Scope - rng1u64_list_push(arena, &null_scope->ranges, rng_1u64(0,max_U32)); - - // Location - RDIB_Location null_loc = {0}; - rng1u64_list_push(arena, &null_loc.ranges, rng_1u64(0,0)); - RDIB_LocationList null_loc_list = {0}; - rdib_location_list_push(arena, &null_loc_list, null_loc); - - // Proc - null_proc->type = null_type; - null_proc->scope = null_scope; - - // Global Var - null_gvar->type = null_type; - null_gvar->locations = null_loc_list; - - // Thread Var - null_tvar->type = null_type; - null_tvar->locations = null_loc_list; - - // Local Var - null_local->type = null_type; - null_local->locations = null_loc_list; - - // Inline Site - null_inline_site->type = null_type; - null_inline_site->owner = 0; - null_inline_site->line_table = null_line_table; - } - - input.null_src_file = null_src_file; - input.null_line_table = null_line_table; - input.null_frag = null_frag; - input.null_type = null_type; - input.null_scope = null_scope; - input.null_unit = null_unit; - input.null_proc = null_proc; - input.null_local = null_local; - input.null_gvar = null_gvar; - input.null_tvar = null_tvar; - input.null_udt_member = null_udt_member; - input.null_enum_member = null_enum_member; - input.null_inline_site = null_inline_site; - - input.variadic_type = rdib_type_chunk_list_push(arena, &input.types, 1); - input.variadic_type->kind = RDI_TypeKind_Variadic; - - ProfEnd(); - return input; -} - -internal String8List -rdib_finish(TP_Context *tp, TP_Arena *arena, RDIB_Input *input) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - RDIB_UnitChunkList all_units = {0}; - RDIB_SourceFileChunkList all_src_files = {0}; - RDIB_LineTableChunkList all_line_tables = {0}; - RDIB_VariableChunkList all_locals = {0}; - RDIB_VariableChunkList all_tvars = {0}; - RDIB_VariableChunkList all_gvars = {0}; - RDIB_ProcedureChunkList all_procs = {0}; - RDIB_ScopeChunkList all_scopes = {0}; - RDIB_InlineSiteChunkList all_inline_sites = {0}; - RDIB_TypeChunkList all_types = {0}; - RDIB_TypeChunkList all_param_types = {0}; - RDIB_TypeChunkList all_udt_member_types = {0}; - RDIB_TypeChunkList all_enum_member_types = {0}; - RDIB_UDTMemberChunkList all_udt_members = {0}; - RDIB_UDTMemberChunkList all_enum_members = {0}; - - //U64 type_chunk_count = types.count; - //U64 struct_chunk_count = struct_list.count; - //U64 union_chunk_count = union_list.count; - //U64 enum_chunk_count = enum_list.count; - //U64 total_struct_count = rdib_type_chunk_list_total_count(struct_list); - //U64 total_union_count = rdib_type_chunk_list_total_count(union_list); - //U64 total_enum_count = rdib_type_chunk_list_total_count(enum_list); - //U64 extern_gvar_chunk_count = extern_gvars.count; - //U64 extern_tvar_chunk_count = extern_tvars.count; - //U64 extern_proc_chunk_count = extern_procs.count; - //U64 static_gvar_chunk_count = static_gvars.count; - //U64 static_tvar_chunk_count = static_tvars.count; - //U64 static_proc_chunk_count = static_procs.count; - //U64 total_extern_gvar_count = rdib_variable_chunk_list_total_count (extern_gvars); - //U64 total_extern_tvar_count = rdib_variable_chunk_list_total_count (extern_tvars); - //U64 total_extern_proc_count = rdib_procedure_chunk_list_total_count(extern_procs); - - ProfBegin("Concat Chunk Lists"); - rdib_unit_chunk_list_concat_in_place (&all_units, &input->units ); - rdib_source_file_chunk_list_concat_in_place(&all_src_files, &input->src_files ); - rdib_line_table_chunk_list_concat_in_place (&all_line_tables, &input->line_tables ); - rdib_scope_chunk_list_concat_in_place (&all_scopes, &input->scopes ); - rdib_variable_chunk_list_concat_in_place (&all_locals, &input->locals ); - rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->tvars ); - rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->extern_tvars ); - rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->static_tvars ); - rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->gvars ); - rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->extern_gvars ); - rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->static_gvars ); - rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->procs ); - rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->extern_procs ); - rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->static_procs ); - rdib_inline_site_chunk_list_concat_in_place(&all_inline_sites, &input->inline_sites ); - rdib_type_chunk_list_concat_in_place (&all_types, &input->types ); - rdib_type_chunk_list_concat_in_place (&all_types, &input->struct_list ); - rdib_type_chunk_list_concat_in_place (&all_types, &input->union_list ); - rdib_type_chunk_list_concat_in_place (&all_types, &input->enum_list ); - rdib_type_chunk_list_concat_in_place (&all_param_types, &input->param_types ); - rdib_type_chunk_list_concat_in_place (&all_udt_member_types, &input->member_types ); - rdib_type_chunk_list_concat_in_place (&all_enum_member_types, &input->enum_types ); - rdib_udt_member_chunk_list_concat_in_place (&all_udt_members, &input->udt_members ); - rdib_udt_member_chunk_list_concat_in_place (&all_enum_members, &input->enum_members ); - ProfEnd(); - - ProfBegin("Chunk Lists -> Chunk Arrays"); - RDIB_UnitChunk **all_unit_chunks = rdib_array_from_unit_chunk_list (scratch.arena, all_units ); - RDIB_SourceFileChunk **all_src_file_chunks = rdib_array_from_source_file_chunk_list(scratch.arena, all_src_files ); - RDIB_LineTableChunk **all_line_table_chunks = rdib_array_from_line_table_chunk_list (scratch.arena, all_line_tables ); - RDIB_ScopeChunk **all_scope_chunks = rdib_array_from_scope_chunk_list (scratch.arena, all_scopes ); - RDIB_VariableChunk **all_local_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_locals ); - RDIB_VariableChunk **all_gvar_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_gvars ); - RDIB_VariableChunk **all_tvar_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_tvars ); - RDIB_ProcedureChunk **all_proc_chunks = rdib_array_from_procedure_chunk_list (scratch.arena, all_procs ); - RDIB_InlineSiteChunk **all_inline_site_chunks = rdib_array_from_inline_site_chunk_list(scratch.arena, all_inline_sites ); - RDIB_TypeChunk **all_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_types ); - //RDIB_TypeChunk **all_param_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_param_types ); - RDIB_TypeChunk **all_udt_member_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_udt_member_types ); - RDIB_TypeChunk **all_enum_member_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_enum_member_types); - RDIB_UDTMemberChunk **all_udt_member_chunks = rdib_array_from_udt_member_chunk_list (scratch.arena, all_udt_members ); - RDIB_UDTMemberChunk **all_enum_member_chunks = rdib_array_from_udt_member_chunk_list (scratch.arena, all_enum_members ); - ProfEnd(); - - ProfBegin("Count Symbols, Types, and etc."); - U64 total_unit_count = rdib_unit_chunk_list_total_count (all_units ); - U64 total_src_file_count = rdib_source_file_chunk_list_total_count(all_src_files ); - U64 total_line_table_count = rdib_line_table_chunk_list_total_count (all_line_tables ); - U64 total_scope_count = rdib_scope_chunk_list_total_count (all_scopes ); - U64 total_local_count = rdib_variable_chunk_list_total_count (all_locals ); - U64 total_inline_site_count = rdib_inline_site_chunk_list_total_count(all_inline_sites ); - U64 total_udt_member_count = rdib_udt_member_chunk_list_total_count (all_udt_members ); - U64 total_enum_member_count = rdib_udt_member_chunk_list_total_count (all_enum_members ); - U64 total_type_count = rdib_type_chunk_list_total_count (all_types ); - U64 total_param_type_count = rdib_type_chunk_list_total_count (all_param_types ); - //U64 total_udt_member_type_count = rdib_type_chunk_list_total_count (all_udt_member_types ); - //U64 total_enum_member_type_count = rdib_type_chunk_list_total_count (all_enum_member_types); - U64 total_tvar_count = rdib_variable_chunk_list_total_count (all_tvars ); - U64 total_gvar_count = rdib_variable_chunk_list_total_count (all_gvars ); - U64 total_proc_count = rdib_procedure_chunk_list_total_count (all_procs ); - ProfEnd(); - - // +1 to skip nulls - //RDIB_VariableChunk **extern_gvar_chunks = all_gvar_chunks + 1; - //RDIB_VariableChunk **extern_tvar_chunks = all_tvar_chunks + 1; - //RDIB_ProcedureChunk **extern_proc_chunks = all_proc_chunks + 1; - //RDIB_VariableChunk **static_gvar_chunks = extern_gvar_chunks + extern_gvar_chunk_count; - //RDIB_VariableChunk **static_tvar_chunks = extern_tvar_chunks + extern_tvar_chunk_count; - //RDIB_ProcedureChunk **static_proc_chunks = extern_proc_chunks + extern_proc_chunk_count; - //RDIB_TypeChunk **type_chunks = all_type_chunks + 1; - //RDIB_TypeChunk **struct_chunks = type_chunks + type_chunk_count; - //RDIB_TypeChunk **union_chunks = struct_chunks + struct_chunk_count; - //RDIB_TypeChunk **enum_chunks = union_chunks + union_chunk_count; - //RDIB_TypeChunk **udt_chunks = struct_chunks; - //U64 udt_chunk_count = struct_chunk_count + union_chunk_count + enum_chunk_count; - - ProfBegin("Assign Type Indices"); - U64 total_type_node_count = 1; - { - struct TypeNode { - struct TypeNode *next; - RDIB_Type *type; - }; - struct TypeNode *stack = 0; - struct TypeNode *free_nodes = 0; -#define push_node(t) do { \ -if (((RDIB_Type*)(t))->kind == RDI_TypeKindExt_VirtualTable) break; \ - struct TypeNode *n; \ - if (free_nodes == 0) { \ - n = push_array(scratch.arena, struct TypeNode, 1); \ - } else { \ - n = free_nodes; \ - SLLStackPop(free_nodes); \ - } \ - Assert(t); \ - n->type = t; \ - SLLStackPush(stack, n); \ -} while (0) - - for (U64 chunk_idx = 0; chunk_idx < all_types.count; ++chunk_idx) { - RDIB_TypeChunk *chunk = all_type_chunks[chunk_idx]; - for (U64 i = 0; i < chunk->count; ++i) { - push_node(&chunk->v[i]); - - for (struct TypeNode *cursor = stack; cursor != 0; cursor = cursor->next) { - if (cursor->type->kind == RDI_TypeKind_NULL){ - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_Variadic) { - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_Union) { - // no type refs - } else if (RDI_IsBuiltinType(cursor->type->kind)) { - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_IncompleteStruct) { - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_IncompleteUnion) { - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_IncompleteClass) { - // no type refs - } else if (cursor->type->kind == RDI_TypeKind_IncompleteEnum) { - push_node(cursor->type->udt.enum_type.base_type); - } else if (cursor->type->kind == RDI_TypeKind_Modifier) { - push_node(cursor->type->modifier.type_ref); - } else if (RDI_IsPtrType(cursor->type->kind)) { - push_node(cursor->type->ptr.type_ref); - } else if (cursor->type->kind == RDI_TypeKind_Function) { - push_node(cursor->type->func.return_type); - push_node(cursor->type->func.params_type); - RDIB_Type *params = cursor->type->func.params_type; - for (U64 i = 0; i < params->params.count; ++i) { - push_node(params->params.types[i]); - } - } else if (cursor->type->kind == RDI_TypeKind_Method) { - push_node(cursor->type->method.class_type); - push_node(cursor->type->method.this_type); - push_node(cursor->type->method.return_type); - RDIB_Type *params = cursor->type->method.params_type; - for (U64 i = 0; i < params->params.count; ++i) { - push_node(params->params.types[i]); - } - } else if (cursor->type->kind == RDI_TypeKindExt_StaticMethod) { - push_node(cursor->type->static_method.class_type); - push_node(cursor->type->static_method.return_type); - RDIB_Type *params = cursor->type->static_method.params_type; - for (U64 i = 0; i < params->params.count; ++i) { - push_node(params->params.types[i]); - } - } else if (cursor->type->kind == RDI_TypeKind_Bitfield) { - push_node(cursor->type->bitfield.value_type); - } else if (cursor->type->kind == RDI_TypeKind_Array) { - push_node(cursor->type->array.entry_type); - } else if (cursor->type->kind == RDI_TypeKind_Struct || cursor->type->kind == RDI_TypeKind_Class) { - if (cursor->type->udt.struct_type.derived != 0) { - push_node(cursor->type->udt.struct_type.derived); - } - //push_node(cursor->type->udt.struct_type.vtshape); - } else if (cursor->type->kind == RDI_TypeKind_Enum) { - push_node(cursor->type->udt.enum_type.base_type); - } else if (cursor->type->kind > RDI_TypeKindExt_Lo) { - InvalidPath; - } else { - InvalidPath; - } - } - - for (struct TypeNode *cursor = stack; cursor != 0; cursor = cursor->next) { - // was this type visisted? - if (cursor->type != input->null_type && cursor->type->final_idx == 0) { - cursor->type->final_idx = total_type_node_count; - ++total_type_node_count; - } - } - - free_nodes = stack; - stack = 0; - } - } -#undef push_node - } - ProfEnd(); - - ProfBegin("Type Stats"); - RDIB_TypeStats type_stats = {0}; - { - type_stats.udt_counts = push_array(scratch.arena, U64, all_types.count); - RDIB_TypeStatsTask task = { .chunks = all_type_chunks, .type_stats = &type_stats }; - tp_for_parallel(tp, 0, all_types.count, rdib_type_stats_task, &task); - } - ProfEnd(); - - RDIB_PathTree *path_tree = rdib_build_path_tree(arena->v[0], - tp->worker_count, - input->null_src_file, - all_units.count, - all_unit_chunks, - all_src_files.count, - all_src_file_chunks); - - // loop over structs and build a map with every possible string - ProfBegin("String Map"); - RDIB_StringMap *string_map; - { - U64 top_level_string_count = 2; - U64 sect_string_count = 1; - U64 src_file_string_count = 1; - U64 unit_string_count = 6; - U64 variable_string_count = 2; - U64 procedure_string_count = 2; - U64 scope_string_count = 0; - U64 inline_site_string_count = 0; - U64 member_string_count = 2; - U64 type_string_count = 3; - U64 path_tree_node_count = 1; - - U64 total_string_count = 1 /* :string_map_null */ + - 1 * top_level_string_count + - input->sect_count * sect_string_count + - total_src_file_count * src_file_string_count + - total_unit_count * unit_string_count + - total_local_count * variable_string_count + - total_gvar_count * variable_string_count + - total_tvar_count * variable_string_count + - total_proc_count * procedure_string_count + - total_inline_site_count * inline_site_string_count + - total_udt_member_count * member_string_count + - total_enum_member_count * member_string_count + - total_type_count * type_string_count + - path_tree->node_count * path_tree_node_count + - total_scope_count * scope_string_count; - - string_map = rdib_init_string_map(arena->v[0], total_string_count); - - RDIB_CollectStringsTask task = {0}; - task.string_map = string_map; - task.string_map_update_func = rdib_string_map_update_null; - task.free_buckets = push_array(scratch.arena, RDIB_StringMapBucket *, tp->worker_count); - task.element_indices = push_array(scratch.arena, U64, tp->worker_count); - - // :string_map_null - rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, str8_lit("")); - - // top level info - rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, input->top_level_info.exe_name); - rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, input->top_level_info.producer_string); - - ProfBegin("Sections"); - task.ranges = tp_divide_work(scratch.arena, input->sect_count, tp->worker_count); - task.sects = input->sections; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_sects_task, &task); - ProfEnd(); - - ProfBegin("Units"); - task.ranges = tp_divide_work(scratch.arena, all_units.count, tp->worker_count); - task.units = all_unit_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_units_task, &task); - ProfEnd(); - - ProfBegin("Source Files"); - task.ranges = tp_divide_work(scratch.arena, all_src_files.count, tp->worker_count); - task.src_file_chunks = all_src_file_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_source_files_task, &task); - ProfEnd(); - - ProfBegin("Locals"); - task.ranges = tp_divide_work(scratch.arena, all_locals.count, tp->worker_count); - task.vars = all_local_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); - ProfEnd(); - - ProfBegin("Global Variables"); - task.ranges = tp_divide_work(scratch.arena, all_gvars.count, tp->worker_count); - task.vars = all_gvar_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); - ProfEnd(); - - ProfBegin("Thread Variables"); - task.ranges = tp_divide_work(scratch.arena, all_tvars.count, tp->worker_count); - task.vars = all_tvar_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); - ProfEnd(); - - ProfBegin("Procedures"); - task.ranges = tp_divide_work(scratch.arena, all_procs.count, tp->worker_count); - task.procs = all_proc_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_procs_task, &task); - ProfEnd(); - - ProfBegin("Inline Sites"); - task.ranges = tp_divide_work(scratch.arena, all_inline_sites.count, tp->worker_count); - task.inline_sites = all_inline_site_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_inline_sites_task, &task); - ProfEnd(); - - ProfBegin("UDT Members"); - task.ranges = tp_divide_work(scratch.arena, all_udt_members.count, tp->worker_count); - task.udt_members = all_udt_member_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_udt_members_task, &task); - ProfEnd(); - - ProfBegin("Enum Members"); - task.ranges = tp_divide_work(scratch.arena, all_enum_members.count, tp->worker_count); - task.udt_members = all_enum_member_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_enum_members_task, &task); - ProfEnd(); - - ProfBegin("Types"); - task.ranges = tp_divide_work(scratch.arena, all_types.count, tp->worker_count); - task.types = all_type_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_types_task, &task); - ProfEnd(); - - ProfBegin("Path Tree"); - task.ranges = tp_divide_work(scratch.arena, path_tree->list_count, tp->worker_count); - task.path_node_lists = path_tree->node_lists; - tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_path_nodes_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Name Maps"); - RDIB_StringMap *name_maps[RDI_NameMapKind_COUNT] = {0}; - { - name_maps[RDI_NameMapKind_NULL ] = rdib_init_string_map(scratch.arena, 1 ); - name_maps[RDI_NameMapKind_GlobalVariables ] = rdib_init_string_map(scratch.arena, total_gvar_count ); - name_maps[RDI_NameMapKind_ThreadVariables ] = rdib_init_string_map(scratch.arena, total_tvar_count ); - name_maps[RDI_NameMapKind_Procedures ] = rdib_init_string_map(scratch.arena, total_proc_count ); - name_maps[RDI_NameMapKind_Types ] = rdib_init_string_map(scratch.arena, total_type_count ); - name_maps[RDI_NameMapKind_LinkNameProcedures] = rdib_init_string_map(scratch.arena, total_proc_count ); - name_maps[RDI_NameMapKind_NormalSourcePaths ] = rdib_init_string_map(scratch.arena, total_src_file_count); - - RDIB_CollectStringsTask task = {0}; - task.string_map = 0; - task.string_map_update_func = rdib_string_map_update_concat_void_list_atomic; - task.free_buckets = push_array(scratch.arena, RDIB_StringMapBucket *, tp->worker_count); - task.element_indices = push_array(scratch.arena, U64, tp->worker_count); - - ProfBegin("Global Variables"); - task.string_map = name_maps[RDI_NameMapKind_GlobalVariables]; - task.ranges = tp_divide_work(scratch.arena, all_gvars.count, tp->worker_count); - task.vars = all_gvar_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_var_task, &task); - ProfEnd(); - - ProfBegin("Thread Variables"); - task.string_map = name_maps[RDI_NameMapKind_ThreadVariables]; - task.ranges = tp_divide_work(scratch.arena, all_tvars.count, tp->worker_count); - task.vars = all_tvar_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_var_task, &task); - ProfEnd(); - - ProfBegin("Procedure Names"); - task.string_map = name_maps[RDI_NameMapKind_Procedures]; - task.ranges = tp_divide_work(scratch.arena, all_procs.count, tp->worker_count); - task.procs = all_proc_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_procedure_task, &task); - ProfEnd(); - - ProfBegin("Types"); - task.string_map = name_maps[RDI_NameMapKind_Types]; - task.ranges = tp_divide_work(scratch.arena, all_types.count, tp->worker_count); - task.types = all_type_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_types_task, &task); - ProfEnd(); - - ProfBegin("Normal Source Paths"); - task.string_map = name_maps[RDI_NameMapKind_NormalSourcePaths]; - task.ranges = tp_divide_work(scratch.arena, all_src_files.count, tp->worker_count); - task.src_file_chunks = all_src_file_chunks; - tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_normal_paths_task, &task); - ProfEnd(); - } - ProfEnd(); - - ProfBeginDynamic("Extract String Table Buckets [Cap: %llu]", string_map->cap); - U64 string_map_bucket_count; - RDIB_StringMapBucket **string_map_buckets = rdib_extant_buckets_from_string_map(tp, scratch.arena, string_map, &string_map_bucket_count); - rdib_string_map_sort_buckets(tp, string_map_buckets, string_map_bucket_count, tp->worker_count); - rdib_string_map_assign_indices(string_map_buckets, string_map_bucket_count); - ProfEnd(); - - ProfBegin("Extract Name Maps Buckets"); - RDIB_StringMapBucket **name_map_buckets[RDI_NameMapKind_COUNT]; - U64 name_map_bucket_counts[RDI_NameMapKind_COUNT]; - for (U64 i = 0; i < ArrayCount(name_map_buckets); ++i) { - ProfBeginDynamic("Name Map: %.*s", str8_varg(rdi_string_from_name_map_kind(i))); - name_map_buckets[i] = rdib_extant_buckets_from_string_map(tp, scratch.arena, name_maps[i], &name_map_bucket_counts[i]); - rdib_string_map_sort_buckets(tp, name_map_buckets[i], name_map_bucket_counts[i], tp->worker_count); - rdib_string_map_assign_indices(name_map_buckets[i], name_map_bucket_counts[i]); - ProfEnd(); - } - ProfEnd(); - - ProfBegin("Index Run Map"); - RDIB_IndexRunMap *idx_run_map; - RDIB_IndexRunBucket **idx_run_buckets; - U64 idx_run_bucket_count; - { - // TODO: we over-allocate for name map index runs since not every bucket has > 1 value - U64 total_name_map_value_count = 0; - for (U64 i = 0; i < ArrayCount(name_map_bucket_counts); ++i) { - total_name_map_value_count += name_map_bucket_counts[i]; - } - - // rough bucket estimate - U64 idx_run_cap = (total_param_type_count + total_name_map_value_count) * 2; - idx_run_map = rdib_init_index_run_map(arena->v[0], idx_run_cap); - - // setup task context - RDIB_BuildIndexRunsTask task = {0}; - task.idx_run_map = idx_run_map; - task.free_buckets = push_array(scratch.arena, RDIB_IndexRunBucket *, tp->worker_count); - - ProfBegin("Type Params Pass"); - task.type_chunks = all_type_chunks; - tp_for_parallel(tp, arena, all_types.count, rdib_build_idx_runs_params_task, &task); - task.sorter_idx += 1; - ProfEnd(); - - ProfBegin("Name Maps Pass - Build Index Runs"); - for (U64 name_map_kind = 0; name_map_kind < ArrayCount(name_maps); ++name_map_kind) { - ProfBeginDynamic("Name Map: %.*s", str8_varg(rdi_string_from_name_map_kind(name_map_kind))); - task.name_map_kind = name_map_kind; - task.ranges = tp_divide_work(scratch.arena, name_map_bucket_counts[name_map_kind], tp->worker_count); - task.name_map_buckets = name_map_buckets[name_map_kind]; - tp_for_parallel(tp, arena, tp->worker_count, rdib_build_idx_runs_name_map_buckets_task, &task); - task.sorter_idx += 1; - ProfEnd(); - } - ProfEnd(); - - idx_run_buckets = rdib_extant_buckets_from_index_run_map(tp, arena->v[0], idx_run_map, &idx_run_bucket_count); - rdib_index_run_map_sort_buckets(tp, idx_run_buckets, idx_run_bucket_count, task.sorter_idx); - rdib_index_run_map_assign_indices(idx_run_buckets, idx_run_bucket_count); - } - ProfEnd(); - - ProfBegin("Serialize Data Sections"); - RDIB_DataSectionList sections = {0}; - rdib_data_sections_from_top_level_info(arena->v[0], §ions, string_map, &input->top_level_info); - rdib_data_sections_from_binary_sections(arena->v[0], §ions, string_map, input->sections, input->sect_count); - rdib_data_sections_from_path_tree(tp, arena->v[0], §ions, string_map, path_tree); - rdib_data_sections_from_string_map(tp, arena->v[0], §ions, string_map_buckets, string_map_bucket_count); - rdib_data_sections_from_index_runs(tp, arena->v[0], §ions, idx_run_buckets, idx_run_bucket_count); - rdib_data_sections_from_name_maps(tp, arena, §ions, string_map, idx_run_map, name_map_buckets, name_map_bucket_counts); - rdib_data_sections_from_types(tp, arena->v[0], §ions, input->top_level_info.arch, string_map, idx_run_map, all_udt_member_types.count, all_udt_member_type_chunks, all_enum_member_types.count, all_enum_member_type_chunks, total_type_node_count, all_types.count, all_type_chunks, type_stats); - rdib_data_sections_from_line_tables(tp, arena, §ions, total_line_table_count, all_line_tables.count, all_line_table_chunks); - rdib_data_sections_from_source_line_maps(tp, arena, §ions, total_src_file_count, all_src_files.count, all_src_file_chunks); - rdib_data_sections_from_source_files(tp, arena, §ions, string_map, path_tree, total_src_file_count, all_src_files.count, all_src_file_chunks); - rdib_data_sections_from_units(arena->v[0], §ions, string_map, path_tree, total_unit_count, all_units.count, all_unit_chunks); - rdib_data_sections_from_global_variables(tp, arena, §ions, string_map, total_gvar_count, all_gvars.count, all_gvar_chunks); - rdib_data_sections_from_thread_variables(tp, arena, §ions, string_map, total_tvar_count, all_tvars.count, all_tvar_chunks); - rdib_data_sections_from_procedures(tp, arena, §ions, string_map, total_proc_count, all_procs.count, all_proc_chunks); - rdib_data_sections_from_scopes(tp, arena, §ions, string_map, total_scope_count, all_scopes.count, all_scope_chunks); - rdib_data_sections_from_unit_gvar_scope_vmaps(tp, arena, §ions, all_units.count, all_unit_chunks, all_gvars.count, all_gvar_chunks, all_scopes.count, all_scope_chunks); - rdib_data_sections_from_inline_sites(tp, arena->v[0], §ions, string_map, total_inline_site_count, all_inline_sites.count, all_inline_site_chunks); - //rdib_data_sections_from_checksums(tp, arena->v[0], §ions); - ProfEnd(); - - ProfBegin("Make RDI header and sections"); - String8List rdi_data = {0}; - { - // concat section datas - String8List raw_section_datas[RDI_SectionKind_COUNT] = {0}; - for (RDIB_DataSectionNode *n = sections.first; n != 0; n = n->next) { - str8_list_concat_in_place(&raw_section_datas[n->v.tag], &n->v.data); - } - - RDI_Header *rdi_header = push_array(arena->v[0], RDI_Header, 1); - RDI_Section *rdi_sections = push_array(arena->v[0], RDI_Section, RDI_SectionKind_COUNT); - - rdi_header->magic = RDI_MAGIC_CONSTANT; - rdi_header->encoding_version = RDI_ENCODING_VERSION; - rdi_header->data_section_off = sizeof(*rdi_header); - rdi_header->data_section_count = RDI_SectionKind_COUNT; - - str8_list_push(arena->v[0], &rdi_data, str8_struct(rdi_header)); - str8_list_push(arena->v[0], &rdi_data, str8_array(rdi_sections, RDI_SectionKind_COUNT)); - - for (U64 sect_idx = 0; sect_idx < RDI_SectionKind_COUNT; ++sect_idx) { - RDI_Section *dst = &rdi_sections[sect_idx]; - dst->encoding = RDI_SectionEncoding_Unpacked; - dst->pad = 0; - dst->off = 0; - dst->encoded_size = 0; - dst->unpacked_size = 0; - - if (raw_section_datas[sect_idx].total_size > 0) { - str8_list_push_aligner(arena->v[0], &rdi_data, 0, 8); - - dst->off = rdi_data.total_size; - dst->encoded_size = raw_section_datas[sect_idx].total_size; - dst->unpacked_size = raw_section_datas[sect_idx].total_size; - - str8_list_concat_in_place(&rdi_data, &raw_section_datas[sect_idx]); - -#if BUILD_DEBUG - { - U64 expected_total_size = 0; - for (String8Node *n = rdi_data.first; n != 0; n = n->next) { - expected_total_size += n->string.size; - } - Assert(expected_total_size == rdi_data.total_size); - } -#endif - } - } - } - ProfEnd(); - - scratch_end(scratch); - ProfEnd(); - return rdi_data; -} - diff --git a/src/linker/rdi/rdi_builder.h b/src/linker/rdi/rdi_builder.h deleted file mode 100644 index 09532d49..00000000 --- a/src/linker/rdi/rdi_builder.h +++ /dev/null @@ -1,1231 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#pragma once - -StaticAssert(sizeof(RDI_Header) == AlignPow2(sizeof(RDI_Header), 8), g_rdi_header_align_check); - -//////////////////////////////// -// TODO: move to rdi_format.h - -#define RDI_IsCompleteUserDefinedTypeKind(x) ((x) == RDI_TypeKind_Class || (x) == RDI_TypeKind_Struct || (x) == RDI_TypeKind_Union || (x) == RDI_TypeKind_Enum) -#define RDI_IsIncompleteUsedDefinedTypeKind(x) (RDI_TypeKind_FirstIncomplete <= (x) && (x) <= RDI_TypeKind_LastIncomplete) -#define RDI_IsUserDefinedType(x) (RDI_IsCompleteUserDefinedTypeKind(x) || RDI_IsIncompleteUsedDefinedTypeKind(x)) -#define RDI_IsBuiltinType(x) (RDI_TypeKind_FirstBuiltIn <= (x) && (x) <= RDI_TypeKind_LastBuiltIn) -#define RDI_IsPtrType(x) ((x) == RDI_TypeKind_Ptr || (x) == RDI_TypeKind_LRef || (x) == RDI_TypeKind_RRef) - -//////////////////////////////// - -typedef enum -{ - RDIB_DataModel_Null, - RDIB_DataModel_ILP32, - RDIB_DataModel_LLP64, - RDIB_DataModel_LP64, - RDIB_DataModel_ILP64, - RDIB_DataModel_SILP64 -} RDIB_DataModel; - -//////////////////////////////// - -typedef void * RDIB_TypeRef; - -typedef struct RDIB_EvalBytecodeOp -{ - struct RDIB_EvalBytecodeOp *next; - RDI_EvalOp op; - U64 p_size; - U64 p; -} RDIB_EvalBytecodeOp; - -typedef struct RDIB_EvalBytecode -{ - U64 count; - U64 size; - RDIB_EvalBytecodeOp *first; - RDIB_EvalBytecodeOp *last; -} RDIB_EvalBytecode; - -typedef struct RDIB_Location -{ - RDI_LocationKind kind; - Rng1U64List ranges; - union { - struct { - RDI_RegCode reg_code; - U64 offset; - }; - RDIB_EvalBytecode bytecode; - }; - - // used by RDI builder - U64 data_offset; -} RDIB_Location; - -typedef struct RDIB_LocationNode -{ - struct RDIB_LocationNode *next; - RDIB_Location v; -} RDIB_LocationNode; - -typedef struct RDIB_LocationList -{ - U64 count; - RDIB_LocationNode *first; - RDIB_LocationNode *last; -} RDIB_LocationList; - - -typedef struct RDIB_Variable -{ - String8 name; - String8 link_name; - struct RDIB_Type *type; - struct RDIB_Type *container_type; - struct RDIB_Procedure *container_proc; - RDIB_LocationList locations; - struct RDIB_VariableChunk *chunk; - struct RDIB_Variable *next; -} RDIB_Variable; - -typedef struct RDIB_VariableNode -{ - struct RDIB_VariableNode *next; - RDIB_Variable v; -} RDIB_VariableNode; - -typedef struct RDIB_VariableList -{ - U64 count; - RDIB_VariableNode *first; - RDIB_VariableNode *last; -} RDIB_VariableList; - -//////////////////////////////// - -typedef struct -{ - RDI_Arch arch; - U64 exe_hash; - U64 voff_max; - String8 exe_name; - String8 producer_string; -} RDIB_TopLevelInfo; - -typedef struct -{ - String8 name; - RDI_BinarySectionFlags flags; - U64 voff_first; - U64 voff_opl; - U64 foff_first; - U64 foff_opl; -} RDIB_BinarySection; - -typedef struct RDIB_LineTableFragment -{ - struct RDIB_SourceFile *src_file; - PairU32 ln_voff; - U64 *voffs; - U32 *line_nums; - U16 *col_nums; - U64 line_count; - U64 col_count; - struct RDIB_LineTableFragment *next_src_file; - struct RDIB_LineTableFragment *next_line_table; - struct RDIB_LineTableFragmentChunk *chunk; -} RDIB_LineTableFragment; - -typedef struct RDIB_LineTableFragmentChunk -{ - struct RDIB_LineTableFragmentChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_LineTableFragment *v; -} RDIB_LineTableFragmentChunk; - -typedef struct RDIB_LineTableFragmentChunkList -{ - U64 count; - RDIB_LineTableFragmentChunk *first; - RDIB_LineTableFragmentChunk *last; -} RDIB_LineTableFragmentChunkList; - -typedef struct RDIB_LineTable -{ - struct RDIB_LineTableChunk *chunk; - U64 count; - RDIB_LineTableFragment *first; - RDIB_LineTableFragment *last; - U32 output_array_idx; -} RDIB_LineTable; - -typedef struct RDIB_LineTableChunk -{ - struct RDIB_LineTableChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_LineTable *v; -} RDIB_LineTableChunk; - -typedef struct RDIB_LineTableChunkList -{ - U64 count; - RDIB_LineTableChunk *first; - RDIB_LineTableChunk *last; -} RDIB_LineTableChunkList; - -typedef struct RDIB_SourceFile -{ - String8 file_path; - String8 normal_full_path; - RDI_ChecksumKind checksum_kind; - String8 checksum; - RDIB_LineTableFragment *line_table_frags; - - U64 src_line_map_idx; - U64 line_table_idx; - - struct RDIB_SourceFileChunk *chunk; -} RDIB_SourceFile; - -typedef struct RDIB_SourceFileChunk -{ - struct RDIB_SourceFileChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_SourceFile *v; -} RDIB_SourceFileChunk; - -typedef struct RDIB_SourceFileChunkList -{ - U64 count; - RDIB_SourceFileChunk *first; - RDIB_SourceFileChunk *last; -} RDIB_SourceFileChunkList; - -typedef struct RDIB_Procedure -{ - String8 name; - String8 link_name; - struct RDIB_Type *type; - struct RDIB_Type *container_type; - struct RDIB_Procedure *container_proc; - - struct RDIB_Scope *scope; - struct RDIB_ScopeNode *scope_first; - struct RDIB_ScopeNode *scope_last; - - U64 scope_count; - struct RDIB_ProcedureChunk *chunk; -} RDIB_Procedure; - -typedef struct RDIB_Scope -{ - struct RDIB_Scope *parent; - struct RDIB_Scope *first_child; - struct RDIB_Scope *last_child; - struct RDIB_Scope *next_sibling; - struct RDIB_Procedure *container_proc; - Rng1U64List ranges; - RDIB_Variable *local_first; - RDIB_Variable *local_last; - U64 local_count; - struct RDIB_InlineSite *inline_site; - - // used by RDI builder - U64 local_first_idx; - - struct RDIB_ScopeChunk *chunk; -} RDIB_Scope; - -typedef struct RDIB_InlineSite -{ - String8 name; - struct RDIB_Type *type; - struct RDIB_Type *owner; - struct RDIB_InlineSiteChunk *chunk; - union { - struct RDIB_LineTable *line_table; - struct { - void *ud0; - U64 ud1; - U64 ud2; - } convert_ref; - }; -} RDIB_InlineSite; - -typedef RDI_MemberKind RDI_MemberKindExt; -enum -{ - RDI_MemberKind_COUNT = RDI_MemberKind_NestedType, - RDI_MemberKindExt_MemberListPointer // NOTE: must always be last in the list! -}; - -typedef struct RDIB_UDTMember -{ - RDI_MemberKindExt kind; - union { - struct { - String8 name; - U64 offset; - RDIB_TypeRef type_ref; - } data_field; - struct { - String8 name; - RDIB_TypeRef type_ref; - } static_data; - RDIB_TypeRef member_list_pointer; - struct { - RDI_MemberKind kind; - String8 name; - RDIB_TypeRef type_ref; - U64 vftable_offset; - } method; - struct { - String8 name; - RDIB_TypeRef type_ref; - } nested_type; - struct { - RDIB_TypeRef type_ref; - U64 offset; - } base_class; - struct { - RDIB_TypeRef type_ref; - U64 vbptr_off; - U64 vtable_off; - } virtual_base_class; - struct { - String8 name; - U64 value; - } enumerate; - }; - struct RDIB_UDTMember *next; - struct RDIB_UDTMemberChunk *chunk; -} RDIB_UDTMember; - -typedef struct RDIB_UDTMemberList -{ - U64 count; - RDIB_UDTMember *first; - RDIB_UDTMember *last; -} RDIB_UDTMemberList; - -typedef struct RDIB_UDT -{ - struct RDIB_Type *self_type; - struct RDIB_Type *members; - RDIB_SourceFile *decl_src_file; - U32 decl_line_num; - U32 decl_col_num; -} RDIB_UDT; - -enum -{ - RDI_TypeKindExt_Lo = RDI_TypeKind_COUNT, - RDI_TypeKindExt_VirtualTable, - RDI_TypeKindExt_StaticMethod, - RDI_TypeKindExt_Members, - RDI_TypeKindExt_Params, - RDI_TypeKindExt_Count, -}; -typedef RDI_TypeKind RDI_TypeKindExt; - -typedef struct RDIB_Type -{ - RDI_TypeKindExt kind; - U64 final_idx; - U64 itype; - union { - struct { - String8 name; - U64 size; - } builtin; - struct { - RDI_TypeModifierFlags flags; - RDIB_TypeRef type_ref; - } modifier; - struct { - RDIB_TypeRef type_ref; - U64 size; - } ptr; - struct { - RDIB_TypeRef return_type; - RDIB_TypeRef params_type; - - U64 param_idx_run_bucket_idx; - } func; - struct { - RDIB_TypeRef class_type; - RDIB_TypeRef this_type; - RDIB_TypeRef return_type; - RDIB_TypeRef params_type; - - U64 param_idx_run_bucket_idx; - } method; - struct { - RDIB_TypeRef class_type; - RDIB_TypeRef return_type; - RDIB_TypeRef params_type; - - U64 param_idx_run_bucket_idx; - } static_method; - struct { - U64 off; - U64 count; - RDIB_TypeRef value_type; - } bitfield; - struct { - RDIB_TypeRef entry_type; - U64 size; - } array; - struct { - String8 name; - String8 link_name; - RDIB_TypeRef members; - // assigned in UDT build step - U64 udt_idx; - union { - struct { - U64 size; - RDIB_TypeRef derived; - RDIB_TypeRef vtshape; - } struct_type; - struct { - U64 size; - } union_type; - struct { - String8 name; - RDIB_TypeRef base_type; - } enum_type; - }; - } udt; - struct { - U64 count; - RDIB_TypeRef *types; - } params; - struct { - RDIB_UDTMemberList list; - - // assigned in member build step - B32 is_head; - U64 first_member_idx; - } members, enum_members; - }; - struct RDIB_TypeChunk *chunk; -} RDIB_Type; - -typedef struct RDIB_Unit -{ - RDI_Arch arch; - String8 unit_name; - String8 compiler_name; - String8 source_file; - String8 object_file; - String8 archive_file; - String8 build_path; - RDI_Language language; - RDIB_LineTable *line_table; - U64 virt_range_count; - Rng1U64 *virt_ranges; - - struct RDIB_UnitChunk *chunk; -} RDIB_Unit; - -typedef struct RDIB_DataSection -{ - RDI_SectionKind tag; - String8List data; -} RDIB_DataSection; - -typedef struct RDIB_DataSectionNode -{ - struct RDIB_DataSectionNode *next; - RDIB_DataSection v; -} RDIB_DataSectionNode; - -typedef struct RDIB_DataSectionList -{ - U64 count; - RDIB_DataSectionNode *first; - RDIB_DataSectionNode *last; -} RDIB_DataSectionList; - - -typedef struct RDIB_UnitChunk -{ - U64 base; - U64 count; - U64 cap; - RDIB_Unit *v; - struct RDIB_UnitChunk *next; -} RDIB_UnitChunk; - -typedef struct RDIB_UnitChunkList -{ - U64 count; - RDIB_UnitChunk *first; - RDIB_UnitChunk *last; -} RDIB_UnitChunkList; - -typedef struct RDIB_VariableChunk -{ - struct RDIB_VariableChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_Variable *v; -} RDIB_VariableChunk; - -typedef struct RDIB_VariableChunkList -{ - U64 count; - RDIB_VariableChunk *first; - RDIB_VariableChunk *last; -} RDIB_VariableChunkList; - -typedef struct RDIB_ProcedureChunk -{ - struct RDIB_ProcedureChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_Procedure *v; -} RDIB_ProcedureChunk; - -typedef struct RDIB_ProcedureChunkList -{ - U64 count; - RDIB_ProcedureChunk *first; - RDIB_ProcedureChunk *last; -} RDIB_ProcedureChunkList; - -typedef struct RDIB_ScopeChunk -{ - struct RDIB_ScopeChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_Scope *v; -} RDIB_ScopeChunk; - -typedef struct RDIB_ScopeChunkList -{ - U64 count; - RDIB_ScopeChunk *first; - RDIB_ScopeChunk *last; -} RDIB_ScopeChunkList; - -typedef struct RDIB_ScopeNode -{ - struct RDIB_ScopeNode *next; - RDIB_Scope *v; -} RDIB_ScopeNode; - -typedef struct RDIB_ScopeList -{ - U64 count; - RDIB_Scope *first; - RDIB_Scope *last; -} RDIB_ScopeList; - -typedef struct RDIB_InlineSiteChunk -{ - struct RDIB_InlineSiteChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_InlineSite *v; -} RDIB_InlineSiteChunk; - -typedef struct RDIB_InlineSiteChunkList -{ - U64 count; - RDIB_InlineSiteChunk *first; - RDIB_InlineSiteChunk *last; -} RDIB_InlineSiteChunkList; - -typedef struct RDIB_TypeChunk -{ - struct RDIB_TypeChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_Type *v; -} RDIB_TypeChunk; - -typedef struct -{ - U64 count; - RDIB_TypeChunk *first; - RDIB_TypeChunk *last; -} RDIB_TypeChunkList; - -typedef struct RDIB_UDTMemberChunk -{ - struct RDIB_UDTMemberChunk *next; - U64 base; - U64 count; - U64 cap; - RDIB_UDTMember *v; -} RDIB_UDTMemberChunk; - -typedef struct RDIB_UDTMemberChunkList -{ - U64 count; - RDIB_UDTMemberChunk *first; - RDIB_UDTMemberChunk *last; -} RDIB_UDTMemberChunkList; - -//////////////////////////////// -// UDT Forward Ref Map - -typedef struct -{ - struct RDIB_Type *type; - U64 idx; -} RDIB_UDTFwdrefBucket; - -//////////////////////////////// -// String Map - -typedef struct RDIB_StringMapBucket -{ - String8 string; - - union { - // to get deterministic output we assign each bucket a unique index - union { - struct { - U32 lo; - U32 hi; - }; - U64 v; - } sorter; - - // after buckets are sorted we replace 'sorter' with indices into output array - U64 idx; - }; - - union { - // depending on the usage context sotres: pointers to variables, procedures, and etc. - VoidNode *raw_values; - - // during index-run-map build step 'raw_values' are replaced with index-run bucket index - struct { - U32 count; - // if we have single index - store it in the bucket - union { - U64 idx_run_bucket_idx; - U32 match_idx; - }; - }; - }; -} RDIB_StringMapBucket; - -typedef struct RDIB_StringMap -{ - U64 cap; - RDIB_StringMapBucket **buckets; -} RDIB_StringMap; - -#define RDIB_STRING_MAP_UPDATE_FUNC(name) void name(VoidNode **head, VoidNode *node) -typedef RDIB_STRING_MAP_UPDATE_FUNC(RDIB_StringMapUpdateFunc); - -typedef struct -{ - RDIB_StringMap *string_map; - Rng1U64 *ranges; - U64 *counts; - U64 *offsets; - RDIB_StringMapBucket **result; -} RDIB_GetExtantBucketsStringMapTask; - -typedef struct -{ - U32 *string_table; - U64 string_data_size; - U8 *string_data; - RDIB_StringMapBucket **buckets; - Rng1U64 *ranges; -} RDIB_CopyStringDataTask; - -typedef struct -{ - U64 chunk_idx_opl; - Rng1U64 *ranges; - RDIB_StringMapBucket **src; - RDIB_StringMapBucket **dst; - U32 *chunk_histo; - U32 *chunk_offsets; -} RDIB_StringMapRadixSort; - -//////////////////////////////// -// Index Run Map - -typedef struct RDIB_IndexRunBucket -{ - union { - struct { - U32 lo; - U32 hi; - }; - U64 v; - } sorter; - U32Array indices; - U64 index_in_output_array; -} RDIB_IndexRunBucket; - -typedef struct RDIB_IndexRunMap -{ - U64 cap; - RDIB_IndexRunBucket **buckets; -} RDIB_IndexRunMap; - -//////////////////////////////// - -typedef struct -{ - U64 voff; - U32 size; - U32 idx; -} RDIB_VMapRange; - -//////////////////////////////// - -#define RDIB_PATH_TREE_NIL_STRING str8_lit("") - -typedef struct RDIB_PathTreeNode -{ - struct RDIB_PathTreeNode *parent; - struct RDIB_PathTreeNode *next_order; - struct RDIB_PathTreeNode *next_sibling; - struct RDIB_PathTreeNode *first_child; - struct RDIB_PathTreeNode *last_child; - U64 node_idx; - String8 sub_path; - RDIB_SourceFile *src_file; -} RDIB_PathTreeNode; - -typedef struct RDIB_PathTreeNodeList -{ - U64 count; - RDIB_PathTreeNode *first; - RDIB_PathTreeNode *last; -} RDIB_PathTreeNodeList; - -typedef struct RDIB_PathTree -{ - RDIB_PathTreeNode *root; - U64 node_count; - U64 next_list_idx; - U64 list_count; - RDIB_PathTreeNodeList *node_lists; -} RDIB_PathTree; - -//////////////////////////////// - -typedef struct RDIB_Input -{ - U64 unit_chunk_cap; - U64 src_file_chunk_cap; - U64 symbol_chunk_cap; - U64 line_table_cap; - U64 inline_site_cap; - U64 type_cap; - U64 udt_cap; - - RDIB_TopLevelInfo top_level_info; - U64 sect_count; - RDIB_BinarySection *sections; - RDIB_UnitChunkList units; - RDIB_SourceFileChunkList src_files; - RDIB_LineTableChunkList line_tables; - RDIB_ScopeChunkList scopes; - RDIB_VariableChunkList locals; - RDIB_VariableChunkList gvars; - RDIB_VariableChunkList extern_gvars; - RDIB_VariableChunkList static_gvars; - RDIB_VariableChunkList tvars; - RDIB_VariableChunkList extern_tvars; - RDIB_VariableChunkList static_tvars; - RDIB_ProcedureChunkList procs; - RDIB_ProcedureChunkList extern_procs; - RDIB_ProcedureChunkList static_procs; - RDIB_InlineSiteChunkList inline_sites; - RDIB_TypeChunkList types; - RDIB_TypeChunkList struct_list; - RDIB_TypeChunkList union_list; - RDIB_TypeChunkList enum_list; - RDIB_TypeChunkList param_types; - RDIB_TypeChunkList member_types; - RDIB_TypeChunkList enum_types; - RDIB_UDTMemberChunkList udt_members; - RDIB_UDTMemberChunkList enum_members; - - RDIB_SourceFile *null_src_file; - RDIB_LineTable *null_line_table; - RDIB_LineTableFragment *null_frag; - RDIB_Type *null_type; - RDIB_Scope *null_scope; - RDIB_Unit *null_unit; - RDIB_Procedure *null_proc; - RDIB_Variable *null_local; - RDIB_Variable *null_gvar; - RDIB_Variable *null_tvar; - RDIB_UDTMember *null_udt_member; - RDIB_UDTMember *null_enum_member; - RDIB_InlineSite *null_inline_site; - - RDIB_Type *variadic_type; - - //RDIB_TypeChunkList struct_list; - //RDIB_TypeChunkList union_list; - //RDIB_TypeChunkList enum_list; - //RDIB_TypeChunkList param_types; -} RDIB_Input; - -//////////////////////////////// -// Parallel For Tasks - -typedef struct -{ - U64 *udt_counts; -} RDIB_TypeStats; - -typedef struct -{ - RDIB_TypeChunk **chunks; - RDIB_TypeStats *type_stats; -} RDIB_TypeStatsTask; - -typedef struct -{ - Rng1U64 *ranges; - U64 *counts; - U64 *offsets; - RDIB_TypeChunk **type_chunks; - RDIB_StringMap *string_map; - union { - RDI_Member *udt_members_rdi; - RDI_EnumMember *enum_members_rdi; - }; -} RDIB_MembersTask; - -typedef struct -{ - RDIB_TypeChunk **type_chunks; - RDIB_TypeStats type_stats; - U64 *udt_base_idx; - RDI_UDT *udts; -} RDIB_UserDefinesTask; - -typedef struct -{ - U64 addr_size; - RDIB_StringMap *string_map; - RDIB_IndexRunMap *idx_run_map; - RDIB_TypeChunk **type_chunks; - RDIB_TypeStats type_stats; - RDI_TypeNode *type_nodes; -} RDIB_TypeNodesTask; - -typedef struct -{ - RDIB_StringMap *string_map; - Rng1U64 *ranges; - RDIB_StringMapUpdateFunc *string_map_update_func; - RDIB_StringMapBucket **free_buckets; - U64 *insert_counts; - U64 *element_indices; - union - { - RDIB_UnitChunk **units; - RDIB_BinarySection *sects; - RDIB_SourceFileChunk **src_file_chunks; - RDIB_VariableChunk **vars; - RDIB_ProcedureChunk **procs; - RDIB_InlineSiteChunk **inline_sites; - RDIB_UDTMemberChunk **udt_members; - RDIB_UDTMemberChunk **enum_members; - RDIB_TypeChunk **types; - RDIB_PathTreeNodeList *path_node_lists; - }; -} RDIB_CollectStringsTask; - -typedef struct -{ - RDIB_StringMap *string_map; - Rng1U64 *ranges; - RDIB_TypeChunk **chunks; - String8List *data_lists; -} RDIB_BuildTypeDataTask; - -typedef struct -{ - RDIB_StringMap *string_map; - Rng1U64 *ranges; - union { - struct { - RDIB_VariableChunk **gvars_rdib; - String8List *gvars_out; - }; - struct { - RDIB_VariableChunk **tvars_rdib; - String8List *tvars_out; - }; - struct { - RDIB_ProcedureChunk **procs_rdib; - String8List *procs_out; - }; - struct { - RDIB_ScopeChunk **scopes_rdib; - U64 *scope_voff_counts; - U64 *loc_data_sizes; - U64 *local_counts; - U64 *loc_block_counts; - U64 *scope_voff_offsets; - U64 *local_offsets; - U64 *loc_block_offsets; - U64 *loc_data_offsets; - U64 *scope_voffs_rdi; - RDI_Scope *scopes_rdi; - RDI_Symbol *locals_rdi; - void *loc_blocks_rdi; - U8 *loc_data_rdi; - }; - }; -} RDIB_BuildSymbolSectionTask; - -typedef union -{ - struct { - U64 *counts; - U64 *offsets; - Rng1U64 *ranges; - RDIB_VMapRange *vmap; - union { - RDIB_UnitChunk **unit_chunks; - RDIB_VariableChunk **gvar_chunks; - RDIB_ScopeChunk **scope_chunks; - }; - }; - - struct { - U64 vmap_counts[3]; - RDIB_VMapRange *vmaps[3]; - String8List raw_vmaps[3]; - }; -} RDIB_VMapBuilderTask; - -typedef struct -{ - U64 sorter_idx; - RDI_NameMapKind name_map_kind; - RDIB_IndexRunMap *idx_run_map; - RDIB_IndexRunBucket **free_buckets; - Rng1U64 *ranges; - union { - RDIB_TypeChunk **type_chunks; - RDIB_StringMapBucket **name_map_buckets; - }; -} RDIB_BuildIndexRunsTask; - -typedef struct -{ - RDIB_IndexRunBucket **buckets; - Rng1U64 *ranges; - U32 *output_array; -} RDIB_IdxRunCopyTask; - -typedef struct -{ - RDIB_IndexRunMap *idx_run_map; - Rng1U64 *ranges; - U64 *counts; - U64 *offsets; - RDIB_IndexRunBucket **result; -} RDIB_GetExtantBucketsIndexRunMapTask; - -typedef struct -{ - U64 chunk_idx_opl; - Rng1U64 *ranges; - RDIB_IndexRunBucket **src; - RDIB_IndexRunBucket **dst; - U32 *chunk_histo; - U32 *chunk_offsets; -} RDIB_IndexRunMapRadixSort; - -typedef struct -{ - RDIB_StringMap *string_map; - RDIB_IndexRunMap *idx_run_map; - U64 *in_bucket_counts; - RDIB_StringMapBucket ***in_buckets; - - RDI_NameMapBucket **out_buckets; - RDI_NameMapNode **out_nodes; - U64 *out_bucket_counts; - U64 *out_node_counts; -} RDIB_NameMapBuilderTask; - -typedef struct -{ - RDIB_PathTree *path_tree; - RDIB_StringMap *string_map; - RDI_FilePathNode *nodes_dst; -} RDIB_BuildFilePathNodesTask; - -typedef struct -{ - RDIB_SourceFile **src_file_arr; - U32 *out_line_counts; - U32 *out_voff_counts; - U32 **out_line_nums; - U32 **out_line_ranges; - U64 **out_voffs; -} RDIB_SrcLineMapsTask; - -typedef struct -{ - RDIB_LineTableChunk **chunks; - Rng1U64 *ranges; - - U64 *out_line_table_counts; - U64 **out_line_table_voffs; - RDI_Line **out_line_table_lines; -} RDIB_BuildLineTablesTask; - -typedef struct -{ - Rng1U64 *ranges; - RDIB_StringMap *string_map; - RDIB_PathTree *path_tree; - RDIB_SourceFileChunk **src_file_chunks; - RDI_SourceFile *src_files_dst; -} RDIB_FillSourceFilesTask; - -//////////////////////////////// -// Data Model Helpers - -internal RDIB_DataModel rdib_infer_data_model(OperatingSystem os, RDI_Arch arch); - -internal RDI_TypeKind rdib_short_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_unsigned_short_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_int_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_unsigned_int_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_long_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_unsigned_long_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_long_long_type_from_data_model (RDIB_DataModel data_model); -internal RDI_TypeKind rdib_unsigned_long_long_type_from_data_model(RDIB_DataModel data_model); -internal RDI_TypeKind rdib_pointer_size_t_type_from_data_model (RDIB_DataModel data_model); - -//////////////////////////////// - -internal void rdib_udt_member_list_push_node (RDIB_UDTMemberList *list, RDIB_UDTMember *node); -internal void rdib_udt_member_list_concat_in_place(RDIB_UDTMemberList *list, RDIB_UDTMemberList *to_concat); - -internal RDIB_LineTableFragment * rdib_line_table_push(Arena *arena, RDIB_LineTable *list); - -//////////////////////////////// -// Chunk Lists - -// push -internal RDIB_Unit * rdib_unit_chunk_list_push (Arena *arena, RDIB_UnitChunkList *list, U64 cap); -internal RDIB_Scope * rdib_scope_chunk_list_push (Arena *arena, RDIB_ScopeChunkList *list, U64 cap); -internal RDIB_Procedure * rdib_procedure_chunk_list_push (Arena *arena, RDIB_ProcedureChunkList *list, U64 cap); -internal RDIB_Variable * rdib_variable_chunk_list_push (Arena *arena, RDIB_VariableChunkList *list, U64 cap); -internal RDIB_LineTable * rdib_line_table_chunk_list_push (Arena *arena, RDIB_LineTableChunkList *list, U64 cap); -internal RDIB_Type * rdib_type_chunk_list_push (Arena *arena, RDIB_TypeChunkList *list, U64 cap); -internal RDIB_UDTMember * rdib_udt_member_chunk_list_push (Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap); -internal RDIB_SourceFile * rdib_source_file_chunk_list_push(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); -internal RDIB_InlineSite * rdib_inline_site_chunk_list_push(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap); - -internal RDIB_Scope * rdib_scope_chunk_list_push_zero (Arena *arena, RDIB_ScopeChunkList *list, U64 cap); -internal RDIB_Procedure * rdib_procedure_chunk_list_push_zero (Arena *arena, RDIB_ProcedureChunkList *list, U64 cap); -internal RDIB_Variable * rdib_variable_chunk_list_push_zero (Arena *arena, RDIB_VariableChunkList *list, U64 cap); -internal RDIB_LineTable * rdib_line_table_chunk_list_push_zero (Arena *arena, RDIB_LineTableChunkList *list, U64 cap); -internal RDIB_Type * rdib_type_chunk_list_push_zero (Arena *arena, RDIB_TypeChunkList *list, U64 cap); -internal RDIB_UDTMember * rdib_udt_member_chunk_list_push_zero (Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap); -internal RDIB_SourceFile * rdib_source_file_chunk_list_push_zero(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); -internal RDIB_InlineSite * rdib_inline_site_chunk_list_push_zero(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap); - -// push many -internal RDIB_UnitChunk * rdib_unit_chunk_list_reserve_ex(Arena *arena, RDIB_UnitChunkList *list, U64 chunk_count, U64 item_count); - -internal void rdib_unit_chunk_list_reserve (Arena *arena, RDIB_UnitChunkList *list, U64 cap); -internal void rdib_type_chunk_list_reserve (Arena *arena, RDIB_TypeChunkList *list, U64 cap); -internal void rdib_source_file_chunk_list_reserve(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); - -// concat in place -internal void rdib_scope_chunk_list_concat_in_place (RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat); -internal void rdib_udt_member_chunk_list_concat_in_place (RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat); -internal void rdib_procedure_chunk_list_concat_in_place (RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat); -internal void rdib_variable_chunk_list_concat_in_place (RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat); -internal void rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat); -internal void rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat); -internal void rdib_type_chunk_list_concat_in_place (RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat); -internal void rdib_source_file_chunk_list_concat_in_place(RDIB_SourceFileChunkList *list, RDIB_SourceFileChunkList *to_concat); - -// concat in place many -internal void rdib_type_chunk_list_concat_in_place_many (RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat, U64 count); -internal void rdib_udt_member_chunk_list_concat_in_place_many(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat, U64 count); - -// array from chunk list -internal RDIB_UnitChunk ** rdib_array_from_unit_chunk_list (Arena *arena, RDIB_UnitChunkList list); -internal RDIB_ScopeChunk ** rdib_array_from_scope_chunk_list (Arena *arena, RDIB_ScopeChunkList list); -internal RDIB_ProcedureChunk ** rdib_array_from_procedure_chunk_list (Arena *arena, RDIB_ProcedureChunkList list); -internal RDIB_VariableChunk ** rdib_array_from_variable_chunk_list (Arena *arena, RDIB_VariableChunkList list); -internal RDIB_LineTableChunk ** rdib_array_from_line_table_chunk_list (Arena *arena, RDIB_LineTableChunkList list); -internal RDIB_InlineSiteChunk ** rdib_array_from_inline_site_chunk_list(Arena *arena, RDIB_InlineSiteChunkList list); -internal RDIB_UDTMemberChunk ** rdib_array_from_udt_member_chunk_list (Arena *arena, RDIB_UDTMemberChunkList list); -internal RDIB_TypeChunk ** rdib_array_from_type_chunk_list (Arena *arena, RDIB_TypeChunkList list); -internal RDIB_SourceFileChunk ** rdib_array_from_source_file_chunk_list(Arena *arena, RDIB_SourceFileChunkList list); - -// total count from chunk list -internal U64 rdib_unit_chunk_list_total_count (RDIB_UnitChunkList list); -internal U64 rdib_scope_chunk_list_total_count (RDIB_ScopeChunkList list); -internal U64 rdib_variable_chunk_list_total_count (RDIB_VariableChunkList list); -internal U64 rdib_line_table_chunk_list_total_count (RDIB_LineTableChunkList list); -internal U64 rdib_procedure_chunk_list_total_count (RDIB_ProcedureChunkList list); -internal U64 rdib_inline_site_chunk_list_total_count(RDIB_InlineSiteChunkList list); -internal U64 rdib_udt_member_chunk_list_total_count (RDIB_UDTMemberChunkList list); -internal U64 rdib_type_chunk_list_total_count (RDIB_TypeChunkList list); -internal U64 rdib_source_file_chunk_list_total_count(RDIB_SourceFileChunkList list); - -// pointer -> array index -internal U32 rdib_idx_from_unit (RDIB_Unit *n); -internal U32 rdib_idx_from_scope (RDIB_Scope *n); -internal U32 rdib_idx_from_variable (RDIB_Variable *n); -internal U32 rdib_idx_from_procedure (RDIB_Procedure *n); -internal U32 rdib_idx_from_source_file(RDIB_SourceFile *n); -internal U32 rdib_idx_from_line_table (RDIB_LineTable *n); -internal U32 rdib_idx_from_type (RDIB_Type *n); -internal U32 rdib_idx_from_udt_type (RDIB_Type *n); -internal U32 rdib_idx_from_inline_site(RDIB_InlineSite *n); - -//////////////////////////////// - -//- Source File - -internal B32 rdib_source_file_match(RDIB_SourceFile *a, RDIB_SourceFile *b, OperatingSystem os); - -//- Eval Ops - -internal RDIB_EvalBytecodeOp * rdib_bytecode_push_op (Arena *arena, RDIB_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p); -internal void rdib_bytecode_push_ucsont(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_U64 uconst); -internal void rdib_bytecode_push_sconst(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_S64 sconst); - -//- Location - -internal RDIB_Location rdib_make_location_addr_byte_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); -internal RDIB_Location rdib_make_location_addr_bytecode_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); -internal RDIB_Location rdib_make_location_val_bytecode_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); -internal RDIB_Location rdib_make_location_addr_reg_plus_u16 (Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); - -internal RDIB_Location rdib_make_location_addr_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); -internal RDIB_Location rdib_make_location_addr_reg_plus_u16 (Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); -internal RDIB_Location rdib_make_location_val_reg (Rng1U64List ranges, RDI_RegCode reg_code); - -internal RDIB_LocationNode * rdib_push_location_addr_reg_off(Arena *arena, RDIB_LocationList *list, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 is_reference, Rng1U64List ranges); - -//- UDT Fwdrefs - -internal U64 rdib_udt_fwdref_map_hash(String8 string); -internal RDIB_UDTFwdrefBucket * rdib_udt_fwdref_map_insert_or_update(RDIB_UDTFwdrefBucket **buckets, U64 cap, U64 hash, RDIB_UDTFwdrefBucket *new_bucket); -internal RDIB_UDTFwdrefBucket * rdib_udt_fwdrefmap_map_lookup(RDIB_UDTFwdrefBucket **buckets, U64 cap, U64 hash, String8 name); - -//- Types - -internal RDIB_TypeRef rdib_make_type_ref(Arena *arena, RDIB_Type *type); -internal void rdib_deref_type_refs(TP_Context *tp, RDIB_TypeChunkList *list); - -internal RDIB_TypeStats rdib_sum_type_stats (RDIB_TypeStats *stats, U64 count); -internal U64 rdib_udt_count_from_type_stats (RDIB_TypeStats *stats); -internal U64 rdib_type_node_count_from_type_stats(RDIB_TypeStats *stats); - -internal U64 rdib_size_from_type (RDIB_Type *type); -internal U64 rdib_count_members_deep(RDIB_Type *type); - -//- Path Tree - -internal RDIB_PathTree * rdib_path_tree_init (Arena *arena, U64 list_count); -internal void rdib_path_tree_insert (Arena *arena, RDIB_PathTree *tree, String8 path, RDIB_SourceFile *src_file); -internal U32 rdib_idx_from_path_tree(RDIB_PathTree *tree, String8 path); - - -//- String Map - -internal U64 rdib_string_map_hash (String8 string); -internal RDIB_StringMap * rdib_init_string_map (Arena *arena, U64 cap); -internal U32 rdib_idx_from_string_map (RDIB_StringMap *string_map, String8 string); -internal RDIB_StringMapBucket * rdib_string_map_insert_or_update (RDIB_StringMapBucket **buckets, U64 cap, U64 hash, RDIB_StringMapBucket *new_bucket, RDIB_StringMapUpdateFunc *update_func); -internal void rdib_string_map_assign_indices (RDIB_StringMapBucket **buckets, U64 bucket_count); -internal RDIB_StringMapBucket ** rdib_extant_buckets_from_string_map(TP_Context *tp, Arena *arena, RDIB_StringMap *string_map, U64 *bucket_count_out); -internal void rdib_string_map_sort_buckets (TP_Context *tp, RDIB_StringMapBucket **buckets, U64 bucket_count, U64 max_sorter); - -//- String Map Specialized Inserters - -internal void rdib_string_map_insert_item (Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, void *value); -internal void rdib_string_map_insert_string_table_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string); -internal void rdib_string_map_insert_name_map_item (Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, VoidNode *node); - -//- Index Run Map - -internal U64 rdib_index_run_hash (U32 count, U32 *idxs); -internal RDIB_IndexRunMap * rdib_init_index_run_map (Arena *arena, U64 cap); -internal RDIB_IndexRunBucket * rdib_index_run_map_insert_or_update (Arena *arena, RDIB_IndexRunBucket **buckets, U64 cap, U64 hash, RDIB_IndexRunBucket *new_bucket, U64 *bucket_idx_out); -internal U32 rdib_idx_run_from_bucket_idx (RDIB_IndexRunMap *map, U64 bucket_idx); -internal void rdib_index_run_map_assign_indices (RDIB_IndexRunBucket **buckets, U64 bucket_count); -internal RDIB_IndexRunBucket ** rdib_extant_buckets_from_index_run_map(TP_Context *tp, Arena *arena, RDIB_IndexRunMap *idx_run_map, U64 *bucket_count_out); -internal void rdib_index_run_map_sort_buckets (TP_Context *tp, RDIB_IndexRunBucket **buckets, U64 bucket_count, U64 chunk_idx_opl); - -//- Index Map Spesialized Query - -internal U32 rdib_idx_from_params(RDIB_IndexRunMap *map, RDIB_Type *params); - -//- Data Sections - -internal void rdib_data_section_list_push_node (RDIB_DataSectionList *list, RDIB_DataSectionNode *node); -internal RDIB_DataSectionNode * rdib_data_section_list_push (Arena *arena, RDIB_DataSectionList *list, RDIB_DataSection v); -internal void rdib_data_section_list_concat_in_place(RDIB_DataSectionList *list, RDIB_DataSectionList *to_concat); - -internal void rdib_data_sections_from_top_level_info (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_TopLevelInfo *src); -internal void rdib_data_sections_from_binary_sections (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_BinarySection *binary_sects, U64 binary_sects_count); -internal void rdib_data_sections_from_string_map (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count); -internal void rdib_data_sections_from_index_runs (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_IndexRunBucket **buckets, U64 bucket_count); -internal void rdib_data_sections_from_file_path_nodes (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_PathTree *tree); -internal void rdib_data_sections_from_source_files (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_file_chunks); -internal void rdib_data_sections_from_units (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_unit_count, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks); -internal void rdib_data_sections_from_string_map (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count); -internal void rdib_data_sections_from_types(TP_Context *tp, - Arena *arena, - RDIB_DataSectionList *sect_list, - RDI_Arch arch, - RDIB_StringMap *string_map, - RDIB_IndexRunMap *idx_run_map, - U64 udt_member_chunk_count, - RDIB_TypeChunk **udt_member_type_chunks, - U64 enum_member_chunk_count, - RDIB_TypeChunk **enum_member_type_chunks, - U64 total_type_node_count, - U64 type_chunk_count, - RDIB_TypeChunk **type_chunks, - RDIB_TypeStats type_stats); -internal void rdib_data_sections_from_global_variables (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks); -internal void rdib_data_sections_from_thread_variables (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks); -internal void rdib_data_sections_from_procedures (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_ProcedureChunk **chunks); -internal void rdib_data_sections_from_scopes (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_ScopeChunk **chunks); -internal void rdib_data_sections_from_name_maps (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_IndexRunMap *idx_run_map, RDIB_StringMapBucket **src_name_maps[RDI_NameMapKind_COUNT], U64 src_name_map_counts[RDI_NameMapKind_COUNT]); -internal void rdib_data_sections_from_source_line_maps (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_fille_chunks); -internal void rdib_data_sections_from_unit_gvar_scope_vmaps(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks, U64 gvar_chunk_count, RDIB_VariableChunk **gvar_chunks, U64 scope_chunk_count, RDIB_ScopeChunk **scope_chunks); -internal void rdib_data_sections_from_inline_sites (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_inline_site_count, U64 inline_site_chunk_count, RDIB_InlineSiteChunk **inline_site_chunks); -internal void rdib_data_sections_from_checksums (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list); - -internal RDIB_Input rdib_init_input(Arena *arena); -internal String8List rdib_finish(TP_Context *tp, TP_Arena *arena, RDIB_Input *input); - diff --git a/src/linker/rdi/rdi_coff.c b/src/linker/rdi/rdi_coff.c deleted file mode 100644 index 1227a480..00000000 --- a/src/linker/rdi/rdi_coff.c +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -internal RDI_Arch -rdi_arch_from_coff_machine(COFF_MachineType machine) -{ - switch (machine) { - case COFF_MachineType_X64: return RDI_Arch_X64; - - case COFF_MachineType_X86: - case COFF_MachineType_Unknown: - case COFF_MachineType_Am33: - case COFF_MachineType_Arm: - case COFF_MachineType_Arm64: - case COFF_MachineType_ArmNt: - case COFF_MachineType_Ebc: - case COFF_MachineType_Ia64: - case COFF_MachineType_M32R: - case COFF_MachineType_Mips16: - case COFF_MachineType_MipsFpu: - case COFF_MachineType_MipsFpu16: - case COFF_MachineType_PowerPc: - case COFF_MachineType_PowerPcFp: - case COFF_MachineType_R4000: - case COFF_MachineType_RiscV32: - case COFF_MachineType_RiscV64: - case COFF_MachineType_Sh3: - case COFF_MachineType_Sh3Dsp: - case COFF_MachineType_Sh4: - case COFF_MachineType_Sh5: - case COFF_MachineType_Thumb: - case COFF_MachineType_WceMipsV2: - NotImplemented; - default: - return RDI_Arch_NULL; - } -} - -internal RDI_BinarySectionFlags -rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) -{ - RDI_BinarySectionFlags result = 0; - if (flags & COFF_SectionFlag_MemRead) { - result |= RDI_BinarySectionFlag_Read; - } - if (flags & COFF_SectionFlag_MemWrite) { - result |= RDI_BinarySectionFlag_Write; - } - if (flags & COFF_SectionFlag_MemExecute) { - result |= RDI_BinarySectionFlag_Execute; - } - return result; -} diff --git a/src/linker/rdi/rdi_coff.h b/src/linker/rdi/rdi_coff.h deleted file mode 100644 index caefb833..00000000 --- a/src/linker/rdi/rdi_coff.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#pragma once - -internal RDI_Arch rdi_arch_from_coff_machine(COFF_MachineType machine); - diff --git a/src/linker/rdi/rdi_cv.c b/src/linker/rdi/rdi_cv.c deleted file mode 100644 index 545777ab..00000000 --- a/src/linker/rdi/rdi_cv.c +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -internal RDI_Arch -rdi_arch_from_cv_arch(CV_Arch arch) -{ - switch (arch) { - case CV_Arch_X64: return RDI_Arch_X64; - - case CV_Arch_8086: - case CV_Arch_8080: - case CV_Arch_80286: - case CV_Arch_80386: - case CV_Arch_80486: - case CV_Arch_PENTIUM: - case CV_Arch_PENTIUMII: - case CV_Arch_PENTIUMIII: - case CV_Arch_MIPS: - case CV_Arch_MIPS16: - case CV_Arch_MIPS32: - case CV_Arch_MIPS64: - case CV_Arch_MIPSI: - case CV_Arch_MIPSII: - case CV_Arch_MIPSIII: - case CV_Arch_MIPSIV: - case CV_Arch_MIPSV: - case CV_Arch_M68000: - case CV_Arch_M68010: - case CV_Arch_M68020: - case CV_Arch_M68030: - case CV_Arch_M68040: - case CV_Arch_ALPHA: - case CV_Arch_ALPHA_21164: - case CV_Arch_ALPHA_21164A: - case CV_Arch_ALPHA_21264: - case CV_Arch_ALPHA_21364: - case CV_Arch_PPC601: - case CV_Arch_PPC603: - case CV_Arch_PPC604: - case CV_Arch_PPC620: - case CV_Arch_PPCFP: - case CV_Arch_PPCBE: - case CV_Arch_SH3: - case CV_Arch_SH3E: - case CV_Arch_SH3DSP: - case CV_Arch_SH4: - case CV_Arch_SHMEDIA: - case CV_Arch_ARM3: - case CV_Arch_ARM4: - case CV_Arch_ARM4T: - case CV_Arch_ARM5: - case CV_Arch_ARM5T: - case CV_Arch_ARM6: - case CV_Arch_ARM_XMAC: - case CV_Arch_ARM_WMMX: - case CV_Arch_ARM7: - case CV_Arch_OMNI: - case CV_Arch_IA64_1: - case CV_Arch_IA64_2: - case CV_Arch_CEE: - case CV_Arch_AM33: - case CV_Arch_M32R: - case CV_Arch_TRICORE: - case CV_Arch_EBC: - case CV_Arch_THUMB: - case CV_Arch_ARMNT: - case CV_Arch_ARM64: - case CV_Arch_D3D11_SHADER: - NotImplemented; - default: - return RDI_Arch_NULL; - } -} - -internal RDI_Language -rdi_language_from_cv_language(CV_Language language) -{ - switch (language) { - case CV_Language_C: return RDI_Language_C; - case CV_Language_CXX: return RDI_Language_CPlusPlus; - case CV_Language_MASM: return RDI_Language_Masm; - case CV_Language_LINK: return RDI_Language_NULL; - case CV_Language_CVTRES: return RDI_Language_NULL; - - case CV_Language_FORTRAN: - case CV_Language_PASCAL: - case CV_Language_BASIC: - case CV_Language_COBOL: - case CV_Language_CVTPGD: - case CV_Language_CSHARP: - case CV_Language_VB: - case CV_Language_ILASM: - case CV_Language_JAVA: - case CV_Language_JSCRIPT: - case CV_Language_MSIL: - case CV_Language_HLSL: - NotImplemented; - default: - return RDI_Language_NULL; - } -} - -internal RDI_TypeModifierFlags -rdi_type_modifier_flags_from_cv_modifier_flags(CV_ModifierFlags flags) -{ - RDI_TypeModifierFlags result = 0; - if (flags & CV_ModifierFlag_Const) { - result |= RDI_TypeModifierFlag_Const; - } - if (flags & CV_ModifierFlag_Volatile) { - result |= RDI_TypeModifierFlag_Volatile; - } - return result; -} - -internal RDI_TypeModifierFlags -rdi_type_modifier_flags_from_cv_pointer_attribs(CV_PointerAttribs attribs) -{ - RDI_TypeModifierFlags result = 0; - if (attribs & CV_PointerAttrib_Const) { - result |= RDI_TypeModifierFlag_Const; - } - if (attribs & CV_PointerAttrib_Volatile) { - result |= RDI_TypeModifierFlag_Volatile; - } - return result; -} - -internal RDI_TypeKind -rdi_type_kind_from_pointer(CV_PointerAttribs attribs, CV_PointerMode mode) -{ - RDI_TypeKind result = RDI_TypeKind_Ptr; - - if (attribs & CV_PointerAttrib_LRef) { - result = RDI_TypeKind_LRef; - } else if (attribs & CV_PointerAttrib_RRef) { - result = RDI_TypeKind_RRef; - } - - if (mode == CV_PointerMode_LRef) { - result = RDI_TypeKind_LRef; - } else if (mode == CV_PointerMode_RRef) { - result = RDI_TypeKind_RRef; - } - - return result; -} - -internal RDI_TypeKind -rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type) -{ - switch (basic_type) { - case CV_BasicType_NOTYPE : return RDI_TypeKind_NULL; - case CV_BasicType_ABS : return RDI_TypeKind_NULL; - case CV_BasicType_SEGMENT : return RDI_TypeKind_NULL; - case CV_BasicType_VOID : return RDI_TypeKind_Void; - case CV_BasicType_CURRENCY : return RDI_TypeKind_NULL; - case CV_BasicType_NBASICSTR : return RDI_TypeKind_NULL; - case CV_BasicType_FBASICSTR : return RDI_TypeKind_NULL; - case CV_BasicType_HRESULT : return RDI_TypeKind_Handle; - case CV_BasicType_CHAR : return RDI_TypeKind_Char8; - case CV_BasicType_SHORT : return RDI_TypeKind_S16; - case CV_BasicType_LONG : return RDI_TypeKind_S32; - case CV_BasicType_QUAD : return RDI_TypeKind_S64; - case CV_BasicType_OCT : return RDI_TypeKind_S128; - case CV_BasicType_UCHAR : return RDI_TypeKind_UChar8; - case CV_BasicType_USHORT : return RDI_TypeKind_U16; - case CV_BasicType_ULONG : return RDI_TypeKind_U32; - case CV_BasicType_UQUAD : return RDI_TypeKind_U64; - case CV_BasicType_UOCT : return RDI_TypeKind_U128; - case CV_BasicType_BOOL8 : return RDI_TypeKind_S8; - case CV_BasicType_BOOL16 : return RDI_TypeKind_S16; - case CV_BasicType_BOOL32 : return RDI_TypeKind_S32; - case CV_BasicType_BOOL64 : return RDI_TypeKind_S64; - case CV_BasicType_FLOAT32 : return RDI_TypeKind_F32; - case CV_BasicType_FLOAT64 : return RDI_TypeKind_F64; - case CV_BasicType_FLOAT80 : return RDI_TypeKind_F80; - case CV_BasicType_FLOAT128 : return RDI_TypeKind_F128; - case CV_BasicType_FLOAT48 : return RDI_TypeKind_F48; - case CV_BasicType_FLOAT32PP : return RDI_TypeKind_F32PP; - case CV_BasicType_FLOAT16 : return RDI_TypeKind_F16; - case CV_BasicType_COMPLEX32 : return RDI_TypeKind_ComplexF32; - case CV_BasicType_COMPLEX64 : return RDI_TypeKind_ComplexF64; - case CV_BasicType_COMPLEX80 : return RDI_TypeKind_ComplexF80; - case CV_BasicType_COMPLEX128: return RDI_TypeKind_ComplexF128; - case CV_BasicType_BIT : return RDI_TypeKind_NULL; - case CV_BasicType_PASCHAR : return RDI_TypeKind_NULL; - case CV_BasicType_BOOL32FF : return RDI_TypeKind_NULL; - case CV_BasicType_INT8 : return RDI_TypeKind_S8; - case CV_BasicType_UINT8 : return RDI_TypeKind_U8; - case CV_BasicType_RCHAR : return RDI_TypeKind_Char8; - case CV_BasicType_WCHAR : return RDI_TypeKind_UChar16; - case CV_BasicType_CHAR16 : return RDI_TypeKind_Char16; - case CV_BasicType_CHAR32 : return RDI_TypeKind_Char32; - case CV_BasicType_INT16 : return RDI_TypeKind_S16; - case CV_BasicType_UINT16 : return RDI_TypeKind_U16; - case CV_BasicType_INT32 : return RDI_TypeKind_S32; - case CV_BasicType_UINT32 : return RDI_TypeKind_U32; - case CV_BasicType_INT64 : return RDI_TypeKind_S64; - case CV_BasicType_UINT64 : return RDI_TypeKind_U64; - case CV_BasicType_INT128 : return RDI_TypeKind_S128; - case CV_BasicType_UINT128 : return RDI_TypeKind_U128; - case CV_BasicType_CHAR8 : return RDI_TypeKind_Char8; - case CV_BasicType_PTR : return RDI_TypeKind_Ptr; - } - return RDI_TypeKind_NULL; -} - -internal RDI_RegCode -rdi_reg_code_from_cv(CV_Arch arch, CV_Reg reg) -{ - RDI_RegCode result = 0; - switch (arch) { - case CV_Arch_X64: { - switch (reg) { -#define X(CVN,C,RDN,BP,BZ) case C: result = RDI_RegCodeX64_##RDN; break; - CV_Reg_X64_XList(X) -#undef X - } - } break; - case CV_Arch_8086: - default: NotImplemented; - } - return result; -} - -internal RDI_ChecksumKind -rdi_checksum_from_cv_c13(CV_C13ChecksumKind kind) -{ - switch (kind) { - case CV_C13ChecksumKind_Null: return RDI_ChecksumKind_NULL; - case CV_C13ChecksumKind_MD5: return RDI_ChecksumKind_MD5; - case CV_C13ChecksumKind_SHA1: return RDI_ChecksumKind_SHA1; - case CV_C13ChecksumKind_SHA256: return RDI_ChecksumKind_SHA256; - } - return RDI_ChecksumKind_NULL; -} diff --git a/src/linker/rdi/rdi_cv.h b/src/linker/rdi/rdi_cv.h deleted file mode 100644 index 98aa8244..00000000 --- a/src/linker/rdi/rdi_cv.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#pragma once - -internal RDI_Arch rdi_arch_from_cv_arch(CV_Arch arch); -internal RDI_Language rdi_language_from_cv_language(CV_Language language); -internal RDI_TypeModifierFlags rdi_type_modifier_flags_from_cv_pointer_attribs(CV_PointerAttribs attribs); -internal RDI_TypeKind rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type); -internal RDI_RegCode rdi_reg_code_from_cv(CV_Arch arch, CV_Reg reg); - -internal RDI_ChecksumKind rdi_checksum_from_cv_c13(CV_C13ChecksumKind kind); - - diff --git a/src/linker/rdi/rdi_overrides.h b/src/linker/rdi/rdi_overrides.h deleted file mode 100644 index b593000e..00000000 --- a/src/linker/rdi/rdi_overrides.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -typedef U8 RDI_U8; -typedef U16 RDI_U16; -typedef U32 RDI_U32; -typedef U64 RDI_U64; -typedef S8 RDI_S8; -typedef S16 RDI_S16; -typedef S32 RDI_S32; -typedef S64 RDI_S64; - -#define RDI_PROC internal -#define RDIM_MEMSET_OVERRIDE -#define rdim_memset MemorySet - -#define RDIM_MEMCPY_OVERRIDE -#define rdim_memcpy MemoryCopy - -#define rdim_vsnprintf raddbg_vsnprintf - diff --git a/src/linker/scripts/obj_paths_from_pdb.py b/src/linker/scripts/obj_paths_from_pdb.py deleted file mode 100644 index 2bd11b50..00000000 --- a/src/linker/scripts/obj_paths_from_pdb.py +++ /dev/null @@ -1,16 +0,0 @@ -import subprocess -import sys -import os - -def get_sorted_objs(pdb_path): - result = subprocess.run(["llvm-pdbutil", "dump", "--modules", pdb_path], stdout=subprocess.PIPE, text=True) - lines = result.stdout.strip().split('\n') - filtered_lines = [line for line in lines if line.lstrip().startswith("Mod ")] - # sort by the obj_path portion (line format: "Mod ") - def extract_path(line): return line.split(maxsplit=2)[2].lower() - #sorted_lines = sorted(filtered_lines, key=extract_path) - return filtered_lines - -if __name__ == "__main__": - sorted_objs = get_sorted_objs(sys.argv[1]) - for l in sorted_objs: print(l.lstrip())