diff --git a/src/lib_raddbgi_make/raddbgi_make.c b/src/lib_raddbgi_make/raddbgi_make.c index 09a15480..b93900e8 100644 --- a/src/lib_raddbgi_make/raddbgi_make.c +++ b/src/lib_raddbgi_make/raddbgi_make.c @@ -2683,3087 +2683,3 @@ rdim_bake(RDIM_Arena *arena, RDIM_BakeParams *params) rdim_scratch_end(scratch); return blobs; } - -#if 0 -//////////////////////////////// -//~ rjf: Loose Debug Info Construction (Anything -> Loose) Functions - -//- rjf: u64 -> ptr map - -RDI_PROC void -rdim_u64toptr_map_init(RDIM_Arena *arena, RDIM_U64ToPtrMap *map, RDI_U64 bucket_count) -{ - rdim_assert(IsPow2OrZero(bucket_count) && bucket_count > 0); - map->buckets = rdim_push_array(arena, RDIM_U64ToPtrNode*, bucket_count); - map->buckets_count = bucket_count; -} - -RDI_PROC void -rdim_u64toptr_map_lookup(RDIM_U64ToPtrMap *map, RDI_U64 key, RDI_U64 hash, RDIM_U64ToPtrLookup *lookup_out) -{ - RDI_U64 bucket_idx = hash&(map->buckets_count - 1); - RDIM_U64ToPtrNode *check_node = map->buckets[bucket_idx]; - for(;check_node != 0; check_node = check_node->next){ - for(RDI_U32 k = 0; k < ArrayCount(check_node->key); k += 1){ - if(check_node->ptr[k] == 0){ - lookup_out->fill_node = check_node; - lookup_out->fill_k = k; - break; - } - else if(check_node->key[k] == key){ - lookup_out->match = check_node->ptr[k]; - break; - } - } - } -} - -RDI_PROC void -rdim_u64toptr_map_insert(RDIM_Arena *arena, RDIM_U64ToPtrMap *map, RDI_U64 key, RDI_U64 hash, RDIM_U64ToPtrLookup *lookup, void *ptr) -{ - if(lookup->fill_node != 0) - { - RDIM_U64ToPtrNode *node = lookup->fill_node; - RDI_U32 k = lookup->fill_k; - node->key[k] = key; - node->ptr[k] = ptr; - } - else - { - RDI_U64 bucket_idx = hash&(map->buckets_count - 1); - - RDIM_U64ToPtrNode *node = rdim_push_array(arena, RDIM_U64ToPtrNode, 1); - SLLStackPush(map->buckets[bucket_idx], node); - node->key[0] = key; - node->ptr[0] = ptr; - - lookup->fill_node = node; - lookup->fill_k = 0; - - map->pair_count += 1; - map->bucket_collision_count += (node->next != 0); - } -} - -//- rjf: string8 -> ptr map - -RDI_PROC void -rdim_str8toptr_map_init(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDI_U64 bucket_count) -{ - map->buckets_count = bucket_count; - map->buckets = rdim_push_array(arena, RDIM_Str8ToPtrNode*, map->buckets_count); -} - -RDI_PROC void* -rdim_str8toptr_map_lookup(RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash) -{ - void *result = 0; - RDI_U64 bucket_idx = hash%map->buckets_count; - for(RDIM_Str8ToPtrNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->hash == hash && rdim_str8_match(node->key, key, 0)) - { - result = node->ptr; - break; - } - } - return result; -} - -RDI_PROC void -rdim_str8toptr_map_insert(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash, void *ptr) -{ - RDI_U64 bucket_idx = hash%map->buckets_count; - RDIM_Str8ToPtrNode *node = rdim_push_array(arena, RDIM_Str8ToPtrNode, 1); - SLLStackPush(map->buckets[bucket_idx], node); - - node->key = rdim_str8_copy(arena, key); - node->hash = hash; - node->ptr = ptr; - map->bucket_collision_count += (node->next != 0); - map->pair_count += 1; -} - -//- rjf: root creation - -RDI_PROC RDIM_Root * -rdim_root_alloc(RDIM_RootParams *params) -{ - RDIM_Arena *arena = rdim_arena_alloc(); - RDIM_Root *result = rdim_push_array(arena, RDIM_Root, 1); - result->arena = arena; - - // fill in root parameters - { - result->addr_size = params->addr_size; - } - - // setup singular types - { - result->nil_type = rdim_type_new(result); - result->variadic_type = rdim_type_new(result); - result->variadic_type->kind = RDI_TypeKind_Variadic; - - // references to "handled nil type" should be emitted as - // references to nil - but should not generate error - // messages when they are detected - they are expected! - rdim_assert(result->nil_type->idx == result->handled_nil_type.idx); - } - - // setup a null scope - { - RDIM_Scope *scope = rdim_push_array(result->arena, RDIM_Scope, 1); - RDIM_SLLQueuePush_N(result->first_scope, result->last_scope, scope, next_order); - result->scope_count += 1; - } - - // rjf: setup null UDT - { - rdim_type_udt_from_any_type(result, result->nil_type); - } - - // initialize maps - { -#define BKTCOUNT(x) ((x)?(u64_up_to_pow2(x)):(128)) - - rdim_u64toptr_map_init(arena, &result->unit_map, BKTCOUNT(params->bucket_count_units)); - rdim_u64toptr_map_init(arena, &result->symbol_map, BKTCOUNT(params->bucket_count_symbols)); - rdim_u64toptr_map_init(arena, &result->scope_map, BKTCOUNT(params->bucket_count_scopes)); - rdim_u64toptr_map_init(arena, &result->local_map, BKTCOUNT(params->bucket_count_locals)); - rdim_u64toptr_map_init(arena, &result->type_from_id_map, BKTCOUNT(params->bucket_count_types)); - rdim_str8toptr_map_init(arena, &result->construct_map, BKTCOUNT(params->bucket_count_type_constructs)); - -#undef BKTCOUNT - } - - return result; -} - -RDI_PROC void -rdim_root_release(RDIM_Root *root) -{ - arena_release(root->arena); -} - -//- rjf: error accumulation - -RDI_PROC void -rdim_push_msg(RDIM_Root *root, RDIM_String8 string) -{ - RDIM_Msg *msg = rdim_push_array(root->arena, RDIM_Msg, 1); - SLLQueuePush(root->msgs.first, root->msgs.last, msg); - root->msgs.count += 1; - msg->string = string; -} - -RDI_PROC void -rdim_push_msgf(RDIM_Root *root, char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - RDIM_String8 str = rdim_str8fv(root->arena, fmt, args); - rdim_push_msg(root, str); - va_end(args); -} - -RDI_PROC RDIM_Msg * -rdim_first_msg_from_root(RDIM_Root *root) -{ - return root->msgs.first; -} - -//- rjf: type info lookups/reservations - -RDI_PROC RDIM_Type* -rdim_type_from_id(RDIM_Root *root, RDI_U64 type_user_id, RDI_U64 type_user_id_hash) -{ - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->type_from_id_map, type_user_id, type_user_id_hash, &lookup); - RDIM_Type *result = (RDIM_Type*)lookup.match; - return result; -} - -RDI_PROC RDIM_Reservation* -rdim_type_reserve_id(RDIM_Root *root, RDI_U64 type_user_id, RDI_U64 type_user_id_hash) -{ - RDIM_Reservation *result = 0; - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->type_from_id_map, type_user_id, type_user_id_hash, &lookup); - if(lookup.match == 0) - { - rdim_u64toptr_map_insert(root->arena, &root->type_from_id_map, type_user_id, type_user_id_hash, &lookup, root->nil_type); - void **slot = &lookup.fill_node->ptr[lookup.fill_k]; - result = (RDIM_Reservation*)slot; - } - return result; -} - -RDI_PROC void -rdim_type_fill_id(RDIM_Root *root, RDIM_Reservation *res, RDIM_Type *type) -{ - if(res != 0 && type != 0) - { - *(void**)res = type; - } -} - -//- rjf: nil/singleton types - -RDI_PROC RDI_S32 -rdim_type_is_unhandled_nil(RDIM_Root *root, RDIM_Type *type) -{ - RDI_S32 result = (type->kind == RDI_TypeKind_NULL && type != &root->handled_nil_type); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_handled_nil(RDIM_Root *root) -{ - return &root->handled_nil_type; -} - -RDI_PROC RDIM_Type* -rdim_type_nil(RDIM_Root *root) -{ - return root->nil_type; -} - -RDI_PROC RDIM_Type* -rdim_type_variadic(RDIM_Root *root) -{ - return root->variadic_type; -} - -//- rjf: base type info constructors - -RDI_PROC RDIM_Type* -rdim_type_new(RDIM_Root *root) -{ - RDIM_Type *result = rdim_push_array(root->arena, RDIM_Type, 1); - result->idx = root->type_count; - RDIM_SLLQueuePush_N(root->first_type, root->last_type, result, next_order); - root->type_count += 1; - return result; -} - -RDI_PROC RDIM_TypeUDT* -rdim_type_udt_from_any_type(RDIM_Root *root, RDIM_Type *type) -{ - if(type->udt == 0) - { - RDIM_TypeUDT *new_udt = rdim_push_array(root->arena, RDIM_TypeUDT, 1); - new_udt->idx = root->type_udt_count; - RDIM_SLLQueuePush_N(root->first_udt, root->last_udt, new_udt, next_order); - root->type_udt_count += 1; - new_udt->self_type = type; - type->udt = new_udt; - } - RDIM_TypeUDT *result = type->udt; - return result; -} - -RDI_PROC RDIM_TypeUDT* -rdim_type_udt_from_record_type(RDIM_Root *root, RDIM_Type *type) -{ - rdim_requiref(root, (type->kind == RDI_TypeKind_Struct || - type->kind == RDI_TypeKind_Class || - type->kind == RDI_TypeKind_Union), - return 0, - "Tried to use non-user-defined-type-kind to create user-defined-type."); - RDIM_TypeUDT *result = 0; - result = rdim_type_udt_from_any_type(root, type); - return result; -} - -//- rjf: basic/operator type construction helpers - -RDI_PROC RDIM_Type* -rdim_type_basic(RDIM_Root *root, RDI_TypeKind type_kind, RDIM_String8 name) -{ - rdim_requiref(root, (RDI_TypeKind_FirstBuiltIn <= type_kind && type_kind <= RDI_TypeKind_LastBuiltIn), return root->nil_type, "Non-basic type kind passed to construct basic type."); - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = sizeof(RDIM_TypeConstructKind) + sizeof(type_kind) + name.size; - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "basic" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Basic; - ptr += sizeof(RDIM_TypeConstructKind); - // type_kind - rdim_memcpy(ptr, &type_kind, sizeof(type_kind)); - ptr += sizeof(type_kind); - // name - rdim_memcpy(ptr, name.str, name.size); - ptr += name.size; - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // calculate size - RDI_U32 byte_size = rdi_size_from_basic_type_kind(type_kind); - if(byte_size == 0xFFFFFFFF) - { - byte_size = root->addr_size; - } - - // setup new node - result = rdim_type_new(root); - result->kind = type_kind; - result->name = rdim_str8_copy(root->arena, name); - result->byte_size = byte_size; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - - // save in name map - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_Types); - rdim_name_map_add_pair(root, map, result->name, result->idx); - } - } - - scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_modifier(RDIM_Root *root, RDIM_Type *direct_type, RDI_TypeModifierFlags flags) -{ - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = sizeof(RDIM_TypeConstructKind) + sizeof(flags) + sizeof(direct_type->idx); - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "modifier" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Modifier; - ptr += sizeof(RDIM_TypeConstructKind); - // flags - rdim_memcpy(ptr, &flags, sizeof(flags)); - ptr += sizeof(flags); - // direct_type->idx - rdim_memcpy(ptr, &direct_type->idx, sizeof(direct_type->idx)); - ptr += sizeof(direct_type->idx); - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0){ - - // setup new node - result = rdim_type_new(root); - result->kind = RDI_TypeKind_Modifier; - result->flags = flags; - result->byte_size = direct_type->byte_size; - result->direct_type = direct_type; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - rdim_scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_bitfield(RDIM_Root *root, RDIM_Type *direct_type, RDI_U32 bit_off, RDI_U32 bit_count) -{ - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = sizeof(RDIM_TypeConstructKind) + sizeof(direct_type->idx) + sizeof(RDI_U32)*2; - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "bitfield" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Bitfield; - ptr += sizeof(RDIM_TypeConstructKind); - // direct_type->idx - rdim_memcpy(ptr, &direct_type->idx, sizeof(direct_type->idx)); - ptr += sizeof(direct_type->idx); - // bit_off - rdim_memcpy(ptr, &bit_off, sizeof(bit_off)); - ptr += sizeof(bit_off); - // bit_count - rdim_memcpy(ptr, &bit_count, sizeof(bit_count)); - ptr += sizeof(bit_count); - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // setup new node - result = rdim_type_new(root); - result->kind = RDI_TypeKind_Bitfield; - result->byte_size = direct_type->byte_size; - result->off = bit_off; - result->count = bit_count; - result->direct_type = direct_type; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - rdim_scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_pointer(RDIM_Root *root, RDIM_Type *direct_type, RDI_TypeKind ptr_type_kind) -{ - rdim_requiref(root, (ptr_type_kind == RDI_TypeKind_Ptr || - ptr_type_kind == RDI_TypeKind_LRef || - ptr_type_kind == RDI_TypeKind_RRef), - return root->nil_type, - "Non-pointer type kind used to construct pointer type."); - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = sizeof(RDIM_TypeConstructKind) + sizeof(ptr_type_kind) + sizeof(direct_type->idx); - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "pointer" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Pointer; - ptr += sizeof(RDIM_TypeConstructKind); - // type_kind - rdim_memcpy(ptr, &ptr_type_kind, sizeof(ptr_type_kind)); - ptr += sizeof(ptr_type_kind); - // direct_type->idx - rdim_memcpy(ptr, &direct_type->idx, sizeof(direct_type->idx)); - ptr += sizeof(direct_type->idx); - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // setup new node - result = rdim_type_new(root); - result->kind = ptr_type_kind; - result->byte_size = root->addr_size; - result->direct_type = direct_type; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - rdim_scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_array(RDIM_Root *root, RDIM_Type *direct_type, RDI_U64 count) -{ - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = - sizeof(RDIM_TypeConstructKind) + sizeof(direct_type->idx) + sizeof(count); - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "array" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Array; - ptr += sizeof(RDIM_TypeConstructKind); - // direct_type->idx - rdim_memcpy(ptr, &direct_type->idx, sizeof(direct_type->idx)); - ptr += sizeof(direct_type->idx); - // count - rdim_memcpy(ptr, &count, sizeof(count)); - ptr += sizeof(count); - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // setup new node - result = rdim_type_new(root); - result->kind = RDI_TypeKind_Array; - result->count = count; - result->direct_type = direct_type; - result->byte_size = direct_type->byte_size*count; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_proc(RDIM_Root *root, RDIM_Type *return_type, struct RDIM_TypeList *params) -{ - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = sizeof(RDIM_TypeConstructKind) + sizeof(return_type->idx)*(1 + params->count); - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "procedure" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Procedure; - ptr += sizeof(RDIM_TypeConstructKind); - // ret_type->idx - rdim_memcpy(ptr, &return_type->idx, sizeof(return_type->idx)); - ptr += sizeof(return_type->idx); - // (params ...)->idx - for(RDIM_TypeNode *node = params->first; - node != 0; - node = node->next) - { - rdim_memcpy(ptr, &node->type->idx, sizeof(node->type->idx)); - ptr += sizeof(node->type->idx); - } - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // setup param buffer - RDIM_Type **param_types = rdim_push_array(root->arena, RDIM_Type*, params->count); - { - RDIM_Type **ptr = param_types; - for(RDIM_TypeNode *node = params->first; - node != 0; - node = node->next) - { - *ptr = node->type; - ptr += 1; - } - } - - // setup new node - result = rdim_type_new(root); - result->kind = RDI_TypeKind_Function; - result->byte_size = root->addr_size; - result->count = params->count; - result->direct_type = return_type; - result->param_types = param_types; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - rdim_scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_method(RDIM_Root *root, RDIM_Type *this_type, RDIM_Type *return_type, struct RDIM_TypeList *params) -{ - RDIM_Type *result = root->nil_type; - RDIM_Temp scratch = rdim_scratch_begin(0, 0); - - // setup construct buffer - RDI_U64 buf_size = - sizeof(RDIM_TypeConstructKind) + sizeof(return_type->idx)*(2 + params->count); - RDI_U8 *buf = rdim_push_array(rdim_temp_arena(scratch), RDI_U8, buf_size); - { - RDI_U8 *ptr = buf; - // "method" - *(RDIM_TypeConstructKind*)ptr = RDIM_TypeConstructKind_Method; - ptr += sizeof(RDIM_TypeConstructKind); - // ret_type->idx - rdim_memcpy(ptr, &return_type->idx, sizeof(return_type->idx)); - ptr += sizeof(return_type->idx); - // this_type->idx - rdim_memcpy(ptr, &this_type->idx, sizeof(this_type->idx)); - ptr += sizeof(this_type->idx); - // (params ...)->idx - for(RDIM_TypeNode *node = params->first; - node != 0; - node = node->next) - { - rdim_memcpy(ptr, &node->type->idx, sizeof(node->type->idx)); - ptr += sizeof(node->type->idx); - } - } - - // check for duplicate construct - RDIM_String8 blob = rdim_str8(buf, buf_size); - RDI_U64 blob_hash = rdi_hash(buf, buf_size); - void *lookup_ptr = rdim_str8toptr_map_lookup(&root->construct_map, blob, blob_hash); - result = (RDIM_Type*)lookup_ptr; - if(result == 0) - { - // setup param buffer - RDIM_Type **param_types = rdim_push_array(root->arena, RDIM_Type*, params->count + 1); - { - RDIM_Type **ptr = param_types; - { - *ptr = this_type; - ptr += 1; - } - for(RDIM_TypeNode *node = params->first; - node != 0; - node = node->next) - { - *ptr = node->type; - ptr += 1; - } - } - - // setup new node - result = rdim_type_new(root); - result->kind = RDI_TypeKind_Method; - result->byte_size = root->addr_size; - result->count = params->count; - result->direct_type = return_type; - result->param_types = param_types; - - // save in construct map - rdim_str8toptr_map_insert(root->arena, &root->construct_map, blob, blob_hash, result); - } - - rdim_scratch_end(scratch); - rdim_assert(result != 0); - return result; -} - -//- rjf: udt type constructors - -RDI_PROC RDIM_Type* -rdim_type_udt(RDIM_Root *root, RDI_TypeKind record_type_kind, RDIM_String8 name, RDI_U64 size) -{ - rdim_requiref(root, (record_type_kind == RDI_TypeKind_Struct || - record_type_kind == RDI_TypeKind_Class || - record_type_kind == RDI_TypeKind_Union), - return root->nil_type, - "Non-user-defined-type-kind used to create user-defined type."); - - // rjf: make type - RDIM_Type *result = rdim_type_new(root); - result->kind = record_type_kind; - result->byte_size = size; - result->name = rdim_str8_copy(root->arena, name); - - // rjf: save in name map - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_Types); - rdim_name_map_add_pair(root, map, result->name, result->idx); - } - - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_enum(RDIM_Root *root, RDIM_Type *direct_type, RDIM_String8 name) -{ - // rjf: make type - RDIM_Type *result = rdim_type_new(root); - result->kind = RDI_TypeKind_Enum; - result->byte_size = direct_type->byte_size; - result->name = rdim_str8_copy(root->arena, name); - result->direct_type = direct_type; - - // rjf: save in name map - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_Types); - rdim_name_map_add_pair(root, map, result->name, result->idx); - } - - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_alias(RDIM_Root *root, RDIM_Type *direct_type, RDIM_String8 name) -{ - // rjf: make type - RDIM_Type *result = rdim_type_new(root); - result->kind = RDI_TypeKind_Alias; - result->byte_size = direct_type->byte_size; - result->name = rdim_str8_copy(root->arena, name); - result->direct_type = direct_type; - - // rjf: save in name map - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_Types); - rdim_name_map_add_pair(root, map, result->name, result->idx); - } - - return result; -} - -RDI_PROC RDIM_Type* -rdim_type_incomplete(RDIM_Root *root, RDI_TypeKind type_kind, RDIM_String8 name) -{ - rdim_requiref(root, (type_kind == RDI_TypeKind_IncompleteStruct || - type_kind == RDI_TypeKind_IncompleteClass || - type_kind == RDI_TypeKind_IncompleteUnion || - type_kind == RDI_TypeKind_IncompleteEnum), - return root->nil_type, - "Non-incomplete-type-kind used to create incomplete type."); - - // rjf: make type - RDIM_Type *result = rdim_type_new(root); - result->kind = type_kind; - result->name = rdim_str8_copy(root->arena, name); - - // save in name map - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_Types); - rdim_name_map_add_pair(root, map, result->name, result->idx); - } - - return result; -} - -//- rjf: type member building - -RDI_PROC void -rdim_type_add_member_data_field(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type, RDI_U32 off) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_DataField; - member->name = rdim_str8_copy(root->arena, name); - member->type = mem_type; - member->off = off; - } -} - -RDI_PROC void -rdim_type_add_member_static_data(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_StaticData; - member->name = rdim_str8_copy(root->arena, name); - member->type = mem_type; - } -} - -RDI_PROC void -rdim_type_add_member_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_Method; - member->name = rdim_str8_copy(root->arena, name); - member->type = mem_type; - } -} - -RDI_PROC void -rdim_type_add_member_static_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - - root->total_member_count += 1; - - member->kind = RDI_MemberKind_StaticMethod; - member->name = rdim_str8_copy(root->arena, name); - member->type = mem_type; - } -} - -RDI_PROC void -rdim_type_add_member_virtual_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_VirtualMethod; - member->name = rdim_str8_copy(root->arena, name); - member->type = mem_type; - } -} - -RDI_PROC void -rdim_type_add_member_base(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *base_type, RDI_U32 off) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_Base; - member->type = base_type; - member->off = off; - } -} - -RDI_PROC void -rdim_type_add_member_virtual_base(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *base_type, RDI_U32 vptr_off, RDI_U32 vtable_off) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_VirtualBase; - member->type = base_type; - // TODO(allen): what to do with the two offsets in this case? - } -} - -RDI_PROC void -rdim_type_add_member_nested_type(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *nested_type) -{ - RDIM_TypeUDT *udt = rdim_type_udt_from_record_type(root, record_type); - if(udt != 0) - { - RDIM_TypeMember *member = rdim_push_array(root->arena, RDIM_TypeMember, 1); - SLLQueuePush(udt->first_member, udt->last_member, member); - udt->member_count += 1; - root->total_member_count += 1; - member->kind = RDI_MemberKind_NestedType; - member->type = nested_type; - } -} - -RDI_PROC void -rdim_type_add_enum_val(RDIM_Root *root, RDIM_Type *enum_type, RDIM_String8 name, RDI_U64 val) -{ - rdim_requiref(root, (enum_type->kind == RDI_TypeKind_Enum), return, "Tried to add enum value to non-enum type."); - RDIM_TypeUDT *udt = rdim_type_udt_from_any_type(root, enum_type); - if(udt != 0) - { - RDIM_TypeEnumVal *enum_val = rdim_push_array(root->arena, RDIM_TypeEnumVal, 1); - SLLQueuePush(udt->first_enum_val, udt->last_enum_val, enum_val); - udt->enum_val_count += 1; - root->total_enum_val_count += 1; - enum_val->name = rdim_str8_copy(root->arena, name); - enum_val->val = val; - } -} - -//- rjf: type source coordinate specifications -RDI_PROC void -rdim_type_set_source_coordinates(RDIM_Root *root, RDIM_Type *defined_type, RDIM_String8 source_path, RDI_U32 line, RDI_U32 col) -{ - rdim_requiref(root, (RDI_TypeKind_FirstUserDefined <= defined_type->kind && defined_type->kind <= RDI_TypeKind_LastUserDefined), - return, "Tried to add source coordinates to non-user-defined type."); - RDIM_TypeUDT *udt = rdim_type_udt_from_any_type(root, defined_type); - if(udt != 0) - { - udt->source_path = rdim_str8_copy(root->arena, source_path); - udt->line = line; - udt->col = col; - } -} - -//- rjf: symbol info building - -RDI_PROC RDIM_Symbol* -rdim_symbol_handle_from_user_id(RDIM_Root *root, RDI_U64 symbol_user_id, RDI_U64 symbol_user_id_hash) -{ - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->symbol_map, symbol_user_id, symbol_user_id_hash, &lookup); - RDIM_Symbol *result = 0; - if(lookup.match != 0) - { - result = (RDIM_Symbol*)lookup.match; - } - else - { - result = rdim_push_array(root->arena, RDIM_Symbol, 1); - RDIM_SLLQueuePush_N(root->first_symbol, root->last_symbol, result, next_order); - root->symbol_count += 1; - rdim_u64toptr_map_insert(root->arena, &root->symbol_map, symbol_user_id, symbol_user_id_hash, &lookup, result); - } - return result; -} - -RDI_PROC void -rdim_symbol_set_info(RDIM_Root *root, RDIM_Symbol *symbol, RDIM_SymbolInfo *info) -{ - // rjf: unpack - RDIM_SymbolKind kind = info->kind; - RDIM_Symbol *container_symbol = info->container_symbol; - RDIM_Type *container_type = info->container_type; - - // rjf: requirements - rdim_requiref(root, RDIM_SymbolKind_NULL == symbol->kind, return, "Symbol information set multiple times."); - rdim_requiref(root, RDIM_SymbolKind_NULL < info->kind && info->kind < RDIM_SymbolKind_COUNT, return, "Invalid symbol kind used to initialize symbol."); - rdim_requiref(root, info->type != 0, return, "Invalid type used to initialize symbol."); - rdim_requiref(root, info->container_symbol == 0 || info->container_type == 0, container_type = 0, "Symbol initialized with both a containing symbol and containing type, when only one is allowed."); - - // rjf: fill - root->symbol_kind_counts[kind] += 1; - symbol->idx = root->symbol_kind_counts[kind]; - symbol->kind = kind; - symbol->name = rdim_str8_copy(root->arena, info->name); - symbol->link_name = rdim_str8_copy(root->arena, info->link_name); - symbol->type = info->type; - symbol->is_extern = info->is_extern; - symbol->offset = info->offset; - symbol->container_symbol = container_symbol; - symbol->container_type = container_type; - - // rjf: set root scope - switch(kind) - { - default:{}break; - case RDIM_SymbolKind_GlobalVariable: - case RDIM_SymbolKind_ThreadVariable: - { - rdim_requiref(root, info->root_scope == 0, rdim_noop, "Global or thread variable initialized with root scope."); - }break; - case RDIM_SymbolKind_Procedure: - { - rdim_requiref(root, info->root_scope != 0, rdim_noop, "Procedure symbol initialized without root scope."); - symbol->root_scope = info->root_scope; - rdim_scope_recursive_set_symbol(info->root_scope, symbol); - }break; - } - - // save name map - { - RDIM_NameMap *map = 0; - switch(kind) - { - default:{}break; - case RDIM_SymbolKind_GlobalVariable: - { - map = rdim_name_map_for_kind(root, RDI_NameMapKind_GlobalVariables); - }break; - case RDIM_SymbolKind_ThreadVariable: - { - map = rdim_name_map_for_kind(root, RDI_NameMapKind_ThreadVariables); - }break; - case RDIM_SymbolKind_Procedure: - { - map = rdim_name_map_for_kind(root, RDI_NameMapKind_Procedures); - }break; - } - if(map != 0) - { - rdim_name_map_add_pair(root, map, symbol->name, symbol->idx); - } - } - - // save link name map - if(kind == RDIM_SymbolKind_Procedure && symbol->link_name.size > 0) - { - RDIM_NameMap *map = rdim_name_map_for_kind(root, RDI_NameMapKind_LinkNameProcedures); - rdim_name_map_add_pair(root, map, symbol->link_name, symbol->idx); - } -} - -//- rjf: scope info building - -RDI_PROC RDIM_Scope * -rdim_scope_handle_from_user_id(RDIM_Root *root, RDI_U64 scope_user_id, RDI_U64 scope_user_id_hash) -{ - RDIM_Scope *result = 0; - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->scope_map, scope_user_id, scope_user_id_hash, &lookup); - if(lookup.match != 0) - { - result = (RDIM_Scope*)lookup.match; - } - else - { - result = rdim_push_array(root->arena, RDIM_Scope, 1); - result->idx = root->scope_count; - RDIM_SLLQueuePush_N(root->first_scope, root->last_scope, result, next_order); - root->scope_count += 1; - rdim_u64toptr_map_insert(root->arena, &root->scope_map, scope_user_id, scope_user_id_hash, &lookup, result); - } - return result; -} - -RDI_PROC void -rdim_scope_set_parent(RDIM_Root *root, RDIM_Scope *scope, RDIM_Scope *parent) -{ - rdim_requiref(root, scope->parent_scope == 0, return, "Scope parent set multiple times."); - rdim_requiref(root, parent != 0, return, "Tried to set invalid parent as scope parent."); - scope->symbol = parent->symbol; - scope->parent_scope = parent; - RDIM_SLLQueuePush_N(parent->first_child, parent->last_child, scope, next_sibling); -} - -RDI_PROC void -rdim_scope_add_voff_range(RDIM_Root *root, RDIM_Scope *scope, RDI_U64 voff_first, RDI_U64 voff_opl) -{ - RDIM_VOffRange *range = rdim_push_array(root->arena, RDIM_VOffRange, 1); - SLLQueuePush(scope->first_range, scope->last_range, range); - scope->range_count += 1; - range->voff_first = voff_first; - range->voff_opl = voff_opl; - scope->voff_base = Min(scope->voff_base, voff_first); - root->scope_voff_count += 2; -} - -RDI_PROC void -rdim_scope_recursive_set_symbol(RDIM_Scope *scope, RDIM_Symbol *symbol) -{ - scope->symbol = symbol; - for(RDIM_Scope *node = scope->first_child; - node != 0; - node = node->next_sibling) - { - rdim_scope_recursive_set_symbol(node, symbol); - } -} - -//- rjf: local info building - -RDI_PROC RDIM_Local* -rdim_local_handle_from_user_id(RDIM_Root *root, RDI_U64 local_user_id, RDI_U64 local_user_id_hash) -{ - RDIM_Local *result = 0; - RDIM_U64ToPtrLookup lookup = {0}; - rdim_u64toptr_map_lookup(&root->local_map, local_user_id, local_user_id_hash, &lookup); - if(lookup.match != 0) - { - result = (RDIM_Local*)lookup.match; - } - else - { - result = rdim_push_array(root->arena, RDIM_Local, 1); - rdim_u64toptr_map_insert(root->arena, &root->local_map, local_user_id, local_user_id_hash, &lookup, result); - } - return result; -} - -RDI_PROC void -rdim_local_set_basic_info(RDIM_Root *root, RDIM_Local *local, RDIM_LocalInfo *info) -{ - rdim_requiref(root, local->kind == RDI_LocalKind_NULL, return, "Local information set multiple times."); - rdim_requiref(root, info->scope != 0, return, "Tried to set invalid scope as local's containing scope."); - rdim_requiref(root, RDI_LocalKind_NULL < info->kind && info->kind < RDI_LocalKind_COUNT, return, "Invalid local kind."); - rdim_requiref(root, info->type != 0, return, "Tried to set invalid type as local's type."); - RDIM_Scope *scope = info->scope; - SLLQueuePush(scope->first_local, scope->last_local, local); - scope->local_count += 1; - root->local_count += 1; - local->kind = info->kind; - local->name = rdim_str8_copy(root->arena, info->name); - local->type = info->type; -} - -RDI_PROC RDIM_LocationSet* -rdim_location_set_from_local(RDIM_Root *root, RDIM_Local *local) -{ - RDIM_LocationSet *result = local->locset; - if(result == 0) - { - local->locset = rdim_push_array(root->arena, RDIM_LocationSet, 1); - result = local->locset; - } - return result; -} - -//- rjf: location info building - -RDI_PROC void -rdim_location_set_add_case(RDIM_Root *root, RDIM_LocationSet *locset, RDI_U64 voff_first, RDI_U64 voff_opl, RDIM_Location *location) -{ - RDIM_LocationCase *location_case = rdim_push_array(root->arena, RDIM_LocationCase, 1); - SLLQueuePush(locset->first_location_case, locset->last_location_case, location_case); - locset->location_case_count += 1; - root->location_count += 1; - location_case->voff_first = voff_first; - location_case->voff_opl = voff_opl; - location_case->location = location; -} - -RDI_PROC RDIM_Location* -rdim_location_addr_bytecode_stream(RDIM_Root *root, struct RDIM_EvalBytecode *bytecode) -{ - RDIM_Location *result = rdim_push_array(root->arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrBytecodeStream; - result->bytecode = *bytecode; - return result; -} - -RDI_PROC RDIM_Location* -rdim_location_val_bytecode_stream(RDIM_Root *root, struct RDIM_EvalBytecode *bytecode) -{ - RDIM_Location *result = rdim_push_array(root->arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_ValBytecodeStream; - result->bytecode = *bytecode; - return result; -} - -RDI_PROC RDIM_Location* -rdim_location_addr_reg_plus_u16(RDIM_Root *root, RDI_U8 reg_code, RDI_U16 offset) -{ - RDIM_Location *result = rdim_push_array(root->arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrRegisterPlusU16; - result->register_code = reg_code; - result->offset = offset; - return result; -} - -RDI_PROC RDIM_Location* -rdim_location_addr_addr_reg_plus_u16(RDIM_Root *root, RDI_U8 reg_code, RDI_U16 offset) -{ - RDIM_Location *result = rdim_push_array(root->arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_AddrAddrRegisterPlusU16; - result->register_code = reg_code; - result->offset = offset; - return result; -} - -RDI_PROC RDIM_Location* -rdim_location_val_reg(RDIM_Root *root, RDI_U8 reg_code) -{ - RDIM_Location *result = rdim_push_array(root->arena, RDIM_Location, 1); - result->kind = RDI_LocationKind_ValRegister; - result->register_code = reg_code; - return result; -} - -//- rjf: name map building - -RDI_PROC RDIM_NameMap* -rdim_name_map_for_kind(RDIM_Root *root, RDI_NameMapKind kind) -{ - RDIM_NameMap *result = 0; - if(kind < RDI_NameMapKind_COUNT) - { - if(root->name_maps[kind] == 0) - { - root->name_maps[kind] = rdim_push_array(root->arena, RDIM_NameMap, 1); - root->name_maps[kind]->buckets_count = 16384; - root->name_maps[kind]->buckets = rdim_push_array(root->arena, RDIM_NameMapNode *, root->name_maps[kind]->buckets_count); - } - result = root->name_maps[kind]; - } - return result; -} - -RDI_PROC void -rdim_name_map_add_pair(RDIM_Root *root, RDIM_NameMap *map, RDIM_String8 string, RDI_U32 idx) -{ - // hash - RDI_U64 hash = rdi_hash(string.str, string.size); - RDI_U64 bucket_idx = hash%map->buckets_count; - - // find existing name node - RDIM_NameMapNode *match = 0; - for(RDIM_NameMapNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->bucket_next) - { - if(rdim_str8_match(string, node->string, 0)) - { - match = node; - break; - } - } - - // make name node if necessary - if(match == 0) - { - match = rdim_push_array(root->arena, RDIM_NameMapNode, 1); - match->string = rdim_str8_copy(root->arena, string); - RDIM_SLLStackPush_N(map->buckets[bucket_idx], match, bucket_next); - RDIM_SLLQueuePush_N(map->first, map->last, match, order_next); - map->name_count += 1; - map->bucket_collision_count += (match->bucket_next != 0); - } - - // find existing idx - RDI_S32 existing_idx = 0; - for(RDIM_NameMapIdxNode *node = match->idx_first; - node != 0; - node = node->next) - { - for(RDI_U32 i = 0; i < ArrayCount(node->idx); i += 1) - { - if(node->idx[i] == 0) - { - break; - } - if(node->idx[i] == idx) - { - existing_idx = 1; - break; - } - } - } - - // insert new idx if necessary - if(!existing_idx) - { - RDIM_NameMapIdxNode *idx_node = match->idx_last; - RDI_U32 insert_i = match->idx_count%ArrayCount(idx_node->idx); - if(insert_i == 0) - { - idx_node = rdim_push_array(root->arena, RDIM_NameMapIdxNode, 1); - SLLQueuePush(match->idx_first, match->idx_last, idx_node); - } - - idx_node->idx[insert_i] = idx; - match->idx_count += 1; - } -} - -//////////////////////////////// -//~ rjf: Debug Info Baking (Loose -> Tight) Functions - -//- rjf: bake context construction - -RDI_PROC RDIM_BakeCtx* -rdim_bake_ctx_begin(RDIM_BakeParams *params) -{ - RDIM_Arena *arena = rdim_arena_alloc(); - RDIM_BakeCtx *result = rdim_push_array(arena, RDIM_BakeCtx, 1); - result->arena = arena; -#define BKTCOUNT(x) ((x)?(u64_up_to_pow2(x)):(16384)) - result->strs.buckets_count = BKTCOUNT(params->strings_bucket_count); - result->idxs.buckets_count = BKTCOUNT(params->idx_runs_bucket_count); -#undef BKTCOUNT - result->strs.buckets = rdim_push_array(arena, RDIM_StringNode *, result->strs.buckets_count); - result->idxs.buckets = rdim_push_array(arena, RDIM_IdxRunNode *, result->idxs.buckets_count); - - rdim_string(result, rdim_str8_lit("")); - rdim_idx_run(result, 0, 0); - - result->tree = rdim_push_array(arena, RDIM_PathTree, 1); - { - RDIM_PathNode *nil_path_node = rdim_paths_new_node(result); - nil_path_node->name = rdim_str8_lit(""); - RDIM_SrcNode *nil_src_node = rdim_paths_new_src_node(result); - nil_src_node->path_node = nil_path_node; - nil_src_node->normal_full_path = rdim_str8_lit(""); - nil_path_node->src_file = nil_src_node; - } - - return result; -} - -RDI_PROC void -rdim_bake_ctx_release(RDIM_BakeCtx *bake_ctx) -{ - arena_release(bake_ctx->arena); -} - -//- rjf: string baking - -RDI_PROC RDI_U32 -rdim_string(RDIM_BakeCtx *bctx, RDIM_String8 str) -{ - RDIM_Arena *arena = bctx->arena; - RDIM_Strings *strs = &bctx->strs; - RDI_U64 hash = rdi_hash(str.str, str.size); - RDI_U64 bucket_idx = hash%strs->buckets_count; - - // look for a match - RDIM_StringNode *match = 0; - for(RDIM_StringNode *node = strs->buckets[bucket_idx]; - node != 0; - node = node->bucket_next) - { - if(node->hash == hash && rdim_str8_match(node->str, str, 0)) - { - match = node; - break; - } - } - - // insert new node if no match - if(match == 0) - { - RDIM_StringNode *node = rdim_push_array_no_zero(arena, RDIM_StringNode, 1); - node->str = rdim_str8_copy(arena, str); - node->hash = hash; - node->idx = strs->count; - strs->count += 1; - RDIM_SLLQueuePush_N(strs->order_first, strs->order_last, node, order_next); - RDIM_SLLStackPush_N(strs->buckets[bucket_idx], node, bucket_next); - match = node; - strs->bucket_collision_count += (node->bucket_next != 0); - } - - // extract idx to return - rdim_assert(match != 0); - RDI_U32 result = match->idx; - return result; -} - -//- rjf: idx run baking - -RDI_PROC RDI_U64 -rdim_idx_run_hash(RDI_U32 *idx_run, RDI_U32 count) -{ - RDI_U64 hash = 5381; - RDI_U32 *ptr = idx_run; - RDI_U32 *opl = idx_run + count; - for(;ptr < opl; ptr += 1) - { - hash = ((hash << 5) + hash) + (*ptr); - } - return(hash); -} - -RDI_PROC RDI_U32 -rdim_idx_run(RDIM_BakeCtx *bctx, RDI_U32 *idx_run, RDI_U32 count) -{ - RDIM_Arena *arena = bctx->arena; - RDIM_IdxRuns *idxs = &bctx->idxs; - - RDI_U64 hash = rdim_idx_run_hash(idx_run, count); - RDI_U64 bucket_idx = hash%idxs->buckets_count; - - // look for a match - RDIM_IdxRunNode *match = 0; - for(RDIM_IdxRunNode *node = idxs->buckets[bucket_idx]; - node != 0; - node = node->bucket_next) - { - if(node->hash == hash) - { - RDI_S32 is_match = 1; - RDI_U32 *node_idx = node->idx_run; - for(RDI_U32 i = 0; i < count; i += 1) - { - if(node_idx[i] != idx_run[i]) - { - is_match = 0; - break; - } - } - if(is_match) - { - match = node; - break; - } - } - } - - // insert new node if no match - if(match == 0) - { - RDIM_IdxRunNode *node = rdim_push_array_no_zero(arena, RDIM_IdxRunNode, 1); - RDI_U32 *idx_run_copy = rdim_push_array_no_zero(arena, RDI_U32, count); - for(RDI_U32 i = 0; i < count; i += 1) - { - idx_run_copy[i] = idx_run[i]; - } - node->idx_run = idx_run_copy; - node->hash = hash; - node->count = count; - node->first_idx = idxs->idx_count; - idxs->count += 1; - idxs->idx_count += count; - RDIM_SLLQueuePush_N(idxs->order_first, idxs->order_last, node, order_next); - RDIM_SLLStackPush_N(idxs->buckets[bucket_idx], node, bucket_next); - match = node; - idxs->bucket_collision_count += (node->bucket_next != 0); - } - - // extract idx to return - rdim_assert(match != 0); - RDI_U32 result = match->first_idx; - return result; -} - -//- rjf: data section baking - -RDI_PROC RDI_U32 -rdim_dsection(RDIM_Arena *arena, RDIM_DSections *dss, void *data, RDI_U64 size, RDI_DataSectionTag tag) -{ - RDI_U32 result = dss->count; - RDIM_DSectionNode *node = rdim_push_array(arena, RDIM_DSectionNode, 1); - SLLQueuePush(dss->first, dss->last, node); - node->data = data; - node->size = size; - node->tag = tag; - dss->count += 1; - return result; -} - -//- rjf: paths baking - -RDI_PROC RDIM_String8 -rdim_normal_string_from_path_node(RDIM_Arena *arena, RDIM_PathNode *node) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - RDIM_String8List list = {0}; - if(node != 0) - { - rdim_normal_string_from_path_node_build(scratch.arena, node, &list); - } - RDIM_String8 result = rdim_str8_list_join(arena, &list, rdim_str8_lit("/")); - { - RDI_U8 *ptr = result.str; - RDI_U8 *opl = result.str + result.size; - for(; ptr < opl; ptr += 1) - { - RDI_U8 c = *ptr; - if('A' <= c && c <= 'Z') { c += 'a' - 'A'; } - *ptr = c; - } - } - scratch_end(scratch); - return result; -} - -RDI_PROC void -rdim_normal_string_from_path_node_build(RDIM_Arena *arena, RDIM_PathNode *node, RDIM_String8List *out) -{ - // TODO(rjf): why is this recursive... - if(node->parent != 0) - { - rdim_normal_string_from_path_node_build(arena, node->parent, out); - } - if(node->name.size > 0) - { - rdim_str8_list_push(arena, out, node->name); - } -} - -RDI_PROC RDIM_PathNode* -rdim_paths_new_node(RDIM_BakeCtx *bctx) -{ - RDIM_PathTree *tree = bctx->tree; - RDIM_PathNode *result = rdim_push_array(bctx->arena, RDIM_PathNode, 1); - RDIM_SLLQueuePush_N(tree->first, tree->last, result, next_order); - result->idx = tree->count; - tree->count += 1; - return result; -} - -RDI_PROC RDIM_PathNode* -rdim_paths_sub_path(RDIM_BakeCtx *bctx, RDIM_PathNode *dir, RDIM_String8 sub_dir) -{ - // look for existing match - RDIM_PathNode *match = 0; - for(RDIM_PathNode *node = dir->first_child; - node != 0; - node = node->next_sibling) - { - if(rdim_str8_match(node->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive)) - { - match = node; - break; - } - } - - // construct new node if no match - RDIM_PathNode *new_node = 0; - if(match == 0){ - new_node = rdim_paths_new_node(bctx); - new_node->parent = dir; - RDIM_SLLQueuePush_N(dir->first_child, dir->last_child, new_node, next_sibling); - new_node->name = rdim_str8_copy(bctx->arena, sub_dir); - } - - // select result from the two paths - RDIM_PathNode *result = match; - if(match == 0){ - result = new_node; - } - - return result; -} - -RDI_PROC RDIM_PathNode* -rdim_paths_node_from_path(RDIM_BakeCtx *bctx, RDIM_String8 path) -{ - RDIM_PathNode *node_cursor = &bctx->tree->root; - - RDI_U8 *ptr = path.str; - RDI_U8 *opl = path.str + path.size; - for(;ptr < opl;){ - // skip past slashes - for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); - - // save beginning of non-slash range - RDI_U8 *range_first = ptr; - - // skip past non-slashes - for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); - - // if range is non-empty advance the node cursor - if(range_first < ptr){ - RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); - node_cursor = rdim_paths_sub_path(bctx, node_cursor, sub_dir); - } - } - - RDIM_PathNode *result = node_cursor; - return result; -} - -RDI_PROC RDI_U32 -rdim_paths_idx_from_path(RDIM_BakeCtx *bctx, RDIM_String8 path) -{ - RDIM_PathNode *node = rdim_paths_node_from_path(bctx, path); - RDI_U32 result = node->idx; - return result; -} - -RDI_PROC RDIM_SrcNode* -rdim_paths_new_src_node(RDIM_BakeCtx *bctx) -{ - RDIM_PathTree *tree = bctx->tree; - RDIM_SrcNode *result = rdim_push_array(bctx->arena, RDIM_SrcNode, 1); - SLLQueuePush(tree->src_first, tree->src_last, result); - result->idx = tree->src_count; - tree->src_count += 1; - return result; -} - -RDI_PROC RDIM_SrcNode* -rdim_paths_src_node_from_path_node(RDIM_BakeCtx *bctx, RDIM_PathNode *path_node) -{ - RDIM_SrcNode *result = path_node->src_file; - if(result == 0) - { - RDIM_SrcNode *new_node = rdim_paths_new_src_node(bctx); - new_node->path_node = path_node; - new_node->normal_full_path = rdim_normal_string_from_path_node(bctx->arena, path_node); - result = path_node->src_file = new_node; - } - return result; -} - -//- rjf: per-unit line info baking - -RDI_PROC RDIM_UnitLinesCombined* -rdim_unit_combine_lines(RDIM_Arena *arena, RDIM_BakeCtx *bctx, RDIM_LineSequenceNode *first_seq) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // gather up all line info into two arrays - // keys: sortable array; pairs voffs with line info records; null records are sequence enders - // recs: contains all the source coordinates for a range of voffs - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *node = first_seq; - node != 0; - node = node->next) - { - seq_count += 1; - line_count += node->line_seq.line_count; - } - - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - - for(RDIM_LineSequenceNode *node = first_seq; - node != 0; - node = node->next) - { - RDIM_PathNode *src_path = - rdim_paths_node_from_path(bctx, node->line_seq.file_name); - RDIM_SrcNode *src_file = rdim_paths_src_node_from_path_node(bctx, src_path); - RDI_U32 file_id = src_file->idx; - - RDI_U64 node_line_count = node->line_seq.line_count; - for(RDI_U64 i = 0; i < node_line_count; i += 1){ - key_ptr->key = node->line_seq.voffs[i]; - key_ptr->val = rec_ptr; - key_ptr += 1; - - rec_ptr->file_id = file_id; - rec_ptr->line_num = node->line_seq.line_nums[i]; - if(node->line_seq.col_nums != 0){ - rec_ptr->col_first = node->line_seq.col_nums[i*2]; - rec_ptr->col_opl = node->line_seq.col_nums[i*2 + 1]; - } - rec_ptr += 1; - } - - key_ptr->key = node->line_seq.voffs[node_line_count]; - key_ptr->val = 0; - key_ptr += 1; - - RDIM_LineMapFragment *fragment = rdim_push_array(arena, RDIM_LineMapFragment, 1); - RDIM_SLLQueuePush(src_file->first_fragment, src_file->last_fragment, fragment); - fragment->sequence = node; - } - } - - // sort - RDIM_SortKey *sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - - // TODO(allen): do a pass over sorted keys to make sure duplicate keys are sorted with - // null record first, and no more than one null record and one non-null record - - // arrange output - RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); - RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); - - for(RDI_U64 i = 0; i < key_count; i += 1){ - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1){ - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0){ - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else{ - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - - RDIM_UnitLinesCombined *result = rdim_push_array(arena, RDIM_UnitLinesCombined, 1); - result->voffs = arranged_voffs; - result->lines = arranged_lines; - result->cols = 0; - result->line_count = key_count; - - scratch_end(scratch); - return result; -} - -//- rjf: per-src line info baking - -RDI_PROC RDIM_SrcLinesCombined* -rdim_source_combine_lines(RDIM_Arena *arena, RDIM_LineMapFragment *first) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // gather line number map - RDIM_SrcLineMapBucket *first_bucket = 0; - RDIM_SrcLineMapBucket *last_bucket = 0; - RDI_U64 line_hash_slots_count = 1024; - RDIM_SrcLineMapBucket **line_hash_slots = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket *, line_hash_slots_count); - RDI_U64 line_count = 0; - RDI_U64 voff_count = 0; - RDI_U64 max_line_num = 0; - { - for(RDIM_LineMapFragment *map_fragment = first; - map_fragment != 0; - map_fragment = map_fragment->next) - { - RDIM_LineSequence *sequence = &map_fragment->sequence->line_seq; - - RDI_U64 *seq_voffs = sequence->voffs; - RDI_U32 *seq_line_nums = sequence->line_nums; - RDI_U64 seq_line_count = sequence->line_count; - for(RDI_U64 i = 0; i < seq_line_count; i += 1){ - RDI_U32 line_num = seq_line_nums[i]; - RDI_U64 voff = seq_voffs[i]; - RDI_U64 line_hash_slot_idx = line_num%line_hash_slots_count; - - // update unique voff counter & max line number - voff_count += 1; - max_line_num = Max(max_line_num, line_num); - - // find match - RDIM_SrcLineMapBucket *match = 0; - { - for(RDIM_SrcLineMapBucket *node = line_hash_slots[line_hash_slot_idx]; - node != 0; - node = node->hash_next){ - if(node->line_num == line_num){ - match = node; - break; - } - } - } - - // introduce new line if no match - if(match == 0){ - match = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket, 1); - RDIM_SLLQueuePush_N(first_bucket, last_bucket, match, order_next); - RDIM_SLLStackPush_N(line_hash_slots[line_hash_slot_idx], match, hash_next); - match->line_num = line_num; - line_count += 1; - } - - // insert new voff - { - RDIM_SrcLineMapVoffBlock *block = rdim_push_array(scratch.arena, RDIM_SrcLineMapVoffBlock, 1); - RDIM_SLLQueuePush(match->first_voff_block, match->last_voff_block, block); - match->voff_count += 1; - block->voff = voff; - } - } - } - } - - // bake sortable keys array - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, line_count); - { - RDIM_SortKey *key_ptr = keys; - for(RDIM_SrcLineMapBucket *node = first_bucket; - node != 0; - node = node->order_next, key_ptr += 1){ - key_ptr->key = node->line_num; - key_ptr->val = node; - } - } - - // sort - RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); - - // bake result - RDI_U32 *line_nums = rdim_push_array_no_zero(arena, RDI_U32, line_count); - RDI_U32 *line_ranges = rdim_push_array_no_zero(arena, RDI_U32, line_count + 1); - RDI_U64 *voffs = rdim_push_array_no_zero(arena, RDI_U64, voff_count); - { - RDI_U64 *voff_ptr = voffs; - for(RDI_U32 i = 0; i < line_count; i += 1){ - line_nums[i] = sorted_keys[i].key; - line_ranges[i] = (RDI_U32)(voff_ptr - voffs); - RDIM_SrcLineMapBucket *bucket = (RDIM_SrcLineMapBucket*)sorted_keys[i].val; - for(RDIM_SrcLineMapVoffBlock *node = bucket->first_voff_block; - node != 0; - node = node->next){ - *voff_ptr = node->voff; - voff_ptr += 1; - } - } - line_ranges[line_count] = voff_count; - } - - RDIM_SrcLinesCombined *result = rdim_push_array(arena, RDIM_SrcLinesCombined, 1); - result->line_nums = line_nums; - result->line_ranges = line_ranges; - result->line_count = line_count; - result->voffs = voffs; - result->voff_count = voff_count; - - scratch_end(scratch); - return result; -} - -//- rjf: vmap baking -RDI_PROC RDIM_VMap -rdim_vmap_from_markers(RDIM_Arena *arena, RDIM_VMapMarker *markers, RDIM_SortKey *keys, RDI_U64 marker_count) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // sort markers - RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, marker_count); - - // determine if an extra vmap entry for zero is needed - RDI_U32 extra_vmap_entry = 0; - if(marker_count > 0 && sorted_keys[0].key != 0){ - extra_vmap_entry = 1; - } - - // fill output vmap entries - RDI_U32 vmap_count_raw = marker_count - 1 + extra_vmap_entry; - RDI_VMapEntry *vmap = rdim_push_array_no_zero(arena, RDI_VMapEntry, vmap_count_raw + 1); - RDI_U32 vmap_entry_count_pass_1 = 0; - - { - RDI_VMapEntry *vmap_ptr = vmap; - - if(extra_vmap_entry){ - vmap_ptr->voff = 0; - vmap_ptr->idx = 0; - vmap_ptr += 1; - } - - RDIM_VMapRangeTracker *tracker_stack = 0; - RDIM_VMapRangeTracker *tracker_free = 0; - - RDIM_SortKey *key_ptr = sorted_keys; - RDIM_SortKey *key_opl = sorted_keys + marker_count; - for(;key_ptr < key_opl;){ - // get initial map state from tracker stack - RDI_U32 initial_idx = (RDI_U32)0xffffffff; - if(tracker_stack != 0){ - initial_idx = tracker_stack->idx; - } - - // update tracker stack - // * we must process _all_ of the changes that apply at this voff before moving on - RDI_U64 voff = key_ptr->key; - - for(;key_ptr < key_opl && key_ptr->key == voff; key_ptr += 1){ - RDIM_VMapMarker *marker = (RDIM_VMapMarker*)key_ptr->val; - RDI_U32 idx = marker->idx; - - // push to stack - if(marker->begin_range){ - RDIM_VMapRangeTracker *new_tracker = tracker_free; - if(new_tracker != 0){ - RDIM_SLLStackPop(tracker_free); - } - else{ - new_tracker = rdim_push_array(scratch.arena, RDIM_VMapRangeTracker, 1); - } - RDIM_SLLStackPush(tracker_stack, new_tracker); - new_tracker->idx = idx; - } - - // pop matching node from stack (not always the top) - else{ - RDIM_VMapRangeTracker **ptr_in = &tracker_stack; - RDIM_VMapRangeTracker *match = 0; - for(RDIM_VMapRangeTracker *node = tracker_stack; - node != 0;){ - if(node->idx == idx){ - match = node; - break; - } - ptr_in = &node->next; - node = node->next; - } - if(match != 0){ - *ptr_in = match->next; - RDIM_SLLStackPush(tracker_free, match); - } - } - } - - // get final map state from tracker stack - RDI_U32 final_idx = 0; - if(tracker_stack != 0){ - final_idx = tracker_stack->idx; - } - - // if final is different from initial - emit new vmap entry - if(final_idx != initial_idx){ - vmap_ptr->voff = voff; - vmap_ptr->idx = final_idx; - vmap_ptr += 1; - } - } - - vmap_entry_count_pass_1 = (RDI_U32)(vmap_ptr - vmap); - } - - // replace zero unit indexes that follow a non-zero - // TODO(rjf): 0 *is* a real unit index right now - if(0) - { - // (the last entry is not replaced because it acts as a terminator) - RDI_U32 last = vmap_entry_count_pass_1 - 1; - - RDI_VMapEntry *vmap_ptr = vmap; - RDI_U64 real_idx = 0; - - for(RDI_U32 i = 0; i < last; i += 1, vmap_ptr += 1){ - // is this a zero after a real index? - if(vmap_ptr->idx == 0){ - vmap_ptr->idx = real_idx; - } - - // remember a real index - else{ - real_idx = vmap_ptr->idx; - } - } - } - - // combine duplicate neighbors - RDI_U32 vmap_entry_count = 0; - { - RDI_VMapEntry *vmap_ptr = vmap; - RDI_VMapEntry *vmap_opl = vmap + vmap_entry_count_pass_1; - RDI_VMapEntry *vmap_out = vmap; - - for(;vmap_ptr < vmap_opl;){ - RDI_VMapEntry *vmap_range_first = vmap_ptr; - RDI_U64 idx = vmap_ptr->idx; - vmap_ptr += 1; - for(;vmap_ptr < vmap_opl && vmap_ptr->idx == idx;) vmap_ptr += 1; - rdim_memcpy_struct(vmap_out, vmap_range_first); - vmap_out += 1; - } - - vmap_entry_count = (RDI_U32)(vmap_out - vmap); - } - - // fill result - RDIM_VMap *result = rdim_push_array(arena, RDIM_VMap, 1); - result->vmap = vmap; - result->count = vmap_entry_count - 1; - - rdim_scratch_end(scratch); - - return result; -} - -RDI_PROC RDIM_VMap* -rdim_vmap_from_unit_ranges(RDIM_Arena *arena, RDIM_UnitVMapRange *first, RDI_U64 count) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // count necessary markers - RDI_U64 marker_count = count*2; - - // fill markers - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - for(RDIM_UnitVMapRange *range = first; - range != 0; - range = range->next){ - if(range->first < range->opl){ - RDI_U32 unit_idx = range->unit->idx; - - key_ptr->key = range->first; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = range->opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - } - - // construct vmap - RDIM_VMap *result = rdim_vmap_from_markers(arena, markers, keys, marker_count); - rdim_scratch_end(scratch); - return result; -} - -//- rjf: type info baking - -RDI_PROC RDI_U32* -rdim_idx_run_from_types(RDIM_Arena *arena, RDIM_Type **types, RDI_U32 count) -{ - RDI_U32 *result = rdim_push_array(arena, RDI_U32, count); - for(RDI_U32 i = 0; i < count; i += 1){ - result[i] = types[i]->idx; - } - return result; -} - -RDI_PROC RDIM_TypeData* -rdim_type_data_combine(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // fill type nodes - RDI_U32 type_count = root->type_count; - RDI_TypeNode *type_nodes = rdim_push_array_no_zero(arena, RDI_TypeNode, type_count); - - { - RDI_TypeNode *ptr = type_nodes; - RDI_TypeNode *opl = ptr + type_count; - RDIM_Type *loose_type = root->first_type; - for(;loose_type != 0 && ptr < opl; - loose_type = loose_type->next_order, ptr += 1){ - - RDI_TypeKind kind = loose_type->kind; - - // shared - ptr->kind = kind; - ptr->flags = loose_type->flags; - ptr->byte_size = loose_type->byte_size; - - // built-in - if(RDI_TypeKind_FirstBuiltIn <= kind && kind <= RDI_TypeKind_LastBuiltIn){ - ptr->built_in.name_string_idx = rdim_string(bctx, loose_type->name); - } - - // constructed - else if(RDI_TypeKind_FirstConstructed <= kind && kind <= RDI_TypeKind_LastConstructed){ - ptr->constructed.direct_type_idx = loose_type->direct_type->idx; - - switch (kind){ - case RDI_TypeKind_Array: - { - ptr->constructed.count = loose_type->count; - }break; - - case RDI_TypeKind_Function: - { - // parameters - RDI_U32 count = loose_type->count; - RDI_U32 *idx_run = rdim_idx_run_from_types(scratch.arena, loose_type->param_types, count); - ptr->constructed.param_idx_run_first = rdim_idx_run(bctx, idx_run, count); - ptr->constructed.count = count; - }break; - - case RDI_TypeKind_Method: - { - // parameters - RDI_U32 count = loose_type->count; - RDI_U32 *idx_run = rdim_idx_run_from_types(scratch.arena, loose_type->param_types, count); - ptr->constructed.param_idx_run_first = rdim_idx_run(bctx, idx_run, count); - ptr->constructed.count = count; - }break; - } - } - - // user-defined - else if(RDI_TypeKind_FirstUserDefined <= kind && kind <= RDI_TypeKind_LastUserDefined){ - ptr->user_defined.name_string_idx = rdim_string(bctx, loose_type->name); - if(loose_type->udt != 0){ - ptr->user_defined.udt_idx = loose_type->udt->idx; - } - if(loose_type->direct_type != 0){ - ptr->user_defined.direct_type_idx = loose_type->direct_type->idx; - } - } - - // bitfield - else if(kind == RDI_TypeKind_Bitfield){ - ptr->bitfield.off = loose_type->off; - ptr->bitfield.size = loose_type->count; - } - - rdim_scratch_end(scratch); - } - - // both iterators should end at the same time - rdim_assert(loose_type == 0); - rdim_assert(ptr == opl); - } - - - // fill udts - RDI_U32 udt_count = root->type_udt_count; - RDI_UDT *udts = rdim_push_array_no_zero(arena, RDI_UDT, udt_count); - - RDI_U32 member_count = root->total_member_count; - RDI_Member *members = rdim_push_array_no_zero(arena, RDI_Member, member_count); - - RDI_U32 enum_member_count = root->total_enum_val_count; - RDI_EnumMember *enum_members = rdim_push_array_no_zero(arena, RDI_EnumMember, enum_member_count); - - { - RDI_UDT *ptr = udts; - RDI_UDT *opl = ptr + udt_count; - - RDI_Member *member_ptr = members; - RDI_Member *member_opl = members + member_count; - - RDI_EnumMember *enum_member_ptr = enum_members; - RDI_EnumMember *enum_member_opl = enum_members + enum_member_count; - - RDIM_TypeUDT *loose_udt = root->first_udt; - for(;loose_udt != 0 && ptr < opl; - loose_udt = loose_udt->next_order, ptr += 1){ - ptr->self_type_idx = loose_udt->self_type->idx; - - rdim_assert(loose_udt->member_count == 0 || - loose_udt->enum_val_count == 0); - - // enum members - if(loose_udt->enum_val_count != 0){ - ptr->flags |= RDI_UserDefinedTypeFlag_EnumMembers; - - ptr->member_first = (RDI_U32)(enum_member_ptr - enum_members); - ptr->member_count = loose_udt->enum_val_count; - - RDI_U32 local_enum_val_count = loose_udt->enum_val_count; - RDIM_TypeEnumVal *loose_enum_val = loose_udt->first_enum_val; - for(RDI_U32 i = 0; - i < local_enum_val_count; - i += 1, enum_member_ptr += 1, loose_enum_val = loose_enum_val->next){ - enum_member_ptr->name_string_idx = rdim_string(bctx, loose_enum_val->name); - enum_member_ptr->val = loose_enum_val->val; - } - } - - // struct/class/union members - else{ - ptr->member_first = (RDI_U32)(member_ptr - members); - ptr->member_count = loose_udt->member_count; - - RDI_U32 local_member_count = loose_udt->member_count; - RDIM_TypeMember *loose_member = loose_udt->first_member; - for(RDI_U32 i = 0; - i < local_member_count; - i += 1, member_ptr += 1, loose_member = loose_member->next){ - member_ptr->kind = loose_member->kind; - // TODO(allen): member_ptr->visibility = ; - member_ptr->name_string_idx = rdim_string(bctx, loose_member->name); - member_ptr->off = loose_member->off; - member_ptr->type_idx = loose_member->type->idx; - - // TODO(allen): - if(loose_member->kind == RDI_MemberKind_Method){ - //loose_member_ptr->unit_idx = ; - //loose_member_ptr->proc_symbol_idx = ; - } - } - - } - - RDI_U32 file_idx = 0; - if(loose_udt->source_path.size > 0){ - RDIM_PathNode *path_node = rdim_paths_node_from_path(bctx, loose_udt->source_path); - RDIM_SrcNode *src_node = rdim_paths_src_node_from_path_node(bctx, path_node); - file_idx = src_node->idx; - } - - ptr->file_idx = file_idx; - ptr->line = loose_udt->line; - ptr->col = loose_udt->col; - } - - // all iterators should end at the same time - rdim_assert(loose_udt == 0); - rdim_assert(ptr == opl); - rdim_assert(member_ptr == member_opl); - rdim_assert(enum_member_ptr == enum_member_opl); - } - - - // fill result - RDIM_TypeData *result = rdim_push_array(arena, RDIM_TypeData, 1); - result->type_nodes = type_nodes; - result->type_node_count = type_count; - result->udts = udts; - result->udt_count = udt_count; - result->members = members; - result->member_count = member_count; - result->enum_members = enum_members; - result->enum_member_count = enum_member_count; - - rdim_scratch_end(scratch); - return result; -} - -//- rjf: symbol data baking - -RDI_PROC RDIM_SymbolData* -rdim_symbol_data_combine(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // count symbol kinds - RDI_U32 globalvar_count = 1 + root->symbol_kind_counts[RDIM_SymbolKind_GlobalVariable]; - RDI_U32 threadvar_count = 1 + root->symbol_kind_counts[RDIM_SymbolKind_ThreadVariable]; - RDI_U32 procedure_count = 1 + root->symbol_kind_counts[RDIM_SymbolKind_Procedure]; - - // allocate symbol arrays - RDI_GlobalVariable *global_variables = - rdim_push_array(arena, RDI_GlobalVariable, globalvar_count); - - RDI_ThreadVariable *thread_variables = - rdim_push_array(arena, RDI_ThreadVariable, threadvar_count); - - RDI_Procedure *procedures = rdim_push_array(arena, RDI_Procedure, procedure_count); - - // fill symbol arrays - { - RDI_GlobalVariable *global_ptr = global_variables; - RDI_ThreadVariable *thread_local_ptr = thread_variables; - RDI_Procedure *procedure_ptr = procedures; - - // nils - global_ptr += 1; - thread_local_ptr += 1; - procedure_ptr += 1; - - // symbol nodes - for(RDIM_Symbol *node = root->first_symbol; - node != 0; - node = node->next_order){ - RDI_U32 name_string_idx = rdim_string(bctx, node->name); - RDI_U32 link_name_string_idx = rdim_string(bctx, node->link_name); - RDI_U32 type_idx = node->type->idx; - - RDI_LinkFlags link_flags = 0; - RDI_U32 container_idx = 0; - { - if(node->is_extern){ - link_flags |= RDI_LinkFlag_External; - } - if(node->container_symbol != 0){ - container_idx = node->container_symbol->idx; - link_flags |= RDI_LinkFlag_ProcScoped; - } - else if(node->container_type != 0 && node->container_type->udt != 0){ - container_idx = node->container_type->udt->idx; - link_flags |= RDI_LinkFlag_TypeScoped; - } - } - - switch (node->kind){ - default:{}break; - - case RDIM_SymbolKind_GlobalVariable: - { - global_ptr->name_string_idx = name_string_idx; - global_ptr->link_flags = link_flags; - global_ptr->voff = node->offset; - global_ptr->type_idx = type_idx; - global_ptr->container_idx = container_idx; - global_ptr += 1; - }break; - - case RDIM_SymbolKind_ThreadVariable: - { - thread_local_ptr->name_string_idx = name_string_idx; - thread_local_ptr->link_flags = link_flags; - thread_local_ptr->tls_off = (RDI_U32)node->offset; - thread_local_ptr->type_idx = type_idx; - thread_local_ptr->container_idx = container_idx; - thread_local_ptr += 1; - }break; - - case RDIM_SymbolKind_Procedure: - { - procedure_ptr->name_string_idx = name_string_idx; - procedure_ptr->link_name_string_idx = link_name_string_idx; - procedure_ptr->link_flags = link_flags; - procedure_ptr->type_idx = type_idx; - procedure_ptr->root_scope_idx = node->root_scope->idx; - procedure_ptr->container_idx = container_idx; - procedure_ptr += 1; - }break; - } - } - - rdim_assert(global_ptr - global_variables == globalvar_count); - rdim_assert(thread_local_ptr - thread_variables == threadvar_count); - rdim_assert(procedure_ptr - procedures == procedure_count); - } - - // global vmap - RDIM_VMap *global_vmap = 0; - { - // count necessary markers - RDI_U32 marker_count = globalvar_count*2; - - // fill markers - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - - // real globals - for(RDIM_Symbol *node = root->first_symbol; - node != 0; - node = node->next_order){ - if(node->kind == RDIM_SymbolKind_GlobalVariable){ - RDI_U32 global_idx = node->idx; - - RDI_U64 first = node->offset; - RDI_U64 opl = first + node->type->byte_size; - - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - // nil global - { - RDI_U32 global_idx = 0; - - RDI_U64 first = 0; - RDI_U64 opl = (RDI_U64)0xffffffffffffffffull; - - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - - // assert we filled all the markers - rdim_assert(key_ptr - keys == marker_count && - marker_ptr - markers == marker_count); - - // construct vmap - global_vmap = rdim_vmap_from_markers(arena, markers, keys, marker_count); - } - - // allocate scope array - - // (assert there is a nil scope) - rdim_assert(root->first_scope != 0 && - root->first_scope->symbol == 0 && - root->first_scope->first_child == 0 && - root->first_scope->next_sibling == 0 && - root->first_scope->range_count == 0); - - RDI_U32 scope_count = root->scope_count; - RDI_Scope *scopes = rdim_push_array(arena, RDI_Scope, scope_count); - - RDI_U32 scope_voff_count = root->scope_voff_count; - RDI_U64 *scope_voffs = rdim_push_array(arena, RDI_U64, scope_voff_count); - - RDI_U32 local_count = root->local_count; - RDI_Local *locals = rdim_push_array(arena, RDI_Local, local_count); - - RDI_U32 location_block_count = root->location_count; - RDI_LocationBlock *location_blocks = - rdim_push_array(arena, RDI_LocationBlock, location_block_count); - - RDIM_String8List location_data = {0}; - - // iterate scopes, locals, and locations - // fill scope voffs, locals, and location information - { - RDI_Scope *scope_ptr = scopes; - RDI_U64 *scope_voff_ptr = scope_voffs; - RDI_Local *local_ptr = locals; - RDI_LocationBlock *location_block_ptr = location_blocks; - - for(RDIM_Scope *node = root->first_scope; - node != 0; - node = node->next_order, scope_ptr += 1){ - - // emit voffs - RDI_U32 voff_first = (RDI_U32)(scope_voff_ptr - scope_voffs); - for(RDIM_VOffRange *range = node->first_range; - range != 0; - range = range->next){ - *scope_voff_ptr = range->voff_first; - scope_voff_ptr += 1; - *scope_voff_ptr = range->voff_opl; - scope_voff_ptr += 1; - } - RDI_U32 voff_opl = (RDI_U32)(scope_voff_ptr - scope_voffs); - - // emit locals - RDI_U32 scope_local_count = node->local_count; - RDI_U32 scope_local_first = (RDI_U32)(local_ptr - locals); - for(RDIM_Local *slocal = node->first_local; - slocal != 0; - slocal = slocal->next, local_ptr += 1){ - local_ptr->kind = slocal->kind; - local_ptr->name_string_idx = rdim_string(bctx, slocal->name); - local_ptr->type_idx = slocal->type->idx; - - RDIM_LocationSet *locset = slocal->locset; - if(locset != 0){ - RDI_U32 location_first = (RDI_U32)(location_block_ptr - location_blocks); - RDI_U32 location_opl = location_first + locset->location_case_count; - local_ptr->location_first = location_first; - local_ptr->location_opl = location_opl; - - for(RDIM_LocationCase *location_case = locset->first_location_case; - location_case != 0; - location_case = location_case->next){ - location_block_ptr->scope_off_first = location_case->voff_first; - location_block_ptr->scope_off_opl = location_case->voff_opl; - location_block_ptr->location_data_off = location_data.total_size; - location_block_ptr += 1; - - RDIM_Location *location = location_case->location; - if(location == 0){ - RDI_U64 data = 0; - str8_serial_push_align(scratch.arena, &location_data, 8); - str8_serial_push_data(scratch.arena, &location_data, &data, 1); - } - else{ - switch (location->kind){ - default: - { - RDI_U64 data = 0; - str8_serial_push_align(scratch.arena, &location_data, 8); - str8_serial_push_data(scratch.arena, &location_data, &data, 1); - }break; - - case RDI_LocationKind_AddrBytecodeStream: - case RDI_LocationKind_ValBytecodeStream: - { - rdim_str8_list_push(scratch.arena, &location_data, rdim_str8_copy(scratch.arena, rdim_str8_struct(&location->kind))); - for(RDIM_EvalBytecodeOp *op_node = location->bytecode.first_op; - op_node != 0; - op_node = op_node->next){ - RDI_U8 op_data[9]; - op_data[0] = op_node->op; - rdim_memcpy(op_data + 1, &op_node->p, op_node->p_size); - RDIM_String8 op_data_str = rdim_str8(op_data, 1 + op_node->p_size); - rdim_str8_list_push(scratch.arena, &location_data, rdim_str8_copy(scratch.arena, op_data_str)); - } - { - RDI_U64 data = 0; - RDIM_String8 data_str = rdim_str8((RDI_U8 *)&data, 1); - rdim_str8_list_push(scratch.arena, &location_data, rdim_str8_copy(scratch.arena, data_str)); - } - }break; - - case RDI_LocationKind_AddrRegisterPlusU16: - case RDI_LocationKind_AddrAddrRegisterPlusU16: - { - RDI_LocationRegisterPlusU16 loc = {0}; - loc.kind = location->kind; - loc.register_code = location->register_code; - loc.offset = location->offset; - rdim_str8_list_push(scratch.arena, &location_data, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - - case RDI_LocationKind_ValRegister: - { - RDI_LocationRegister loc = {0}; - loc.kind = location->kind; - loc.register_code = location->register_code; - rdim_str8_list_push(scratch.arena, &location_data, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - } - } - } - - rdim_assert(location_block_ptr - location_blocks == location_opl); - } - } - - rdim_assert(local_ptr - locals == scope_local_first + scope_local_count); - - // emit scope - scope_ptr->proc_idx = (node->symbol == 0)?0:node->symbol->idx; - scope_ptr->parent_scope_idx = (node->parent_scope == 0)?0:node->parent_scope->idx; - scope_ptr->first_child_scope_idx = (node->first_child == 0)?0:node->first_child->idx; - scope_ptr->next_sibling_scope_idx = (node->next_sibling == 0)?0:node->next_sibling->idx; - scope_ptr->voff_range_first = voff_first; - scope_ptr->voff_range_opl = voff_opl; - scope_ptr->local_first = scope_local_first; - scope_ptr->local_count = scope_local_count; - - // TODO(allen): - //scope_ptr->static_local_idx_run_first = ; - //scope_ptr->static_local_count = ; - } - - rdim_assert(scope_ptr - scopes == scope_count); - rdim_assert(local_ptr - locals == local_count); - } - - // flatten location data - RDIM_String8 location_data_str = rdim_str8_list_join(arena, &location_data, rdim_str8_lit("")); - - // scope vmap - RDIM_VMap *scope_vmap = 0; - { - // count necessary markers - RDI_U32 marker_count = scope_voff_count; - - // fill markers - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - - for(RDIM_Scope *node = root->first_scope; - node != 0; - node = node->next_order){ - RDI_U32 scope_idx = node->idx; - - for(RDIM_VOffRange *range = node->first_range; - range != 0; - range = range->next){ - key_ptr->key = range->voff_first; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = range->voff_opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - scope_vmap = rdim_vmap_from_markers(arena, markers, keys, marker_count); - } - - // fill result - RDIM_SymbolData *result = rdim_push_array(arena, RDIM_SymbolData, 1); - result->global_variables = global_variables; - result->global_variable_count = globalvar_count; - result->global_vmap = global_vmap; - result->thread_variables = thread_variables; - result->thread_variable_count = threadvar_count; - result->procedures = procedures; - result->procedure_count = procedure_count; - result->scopes = scopes; - result->scope_count = scope_count; - result->scope_voffs = scope_voffs; - result->scope_voff_count = scope_voff_count; - result->scope_vmap = scope_vmap; - result->locals = locals; - result->local_count = local_count; - result->location_blocks = location_blocks; - result->location_block_count = location_block_count; - result->location_data = location_data_str.str; - result->location_data_size = location_data_str.size; - - rdim_scratch_end(scratch); - return result; -} - -//- rjf: name map baking - -RDI_PROC RDIM_NameMapBaked* -rdim_name_map_bake(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx, RDIM_NameMap *map) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - RDI_U32 bucket_count = map->name_count; - RDI_U32 node_count = map->name_count; - - // setup the final bucket layouts - RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, bucket_count); - for(RDIM_NameMapNode *node = map->first; - node != 0; - node = node->order_next){ - RDI_U64 hash = rdi_hash(node->string.str, node->string.size); - RDI_U64 bi = hash%bucket_count; - RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); - SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); - snode->node = node; - sbuckets[bi].count += 1; - } - - // allocate tables - RDI_NameMapBucket *buckets = rdim_push_array(arena, RDI_NameMapBucket, bucket_count); - RDI_NameMapNode *nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, node_count); - - // convert to serialized buckets & nodes - { - RDI_NameMapBucket *bucket_ptr = buckets; - RDI_NameMapNode *node_ptr = nodes; - for(RDI_U32 i = 0; i < bucket_count; i += 1, bucket_ptr += 1){ - bucket_ptr->first_node = (RDI_U32)(node_ptr - nodes); - bucket_ptr->node_count = sbuckets[i].count; - - for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; - snode != 0; - snode = snode->next){ - RDIM_NameMapNode *node = snode->node; - - // cons name and index(es) - RDI_U32 string_idx = rdim_string(bctx, node->string); - RDI_U32 match_count = node->idx_count; - RDI_U32 idx = 0; - if(match_count == 1){ - idx = node->idx_first->idx[0]; - } - else{ - RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); - RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); - RDI_U32 *idx_ptr = idx_run; - for(RDIM_NameMapIdxNode *idxnode = node->idx_first; - idxnode != 0; - idxnode = idxnode->next){ - for(RDI_U32 i = 0; i < ArrayCount(idxnode->idx); i += 1){ - if(idxnode->idx[i] == 0){ - goto dblbreak; - } - *idx_ptr = idxnode->idx[i]; - idx_ptr += 1; - } - } - dblbreak:; - rdim_assert(idx_ptr == idx_run + match_count); - idx = rdim_idx_run(bctx, idx_run, match_count); - rdim_arena_pop_to(scratch.arena, temp_pos); - } - - // write to node - node_ptr->string_idx = string_idx; - node_ptr->match_count = match_count; - node_ptr->match_idx_or_idx_run_first = idx; - node_ptr += 1; - } - } - rdim_assert(node_ptr - nodes == node_count); - } - - rdim_scratch_end(scratch); - - RDIM_NameMapBaked *result = rdim_push_array(arena, RDIM_NameMapBaked, 1); - result->buckets = buckets; - result->nodes = nodes; - result->bucket_count = bucket_count; - result->node_count = node_count; - return result; -} - -//- rjf: top-level baking entry point - -RDI_PROC void -rdim_bake_file(RDIM_Arena *arena, RDIM_Root *root, RDIM_String8List *out) -{ - str8_serial_begin(arena, out); - - // setup cons helpers - RDIM_DSections dss = {0}; - rdim_dsection(arena, &dss, 0, 0, RDI_DataSectionTag_NULL); - - RDIM_BakeParams bctx_params = {0}; - { - bctx_params.strings_bucket_count = u64_up_to_pow2(root->symbol_map.pair_count*8); - bctx_params.idx_runs_bucket_count = u64_up_to_pow2(root->symbol_map.pair_count*8); - } - RDIM_BakeCtx *bctx = rdim_bake_ctx_begin(&bctx_params); - - //////////////////////////////// - // MAIN PART: allocating and filling out sections of the file - - // top level info - RDI_TopLevelInfo *tli = rdim_push_array(arena, RDI_TopLevelInfo, 1); - { - RDIM_TopLevelInfo *rdim_tli = &root->top_level_info; - tli->architecture = rdim_tli->architecture; - tli->exe_name_string_idx = rdim_string(bctx, rdim_tli->exe_name); - tli->exe_hash = rdim_tli->exe_hash; - tli->voff_max = rdim_tli->voff_max; - } - rdim_dsection(arena, &dss, tli, sizeof(*tli), RDI_DataSectionTag_TopLevelInfo); - - // binary sections array - { - RDI_U32 count = root->binary_section_count; - RDI_BinarySection *sections = rdim_push_array(arena, RDI_BinarySection, count); - RDI_BinarySection *dsec = sections; - for(RDIM_BinarySection *ssec = root->binary_section_first; - ssec != 0; - ssec = ssec->next, dsec += 1){ - dsec->name_string_idx = rdim_string(bctx, ssec->name); - dsec->flags = ssec->flags; - dsec->voff_first = ssec->voff_first; - dsec->voff_opl = ssec->voff_opl; - dsec->foff_first = ssec->foff_first; - dsec->foff_opl = ssec->foff_opl; - } - rdim_dsection(arena, &dss, sections, sizeof(*sections)*count, RDI_DataSectionTag_BinarySections); - } - - // units array - // * pass for per-unit information including: - // * top-level unit information - // * combining line info for whole unit - { - RDI_U32 count = root->unit_count; - RDI_Unit *units = rdim_push_array(arena, RDI_Unit, count); - RDI_Unit *dunit = units; - for(RDIM_Unit *sunit = root->unit_first; - sunit != 0; - sunit = sunit->next_order, dunit += 1){ - // strings & paths - RDI_U32 unit_name = rdim_string(bctx, sunit->unit_name); - RDI_U32 cmp_name = rdim_string(bctx, sunit->compiler_name); - - RDI_U32 src_path = rdim_paths_idx_from_path(bctx, sunit->source_file); - RDI_U32 obj_path = rdim_paths_idx_from_path(bctx, sunit->object_file); - RDI_U32 archive_path = rdim_paths_idx_from_path(bctx, sunit->archive_file); - RDI_U32 build_path = rdim_paths_idx_from_path(bctx, sunit->build_path); - - dunit->unit_name_string_idx = unit_name; - dunit->compiler_name_string_idx = cmp_name; - dunit->source_file_path_node = src_path; - dunit->object_file_path_node = obj_path; - dunit->archive_file_path_node = archive_path; - dunit->build_path_node = build_path; - dunit->language = sunit->language; - - // line info (voff -> file*line*col) - RDIM_LineSequenceNode *first_seq = sunit->line_seq_first; - RDIM_UnitLinesCombined *lines = rdim_unit_combine_lines(arena, bctx, first_seq); - - RDI_U32 line_count = lines->line_count; - if(line_count > 0){ - dunit->line_info_voffs_data_idx = - rdim_dsection(arena, &dss, lines->voffs, sizeof(RDI_U64)*(line_count + 1), - RDI_DataSectionTag_LineInfoVoffs); - dunit->line_info_data_idx = - rdim_dsection(arena, &dss, lines->lines, sizeof(RDI_Line)*line_count, - RDI_DataSectionTag_LineInfoData); - if(lines->cols != 0){ - dunit->line_info_col_data_idx = - rdim_dsection(arena, &dss, lines->cols, sizeof(RDI_Column)*line_count, - RDI_DataSectionTag_LineInfoColumns); - } - dunit->line_info_count = line_count; - } - } - - rdim_dsection(arena, &dss, units, sizeof(*units)*count, RDI_DataSectionTag_Units); - } - - // source file line info baking - // * pass for "source_combine_line" for each source file - - // * can only be run after a pass that does "unit_combine_lines" for each unit. - for(RDIM_SrcNode *src_node = bctx->tree->src_first; - src_node != 0; - src_node = src_node->next){ - RDIM_LineMapFragment *first_fragment = src_node->first_fragment; - RDIM_SrcLinesCombined *lines = rdim_source_combine_lines(arena, first_fragment); - RDI_U32 line_count = lines->line_count; - - if(line_count > 0){ - src_node->line_map_count = line_count; - - src_node->line_map_nums_data_idx = - rdim_dsection(arena, &dss, lines->line_nums, sizeof(*lines->line_nums)*line_count, - RDI_DataSectionTag_LineMapNumbers); - - src_node->line_map_range_data_idx = - rdim_dsection(arena, &dss, lines->line_ranges, sizeof(*lines->line_ranges)*(line_count + 1), - RDI_DataSectionTag_LineMapRanges); - - src_node->line_map_voff_data_idx = - rdim_dsection(arena, &dss, lines->voffs, sizeof(*lines->voffs)*lines->voff_count, - RDI_DataSectionTag_LineMapVoffs); - } - } - - // source file name mapping - { - RDIM_NameMap* map = rdim_name_map_for_kind(root, RDI_NameMapKind_NormalSourcePaths); - for(RDIM_SrcNode *src_node = bctx->tree->src_first; - src_node != 0; - src_node = src_node->next){ - if(src_node->idx != 0){ - rdim_name_map_add_pair(root, map, src_node->normal_full_path, src_node->idx); - } - } - } - - // unit vmap baking - { - RDIM_VMap *vmap = rdim_vmap_from_unit_ranges(arena, - root->unit_vmap_range_first, - root->unit_vmap_range_count); - - RDI_U64 vmap_size = sizeof(*vmap->vmap)*(vmap->count + 1); - rdim_dsection(arena, &dss, vmap->vmap, vmap_size, RDI_DataSectionTag_UnitVmap); - } - - // type info baking - { - RDIM_TypeData *types = rdim_type_data_combine(arena, root, bctx); - - RDI_U64 type_nodes_size = sizeof(*types->type_nodes)*types->type_node_count; - rdim_dsection(arena, &dss, types->type_nodes, type_nodes_size, RDI_DataSectionTag_TypeNodes); - - RDI_U64 udt_size = sizeof(*types->udts)*types->udt_count; - rdim_dsection(arena, &dss, types->udts, udt_size, RDI_DataSectionTag_UDTs); - - RDI_U64 member_size = sizeof(*types->members)*types->member_count; - rdim_dsection(arena, &dss, types->members, member_size, RDI_DataSectionTag_Members); - - RDI_U64 enum_member_size = sizeof(*types->enum_members)*types->enum_member_count; - rdim_dsection(arena, &dss, types->enum_members, enum_member_size, RDI_DataSectionTag_EnumMembers); - } - - // symbol info baking - { - RDIM_SymbolData *symbol_data = rdim_symbol_data_combine(arena, root, bctx); - - RDI_U64 global_variables_size = - sizeof(*symbol_data->global_variables)*symbol_data->global_variable_count; - rdim_dsection(arena, &dss, symbol_data->global_variables, global_variables_size, - RDI_DataSectionTag_GlobalVariables); - - RDIM_VMap *global_vmap = symbol_data->global_vmap; - RDI_U64 global_vmap_size = sizeof(*global_vmap->vmap)*(global_vmap->count + 1); - rdim_dsection(arena, &dss, global_vmap->vmap, global_vmap_size, - RDI_DataSectionTag_GlobalVmap); - - RDI_U64 thread_variables_size = - sizeof(*symbol_data->thread_variables)*symbol_data->thread_variable_count; - rdim_dsection(arena, &dss, symbol_data->thread_variables, thread_variables_size, - RDI_DataSectionTag_ThreadVariables); - - RDI_U64 procedures_size = sizeof(*symbol_data->procedures)*symbol_data->procedure_count; - rdim_dsection(arena, &dss, symbol_data->procedures, procedures_size, - RDI_DataSectionTag_Procedures); - - RDI_U64 scopes_size = sizeof(*symbol_data->scopes)*symbol_data->scope_count; - rdim_dsection(arena, &dss, symbol_data->scopes, scopes_size, RDI_DataSectionTag_Scopes); - - RDI_U64 scope_voffs_size = sizeof(*symbol_data->scope_voffs)*symbol_data->scope_voff_count; - rdim_dsection(arena, &dss, symbol_data->scope_voffs, scope_voffs_size, - RDI_DataSectionTag_ScopeVoffData); - - RDIM_VMap *scope_vmap = symbol_data->scope_vmap; - RDI_U64 scope_vmap_size = sizeof(*scope_vmap->vmap)*(scope_vmap->count + 1); - rdim_dsection(arena, &dss, scope_vmap->vmap, scope_vmap_size, RDI_DataSectionTag_ScopeVmap); - - RDI_U64 local_size = sizeof(*symbol_data->locals)*symbol_data->local_count; - rdim_dsection(arena, &dss, symbol_data->locals, local_size, RDI_DataSectionTag_Locals); - - RDI_U64 location_blocks_size = - sizeof(*symbol_data->location_blocks)*symbol_data->location_block_count; - rdim_dsection(arena, &dss, symbol_data->location_blocks, location_blocks_size, - RDI_DataSectionTag_LocationBlocks); - - RDI_U64 location_data_size = symbol_data->location_data_size; - rdim_dsection(arena, &dss, symbol_data->location_data, location_data_size, - RDI_DataSectionTag_LocationData); - } - - // name map baking - { - RDI_U32 name_map_count = 0; - for(RDI_U32 i = 0; i < RDI_NameMapKind_COUNT; i += 1){ - if(root->name_maps[i] != 0){ - name_map_count += 1; - } - } - - RDI_NameMap *name_maps = rdim_push_array(arena, RDI_NameMap, name_map_count); - - RDI_NameMap *name_map_ptr = name_maps; - for(RDI_U32 i = 0; i < RDI_NameMapKind_COUNT; i += 1){ - RDIM_NameMap *map = root->name_maps[i]; - if(map != 0){ - RDIM_NameMapBaked *baked = rdim_name_map_bake(arena, root, bctx, map); - - name_map_ptr->kind = i; - name_map_ptr->bucket_data_idx = - rdim_dsection(arena, &dss, baked->buckets, sizeof(*baked->buckets)*baked->bucket_count, - RDI_DataSectionTag_NameMapBuckets); - name_map_ptr->node_data_idx = - rdim_dsection(arena, &dss, baked->nodes, sizeof(*baked->nodes)*baked->node_count, - RDI_DataSectionTag_NameMapNodes); - name_map_ptr += 1; - } - } - - rdim_dsection(arena, &dss, name_maps, sizeof(*name_maps)*name_map_count, - RDI_DataSectionTag_NameMaps); - } - - //////////////////////////////// - // LATE PART: baking loose structures and creating final layout - - // generate data sections for file paths - { - RDI_U32 count = bctx->tree->count; - RDI_FilePathNode *nodes = rdim_push_array(arena, RDI_FilePathNode, count); - - RDI_FilePathNode *out_node = nodes; - for(RDIM_PathNode *node = bctx->tree->first; - node != 0; - node = node->next_order, out_node += 1){ - out_node->name_string_idx = rdim_string(bctx, node->name); - if(node->parent != 0){ - out_node->parent_path_node = node->parent->idx; - } - if(node->first_child != 0){ - out_node->first_child = node->first_child->idx; - } - if(node->next_sibling != 0){ - out_node->next_sibling = node->next_sibling->idx; - } - if(node->src_file != 0){ - out_node->source_file_idx = node->src_file->idx; - } - } - - rdim_dsection(arena, &dss, nodes, sizeof(*nodes)*count, RDI_DataSectionTag_FilePathNodes); - } - - // generate data sections for files - { - RDI_U32 count = bctx->tree->src_count; - RDI_SourceFile *src_files = rdim_push_array(arena, RDI_SourceFile, count); - - RDI_SourceFile *out_src_file = src_files; - for(RDIM_SrcNode *node = bctx->tree->src_first; - node != 0; - node = node->next, out_src_file += 1){ - out_src_file->file_path_node_idx = node->path_node->idx; - out_src_file->normal_full_path_string_idx = rdim_string(bctx, node->normal_full_path); - out_src_file->line_map_nums_data_idx = node->line_map_nums_data_idx; - out_src_file->line_map_range_data_idx = node->line_map_range_data_idx; - out_src_file->line_map_count = node->line_map_count; - out_src_file->line_map_voff_data_idx = node->line_map_voff_data_idx; - } - - rdim_dsection(arena, &dss, src_files, sizeof(*src_files)*count, RDI_DataSectionTag_SourceFiles); - } - - // generate data sections for strings - { - RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, bctx->strs.count + 1); - - RDI_U32 off_cursor = 0; - { - RDI_U32 *off_ptr = str_offs; - *off_ptr = 0; - off_ptr += 1; - for(RDIM_StringNode *node = bctx->strs.order_first; - node != 0; - node = node->order_next){ - off_cursor += node->str.size; - *off_ptr = off_cursor; - off_ptr += 1; - } - } - - RDI_U8 *buf = rdim_push_array(arena, RDI_U8, off_cursor); - { - RDI_U8 *ptr = buf; - for(RDIM_StringNode *node = bctx->strs.order_first; - node != 0; - node = node->order_next){ - rdim_memcpy(ptr, node->str.str, node->str.size); - ptr += node->str.size; - } - } - - rdim_dsection(arena, &dss, str_offs, sizeof(*str_offs)*(bctx->strs.count + 1), - RDI_DataSectionTag_StringTable); - rdim_dsection(arena, &dss, buf, off_cursor, RDI_DataSectionTag_StringData); - } - - // generate data sections for index runs - { - RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, bctx->idxs.idx_count); - - { - RDI_U32 *out_ptr = idx_data; - RDI_U32 *opl = out_ptr + bctx->idxs.idx_count; - RDIM_IdxRunNode *node = bctx->idxs.order_first; - for(;node != 0 && out_ptr < opl; - node = node->order_next){ - rdim_memcpy(out_ptr, node->idx_run, sizeof(*node->idx_run)*node->count); - out_ptr += node->count; - } - rdim_assert(out_ptr == opl); - } - - rdim_dsection(arena, &dss, idx_data, sizeof(*idx_data)*bctx->idxs.idx_count, - RDI_DataSectionTag_IndexRuns); - } - - // layout - // * the header and data section table have to be initialized "out of order" - // * so that the rest of the system can avoid this tricky order-layout interdependence stuff - RDI_Header *header = rdim_push_array(arena, RDI_Header, 1); - RDI_DataSection *dstable = rdim_push_array(arena, RDI_DataSection, dss.count); - str8_serial_push_align(arena, out, 8); - RDI_U64 header_off = out->total_size; - str8_list_push(arena, out, str8_struct(header)); - str8_serial_push_align(arena, out, 8); - RDI_U64 data_section_off = out->total_size; - str8_list_push(arena, out, str8((RDI_U8 *)dstable, sizeof(*dstable)*dss.count)); - { - header->magic = RDI_MAGIC_CONSTANT; - header->encoding_version = RDI_ENCODING_VERSION; - header->data_section_off = data_section_off; - header->data_section_count = dss.count; - } - { - RDI_U64 test_dss_count = 0; - for(RDIM_DSectionNode *node = dss.first; - node != 0; - node = node->next){ - test_dss_count += 1; - } - rdim_assert(test_dss_count == dss.count); - - RDI_DataSection *ptr = dstable; - for(RDIM_DSectionNode *node = dss.first; - node != 0; - node = node->next, ptr += 1){ - RDI_U64 data_section_offset = 0; - if(node->size != 0) - { - str8_serial_push_align(arena, out, 8); - data_section_offset = out->total_size; - str8_list_push(arena, out, str8((RDI_U8 *)node->data, node->size)); - } - ptr->tag = node->tag; - ptr->encoding = RDI_DataSectionEncoding_Unpacked; - ptr->off = data_section_offset; - ptr->encoded_size = node->size; - ptr->unpacked_size = node->size; - } - rdim_assert(ptr == dstable + dss.count); - } - - rdim_bake_ctx_release(bctx); -} -#endif diff --git a/src/lib_raddbgi_make/raddbgi_make.h b/src/lib_raddbgi_make/raddbgi_make.h index 28eaa664..e23f9595 100644 --- a/src/lib_raddbgi_make/raddbgi_make.h +++ b/src/lib_raddbgi_make/raddbgi_make.h @@ -947,352 +947,6 @@ struct RDIM_VMapMarker RDI_U32 begin_range; }; -#if 0 -//////////////////////////////// -//~ rjf: Root Construction Bundle Types - -typedef struct RDIM_RootParams RDIM_RootParams; -struct RDIM_RootParams -{ - RDI_U64 addr_size; - RDI_U32 bucket_count_units; // optional; default chosen if 0 - RDI_U32 bucket_count_symbols; // optional; default chosen if 0 - RDI_U32 bucket_count_scopes; // optional; default chosen if 0 - RDI_U32 bucket_count_locals; // optional; default chosen if 0 - RDI_U32 bucket_count_types; // optional; default chosen if 0 - RDI_U64 bucket_count_type_constructs; // optional; default chosen if 0 -}; - -typedef struct RDIM_Root RDIM_Root; -struct RDIM_Root -{ - RDIM_Arena *arena; - RDIM_MsgList msgs; - - //////// Contextual Information - - RDI_U64 addr_size; - - //////// Info Declared By User - - RDI_U64 total_member_count; - RDI_U64 total_enum_val_count; - - // symbols - RDIM_Symbol *first_symbol; - RDIM_Symbol *last_symbol; - union - { - RDI_U64 symbol_count; - RDI_U64 symbol_kind_counts[RDIM_SymbolKind_COUNT]; - }; - - RDIM_Scope *first_scope; - RDIM_Scope *last_scope; - RDI_U64 scope_count; - RDI_U64 scope_voff_count; - - RDIM_Local *first_local; - RDIM_Local *last_local; - RDI_U64 local_count; - RDI_U64 location_count; - - // name maps - RDIM_NameMap *name_maps[RDI_NameMapKind_COUNT]; - - //////// Handle Relationship Maps - - RDIM_U64ToPtrMap unit_map; - RDIM_U64ToPtrMap symbol_map; - RDIM_U64ToPtrMap scope_map; - RDIM_U64ToPtrMap local_map; - RDIM_U64ToPtrMap type_from_id_map; - RDIM_Str8ToPtrMap construct_map; -}; - -//////////////////////////////// -//~ rjf: Baking Phase Types - -//- rjf: bake data section data structure - -typedef struct RDIM_DSectionNode RDIM_DSectionNode; -struct RDIM_DSectionNode -{ - RDIM_DSectionNode *next; - void *data; - RDI_U64 size; - RDI_DataSectionTag tag; -}; - -typedef struct RDIM_DSections RDIM_DSections; -struct RDIM_DSections -{ - RDIM_DSectionNode *first; - RDIM_DSectionNode *last; - RDI_U32 count; -}; - -//- rjf: bake string data structure - -typedef struct RDIM_StringNode RDIM_StringNode; -struct RDIM_StringNode -{ - RDIM_StringNode *order_next; - RDIM_StringNode *bucket_next; - RDIM_String8 str; - RDI_U64 hash; - RDI_U32 idx; -}; - -typedef struct RDIM_Strings RDIM_Strings; -struct RDIM_Strings -{ - RDIM_StringNode *order_first; - RDIM_StringNode *order_last; - RDIM_StringNode **buckets; - RDI_U64 buckets_count; - RDI_U64 bucket_collision_count; - RDI_U32 count; -}; - -//- rjf: index run baking data structure - -typedef struct RDIM_IdxRunNode RDIM_IdxRunNode; -struct RDIM_IdxRunNode -{ - RDIM_IdxRunNode *order_next; - RDIM_IdxRunNode *bucket_next; - RDI_U32 *idx_run; - RDI_U64 hash; - RDI_U32 count; - RDI_U32 first_idx; -}; - -typedef struct RDIM_IdxRuns RDIM_IdxRuns; -struct RDIM_IdxRuns -{ - RDIM_IdxRunNode *order_first; - RDIM_IdxRunNode *order_last; - RDIM_IdxRunNode **buckets; - RDI_U64 buckets_count; - RDI_U64 bucket_collision_count; - RDI_U32 count; - RDI_U32 idx_count; -}; - -//- rjf: source file & file path baking data structures - -typedef struct RDIM_PathNode RDIM_PathNode; -struct RDIM_PathNode -{ - RDIM_PathNode *next_order; - RDIM_PathNode *parent; - RDIM_PathNode *first_child; - RDIM_PathNode *last_child; - RDIM_PathNode *next_sibling; - RDIM_String8 name; - struct RDIM_SrcNode *src_file; - RDI_U32 idx; -}; - -typedef struct RDIM_LineMapFragment RDIM_LineMapFragment; -struct RDIM_LineMapFragment -{ - RDIM_LineMapFragment *next; - RDIM_LineSequenceNode *sequence; -}; - -typedef struct RDIM_SrcNode RDIM_SrcNode; -struct RDIM_SrcNode -{ - RDIM_SrcNode *next; - RDIM_PathNode *path_node; - RDI_U32 idx; - - RDIM_String8 normal_full_path; - - // place to gather the line info attached to this src file - RDIM_LineMapFragment *first_fragment; - RDIM_LineMapFragment *last_fragment; - - // place to put the final baked version of this file's line map - RDI_U32 line_map_nums_data_idx; - RDI_U32 line_map_range_data_idx; - RDI_U32 line_map_count; - RDI_U32 line_map_voff_data_idx; -}; - -typedef struct RDIM_PathTree RDIM_PathTree; -struct RDIM_PathTree -{ - RDIM_PathNode *first; - RDIM_PathNode *last; - RDI_U32 count; - RDIM_PathNode root; - RDIM_SrcNode *src_first; - RDIM_SrcNode *src_last; - RDI_U32 src_count; -}; - -//- rjf: line info baking data structures - -typedef struct RDIM_UnitLinesCombined RDIM_UnitLinesCombined; -struct RDIM_UnitLinesCombined -{ - RDI_U64 *voffs; - RDI_Line *lines; - RDI_U16 *cols; - RDI_U32 line_count; -}; - -typedef struct RDIM_SrcLinesCombined RDIM_SrcLinesCombined; -struct RDIM_SrcLinesCombined -{ - RDI_U32 *line_nums; - RDI_U32 *line_ranges; - RDI_U64 *voffs; - RDI_U32 line_count; - RDI_U32 voff_count; -}; - -typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; -struct RDIM_SrcLineMapVoffBlock -{ - RDIM_SrcLineMapVoffBlock *next; - RDI_U64 voff; -}; - -typedef struct RDIM_SrcLineMapBucket RDIM_SrcLineMapBucket; -struct RDIM_SrcLineMapBucket -{ - RDIM_SrcLineMapBucket *order_next; - RDIM_SrcLineMapBucket *hash_next; - RDI_U32 line_num; - RDIM_SrcLineMapVoffBlock *first_voff_block; - RDIM_SrcLineMapVoffBlock *last_voff_block; - RDI_U64 voff_count; -}; - -//- rjf: vmap baking data structure - -typedef struct RDIM_VMap RDIM_VMap; -struct RDIM_VMap -{ - RDI_VMapEntry *vmap; // [count + 1] - RDI_U32 count; -}; - -typedef struct RDIM_VMapMarker RDIM_VMapMarker; -struct RDIM_VMapMarker -{ - RDI_U32 idx; - RDI_U32 begin_range; -}; - -typedef struct RDIM_VMapRangeTracker RDIM_VMapRangeTracker; -struct RDIM_VMapRangeTracker -{ - RDIM_VMapRangeTracker *next; - RDI_U32 idx; -}; - -//- rjf: type data baking types - -typedef struct RDIM_TypeData RDIM_TypeData; -struct RDIM_TypeData -{ - RDI_TypeNode *type_nodes; - RDI_U32 type_node_count; - - RDI_UDT *udts; - RDI_U32 udt_count; - - RDI_Member *members; - RDI_U32 member_count; - - RDI_EnumMember *enum_members; - RDI_U32 enum_member_count; -}; - -//- rjf: symbol data baking types - -typedef struct RDIM_SymbolData RDIM_SymbolData; -struct RDIM_SymbolData -{ - RDI_GlobalVariable *global_variables; - RDI_U32 global_variable_count; - - RDIM_VMap *global_vmap; - - RDI_ThreadVariable *thread_variables; - RDI_U32 thread_variable_count; - - RDI_Procedure *procedures; - RDI_U32 procedure_count; - - RDI_Scope *scopes; - RDI_U32 scope_count; - - RDI_U64 *scope_voffs; - RDI_U32 scope_voff_count; - - RDIM_VMap *scope_vmap; - - RDI_Local *locals; - RDI_U32 local_count; - - RDI_LocationBlock *location_blocks; - RDI_U32 location_block_count; - - void *location_data; - RDI_U32 location_data_size; -}; - -//- rjf: name map baking types - -typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; -struct RDIM_NameMapSemiNode -{ - RDIM_NameMapSemiNode *next; - RDIM_NameMapNode *node; -}; - -typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; -struct RDIM_NameMapSemiBucket -{ - RDIM_NameMapSemiNode *first; - RDIM_NameMapSemiNode *last; - RDI_U64 count; -}; - -typedef struct RDIM_NameMapBaked RDIM_NameMapBaked; -struct RDIM_NameMapBaked -{ - RDI_NameMapBucket *buckets; - RDI_NameMapNode *nodes; - RDI_U32 bucket_count; - RDI_U32 node_count; -}; - -//- rjf: bundle baking context type - -typedef struct RDIM_BakeParams RDIM_BakeParams; -struct RDIM_BakeParams -{ - RDI_U64 strings_bucket_count; - RDI_U64 idx_runs_bucket_count; -}; - -typedef struct RDIM_BakeCtx RDIM_BakeCtx; -struct RDIM_BakeCtx -{ - RDIM_Arena *arena; - RDIM_Strings strs; - RDIM_IdxRuns idxs; - RDIM_PathTree *tree; -}; -#endif - //////////////////////////////// //~ rjf: Basic Helpers @@ -1431,150 +1085,4 @@ RDI_PROC RDIM_VMap rdim_vmap_from_markers(RDIM_Arena *arena, RDIM_VMapMarker *ma //- rjf: main baking entry point RDI_PROC RDIM_String8List rdim_bake(RDIM_Arena *arena, RDIM_BakeParams *params); - -#if 0 -//////////////////////////////// -//~ rjf: Loose Debug Info Construction (Anything -> Loose) Functions - -//- rjf: u64 -> ptr map -RDI_PROC void rdim_u64toptr_map_init(RDIM_Arena *arena, RDIM_U64ToPtrMap *map, RDI_U64 bucket_count); -RDI_PROC void rdim_u64toptr_map_lookup(RDIM_U64ToPtrMap *map, RDI_U64 key, RDI_U64 hash, RDIM_U64ToPtrLookup *lookup_out); -RDI_PROC void rdim_u64toptr_map_insert(RDIM_Arena *arena, RDIM_U64ToPtrMap *map, RDI_U64 key, RDI_U64 hash, RDIM_U64ToPtrLookup *lookup, void *ptr); - -//- rjf: string8 -> ptr map -RDI_PROC void rdim_str8toptr_map_init(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDI_U64 bucket_count); -RDI_PROC void*rdim_str8toptr_map_lookup(RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash); -RDI_PROC void rdim_str8toptr_map_insert(RDIM_Arena *arena, RDIM_Str8ToPtrMap *map, RDIM_String8 key, RDI_U64 hash, void *ptr); - -//- rjf: root creation -RDI_PROC RDIM_Root* rdim_root_alloc(RDIM_RootParams *params); -RDI_PROC void rdim_root_release(RDIM_Root *root); - -//- rjf: error accumulation -RDI_PROC void rdim_push_msg(RDIM_Root *root, RDIM_String8 string); -RDI_PROC void rdim_push_msgf(RDIM_Root *root, char *fmt, ...); -RDI_PROC RDIM_Msg* rdim_first_msg_from_root(RDIM_Root *root); - -//- rjf: type info lookups/reservations -RDI_PROC RDIM_Type* rdim_type_from_id(RDIM_Root *root, RDI_U64 type_user_id, RDI_U64 type_user_id_hash); -RDI_PROC RDIM_Reservation* rdim_type_reserve_id(RDIM_Root *root, RDI_U64 type_user_id, RDI_U64 type_user_id_hash); -RDI_PROC void rdim_type_fill_id(RDIM_Root *root, RDIM_Reservation *res, RDIM_Type *type); - -//- rjf: nil/singleton types -RDI_PROC RDI_S32 rdim_type_is_unhandled_nil(RDIM_Root *root, RDIM_Type *type); -RDI_PROC RDIM_Type* rdim_type_handled_nil(RDIM_Root *root); -RDI_PROC RDIM_Type* rdim_type_nil(RDIM_Root *root); -RDI_PROC RDIM_Type* rdim_type_variadic(RDIM_Root *root); - -//- rjf: base type info constructors -RDI_PROC RDIM_Type* rdim_type_new(RDIM_Root *root); -RDI_PROC RDIM_TypeUDT* rdim_type_udt_from_any_type(RDIM_Root *root, RDIM_Type *type); -RDI_PROC RDIM_TypeUDT* rdim_type_udt_from_record_type(RDIM_Root *root, RDIM_Type *type); - -//- rjf: basic/operator type construction helpers -RDI_PROC RDIM_Type* rdim_type_basic(RDIM_Root *root, RDI_TypeKind type_kind, RDIM_String8 name); -RDI_PROC RDIM_Type* rdim_type_modifier(RDIM_Root *root, RDIM_Type *direct_type, RDI_TypeModifierFlags flags); -RDI_PROC RDIM_Type* rdim_type_bitfield(RDIM_Root *root, RDIM_Type *direct_type, RDI_U32 bit_off, RDI_U32 bit_count); -RDI_PROC RDIM_Type* rdim_type_pointer(RDIM_Root *root, RDIM_Type *direct_type, RDI_TypeKind ptr_type_kind); -RDI_PROC RDIM_Type* rdim_type_array(RDIM_Root *root, RDIM_Type *direct_type, RDI_U64 count); -RDI_PROC RDIM_Type* rdim_type_proc(RDIM_Root *root, RDIM_Type *return_type, struct RDIM_TypeList *params); -RDI_PROC RDIM_Type* rdim_type_method(RDIM_Root *root, RDIM_Type *this_type, RDIM_Type *return_type, struct RDIM_TypeList *params); - -//- rjf: udt type constructors -RDI_PROC RDIM_Type* rdim_type_udt(RDIM_Root *root, RDI_TypeKind record_type_kind, RDIM_String8 name, RDI_U64 size); -RDI_PROC RDIM_Type* rdim_type_enum(RDIM_Root *root, RDIM_Type *direct_type, RDIM_String8 name); -RDI_PROC RDIM_Type* rdim_type_alias(RDIM_Root *root, RDIM_Type *direct_type, RDIM_String8 name); -RDI_PROC RDIM_Type* rdim_type_incomplete(RDIM_Root *root, RDI_TypeKind type_kind, RDIM_String8 name); - -//- rjf: type member building -RDI_PROC void rdim_type_add_member_data_field(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type, RDI_U32 off); -RDI_PROC void rdim_type_add_member_static_data(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type); -RDI_PROC void rdim_type_add_member_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type); -RDI_PROC void rdim_type_add_member_static_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type); -RDI_PROC void rdim_type_add_member_virtual_method(RDIM_Root *root, RDIM_Type *record_type, RDIM_String8 name, RDIM_Type *mem_type); -RDI_PROC void rdim_type_add_member_base(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *base_type, RDI_U32 off); -RDI_PROC void rdim_type_add_member_virtual_base(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *base_type, RDI_U32 vptr_off, RDI_U32 vtable_off); -RDI_PROC void rdim_type_add_member_nested_type(RDIM_Root *root, RDIM_Type *record_type, RDIM_Type *nested_type); -RDI_PROC void rdim_type_add_enum_val(RDIM_Root *root, RDIM_Type *enum_type, RDIM_String8 name, RDI_U64 val); - -//- rjf: type source coordinate specifications -RDI_PROC void rdim_type_set_source_coordinates(RDIM_Root *root, RDIM_Type *defined_type, RDIM_String8 source_path, RDI_U32 line, RDI_U32 col); - -//- rjf: symbol info building -RDI_PROC RDIM_Symbol* rdim_symbol_handle_from_user_id(RDIM_Root *root, RDI_U64 symbol_user_id, RDI_U64 symbol_user_id_hash); -RDI_PROC void rdim_symbol_set_info(RDIM_Root *root, RDIM_Symbol *symbol, RDIM_SymbolInfo *info); - -//- rjf: scope info building -RDI_PROC RDIM_Scope *rdim_scope_handle_from_user_id(RDIM_Root *root, RDI_U64 scope_user_id, RDI_U64 scope_user_id_hash); -RDI_PROC void rdim_scope_set_parent(RDIM_Root *root, RDIM_Scope *scope, RDIM_Scope *parent); -RDI_PROC void rdim_scope_add_voff_range(RDIM_Root *root, RDIM_Scope *scope, RDI_U64 voff_first, RDI_U64 voff_opl); -RDI_PROC void rdim_scope_recursive_set_symbol(RDIM_Scope *scope, RDIM_Symbol *symbol); - -//- rjf: local info building -RDI_PROC RDIM_Local* rdim_local_handle_from_user_id(RDIM_Root *root, RDI_U64 local_user_id, RDI_U64 local_user_id_hash); -RDI_PROC void rdim_local_set_basic_info(RDIM_Root *root, RDIM_Local *local, RDIM_LocalInfo *info); -RDI_PROC RDIM_LocationSet* rdim_location_set_from_local(RDIM_Root *root, RDIM_Local *local); - -//- rjf: location info building -RDI_PROC void rdim_location_set_add_case(RDIM_Root *root, RDIM_LocationSet *locset, RDI_U64 voff_first, RDI_U64 voff_opl, RDIM_Location *location); -RDI_PROC RDIM_Location* rdim_location_addr_bytecode_stream(RDIM_Root *root, struct RDIM_EvalBytecode *bytecode); -RDI_PROC RDIM_Location* rdim_location_val_bytecode_stream(RDIM_Root *root, struct RDIM_EvalBytecode *bytecode); -RDI_PROC RDIM_Location* rdim_location_addr_reg_plus_u16(RDIM_Root *root, RDI_U8 reg_code, RDI_U16 offset); -RDI_PROC RDIM_Location* rdim_location_addr_addr_reg_plus_u16(RDIM_Root *root, RDI_U8 reg_code, RDI_U16 offset); -RDI_PROC RDIM_Location* rdim_location_val_reg(RDIM_Root *root, RDI_U8 reg_code); - -//- rjf: name map building -RDI_PROC RDIM_NameMap* rdim_name_map_for_kind(RDIM_Root *root, RDI_NameMapKind kind); -RDI_PROC void rdim_name_map_add_pair(RDIM_Root *root, RDIM_NameMap *map, RDIM_String8 name, RDI_U32 idx); - -//////////////////////////////// -//~ rjf: Debug Info Baking (Loose -> Tight) Functions - -//- rjf: bake context construction -RDI_PROC RDIM_BakeCtx* rdim_bake_ctx_begin(RDIM_BakeParams *params); -RDI_PROC void rdim_bake_ctx_release(RDIM_BakeCtx *bake_ctx); - -//- rjf: string baking -RDI_PROC RDI_U32 rdim_string(RDIM_BakeCtx *bctx, RDIM_String8 str); - -//- rjf: idx run baking -RDI_PROC RDI_U64 rdim_idx_run_hash(RDI_U32 *idx_run, RDI_U32 count); -RDI_PROC RDI_U32 rdim_idx_run(RDIM_BakeCtx *bctx, RDI_U32 *idx_run, RDI_U32 count); - -//- rjf: data section baking -RDI_PROC RDI_U32 rdim_dsection(RDIM_Arena *arena, RDIM_DSections *dss, void *data, RDI_U64 size, RDI_DataSectionTag tag); - -//- rjf: paths baking -RDI_PROC RDIM_String8 rdim_normal_string_from_path_node(RDIM_Arena *arena, RDIM_PathNode *node); -RDI_PROC RDIM_BakePathNode *rdim_bake_path_tree_push_path_node(RDIM_Arena *arena, RDIM_BakePathTree *tree); -RDI_PROC RDIM_BakePathNode *rdim_paths_sub_path(RDIM_BakeCtx *bctx, RDIM_PathNode *dir, RDIM_String8 sub_dir); -RDI_PROC RDIM_BakePathNode *rdim_paths_node_from_path(RDIM_BakeCtx *bctx, RDIM_String8 path); -RDI_PROC RDI_U32 rdim_paths_idx_from_path(RDIM_BakeCtx *bctx, RDIM_String8 path); -RDI_PROC RDIM_BakeSrcNode * rdim_paths_new_src_node(RDIM_BakeCtx *bctx); -RDI_PROC RDIM_BakeSrcNode * rdim_paths_src_node_from_path_node(RDIM_BakeCtx *bctx, RDIM_PathNode *path_node); - -//- rjf: per-unit line info baking -RDI_PROC RDIM_UnitLinesCombined* rdim_unit_combine_lines(RDIM_Arena *arena, RDIM_BakeCtx *bctx, RDIM_LineSequenceNode *first_seq); - -//- rjf: per-src line info baking -RDI_PROC RDIM_SrcLinesCombined* rdim_source_combine_lines(RDIM_Arena *arena, RDIM_LineMapFragment *first); - -//- rjf: vmap baking -RDI_PROC RDIM_VMap* rdim_vmap_from_markers(RDIM_Arena *arena, RDIM_VMapMarker *markers, RDIM_SortKey *keys, RDI_U64 marker_count); -RDI_PROC RDIM_VMap* rdim_vmap_from_unit_ranges(RDIM_Arena *arena, RDIM_UnitVMapRange *first, RDI_U64 count); - -//- rjf: type info baking -RDI_PROC RDI_U32* rdim_idx_run_from_types(RDIM_Arena *arena, RDIM_Type **types, RDI_U32 count); -RDI_PROC RDIM_TypeData* rdim_type_data_combine(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx); - -//- rjf: symbol data baking -RDI_PROC RDIM_SymbolData* rdim_symbol_data_combine(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx); - -//- rjf: name map baking -RDI_PROC RDIM_NameMapBaked* rdim_name_map_bake(RDIM_Arena *arena, RDIM_Root *root, RDIM_BakeCtx *bctx, RDIM_NameMap *map); - -//- rjf: top-level baking entry point -RDI_PROC void rdim_bake_file(RDIM_Arena *arena, RDIM_Root *root, RDIM_String8List *out); -#endif - #endif // RDI_MAKE_H diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.c b/src/raddbgi_from_pdb/raddbgi_from_pdb.c index e92700c8..68503c7c 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.c +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.c @@ -539,2905 +539,6 @@ p2r_location_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkList *scopes, RDI } } -#if 0 - -//////////////////////////////// -//~ rjf: Conversion Implementation Helpers - -//- rjf: pdb conversion context creation - -internal P2R_Ctx * -p2r_ctx_alloc(P2R_CtxParams *params, RDIM_Root *out_root) -{ - Arena *arena = arena_alloc(); - P2R_Ctx *pdb_ctx = push_array(arena, P2R_Ctx, 1); - pdb_ctx->arena = arena; - pdb_ctx->arch = params->arch; - pdb_ctx->addr_size = rdi_addr_size_from_arch(pdb_ctx->arch); - pdb_ctx->hash = params->tpi_hash; - pdb_ctx->leaf = params->tpi_leaf; - pdb_ctx->sections = params->sections->sections; - pdb_ctx->section_count = params->sections->count; - pdb_ctx->root = out_root; -#define BKTCOUNT(x) ((x)?(u64_up_to_pow2(x)):(4096)) - pdb_ctx->fwd_map.buckets_count = BKTCOUNT(params->fwd_map_bucket_count); - pdb_ctx->frame_proc_map.buckets_count = BKTCOUNT(params->frame_proc_map_bucket_count); - pdb_ctx->known_globals.buckets_count = BKTCOUNT(params->known_global_map_bucket_count); - pdb_ctx->link_names.buckets_count = BKTCOUNT(params->link_name_map_bucket_count); -#undef BKTCOUNT - pdb_ctx->fwd_map.buckets = push_array(pdb_ctx->arena, P2R_FwdNode *, pdb_ctx->fwd_map.buckets_count); - pdb_ctx->frame_proc_map.buckets = push_array(pdb_ctx->arena, P2R_FrameProcNode *, pdb_ctx->frame_proc_map.buckets_count); - pdb_ctx->known_globals.buckets = push_array(pdb_ctx->arena, P2R_KnownGlobalNode *, pdb_ctx->known_globals.buckets_count); - pdb_ctx->link_names.buckets = push_array(pdb_ctx->arena, P2R_LinkNameNode *, pdb_ctx->link_names.buckets_count); - return pdb_ctx; -} - -//- rjf: pdb types and symbols - -internal void -p2r_types_and_symbols(P2R_Ctx *pdb_ctx, P2R_TypesSymbolsParams *params) -{ - ProfBeginFunction(); - - // convert types - p2r_type_cons_main_passes(pdb_ctx); - if(params->sym != 0) - { - p2r_gather_link_names(pdb_ctx, params->sym); - p2r_symbol_cons(pdb_ctx, params->sym, 0); - } - U64 unit_count = params->unit_count; - for(U64 i = 0; i < unit_count; i += 1) - { - CV_SymParsed *unit_sym = params->sym_for_unit[i]; - p2r_symbol_cons(pdb_ctx, unit_sym, 1 + i); - } - - ProfEnd(); -} - -//- rjf: decoding helpers - -internal U32 -p2r_u32_from_numeric(P2R_Ctx *ctx, CV_NumericParsed *num) -{ - U64 n_u64 = cv_u64_from_numeric(num); - U32 n_u32 = (U32)n_u64; - if(n_u64 > 0xFFFFFFFF) - { - rdim_push_msgf(ctx->root, "constant too large"); - n_u32 = 0; - } - return(n_u32); -} - -internal COFF_SectionHeader * -p2r_sec_header_from_sec_num(P2R_Ctx *ctx, U32 sec_num) -{ - COFF_SectionHeader *result = 0; - if(0 < sec_num && sec_num <= ctx->section_count) - { - result = ctx->sections + sec_num - 1; - } - return(result); -} - -//- rjf: type info - -internal void -p2r_type_cons_main_passes(P2R_Ctx *ctx) -{ - ProfBeginFunction(); - CV_TypeId itype_first = ctx->leaf->itype_first; - CV_TypeId itype_opl = ctx->leaf->itype_opl; - - // setup variadic itype -> node - ProfScope("setup variadic itype -> node") - { - RDIM_Type *variadic_type = rdim_type_variadic(ctx->root); - RDIM_Reservation *res = rdim_type_reserve_id(ctx->root, CV_TypeId_Variadic, CV_TypeId_Variadic); - rdim_type_fill_id(ctx->root, res, variadic_type); - } - - // resolve forward references - ProfScope("resolve forward references") - { - for(CV_TypeId itype = itype_first; itype < itype_opl; itype += 1) - { - p2r_type_resolve_fwd(ctx, itype); - } - } - - // construct type info - ProfScope("construct type info") - { - for(CV_TypeId itype = itype_first; itype < itype_opl; itype += 1) - { - p2r_type_resolve_itype(ctx, itype); - } - } - - // construct member info - ProfScope("construct member info") - { - for(P2R_TypeRev *rev = ctx->member_revisit_first; - rev != 0; - rev = rev->next) - { - p2r_type_equip_members(ctx, rev->owner_type, rev->field_itype); - } - } - - // construct enum info - ProfScope("construct enum info") - { - for(P2R_TypeRev *rev = ctx->enum_revisit_first; - rev != 0; - rev = rev->next) - { - p2r_type_equip_enumerates(ctx, rev->owner_type, rev->field_itype); - } - } - - // TODO(allen): equip udts with location information - ProfEnd(); -} - -internal CV_TypeId -p2r_type_resolve_fwd(P2R_Ctx *ctx, CV_TypeId itype) -{ - ProfBeginFunction(); - Assert(ctx->leaf->itype_first <= itype && itype < ctx->leaf->itype_opl); - - CV_TypeId result = 0; - - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[itype - ctx->leaf->itype_first]; - String8 data = ctx->leaf->data; - if(range->off + range->hdr.size <= data.size) - { - U8 *first = data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - - // figure out if this itype resolves to another - switch (range->hdr.kind) - { - default:break; - - case CV_LeafKind_CLASS: - case CV_LeafKind_STRUCTURE: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafStruct) <= cap) - { - CV_LeafStruct *lf_struct = (CV_LeafStruct*)first; - - // size - U8 *numeric_ptr = (U8*)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - - // name - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // unique name - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, first + cap); - - if(lf_struct->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = ((lf_struct->props & CV_TypeProp_Scoped) != 0) && - ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0); - if(do_unique_name_lookup) - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, unique_name, 1); - } - else - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, name, 0); - } - } - } - }break; - - case CV_LeafKind_CLASS2: - case CV_LeafKind_STRUCT2: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafStruct2) <= cap) - { - CV_LeafStruct2 *lf_struct = (CV_LeafStruct2*)first; - - // size - U8 *numeric_ptr = (U8*)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - - // name - U8 *name_ptr = (U8 *)numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // unique name - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, first + cap); - - if(lf_struct->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = ((lf_struct->props & CV_TypeProp_Scoped) != 0) && - ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0); - if(do_unique_name_lookup) - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, unique_name, 1); - } - else - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, name, 0); - } - } - } - }break; - - case CV_LeafKind_UNION: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafUnion) <= cap) - { - CV_LeafUnion *lf_union = (CV_LeafUnion*)first; - - // size - U8 *numeric_ptr = (U8*)(lf_union + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - - // name - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // unique name - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, first + cap); - - if(lf_union->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = ((lf_union->props & CV_TypeProp_Scoped) != 0) && - ((lf_union->props & CV_TypeProp_HasUniqueName) != 0); - if(do_unique_name_lookup) - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, unique_name, 1); - } - else - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, name, 0); - } - } - } - }break; - - case CV_LeafKind_ENUM: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafEnum) <= cap) - { - CV_LeafEnum *lf_enum = (CV_LeafEnum*)first; - - // name - U8 *name_ptr = (U8*)(lf_enum + 1); - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // unique name - U8 *unique_name_ptr = name_ptr + name.size + 1; - String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, first + cap); - - if(lf_enum->props & CV_TypeProp_FwdRef) - { - B32 do_unique_name_lookup = ((lf_enum->props & CV_TypeProp_Scoped) != 0) && - ((lf_enum->props & CV_TypeProp_HasUniqueName) != 0); - if(do_unique_name_lookup) - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, unique_name, 1); - } - else - { - result = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, name, 0); - } - } - } - }break; - } - } - - // save in map - if(result != 0) - { - p2r_type_fwd_map_set(ctx->arena, &ctx->fwd_map, itype, result); - } - - ProfEnd(); - return(result); -} - -internal RDIM_Type* -p2r_type_resolve_itype(P2R_Ctx *ctx, CV_TypeId itype) -{ - B32 is_basic = (itype < 0x1000); - - // convert fwd references to real types - if(!is_basic) - { - CV_TypeId resolved_itype = p2r_type_fwd_map_get(&ctx->fwd_map, itype); - if(resolved_itype != 0) - { - itype = resolved_itype; - } - } - - // type handle from id - RDIM_Type *result = rdim_type_from_id(ctx->root, itype, itype); - - // basic type - if(result == 0 && is_basic) - { - result = p2r_type_cons_basic(ctx, itype); - } - - // leaf decode - if(result == 0 && (ctx->leaf->itype_first <= itype && itype < ctx->leaf->itype_opl)) - { - result = p2r_type_cons_leaf_record(ctx, itype); - } - - // never return null, return "nil" instead - if(result == 0) - { - result = rdim_type_nil(ctx->root); - } - - return(result); -} - -internal void -p2r_type_equip_members(P2R_Ctx *ctx, RDIM_Type *owner_type, CV_TypeId field_itype) -{ - Temp scratch = scratch_begin(0, 0); - - String8 data = ctx->leaf->data; - - // field stack - // TODO(allen): add notes about field tasks - struct FieldTask{ - struct FieldTask *next; - CV_TypeId itype; - }; - struct FieldTask *handled = 0; - struct FieldTask *todo = 0; - { - struct FieldTask *task = push_array(scratch.arena, struct FieldTask, 1); - SLLStackPush(todo, task); - task->itype = field_itype; - } - - for(;;) - { - // exit condition - if(todo == 0) - { - break; - } - - // determine itype - CV_TypeId field_itype = todo->itype; - { - struct FieldTask *task = todo; - SLLStackPop(todo); - SLLStackPush(handled, task); - } - - // get leaf range - // TODO(allen): error if this itype is bad - U8 *first = 0; - U64 cap = 0; - if(ctx->leaf->itype_first <= field_itype && field_itype < ctx->leaf->itype_opl) - { - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[field_itype - ctx->leaf->itype_first]; - // check valid arglist - if(range->hdr.kind == CV_LeafKind_FIELDLIST && - range->off + range->hdr.size <= data.size) - { - first = data.str + range->off + 2; - cap = range->hdr.size - 2; - } - } - - U64 cursor = 0; - for(;cursor + sizeof(CV_LeafKind) <= cap;) - { - CV_LeafKind field_kind = *(CV_LeafKind*)(first + cursor); - - U64 list_item_off = cursor + 2; - // if we hit an error or forget to set next cursor for a case - // default to exiting the loop - U64 list_item_opl_off = cap; - - switch (field_kind) - { - case CV_LeafKind_INDEX: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafIndex) <= cap) - { - // compute whole layout - CV_LeafIndex *index = (CV_LeafIndex*)(first + list_item_off); - - list_item_opl_off = list_item_off + sizeof(*index); - - // create new todo task - CV_TypeId new_itype = index->itype; - B32 is_new = 1; - for(struct FieldTask *task = handled; - task != 0; - task = task->next) - { - if(task->itype == new_itype) - { - is_new = 0; - break; - } - } - if(is_new) - { - struct FieldTask *task = push_array(scratch.arena, struct FieldTask, 1); - SLLStackPush(todo, task); - task->itype = new_itype; - } - } - }break; - - case CV_LeafKind_MEMBER: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafMember) <= cap) - { - // compute whole layout - CV_LeafMember *member = (CV_LeafMember*)(first + list_item_off); - - U64 offset_off = list_item_off + sizeof(*member); - CV_NumericParsed offset = cv_numeric_from_data_range(first + offset_off, first + cap); - - U64 name_off = offset_off + offset.encoded_size; - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // emit member - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, member->itype); - U32 offset_u32 = p2r_u32_from_numeric(ctx, &offset); - rdim_type_add_member_data_field(ctx->root, owner_type, name, mem_type, offset_u32); - } - }break; - - case CV_LeafKind_STMEMBER: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafStMember) <= cap) - { - // compute whole layout - CV_LeafStMember *stmember = (CV_LeafStMember*)(first + list_item_off); - - U64 name_off = list_item_off + sizeof(*stmember); - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // TODO(allen): handle attribs - - // emit member - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, stmember->itype); - rdim_type_add_member_static_data(ctx->root, owner_type, name, mem_type); - } - }break; - - case CV_LeafKind_METHOD: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafMethod) <= cap) - { - // compute whole layout - CV_LeafMethod *method = (CV_LeafMethod*)(first + list_item_off); - - U64 name_off = list_item_off + sizeof(*method); - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // extract method list - U8 *first = 0; - U64 cap = 0; - - // TODO(allen): error if bad itype - CV_TypeId methodlist_itype = method->list_itype; - if(ctx->leaf->itype_first <= methodlist_itype && - methodlist_itype < ctx->leaf->itype_opl) - { - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[methodlist_itype - ctx->leaf->itype_first]; - - // check valid methodlist - if(range->hdr.kind == CV_LeafKind_METHODLIST && - range->off + range->hdr.size <= data.size) - { - first = data.str + range->off + 2; - cap = range->hdr.size - 2; - } - } - - // emit loop - U64 cursor = 0; - for(;cursor + sizeof(CV_LeafMethodListMember) <= cap;) - { - CV_LeafMethodListMember *method = (CV_LeafMethodListMember*)(first + cursor); - - CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(method->attribs); - - // TODO(allen): PROBLEM - // We only get offsets for virtual functions (the "vbaseoff") from - // "Intro" and "PureIntro". In C++ inheritance, when we have a chain - // of inheritance (let's just talk single inheritance for now) the - // first class in the chain that introduces a new virtual function - // has this "Intro" method. If a later class in the chain redefines - // the virtual function it only has a "Virtual" method which does - // not update the offset. There is a "Virtual" and "PureVirtual" - // variant of "Virtual". The "Pure" in either case means there - // is no concrete procedure. When there is no "Pure" the method - // should have a corresponding procedure symbol id. - // - // The issue is we will want to mark all of our virtual methods as - // virtual and give them an offset, but that means we have to do - // some extra figuring to propogate offsets from "Intro" methods - // to "Virtual" methods in inheritance trees. That is - IF we want - // to start preserving the offsets of virtuals. There is room in - // the method struct to make this work, but for now I've just - // decided to drop this information. It is not urgently useful to - // us and greatly complicates matters. - - // extract vbaseoff - U64 next_cursor = cursor + sizeof(*method); - U32 vbaseoff = 0; - if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) - { - if(cursor + sizeof(*method) + 4 <= cap) - { - vbaseoff = *(U32*)(method + 1); - } - next_cursor += 4; - } - - // update cursor - cursor = next_cursor; - - // TODO(allen): handle attribs - - // emit - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, method->itype); - - switch (prop) - { - default: - { - rdim_type_add_member_method(ctx->root, owner_type, name, mem_type); - }break; - - case CV_MethodProp_Static: - { - rdim_type_add_member_static_method(ctx->root, owner_type, name, mem_type); - }break; - - case CV_MethodProp_Virtual: - case CV_MethodProp_PureVirtual: - case CV_MethodProp_Intro: - case CV_MethodProp_PureIntro: - { - rdim_type_add_member_virtual_method(ctx->root, owner_type, name, mem_type); - }break; - } - } - - } - }break; - - case CV_LeafKind_ONEMETHOD: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafOneMethod) <= cap) - { - // compute whole layout - CV_LeafOneMethod *one_method = (CV_LeafOneMethod*)(first + list_item_off); - - CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(one_method->attribs); - - U64 vbaseoff_off = list_item_off + sizeof(*one_method); - U64 vbaseoff_opl_off = vbaseoff_off; - U32 vbaseoff = 0; - if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) - { - vbaseoff = *(U32*)(first + vbaseoff_off); - vbaseoff_opl_off += sizeof(vbaseoff); - } - - U64 name_off = vbaseoff_opl_off; - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // TODO(allen): handle attribs - - // emit - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, one_method->itype); - - switch (prop) - { - default: - { - rdim_type_add_member_method(ctx->root, owner_type, name, mem_type); - }break; - - case CV_MethodProp_Static: - { - rdim_type_add_member_static_method(ctx->root, owner_type, name, mem_type); - }break; - - case CV_MethodProp_Virtual: - case CV_MethodProp_PureVirtual: - case CV_MethodProp_Intro: - case CV_MethodProp_PureIntro: - { - rdim_type_add_member_virtual_method(ctx->root, owner_type, name, mem_type); - }break; - } - } - }break; - - case CV_LeafKind_NESTTYPE: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafNestType) <= cap) - { - // compute whole layout - CV_LeafNestType *nest_type = (CV_LeafNestType*)(first + list_item_off); - - U64 name_off = list_item_off + sizeof(*nest_type); - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // emit member - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, nest_type->itype); - rdim_type_add_member_nested_type(ctx->root, owner_type, mem_type); - } - }break; - - case CV_LeafKind_NESTTYPEEX: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafNestTypeEx) <= cap) - { - // compute whole layout - CV_LeafNestTypeEx *nest_type = (CV_LeafNestTypeEx*)(first + list_item_off); - - U64 name_off = list_item_off + sizeof(*nest_type); - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // TODO(allen): handle attribs - - // emit member - RDIM_Type *mem_type = p2r_type_resolve_itype(ctx, nest_type->itype); - rdim_type_add_member_nested_type(ctx->root, owner_type, mem_type); - } - }break; - - case CV_LeafKind_BCLASS: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafBClass) <= cap) - { - // compute whole layout - CV_LeafBClass *bclass = (CV_LeafBClass*)(first + list_item_off); - - U64 offset_off = list_item_off + sizeof(*bclass); - CV_NumericParsed offset = cv_numeric_from_data_range(first + offset_off, first + cap); - - list_item_opl_off = offset_off + offset.encoded_size; - - // TODO(allen): handle attribs - - // emit member - RDIM_Type *base_type = p2r_type_resolve_itype(ctx, bclass->itype); - U32 offset_u32 = p2r_u32_from_numeric(ctx, &offset); - rdim_type_add_member_base(ctx->root, owner_type, base_type, offset_u32); - } - }break; - - case CV_LeafKind_VBCLASS: - case CV_LeafKind_IVBCLASS: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafVBClass) <= cap) - { - // compute whole layout - CV_LeafVBClass *vbclass = (CV_LeafVBClass*)(first + list_item_off); - - U64 num1_off = list_item_off + sizeof(*vbclass); - CV_NumericParsed num1 = cv_numeric_from_data_range(first + num1_off, first + cap); - - U64 num2_off = num1_off + num1.encoded_size; - CV_NumericParsed num2 = cv_numeric_from_data_range(first + num2_off, first + cap); - - list_item_opl_off = num2_off + num2.encoded_size; - - // TODO(allen): handle attribs - - // emit member - RDIM_Type *base_type = p2r_type_resolve_itype(ctx, vbclass->itype); - U32 vbptr_offset_u32 = p2r_u32_from_numeric(ctx, &num1); - U32 vtable_offset_u32 = p2r_u32_from_numeric(ctx, &num2); - rdim_type_add_member_virtual_base(ctx->root, owner_type, base_type, - vbptr_offset_u32, vtable_offset_u32); - } - }break; - - // discard cases - we don't currently do anything with these - case CV_LeafKind_VFUNCTAB: - { - // TODO(rjf): error if bad range - if(list_item_off + sizeof(CV_LeafVFuncTab) <= cap) - { - list_item_opl_off = list_item_off + sizeof(CV_LeafVFuncTab); - } - }break; - - // unhandled or invalid cases - default: - { - String8 kind_str = cv_string_from_leaf_kind(field_kind); - rdim_push_msgf(ctx->root, "unhandled/invalid case: equip_members -> %.*s", - str8_varg(kind_str)); - }break; - } - - // update cursor - U64 next_cursor = AlignPow2(list_item_opl_off, 4); - cursor = next_cursor; - } - } - - scratch_end(scratch); -} - -internal void -p2r_type_equip_enumerates(P2R_Ctx *ctx, RDIM_Type *owner_type, CV_TypeId field_itype) -{ - Temp scratch = scratch_begin(0, 0); - - String8 data = ctx->leaf->data; - - // field stack - // TODO(allen): add notes about field tasks - struct FieldTask{ - struct FieldTask *next; - CV_TypeId itype; - }; - struct FieldTask *handled = 0; - struct FieldTask *todo = 0; - { - struct FieldTask *task = push_array(scratch.arena, struct FieldTask, 1); - SLLStackPush(todo, task); - task->itype = field_itype; - } - - for(;;) - { - // exit condition - if(todo == 0) - { - break; - } - - // determine itype - CV_TypeId field_itype = todo->itype; - { - struct FieldTask *task = todo; - SLLStackPop(todo); - SLLStackPush(handled, task); - } - - // get leaf range - // TODO(allen): error if this itype is bad - U8 *first = 0; - U64 cap = 0; - if(ctx->leaf->itype_first <= field_itype && field_itype < ctx->leaf->itype_opl) - { - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[field_itype - ctx->leaf->itype_first]; - // check valid arglist - if(range->hdr.kind == CV_LeafKind_FIELDLIST && - range->off + range->hdr.size <= data.size) - { - first = data.str + range->off + 2; - cap = range->hdr.size - 2; - } - } - - U64 cursor = 0; - for(;cursor + sizeof(CV_LeafKind) <= cap;) - { - CV_LeafKind field_kind = *(CV_LeafKind*)(first + cursor); - - U64 list_item_off = cursor + 2; - // if we hit an error or forget to set next cursor for a case - // default to exiting the loop - U64 list_item_opl_off = cap; - - switch (field_kind) - { - case CV_LeafKind_INDEX: - { - // TODO(allen): error if bad range - if(list_item_off + sizeof(CV_LeafIndex) <= cap) - { - // compute whole layout - CV_LeafIndex *index = (CV_LeafIndex*)(first + list_item_off); - - list_item_opl_off = list_item_off + sizeof(*index); - - // create new todo task - CV_TypeId new_itype = index->itype; - B32 is_new = 1; - for(struct FieldTask *task = handled; - task != 0; - task = task->next) - { - if(task->itype == new_itype) - { - is_new = 0; - break; - } - } - if(is_new) - { - struct FieldTask *task = push_array(scratch.arena, struct FieldTask, 1); - SLLStackPush(todo, task); - task->itype = new_itype; - } - } - }break; - - case CV_LeafKind_ENUMERATE: - { - // compute whole layout - CV_LeafEnumerate *enumerate = (CV_LeafEnumerate*)(first + list_item_off); - - U64 val_off = list_item_off + sizeof(*enumerate); - CV_NumericParsed val = cv_numeric_from_data_range(first + val_off, first + cap); - - U64 name_off = val_off + val.encoded_size; - String8 name = str8_cstring_capped(first + name_off, first + cap); - - list_item_opl_off = name_off + name.size + 1; - - // TODO(allen): handle attribs - - // emit enum val - U64 val_u64 = cv_u64_from_numeric(&val); - rdim_type_add_enum_val(ctx->root, owner_type, name, val_u64); - }break; - - // unhandled or invalid cases - default: - { - String8 kind_str = cv_string_from_leaf_kind(field_kind); - rdim_push_msgf(ctx->root, "unhandled/invalid case: equip_enumerates -> %.*s", - str8_varg(kind_str)); - }break; - } - - // update cursor - U64 next_cursor = AlignPow2(list_item_opl_off, 4); - cursor = next_cursor; - } - } - - scratch_end(scratch); -} - -internal RDIM_Type* -p2r_type_cons_basic(P2R_Ctx *ctx, CV_TypeId itype) -{ - Assert(itype < 0x1000); - - CV_BasicPointerKind basic_ptr_kind = CV_BasicPointerKindFromTypeId(itype); - CV_BasicType basic_type_code = CV_BasicTypeFromTypeId(itype); - - RDIM_Reservation *basic_res = rdim_type_reserve_id(ctx->root, basic_type_code, basic_type_code); - - RDIM_Type *basic_type = 0; - switch (basic_type_code) - { - case CV_BasicType_VOID: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Void, str8_lit("void")); - }break; - - case CV_BasicType_HRESULT: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Handle, str8_lit("HRESULT")); - }break; - - case CV_BasicType_RCHAR: - case CV_BasicType_CHAR: - case CV_BasicType_CHAR8: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Char8, str8_lit("char")); - }break; - - case CV_BasicType_UCHAR: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_UChar8, str8_lit("UCHAR")); - }break; - - case CV_BasicType_WCHAR: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_UChar16, str8_lit("WCHAR")); - }break; - - case CV_BasicType_CHAR16: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Char16, str8_lit("CHAR16")); - }break; - - case CV_BasicType_CHAR32: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Char32, str8_lit("CHAR32")); - }break; - - case CV_BasicType_BOOL8: - case CV_BasicType_INT8: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_S8, str8_lit("S8")); - }break; - - case CV_BasicType_BOOL16: - case CV_BasicType_INT16: - case CV_BasicType_SHORT: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_S16, str8_lit("S16")); - }break; - - case CV_BasicType_BOOL32: - case CV_BasicType_INT32: - case CV_BasicType_LONG: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_S32, str8_lit("S32")); - }break; - - case CV_BasicType_BOOL64: - case CV_BasicType_INT64: - case CV_BasicType_QUAD: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_S64, str8_lit("S64")); - }break; - - case CV_BasicType_INT128: - case CV_BasicType_OCT: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_S128, str8_lit("S128")); - }break; - - case CV_BasicType_UINT8: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_U8, str8_lit("U8")); - }break; - - case CV_BasicType_UINT16: - case CV_BasicType_USHORT: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_U16, str8_lit("U16")); - }break; - - case CV_BasicType_UINT32: - case CV_BasicType_ULONG: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_U32, str8_lit("U32")); - }break; - - case CV_BasicType_UINT64: - case CV_BasicType_UQUAD: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_U64, str8_lit("U64")); - }break; - - case CV_BasicType_UINT128: - case CV_BasicType_UOCT: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_U128, str8_lit("U128")); - }break; - - case CV_BasicType_FLOAT16: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F16, str8_lit("F16")); - }break; - - case CV_BasicType_FLOAT32: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F32, str8_lit("F32")); - }break; - - case CV_BasicType_FLOAT32PP: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F32PP, str8_lit("F32PP")); - }break; - - case CV_BasicType_FLOAT48: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F48, str8_lit("F48")); - }break; - - case CV_BasicType_FLOAT64: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F64, str8_lit("F64")); - }break; - - case CV_BasicType_FLOAT80: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F80, str8_lit("F80")); - }break; - - case CV_BasicType_FLOAT128: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_F128, str8_lit("F128")); - }break; - - case CV_BasicType_COMPLEX32: - { - basic_type = - rdim_type_basic(ctx->root, RDI_TypeKind_ComplexF32, str8_lit("ComplexF32")); - }break; - - case CV_BasicType_COMPLEX64: - { - basic_type = - rdim_type_basic(ctx->root, RDI_TypeKind_ComplexF64, str8_lit("ComplexF64")); - }break; - - case CV_BasicType_COMPLEX80: - { - basic_type = - rdim_type_basic(ctx->root, RDI_TypeKind_ComplexF80, str8_lit("ComplexF80")); - }break; - - case CV_BasicType_COMPLEX128: - { - basic_type = - rdim_type_basic(ctx->root, RDI_TypeKind_ComplexF128, str8_lit("ComplexF128")); - }break; - - case CV_BasicType_PTR: - { - basic_type = rdim_type_basic(ctx->root, RDI_TypeKind_Handle, str8_lit("PTR")); - }break; - } - - // basic resolve - rdim_type_fill_id(ctx->root, basic_res, basic_type); - - // wrap in constructed type - RDIM_Type *constructed_type = 0; - if(basic_ptr_kind != 0 && basic_type != 0) - { - RDIM_Reservation *constructed_res = rdim_type_reserve_id(ctx->root, itype, itype); - - switch (basic_ptr_kind) - { - case CV_BasicPointerKind_16BIT: - case CV_BasicPointerKind_FAR_16BIT: - case CV_BasicPointerKind_HUGE_16BIT: - case CV_BasicPointerKind_32BIT: - case CV_BasicPointerKind_16_32BIT: - case CV_BasicPointerKind_64BIT: - { - constructed_type = rdim_type_pointer(ctx->root, basic_type, RDI_TypeKind_Ptr); - }break; - } - - // constructed resolve - rdim_type_fill_id(ctx->root, constructed_res, constructed_type); - } - - // select output - RDIM_Type *result = basic_type; - if(basic_ptr_kind != 0) - { - result = constructed_type; - } - - return(result); -} - -internal RDIM_Type* -p2r_type_cons_leaf_record(P2R_Ctx *ctx, CV_TypeId itype) -{ - Assert(ctx->leaf->itype_first <= itype && itype < ctx->leaf->itype_opl); - - RDIM_Reservation *res = rdim_type_reserve_id(ctx->root, itype, itype); - - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[itype - ctx->leaf->itype_first]; - String8 data = ctx->leaf->data; - - RDIM_Type *result = 0; - if(range->off + range->hdr.size <= data.size) - { - U8 *first = data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - - switch (range->hdr.kind) - { - case CV_LeafKind_MODIFIER: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafModifier) <= cap) - { - CV_LeafModifier *modifier = (CV_LeafModifier*)first; - - RDI_TypeModifierFlags flags = 0; - if(modifier->flags & CV_ModifierFlag_Const) - { - flags |= RDI_TypeModifierFlag_Const; - } - if(modifier->flags & CV_ModifierFlag_Volatile) - { - flags |= RDI_TypeModifierFlag_Volatile; - } - - RDIM_Type *direct_type = p2r_type_resolve_and_check(ctx, modifier->itype); - if(flags != 0) - { - result = rdim_type_modifier(ctx->root, direct_type, flags); - } - else - { - result = direct_type; - } - } - }break; - - case CV_LeafKind_POINTER: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafPointer) <= cap) - { - CV_LeafPointer *pointer = (CV_LeafPointer*)first; - - CV_PointerKind ptr_kind = CV_PointerAttribs_ExtractKind(pointer->attribs); - CV_PointerMode ptr_mode = CV_PointerAttribs_ExtractMode(pointer->attribs); - U32 ptr_size = CV_PointerAttribs_ExtractSize(pointer->attribs); - - // TODO(allen): if ptr_mode in {PtrMem, PtrMethod} then output a member pointer instead - - // extract modifier flags - RDI_TypeModifierFlags modifier_flags = 0; - if(pointer->attribs & CV_PointerAttrib_Const) - { - modifier_flags |= RDI_TypeModifierFlag_Const; - } - if(pointer->attribs & CV_PointerAttrib_Volatile) - { - modifier_flags |= RDI_TypeModifierFlag_Volatile; - } - - // determine type kind - RDI_TypeKind type_kind = RDI_TypeKind_Ptr; - if(pointer->attribs & CV_PointerAttrib_LRef) - { - type_kind = RDI_TypeKind_LRef; - } - else if(pointer->attribs & CV_PointerAttrib_RRef) - { - type_kind = RDI_TypeKind_RRef; - } - if(ptr_mode == CV_PointerMode_LRef) - { - type_kind = RDI_TypeKind_LRef; - } - else if(ptr_mode == CV_PointerMode_RRef) - { - type_kind = RDI_TypeKind_RRef; - } - - RDIM_Type *direct_type = p2r_type_resolve_and_check(ctx, pointer->itype); - RDIM_Type *ptr_type = rdim_type_pointer(ctx->root, direct_type, type_kind); - - result = ptr_type; - if(modifier_flags != 0) - { - result = rdim_type_modifier(ctx->root, ptr_type, modifier_flags); - } - } - }break; - - case CV_LeafKind_PROCEDURE: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafProcedure) <= cap) - { - CV_LeafProcedure *procedure = (CV_LeafProcedure*)first; - - Temp scratch = scratch_begin(0, 0); - - // TODO(allen): handle call_kind & attribs - - RDIM_Type *ret_type = p2r_type_resolve_and_check(ctx, procedure->ret_itype); - - RDIM_TypeList param_list = {0}; - p2r_type_resolve_arglist(scratch.arena, ¶m_list, ctx, procedure->arg_itype); - - result = rdim_type_proc(ctx->root, ret_type, ¶m_list); - - scratch_end(scratch); - } - }break; - - case CV_LeafKind_MFUNCTION: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafMFunction) <= cap) - { - CV_LeafMFunction *mfunction = (CV_LeafMFunction*)first; - - Temp scratch = scratch_begin(0, 0); - - // TODO(allen): handle call_kind & attribs - // TODO(allen): preserve "this_adjust" - - RDIM_Type *ret_type = p2r_type_resolve_and_check(ctx, mfunction->ret_itype); - - RDIM_TypeList param_list = {0}; - p2r_type_resolve_arglist(scratch.arena, ¶m_list, ctx, mfunction->arg_itype); - - RDIM_Type *this_type = 0; - if(mfunction->this_itype != 0) - { - this_type = p2r_type_resolve_and_check(ctx, mfunction->this_itype); - result = rdim_type_method(ctx->root, this_type, ret_type, ¶m_list); - } - else - { - result = rdim_type_proc(ctx->root, ret_type, ¶m_list); - } - - scratch_end(scratch); - } - }break; - - case CV_LeafKind_BITFIELD: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafBitField) <= cap) - { - CV_LeafBitField *bit_field = (CV_LeafBitField*)first; - RDIM_Type *direct_type = p2r_type_resolve_and_check(ctx, bit_field->itype); - result = rdim_type_bitfield(ctx->root, direct_type, bit_field->pos, bit_field->len); - } - }break; - - case CV_LeafKind_ARRAY: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafArray) <= cap) - { - CV_LeafArray *array = (CV_LeafArray*)first; - - // parse count - U8 *numeric_ptr = (U8*)(array + 1); - CV_NumericParsed array_count = cv_numeric_from_data_range(numeric_ptr, first + cap); - - U64 full_size = cv_u64_from_numeric(&array_count); - - RDIM_Type *direct_type = p2r_type_resolve_and_check(ctx, array->entry_itype); - U64 count = full_size; - if(direct_type != 0 && direct_type->byte_size != 0) - { - count /= direct_type->byte_size; - } - - // build type - result = rdim_type_array(ctx->root, direct_type, count); - } - }break; - - case CV_LeafKind_CLASS: - case CV_LeafKind_STRUCTURE: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafStruct) <= cap) - { - CV_LeafStruct *lf_struct = (CV_LeafStruct*)first; - - // TODO(allen): handle props - - // size - U8 *numeric_ptr = (U8*)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - U64 size_u64 = cv_u64_from_numeric(&size); - - // name - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // incomplete type - if(lf_struct->props & CV_TypeProp_FwdRef) - { - RDI_TypeKind type_kind = RDI_TypeKind_IncompleteStruct; - if(range->hdr.kind == CV_LeafKind_CLASS) - { - type_kind = RDI_TypeKind_IncompleteClass; - } - result = rdim_type_incomplete(ctx->root, type_kind, name); - } - - // complete type - else - { - RDI_TypeKind type_kind = RDI_TypeKind_Struct; - if(range->hdr.kind == CV_LeafKind_CLASS) - { - type_kind = RDI_TypeKind_Class; - } - result = rdim_type_udt(ctx->root, type_kind, name, size_u64); - - // remember to revisit this for members - { - P2R_TypeRev *rev = push_array(ctx->arena, P2R_TypeRev, 1); - rev->owner_type = result; - rev->field_itype = lf_struct->field_itype; - SLLQueuePush(ctx->member_revisit_first, ctx->member_revisit_last, rev); - } - } - } - }break; - - case CV_LeafKind_CLASS2: - case CV_LeafKind_STRUCT2: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafStruct2) <= cap) - { - CV_LeafStruct2 *lf_struct = (CV_LeafStruct2*)first; - - // TODO(allen): handle props - - // size - U8 *numeric_ptr = (U8*)(lf_struct + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - U64 size_u64 = cv_u64_from_numeric(&size); - - // name - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // incomplete type - if(lf_struct->props & CV_TypeProp_FwdRef) - { - RDI_TypeKind type_kind = RDI_TypeKind_IncompleteStruct; - if(range->hdr.kind == CV_LeafKind_CLASS2) - { - type_kind = RDI_TypeKind_IncompleteClass; - } - result = rdim_type_incomplete(ctx->root, type_kind, name); - } - - // complete type - else - { - RDI_TypeKind type_kind = RDI_TypeKind_Struct; - if(range->hdr.kind == CV_LeafKind_CLASS2) - { - type_kind = RDI_TypeKind_Class; - } - result = rdim_type_udt(ctx->root, type_kind, name, size_u64); - - // remember to revisit this for members - { - P2R_TypeRev *rev = push_array(ctx->arena, P2R_TypeRev, 1); - rev->owner_type = result; - rev->field_itype = lf_struct->field_itype; - SLLQueuePush(ctx->member_revisit_first, ctx->member_revisit_last, rev); - } - } - } - }break; - - case CV_LeafKind_UNION: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafUnion) <= cap) - { - CV_LeafUnion *lf_union = (CV_LeafUnion*)first; - - // TODO(allen): handle props - - // size - U8 *numeric_ptr = (U8*)(lf_union + 1); - CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); - U64 size_u64 = cv_u64_from_numeric(&size); - - // name - U8 *name_ptr = numeric_ptr + size.encoded_size; - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // incomplete type - if(lf_union->props & CV_TypeProp_FwdRef) - { - result = - rdim_type_incomplete(ctx->root, RDI_TypeKind_IncompleteUnion, name); - } - - // complete type - else - { - result = rdim_type_udt(ctx->root, RDI_TypeKind_Union, name, size_u64); - - // remember to revisit this for members - { - P2R_TypeRev *rev = push_array(ctx->arena, P2R_TypeRev, 1); - rev->owner_type = result; - rev->field_itype = lf_union->field_itype; - SLLQueuePush(ctx->member_revisit_first, ctx->member_revisit_last, rev); - } - } - } - }break; - - case CV_LeafKind_ENUM: - { - // TODO(allen): error if bad range - if(sizeof(CV_LeafEnum) <= cap) - { - CV_LeafEnum *lf_enum = (CV_LeafEnum*)first; - - // TODO(allen): handle props - - // name - U8 *name_ptr = (U8*)(lf_enum + 1); - String8 name = str8_cstring_capped((char*)name_ptr, first + cap); - - // incomplete type - if(lf_enum->props & CV_TypeProp_FwdRef) - { - result = rdim_type_incomplete(ctx->root, RDI_TypeKind_IncompleteEnum, name); - } - - // complete type - else - { - RDIM_Type *direct_type = p2r_type_resolve_and_check(ctx, lf_enum->base_itype); - result = rdim_type_enum(ctx->root, direct_type, name); - - // remember to revisit this for enumerates - { - P2R_TypeRev *rev = push_array(ctx->arena, P2R_TypeRev, 1); - rev->owner_type = result; - rev->field_itype = lf_enum->field_itype; - SLLQueuePush(ctx->enum_revisit_first, ctx->enum_revisit_last, rev); - } - } - } - }break; - - // discard cases - we currently discard these these intentionally - // so we mark them as "handled nil" - case CV_LeafKind_VTSHAPE: - case CV_LeafKind_VFTABLE: - case CV_LeafKind_LABEL: - { - result = rdim_type_handled_nil(ctx->root); - }break; - - // do nothing cases - these get handled in special passes and - // they should not be appearing as direct types - // or parameter types for any other types - // so if the input data is valid we won't get - // error messages even if they resolve to nil - case CV_LeafKind_FIELDLIST: - case CV_LeafKind_ARGLIST: - case CV_LeafKind_METHODLIST: - {}break; - - // Leaf Kinds - case CV_LeafKind_MODIFIER_16t: - case CV_LeafKind_POINTER_16t: - case CV_LeafKind_ARRAY_16t: - case CV_LeafKind_CLASS_16t: - case CV_LeafKind_STRUCTURE_16t: - case CV_LeafKind_UNION_16t: - case CV_LeafKind_ENUM_16t: - case CV_LeafKind_PROCEDURE_16t: - case CV_LeafKind_MFUNCTION_16t: - //case CV_LeafKind_VTSHAPE: - case CV_LeafKind_COBOL0_16t: - case CV_LeafKind_COBOL1: - case CV_LeafKind_BARRAY_16t: - //case CV_LeafKind_LABEL: - case CV_LeafKind_NULL: - case CV_LeafKind_NOTTRAN: - case CV_LeafKind_DIMARRAY_16t: - case CV_LeafKind_VFTPATH_16t: - case CV_LeafKind_PRECOMP_16t: - case CV_LeafKind_ENDPRECOMP: - case CV_LeafKind_OEM_16t: - case CV_LeafKind_TYPESERVER_ST: - case CV_LeafKind_SKIP_16t: - case CV_LeafKind_ARGLIST_16t: - case CV_LeafKind_DEFARG_16t: - case CV_LeafKind_LIST: - case CV_LeafKind_FIELDLIST_16t: - case CV_LeafKind_DERIVED_16t: - case CV_LeafKind_BITFIELD_16t: - case CV_LeafKind_METHODLIST_16t: - case CV_LeafKind_DIMCONU_16t: - case CV_LeafKind_DIMCONLU_16t: - case CV_LeafKind_DIMVARU_16t: - case CV_LeafKind_DIMVARLU_16t: - case CV_LeafKind_REFSYM: - case CV_LeafKind_BCLASS_16t: - case CV_LeafKind_VBCLASS_16t: - case CV_LeafKind_IVBCLASS_16t: - case CV_LeafKind_ENUMERATE_ST: - case CV_LeafKind_FRIENDFCN_16t: - case CV_LeafKind_INDEX_16t: - case CV_LeafKind_MEMBER_16t: - case CV_LeafKind_STMEMBER_16t: - case CV_LeafKind_METHOD_16t: - case CV_LeafKind_NESTTYPE_16t: - case CV_LeafKind_VFUNCTAB_16t: - case CV_LeafKind_FRIENDCLS_16t: - case CV_LeafKind_ONEMETHOD_16t: - case CV_LeafKind_VFUNCOFF_16t: - case CV_LeafKind_TI16_MAX: - //case CV_LeafKind_MODIFIER: - //case CV_LeafKind_POINTER: - case CV_LeafKind_ARRAY_ST: - case CV_LeafKind_CLASS_ST: - case CV_LeafKind_STRUCTURE_ST: - case CV_LeafKind_UNION_ST: - case CV_LeafKind_ENUM_ST: - //case CV_LeafKind_PROCEDURE: - //case CV_LeafKind_MFUNCTION: - case CV_LeafKind_COBOL0: - case CV_LeafKind_BARRAY: - case CV_LeafKind_DIMARRAY_ST: - case CV_LeafKind_VFTPATH: - case CV_LeafKind_PRECOMP_ST: - case CV_LeafKind_OEM: - case CV_LeafKind_ALIAS_ST: - case CV_LeafKind_OEM2: - case CV_LeafKind_SKIP: - //case CV_LeafKind_ARGLIST: - case CV_LeafKind_DEFARG_ST: - //case CV_LeafKind_FIELDLIST: - case CV_LeafKind_DERIVED: - //case CV_LeafKind_BITFIELD: - //case CV_LeafKind_METHODLIST: - case CV_LeafKind_DIMCONU: - case CV_LeafKind_DIMCONLU: - case CV_LeafKind_DIMVARU: - case CV_LeafKind_DIMVARLU: - case CV_LeafKind_BCLASS: - case CV_LeafKind_VBCLASS: - case CV_LeafKind_IVBCLASS: - case CV_LeafKind_FRIENDFCN_ST: - case CV_LeafKind_INDEX: - case CV_LeafKind_MEMBER_ST: - case CV_LeafKind_STMEMBER_ST: - case CV_LeafKind_METHOD_ST: - case CV_LeafKind_NESTTYPE_ST: - case CV_LeafKind_VFUNCTAB: - case CV_LeafKind_FRIENDCLS: - case CV_LeafKind_ONEMETHOD_ST: - case CV_LeafKind_VFUNCOFF: - case CV_LeafKind_NESTTYPEEX_ST: - case CV_LeafKind_MEMBERMODIFY_ST: - case CV_LeafKind_MANAGED_ST: - case CV_LeafKind_ST_MAX: - case CV_LeafKind_TYPESERVER: - case CV_LeafKind_ENUMERATE: - //case CV_LeafKind_ARRAY: - //case CV_LeafKind_CLASS: - //case CV_LeafKind_STRUCTURE: - //case CV_LeafKind_UNION: - //case CV_LeafKind_ENUM: - case CV_LeafKind_DIMARRAY: - case CV_LeafKind_PRECOMP: - case CV_LeafKind_ALIAS: - case CV_LeafKind_DEFARG: - case CV_LeafKind_FRIENDFCN: - case CV_LeafKind_MEMBER: - case CV_LeafKind_STMEMBER: - case CV_LeafKind_METHOD: - case CV_LeafKind_NESTTYPE: - case CV_LeafKind_ONEMETHOD: - case CV_LeafKind_NESTTYPEEX: - case CV_LeafKind_MEMBERMODIFY: - case CV_LeafKind_MANAGED: - case CV_LeafKind_TYPESERVER2: - case CV_LeafKind_STRIDED_ARRAY: - case CV_LeafKind_HLSL: - case CV_LeafKind_MODIFIER_EX: - case CV_LeafKind_INTERFACE: - case CV_LeafKind_BINTERFACE: - case CV_LeafKind_VECTOR: - case CV_LeafKind_MATRIX: - //case CV_LeafKind_VFTABLE: - default: - { - String8 kind_str = cv_string_from_leaf_kind(range->hdr.kind); - rdim_push_msgf(ctx->root, "pdbconv: unhandled leaf case %.*s (0x%x)", - str8_varg(kind_str), range->hdr.kind); - }break; - } - } - - rdim_type_fill_id(ctx->root, res, result); - - return(result); -} - -internal RDIM_Type* -p2r_type_resolve_and_check(P2R_Ctx *ctx, CV_TypeId itype) -{ - RDIM_Type *result = p2r_type_resolve_itype(ctx, itype); - if(rdim_type_is_unhandled_nil(ctx->root, result)) - { - rdim_push_msgf(ctx->root, "pdbconv: could not resolve itype (itype = %u)", itype); - } - return(result); -} - -internal void -p2r_type_resolve_arglist(Arena *arena, RDIM_TypeList *out, - P2R_Ctx *ctx, CV_TypeId arglist_itype) -{ - ProfBeginFunction(); - - // get leaf range - if(ctx->leaf->itype_first <= arglist_itype && arglist_itype < ctx->leaf->itype_opl) - { - CV_RecRange *range = &ctx->leaf->leaf_ranges.ranges[arglist_itype - ctx->leaf->itype_first]; - - // check valid arglist - String8 data = ctx->leaf->data; - if(range->hdr.kind == CV_LeafKind_ARGLIST && - range->off + range->hdr.size <= data.size) - { - U8 *first = data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - if(sizeof(CV_LeafArgList) <= cap) - { - - // resolve parameters - CV_LeafArgList *arglist = (CV_LeafArgList*)first; - CV_TypeId *itypes = (CV_TypeId*)(arglist + 1); - U32 max_count = (cap - sizeof(*arglist))/sizeof(CV_TypeId); - U32 clamped_count = ClampTop(arglist->count, max_count); - for(U32 i = 0; i < clamped_count; i += 1) - { - RDIM_Type *param_type = p2r_type_resolve_and_check(ctx, itypes[i]); - rdim_type_list_push(arena, out, param_type); - } - - } - } - } - - ProfEnd(); -} - -internal RDIM_Type* -p2r_type_from_name(P2R_Ctx *ctx, String8 name) -{ - // TODO(rjf): no idea if this is correct - CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(ctx->hash, ctx->leaf, name, 0); - RDIM_Type *result = rdim_type_from_id(ctx->root, cv_type_id, cv_type_id); - return(result); -} - -internal void -p2r_type_fwd_map_set(Arena *arena, P2R_FwdMap *map, CV_TypeId key, CV_TypeId val) -{ - U64 bucket_idx = key%map->buckets_count; - - // search for an existing match - P2R_FwdNode *match = 0; - for(P2R_FwdNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->key == key) - { - match = node; - break; - } - } - - // create a new node if no match - if(match == 0) - { - match = push_array(arena, P2R_FwdNode, 1); - SLLStackPush(map->buckets[bucket_idx], match); - match->key = key; - map->pair_count += 1; - map->bucket_collision_count += (match->next != 0); - } - - // set node's val - match->val = val; -} - -internal CV_TypeId -p2r_type_fwd_map_get(P2R_FwdMap *map, CV_TypeId key) -{ - U64 bucket_idx = key%map->buckets_count; - - // search for an existing match - P2R_FwdNode *match = 0; - for(P2R_FwdNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->key == key) - { - match = node; - break; - } - } - - // extract result - CV_TypeId result = 0; - if(match != 0) - { - result = match->val; - } - - return(result); -} - -//- symbols - -internal U64 -p2r_hash_from_local_user_id(U64 sym_hash, U64 id) -{ - U64 hash = id ^ (sym_hash<<1) ^ (sym_hash<<4); - return hash; -} - -internal U64 -p2r_hash_from_scope_user_id(U64 sym_hash, U64 id) -{ - U64 hash = id ^ (sym_hash<<1) ^ (sym_hash<<4); - return hash; -} - -internal U64 -p2r_hash_from_symbol_user_id(U64 sym_hash, U64 id) -{ - U64 hash = id/8 + id ^ (sym_hash<<1) ^ (sym_hash<<4); - return hash; -} - -internal void -p2r_symbol_cons(P2R_Ctx *ctx, CV_SymParsed *sym, U32 sym_unique_id) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - String8 data = sym->data; - U64 user_id_base = (((U64)sym_unique_id) << 32); - U64 sym_unique_id_hash = rdi_hash((U8*)&sym_unique_id, sizeof(sym_unique_id)); - - ////////////////////////////// - //- rjf: PASS 1: map out data associations - // - ProfScope("map out data associations") - { - RDIM_Symbol *current_proc = 0; - CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges; - CV_RecRange *rec_ranges_opl = rec_ranges_first + sym->sym_ranges.count; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: rec range -> symbol info range - U64 sym_off_first = rec_range->off + 2; - U64 sym_off_opl = rec_range->off + rec_range->hdr.size; - - //- rjf: skip invalid ranges - if(sym_off_opl > data.size || sym_off_first > data.size || sym_off_first > sym_off_opl) - { - continue; - } - - //- rjf: unpack symbol info - CV_SymKind kind = rec_range->hdr.kind; - U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = data.str + sym_off_first; - - //- rjf: skip bad sizes - if(sym_off_first + sym_header_struct_size > sym_off_opl) - { - continue; - } - - //- rjf: consume symbol based on kind - switch(kind) - { - default:{}break; - - //- rjf: FRAMEPROC - case CV_SymKind_FRAMEPROC: - { - if(current_proc == 0) { break; } - CV_SymFrameproc *frameproc = (CV_SymFrameproc*)sym_header_struct_base; - P2R_FrameProcData data = {0}; - data.frame_size = frameproc->frame_size; - data.flags = frameproc->flags; - p2r_symbol_frame_proc_write(ctx, current_proc, &data); - }break; - - //- rjf: LPROC32/GPROC32 - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: - { - U64 symbol_id = user_id_base + sym_off_first; - U64 symbol_hash = p2r_hash_from_symbol_user_id(sym_unique_id_hash, symbol_id); - current_proc = rdim_symbol_handle_from_user_id(ctx->root, symbol_id, symbol_hash); - }break; - } - } - } - - ////////////////////////////// - //- rjf: PASS 2: main symbol construction pass - // - ProfScope("main symbol construction pass") - { - RDIM_LocationSet *defrange_target = 0; - B32 defrange_target_is_param = 0; - U64 local_num = 1; - U64 scope_num = 1; - CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges; - CV_RecRange *rec_ranges_opl = rec_ranges_first + sym->sym_ranges.count; - for(CV_RecRange *rec_range = rec_ranges_first; - rec_range < rec_ranges_opl; - rec_range += 1) - { - //- rjf: rec range -> symbol info range - U64 sym_off_first = rec_range->off + 2; - U64 sym_off_opl = rec_range->off + rec_range->hdr.size; - - //- rjf: skip invalid ranges - if(sym_off_opl > data.size || sym_off_first > data.size || sym_off_first > sym_off_opl) - { - continue; - } - - //- rjf: unpack symbol info - CV_SymKind kind = rec_range->hdr.kind; - U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = data.str + sym_off_first; - void *sym_data_opl = data.str + sym_off_opl; - - //- rjf: skip bad sizes - if(sym_off_first + sym_header_struct_size > sym_off_opl) - { - continue; - } - - //- rjf: unpack current state - RDIM_Scope *current_scope = p2r_symbol_current_scope(ctx); - RDIM_Symbol *current_procedure = 0; - if(current_scope != 0) - { - current_procedure = current_scope->symbol; - } - - //- rjf: consume symbol based on kind - switch(kind) - { - default:{}break; - - //- rjf: END - case CV_SymKind_END: - { - p2r_symbol_pop_scope(ctx); - defrange_target = 0; - defrange_target_is_param = 0; - }break; - - //- rjf: BLOCK32 - case CV_SymKind_BLOCK32: - { - CV_SymBlock32 *block32 = (CV_SymBlock32*)sym_header_struct_base; - - // scope - U64 scope_id = user_id_base + scope_num; - scope_num += 1; - U64 scope_hash = p2r_hash_from_scope_user_id(sym_unique_id_hash, scope_id); - RDIM_Scope *block_scope = rdim_scope_handle_from_user_id(ctx->root, scope_id, scope_hash); - rdim_scope_set_parent(ctx->root, block_scope, current_scope); - p2r_symbol_push_scope(ctx, block_scope, current_procedure); - - // set voff range - COFF_SectionHeader *section = p2r_sec_header_from_sec_num(ctx, block32->sec); - if(section != 0) - { - U64 voff_first = section->voff + block32->off; - U64 voff_last = voff_first + block32->len; - rdim_scope_add_voff_range(ctx->root, block_scope, voff_first, voff_last); - } - }break; - - //- rjf: LDATA32/GDATA32 - case CV_SymKind_LDATA32: - case CV_SymKind_GDATA32: - { - CV_SymData32 *data32 = (CV_SymData32*)sym_header_struct_base; - String8 name = str8_cstring_capped(data32+1, sym_data_opl); - - // determine voff - COFF_SectionHeader *section = p2r_sec_header_from_sec_num(ctx, data32->sec); - U64 voff = ((section != 0)?section->voff:0) + data32->off; - - // deduplicate global variable symbols with the same name & offset - // * PDB likes to have duplicates of these spread across - // * different symbol streams so we deduplicate across the - // * entire translation context. - if(!p2r_known_global_lookup(&ctx->known_globals, name, voff)) - { - p2r_known_global_insert(ctx->arena, &ctx->known_globals, name, voff); - - // type of variable - RDIM_Type *type = p2r_type_resolve_itype(ctx, data32->itype); - - // container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2) - { - String8 container_name = str8(name.str, container_name_opl - 2); - container_type = p2r_type_from_name(ctx, container_name); - } - - // container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0) - { - container_symbol = current_procedure; - } - - // determine link kind - B32 is_extern = (kind == CV_SymKind_GDATA32); - - // cons this symbol - U64 symbol_id = user_id_base + sym_off_first; - U64 symbol_hash = p2r_hash_from_symbol_user_id(sym_unique_id_hash, symbol_id); - RDIM_Symbol *symbol = rdim_symbol_handle_from_user_id(ctx->root, symbol_id, symbol_hash); - - RDIM_SymbolInfo info = zero_struct; - info.kind = RDIM_SymbolKind_GlobalVariable; - info.name = name; - info.type = type; - info.is_extern = is_extern; - info.offset = voff; - info.container_type = container_type; - info.container_symbol = container_symbol; - - rdim_symbol_set_info(ctx->root, symbol, &info); - } - }break; - - //- rjf: LPROC32/GPROC32 - case CV_SymKind_LPROC32: - case CV_SymKind_GPROC32: - { - CV_SymProc32 *proc32 = (CV_SymProc32*)sym_header_struct_base; - String8 name = str8_cstring_capped(proc32+1, sym_data_opl); - RDIM_Type *type = p2r_type_resolve_itype(ctx, proc32->itype); - - // container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2) - { - String8 container_name = str8(name.str, container_name_opl - 2); - container_type = p2r_type_from_name(ctx, container_name); - } - - // container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0) - { - container_symbol = current_procedure; - } - - // get this symbol handle - U64 symbol_id = user_id_base + sym_off_first; - U64 symbol_hash = p2r_hash_from_symbol_user_id(sym_unique_id_hash, symbol_id); - RDIM_Symbol *proc_symbol = rdim_symbol_handle_from_user_id(ctx->root, symbol_id, symbol_hash); - - // scope - - // NOTE: even if there could be a containing scope at this point (which should be - // illegal in C/C++ but not necessarily in another language) we would not pass - // it here because these scopes refer to the ranges of code that make up a - // procedure *not* the namespaces, so a procedure's root scope always has - // no parent. - U64 scope_id = user_id_base + scope_num; - U64 scope_hash = p2r_hash_from_scope_user_id(sym_unique_id_hash, scope_id); - RDIM_Scope *root_scope = rdim_scope_handle_from_user_id(ctx->root, scope_id, scope_hash); - p2r_symbol_push_scope(ctx, root_scope, proc_symbol); - scope_num += 1; - - // set voff range - U64 voff = 0; - COFF_SectionHeader *section = p2r_sec_header_from_sec_num(ctx, proc32->sec); - if(section != 0) - { - U64 voff_first = section->voff + proc32->off; - U64 voff_last = voff_first + proc32->len; - rdim_scope_add_voff_range(ctx->root, root_scope, voff_first, voff_last); - - voff = voff_first; - } - - // link name - String8 link_name = {0}; - if(voff != 0) - { - link_name = p2r_link_name_find(&ctx->link_names, voff); - } - - // determine link kind - B32 is_extern = (kind == CV_SymKind_GPROC32); - - // set symbol info - RDIM_SymbolInfo info = zero_struct; - info.kind = RDIM_SymbolKind_Procedure; - info.name = name; - info.link_name = link_name; - info.type = type; - info.is_extern = is_extern; - info.container_type = container_type; - info.container_symbol = container_symbol; - info.root_scope = root_scope; - - rdim_symbol_set_info(ctx->root, proc_symbol, &info); - }break; - - //- rjf: REGREL32 - case CV_SymKind_REGREL32: - { - // TODO(allen): hide this when it's redundant with better information - // from a CV_SymKind_LOCAL record. - - CV_SymRegrel32 *regrel32 = (CV_SymRegrel32*)sym_header_struct_base; - String8 name = str8_cstring_capped(regrel32+1, sym_data_opl); - RDIM_Type *type = p2r_type_resolve_itype(ctx, regrel32->itype); - - // extract regrel's info - CV_Reg cv_reg = regrel32->reg; - U32 var_off = regrel32->reg_off; - - // need arch for analyzing register stuff - RDI_Arch arch = ctx->arch; - U64 addr_size = ctx->addr_size; - - // determine if this is a parameter - RDI_LocalKind local_kind = RDI_LocalKind_Variable; - { - B32 is_stack_reg = 0; - switch (arch) - { - case RDI_Arch_X86: is_stack_reg = (cv_reg == CV_Regx86_ESP); break; - case RDI_Arch_X64: is_stack_reg = (cv_reg == CV_Regx64_RSP); break; - } - if(is_stack_reg) - { - U32 frame_size = 0xFFFFFFFF; - if(current_procedure != 0) - { - P2R_FrameProcData *frameproc = - p2r_symbol_frame_proc_read(ctx, current_procedure); - frame_size = frameproc->frame_size; - } - if(var_off > frame_size) - { - local_kind = RDI_LocalKind_Parameter; - } - } - } - - // emit local - U64 local_id = user_id_base + local_num;; - U64 local_id_hash = p2r_hash_from_local_user_id(sym_unique_id_hash, local_id); - RDIM_Local *local_var = rdim_local_handle_from_user_id(ctx->root, local_id, local_id_hash); - local_num += 1; - - RDIM_LocalInfo info = {0}; - info.kind = local_kind; - info.scope = current_scope; - info.name = name; - info.type = type; - rdim_local_set_basic_info(ctx->root, local_var, &info); - - // add location to local - { - // will there be an extra indirection to the value - B32 extra_indirection_to_value = 0; - switch (arch) - { - case RDI_Arch_X86: - { - if(local_kind == RDI_LocalKind_Parameter && - (type->byte_size > 4 || !IsPow2OrZero(type->byte_size))) - { - extra_indirection_to_value = 1; - } - }break; - - case RDI_Arch_X64: - { - if(local_kind == RDI_LocalKind_Parameter && - (type->byte_size > 8 || !IsPow2OrZero(type->byte_size))) - { - extra_indirection_to_value = 1; - } - }break; - } - - // get raddbg register code - RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg); - // TODO(allen): real byte_size & byte_pos from cv_reg goes here - U32 byte_size = 8; - U32 byte_pos = 0; - - // set location case - RDIM_Location *loc = - p2r_location_from_addr_reg_off(ctx, register_code, byte_size, byte_pos, - (S64)(S32)var_off, extra_indirection_to_value); - - RDIM_LocationSet *locset = rdim_location_set_from_local(ctx->root, local_var); - rdim_location_set_add_case(ctx->root, locset, 0, max_U64, loc); - } - }break; - - //- rjf: LTHREAD32/GTHREAD32 - case CV_SymKind_LTHREAD32: - case CV_SymKind_GTHREAD32: - { - CV_SymThread32 *thread32 = (CV_SymThread32*)sym_header_struct_base; - String8 name = str8_cstring_capped(thread32+1, sym_data_opl); - U32 tls_off = thread32->tls_off; - RDIM_Type *type = p2r_type_resolve_itype(ctx, thread32->itype); - - // container type - RDIM_Type *container_type = 0; - U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); - if(container_name_opl > 2) - { - String8 container_name = str8(name.str, container_name_opl - 2); - container_type = p2r_type_from_name(ctx, container_name); - } - - // container symbol - RDIM_Symbol *container_symbol = 0; - if(container_type == 0) - { - container_symbol = current_procedure; - } - - // determine link kind - B32 is_extern = (kind == CV_SymKind_GTHREAD32); - - // setup symbol - U64 symbol_id = user_id_base + sym_off_first; - U64 symbol_hash = p2r_hash_from_symbol_user_id(sym_unique_id_hash, symbol_id); - RDIM_Symbol *symbol = rdim_symbol_handle_from_user_id(ctx->root, symbol_id, symbol_hash); - - RDIM_SymbolInfo info = zero_struct; - info.kind = RDIM_SymbolKind_ThreadVariable; - info.name = name; - info.type = type; - info.is_extern = is_extern; - info.offset = tls_off; - info.container_type = container_type; - info.container_symbol = container_symbol; - - rdim_symbol_set_info(ctx->root, symbol, &info); - }break; - - //- rjf: LOCAL - case CV_SymKind_LOCAL: - { - CV_SymLocal *slocal = (CV_SymLocal*)sym_header_struct_base; - String8 name = str8_cstring_capped(slocal+1, sym_data_opl); - RDIM_Type *type = p2r_type_resolve_itype(ctx, slocal->itype); - - // determine how to handle - B32 begin_a_global_modification = 0; - if((slocal->flags & CV_LocalFlag_Global) || - (slocal->flags & CV_LocalFlag_Static)) - { - begin_a_global_modification = 1; - } - - // emit a global modification - if(begin_a_global_modification) - { - // TODO(allen): add global modification symbols - defrange_target = 0; - defrange_target_is_param = 0; - } - - // emit a local variable - else - { - // local kind - RDI_LocalKind local_kind = RDI_LocalKind_Variable; - if(slocal->flags & CV_LocalFlag_Param) - { - local_kind = RDI_LocalKind_Parameter; - } - - // emit local - U64 local_id = user_id_base + local_num; - U64 local_id_hash = p2r_hash_from_local_user_id(sym_unique_id_hash, local_id); - RDIM_Local *local_var = rdim_local_handle_from_user_id(ctx->root, local_id, local_id_hash); - local_num += 1; - local_var->kind = local_kind; - local_var->name = name; - local_var->type = type; - - RDIM_LocalInfo info = {0}; - info.kind = local_kind; - info.scope = current_scope; - info.name = name; - info.type = type; - rdim_local_set_basic_info(ctx->root, local_var, &info); - - defrange_target = rdim_location_set_from_local(ctx->root, local_var); - defrange_target_is_param = (local_kind == RDI_LocalKind_Parameter); - } - }break; - - //- rjf: DEFRANGE_REGISTESR - case CV_SymKind_DEFRANGE_REGISTER: - { - if(defrange_target == 0) { break; } - CV_SymDefrangeRegister *defrange_register = (CV_SymDefrangeRegister*)sym_header_struct_base; - - // TODO(allen): offset & size from cv_reg code - RDI_Arch arch = ctx->arch; - CV_Reg cv_reg = defrange_register->reg; - RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg); - - // setup location - RDIM_Location *location = rdim_location_val_reg(ctx->root, register_code); - - // extract range info - CV_LvarAddrRange *range = &defrange_register->range; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register+1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // emit locations - p2r_location_over_lvar_addr_range(ctx, defrange_target, location, - range, gaps, gap_count); - }break; - - //- rjf: DEFRANGE_FRAMEPOINTER_REL - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: - { - if(defrange_target == 0) { break; } - CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel*)sym_header_struct_base; - - // select frame pointer register - CV_EncodedFramePtrReg encoded_fp_reg = - p2r_cv_encoded_fp_reg_from_proc(ctx, current_procedure, defrange_target_is_param); - RDI_RegisterCode fp_register_code = - p2r_reg_code_from_arch_encoded_fp_reg(ctx->arch, encoded_fp_reg); - - // setup location - B32 extra_indirection = 0; - U32 byte_size = ctx->addr_size; - U32 byte_pos = 0; - S64 var_off = (S64)defrange_fprel->off; - RDIM_Location *location = - p2r_location_from_addr_reg_off(ctx, fp_register_code, byte_size, byte_pos, - var_off, extra_indirection); - - // extract range info - CV_LvarAddrRange *range = &defrange_fprel->range; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_fprel + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // emit locations - p2r_location_over_lvar_addr_range(ctx, defrange_target, location, - range, gaps, gap_count); - }break; - - //- rjf: DEFRANGE_SUBFIELD_REGISTER - case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: - { - if(defrange_target == 0) { break; } - CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister*)sym_header_struct_base; - - // TODO(allen): full "subfield" location system - if(defrange_subfield_register->field_offset == 0) - { - - // TODO(allen): offset & size from cv_reg code - RDI_Arch arch = ctx->arch; - CV_Reg cv_reg = defrange_subfield_register->reg; - RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg); - - // setup location - RDIM_Location *location = rdim_location_val_reg(ctx->root, register_code); - - // extract range info - CV_LvarAddrRange *range = &defrange_subfield_register->range; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_subfield_register + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // emit locations - p2r_location_over_lvar_addr_range(ctx, defrange_target, location, - range, gaps, gap_count); - } - }break; - - //- rjf: DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE - case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: - { - if(defrange_target == 0) { break; } - CV_SymDefrangeFramepointerRelFullScope *defrange_fprel_full_scope = - (CV_SymDefrangeFramepointerRelFullScope*)sym_header_struct_base; - - // select frame pointer register - CV_EncodedFramePtrReg encoded_fp_reg = - p2r_cv_encoded_fp_reg_from_proc(ctx, current_procedure, defrange_target_is_param); - RDI_RegisterCode fp_register_code = - p2r_reg_code_from_arch_encoded_fp_reg(ctx->arch, encoded_fp_reg); - - // setup location - B32 extra_indirection = 0; - U32 byte_size = ctx->addr_size; - U32 byte_pos = 0; - S64 var_off = (S64)defrange_fprel_full_scope->off; - RDIM_Location *location = - p2r_location_from_addr_reg_off(ctx, fp_register_code, byte_size, byte_pos, - var_off, extra_indirection); - - - // emit location - rdim_location_set_add_case(ctx->root, defrange_target, 0, max_U64, location); - }break; - - //- rjf: DEFRANGE_REGISTER_REL - case CV_SymKind_DEFRANGE_REGISTER_REL: - { - if(defrange_target == 0) { break; } - CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel*)sym_header_struct_base; - - // TODO(allen): offset & size from cv_reg code - RDI_Arch arch = ctx->arch; - CV_Reg cv_reg = defrange_register_rel->reg; - RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg); - U32 byte_size = ctx->addr_size; - U32 byte_pos = 0; - - B32 extra_indirection_to_value = 0; - S64 var_off = defrange_register_rel->reg_off; - - // setup location - RDIM_Location *location = - p2r_location_from_addr_reg_off(ctx, register_code, byte_size, byte_pos, - var_off, extra_indirection_to_value); - - // extract range info - CV_LvarAddrRange *range = &defrange_register_rel->range; - CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register_rel + 1); - U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); - - // emit locations - p2r_location_over_lvar_addr_range(ctx, defrange_target, location, - range, gaps, gap_count); - }break; - - //- rjf: FILESTATIC - case CV_SymKind_FILESTATIC: - { - CV_SymFileStatic *file_static = (CV_SymFileStatic*)sym_header_struct_base; - String8 name = str8_cstring_capped(file_static+1, sym_data_opl); - RDIM_Type *type = p2r_type_resolve_itype(ctx, file_static->itype); - - // TODO(allen): emit a global modifier symbol - - // defrange records from this point attach to this location information - defrange_target = 0; - defrange_target_is_param = 0; - }break; - } - } - - //- rjf: non-empty scope stack? -> error - { - RDIM_Scope *scope = p2r_symbol_current_scope(ctx); - if(scope != 0) - { - // TODO(allen): emit error - } - } - - //- rjf: clear scope stack - p2r_symbol_clear_scope_stack(ctx); - } - - scratch_end(scratch); - ProfEnd(); -} - -internal void -p2r_gather_link_names(P2R_Ctx *ctx, CV_SymParsed *sym) -{ - ProfBeginFunction(); - // extract important values from parameters - String8 data = sym->data; - - // loop - CV_RecRange *rec_range = sym->sym_ranges.ranges; - CV_RecRange *opl = rec_range + sym->sym_ranges.count; - for(;rec_range < opl; rec_range += 1) - { - // symbol data range - U64 opl_off_raw = rec_range->off + rec_range->hdr.size; - U64 opl_off = ClampTop(opl_off_raw, data.size); - - U64 off_raw = rec_range->off + 2; - U64 off = ClampTop(off_raw, opl_off); - - U8 *first = data.str + off; - U64 cap = (opl_off - off); - - CV_SymKind kind = rec_range->hdr.kind; - switch (kind) - { - default: break; - - case CV_SymKind_PUB32: - { - if(sizeof(CV_SymPub32) > cap) - { - // TODO(allen): error - } - else - { - CV_SymPub32 *pub32 = (CV_SymPub32*)first; - - // name - String8 name = str8_cstring_capped((char*)(pub32 + 1), first + cap); - - // calculate voff - U64 voff = 0; - COFF_SectionHeader *section = p2r_sec_header_from_sec_num(ctx, pub32->sec); - if(section != 0) - { - voff = section->voff + pub32->off; - } - - // save link name - p2r_link_name_save(ctx->arena, &ctx->link_names, voff, name); - } - }break; - } - } - ProfEnd(); -} - -// "frameproc" map - -internal void -p2r_symbol_frame_proc_write(P2R_Ctx *ctx,RDIM_Symbol *key,P2R_FrameProcData *data) -{ - ProfBeginFunction(); - U64 key_int = IntFromPtr(key); - P2R_FrameProcMap *map = &ctx->frame_proc_map; - U32 bucket_idx = key_int%map->buckets_count; - - // find match - P2R_FrameProcNode *match = 0; - for(P2R_FrameProcNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->key == key) - { - match = node; - break; - } - } - - // if there is already a match emit error - if(match != 0) - { - // TODO(allen): error - } - - // insert new association if no match - if(match == 0) - { - match = push_array(ctx->arena, P2R_FrameProcNode, 1); - SLLStackPush(map->buckets[bucket_idx], match); - match->key = key; - MemoryCopyStruct(&match->data, data); - map->pair_count += 1; - map->bucket_collision_count += (match->next != 0); - } - ProfEnd(); -} - -internal P2R_FrameProcData* -p2r_symbol_frame_proc_read(P2R_Ctx *ctx, RDIM_Symbol *key) -{ - U64 key_int = IntFromPtr(key); - P2R_FrameProcMap *map = &ctx->frame_proc_map; - U32 bucket_idx = key_int%map->buckets_count; - - // find match - P2R_FrameProcData *result = 0; - for(P2R_FrameProcNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->key == key) - { - result = &node->data; - break; - } - } - - return(result); -} - -// scope stack -internal void -p2r_symbol_push_scope(P2R_Ctx *ctx, RDIM_Scope *scope, RDIM_Symbol *symbol) -{ - P2R_ScopeNode *node = ctx->scope_node_free; - if(node == 0) - { - node = push_array(ctx->arena, P2R_ScopeNode, 1); - } - else - { - SLLStackPop(ctx->scope_node_free); - } - SLLStackPush(ctx->scope_stack, node); - node->scope = scope; - node->symbol = symbol; -} - -internal void -p2r_symbol_pop_scope(P2R_Ctx *ctx) -{ - P2R_ScopeNode *node = ctx->scope_stack; - if(node != 0) - { - SLLStackPop(ctx->scope_stack); - SLLStackPush(ctx->scope_node_free, node); - } -} - -internal void -p2r_symbol_clear_scope_stack(P2R_Ctx *ctx) -{ - for(;;) - { - P2R_ScopeNode *node = ctx->scope_stack; - if(node == 0) - { - break; - } - SLLStackPop(ctx->scope_stack); - SLLStackPush(ctx->scope_node_free, node); - } -} - -// PDB/C++ name parsing helper - -internal U64 -p2r_end_of_cplusplus_container_name(String8 str) -{ - // NOTE: This finds the index one past the last "::" contained in str. - // if no "::" is contained in str, then the returned index is 0. - // The intent is that [0,clamp_bot(0,result - 2)) gives the - // "container name" and [result,str.size) gives the leaf name. - U64 result = 0; - if(str.size >= 2) - { - for(U64 i = str.size; i >= 2; i -= 1) - { - if(str.str[i - 2] == ':' && str.str[i - 1] == ':') - { - result = i; - break; - } - } - } - return(result); -} - -// known global set - -internal U64 -p2r_known_global_hash(String8 name, U64 voff) -{ - U64 result = 5381 ^ voff; - U8 *ptr = name.str; - U8 *opl = ptr + name.size; - for(; ptr < opl; ptr += 1) - { - result = ((result << 5) + result) + *ptr; - } - return(result); -} - -internal B32 -p2r_known_global_lookup(P2R_KnownGlobalSet *set, String8 name, U64 voff) -{ - U64 hash = p2r_known_global_hash(name, voff); - U64 bucket_idx = hash%set->buckets_count; - - P2R_KnownGlobalNode *match = 0; - for(P2R_KnownGlobalNode *node = set->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->hash == hash && - node->key_voff == voff && - str8_match(node->key_name, name, 0)) - { - match = node; - break; - } - } - - B32 result = (match != 0); - return(result); -} - -internal void -p2r_known_global_insert(Arena *arena, P2R_KnownGlobalSet *set, String8 name, U64 voff) -{ - U64 hash = p2r_known_global_hash(name, voff); - U64 bucket_idx = hash%set->buckets_count; - - P2R_KnownGlobalNode *match = 0; - for(P2R_KnownGlobalNode *node = set->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->hash == hash && - node->key_voff == voff && - str8_match(node->key_name, name, 0)) - { - match = node; - break; - } - } - - if(match == 0) - { - P2R_KnownGlobalNode *node = push_array(arena, P2R_KnownGlobalNode, 1); - SLLStackPush(set->buckets[bucket_idx], node); - node->key_name = push_str8_copy(arena, name); - node->key_voff = voff; - node->hash = hash; - set->global_count += 1; - set->bucket_collision_count += (node->next != 0); - } -} - -// location info helpers - -internal RDIM_Location* -p2r_location_from_addr_reg_off(P2R_Ctx *ctx, - RDI_RegisterCode reg_code, - U32 reg_byte_size, - U32 reg_byte_pos, - S64 offset, - B32 extra_indirection) -{ - RDIM_Location *result = 0; - if(0 <= offset && offset <= (S64)max_U16) - { - if(extra_indirection) - { - result = rdim_location_addr_addr_reg_plus_u16(ctx->root, reg_code, (U16)offset); - } - else - { - result = rdim_location_addr_reg_plus_u16(ctx->root, reg_code, (U16)offset); - } - } - else - { - Arena *arena = ctx->arena; - - RDIM_EvalBytecode bytecode = {0}; - U32 regread_param = RDI_EncodeRegReadParam(reg_code, reg_byte_size, reg_byte_pos); - rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_RegRead, regread_param); - rdim_bytecode_push_sconst(arena, &bytecode, offset); - rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_Add, 0); - if(extra_indirection) - { - rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_MemRead, ctx->addr_size); - } - - result = rdim_location_addr_bytecode_stream(ctx->root, &bytecode); - } - - return(result); -} - -internal CV_EncodedFramePtrReg -p2r_cv_encoded_fp_reg_from_proc(P2R_Ctx *ctx, RDIM_Symbol *proc, B32 param_base) -{ - CV_EncodedFramePtrReg result = 0; - if(proc != 0) - { - P2R_FrameProcData *frame_proc = p2r_symbol_frame_proc_read(ctx, proc); - CV_FrameprocFlags flags = frame_proc->flags; - if(param_base) - { - result = CV_FrameprocFlags_ExtractParamBasePointer(flags); - } - else - { - result = CV_FrameprocFlags_ExtractLocalBasePointer(flags); - } - } - return(result); -} - -internal RDI_RegisterCode -p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg) -{ - RDI_RegisterCode result = 0; - - switch (arch) - { - case RDI_Arch_X86: - { - switch (encoded_reg) - { - case CV_EncodedFramePtrReg_StackPtr: - { - // TODO(allen): support CV_AllReg_VFRAME - // TODO(allen): error - }break; - case CV_EncodedFramePtrReg_FramePtr: - { - result = RDI_RegisterCode_X86_ebp; - }break; - case CV_EncodedFramePtrReg_BasePtr: - { - result = RDI_RegisterCode_X86_ebx; - }break; - } - }break; - - case RDI_Arch_X64: - { - switch (encoded_reg) - { - case CV_EncodedFramePtrReg_StackPtr: - { - result = RDI_RegisterCode_X64_rsp; - }break; - case CV_EncodedFramePtrReg_FramePtr: - { - result = RDI_RegisterCode_X64_rbp; - }break; - case CV_EncodedFramePtrReg_BasePtr: - { - result = RDI_RegisterCode_X64_r13; - }break; - } - }break; - } - - return(result); -} - -internal void -p2r_location_over_lvar_addr_range(P2R_Ctx *ctx, - RDIM_LocationSet *locset, - RDIM_Location *location, - CV_LvarAddrRange *range, - CV_LvarAddrGap *gaps, U64 gap_count) -{ - // extract range info - U64 voff_first = 0; - U64 voff_opl = 0; - { - COFF_SectionHeader *section = p2r_sec_header_from_sec_num(ctx, range->sec); - if(section != 0) - { - voff_first = section->voff + range->off; - voff_opl = voff_first + range->len; - } - } - - // emit ranges - CV_LvarAddrGap *gap_ptr = gaps; - U64 voff_cursor = voff_first; - for(U64 i = 0; i < gap_count; i += 1, gap_ptr += 1) - { - U64 voff_gap_first = voff_first + gap_ptr->off; - U64 voff_gap_opl = voff_gap_first + gap_ptr->len; - if(voff_cursor < voff_gap_first) - { - rdim_location_set_add_case(ctx->root, locset, voff_cursor, voff_gap_first, location); - } - voff_cursor = voff_gap_opl; - } - - if(voff_cursor < voff_opl) - { - rdim_location_set_add_case(ctx->root, locset, voff_cursor, voff_opl, location); - } -} - -// link names - -internal void -p2r_link_name_save(Arena *arena, P2R_LinkNameMap *map, U64 voff, String8 name) -{ - U64 hash = (voff >> 3) ^ ((7 & voff) << 6); - U64 bucket_idx = hash%map->buckets_count; - - P2R_LinkNameNode *node = push_array(arena, P2R_LinkNameNode, 1); - SLLStackPush(map->buckets[bucket_idx], node); - node->voff = voff; - node->name = push_str8_copy(arena, name); - map->link_name_count += 1; - map->bucket_collision_count += (node->next != 0); -} - -internal String8 -p2r_link_name_find(P2R_LinkNameMap *map, U64 voff) -{ - U64 hash = (voff >> 3) ^ ((7 & voff) << 6); - U64 bucket_idx = hash%map->buckets_count; - - String8 result = {0}; - for(P2R_LinkNameNode *node = map->buckets[bucket_idx]; - node != 0; - node = node->next) - { - if(node->voff == voff) - { - result = node->name; - break; - } - } - - return(result); -} - -#endif - //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point @@ -5835,438 +2936,6 @@ p2r_convert(Arena *arena, P2R_ConvertIn *in) out->scopes = all_scopes; } - //~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvv -#if 0 - - // output generation - P2R_Ctx *p2r_ctx = 0; - if(in->output_name.size > 0) - { - // setup root - RDIM_RootParams root_params = {0}; - root_params.addr_size = addr_size; - - root_params.bucket_count_units = comp_unit_count; - root_params.bucket_count_symbols = symbol_count_prediction; - root_params.bucket_count_scopes = symbol_count_prediction; - root_params.bucket_count_locals = symbol_count_prediction*2; - root_params.bucket_count_types = tpi->itype_opl; - root_params.bucket_count_type_constructs = tpi->itype_opl; - - RDIM_Root *root = rdim_root_alloc(&root_params); - out->root = root; - - // top level info - { - // calculate voff max - U64 voff_max = 0; - { - COFF_SectionHeader *coff_sec_ptr = coff_sections->sections; - COFF_SectionHeader *coff_ptr_opl = coff_sec_ptr + coff_section_count; - for(;coff_sec_ptr < coff_ptr_opl; coff_sec_ptr += 1) - { - U64 sec_voff_max = coff_sec_ptr->voff + coff_sec_ptr->vsize; - voff_max = Max(voff_max, sec_voff_max); - } - } - - // set top level info - RDIM_TopLevelInfo tli = {0}; - tli.architecture = architecture; - tli.exe_name = in->input_exe_name; - tli.exe_hash = exe_hash; - tli.voff_max = voff_max; - - rdim_set_top_level_info(root, &tli); - } - - - // setup binary sections - { - COFF_SectionHeader *coff_ptr = coff_sections->sections; - COFF_SectionHeader *coff_opl = coff_ptr + coff_section_count; - for(;coff_ptr < coff_opl; coff_ptr += 1) - { - char *name_first = (char*)coff_ptr->name; - char *name_opl = name_first + sizeof(coff_ptr->name); - String8 name = str8_cstring_capped(name_first, name_opl); - RDI_BinarySectionFlags flags = - rdi_binary_section_flags_from_coff_section_flags(coff_ptr->flags); - rdim_add_binary_section(root, name, flags, - coff_ptr->voff, coff_ptr->voff + coff_ptr->vsize, - coff_ptr->foff, coff_ptr->foff + coff_ptr->fsize); - } - } - - - // setup compilation units - { - PDB_CompUnit **units = comp_units->units; - for(U64 i = 0; i < comp_unit_count; i += 1) - { - PDB_CompUnit *unit = units[i]; - CV_SymParsed *unit_sym = sym_for_unit[i]; - CV_C13Parsed *unit_c13 = c13_for_unit[i]; - - // resolve names - String8 raw_name = unit->obj_name; - - String8 unit_name = raw_name; - { - U64 first_after_slashes = 0; - for(S64 i = unit_name.size - 1; i >= 0; i -= 1) - { - if(unit_name.str[i] == '/' || unit_name.str[i] == '\\') - { - first_after_slashes = i + 1; - break; - } - } - unit_name = str8_range(raw_name.str + first_after_slashes, - raw_name.str + raw_name.size); - } - - String8 obj_name = raw_name; - if(str8_match(obj_name, str8_lit("* Linker *"), 0) || - str8_match(obj_name, str8_lit("Import:"), - StringMatchFlag_RightSideSloppy)) - { - MemoryZeroStruct(&obj_name); - } - - String8 compiler_name = unit_sym->info.compiler_name; - String8 archive_file = unit->group_name; - - // extract langauge - RDI_Language lang = rdi_language_from_cv_language(sym->info.language); - - // basic per unit info - RDIM_Unit *unit_handle = rdim_unit_handle_from_user_id(root, i, i); - - RDIM_UnitInfo info = {0}; - info.unit_name = unit_name; - info.compiler_name = compiler_name; - info.object_file = obj_name; - info.archive_file = archive_file; - info.language = lang; - - rdim_unit_set_info(root, unit_handle, &info); - - // unit's line info - for(CV_C13SubSectionNode *node = unit_c13->first_sub_section; - node != 0; - node = node->next) - { - if(node->kind == CV_C13_SubSectionKind_Lines) - { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) - { - CV_C13LinesParsed *lines = &lines_n->v; - RDIM_LineSequence seq = {0}; - seq.file_name = lines->file_name; - seq.voffs = lines->voffs; - seq.line_nums = lines->line_nums; - seq.col_nums = lines->col_nums; - seq.line_count = lines->line_count; - rdim_unit_add_line_sequence(root, unit_handle, &seq); - } - } - } - } - } - - - // unit vmap ranges - { - PDB_CompUnitContribution *contrib_ptr = comp_unit_contributions->contributions; - PDB_CompUnitContribution *contrib_opl = contrib_ptr + comp_unit_contribution_count; - for(;contrib_ptr < contrib_opl; contrib_ptr += 1) - { - if(contrib_ptr->mod < root->unit_count) - { - RDIM_Unit *unit_handle = rdim_unit_handle_from_user_id(root, contrib_ptr->mod, contrib_ptr->mod); - rdim_unit_vmap_add_range(root, unit_handle, - contrib_ptr->voff_first, - contrib_ptr->voff_opl); - } - } - } - - // rjf: produce pdb conversion context - { - P2R_CtxParams p = {0}; - { - p.arch = architecture; - p.tpi_hash = tpi_hash; - p.tpi_leaf = tpi_leaf; - p.sections = coff_sections; - p.fwd_map_bucket_count = tpi->itype_opl/10; - p.frame_proc_map_bucket_count = symbol_count_prediction; - p.known_global_map_bucket_count = symbol_count_prediction; - p.link_name_map_bucket_count = symbol_count_prediction; - } - p2r_ctx = p2r_ctx_alloc(&p, root); - } - - // types & symbols - { - P2R_TypesSymbolsParams p = {0}; - p.sym = sym; - p.sym_for_unit = sym_for_unit; - p.unit_count = comp_unit_count; - p2r_types_and_symbols(p2r_ctx, &p); - } - - // conversion errors - if(!in->hide_errors.converting) - { - for(RDIM_Msg *msg = rdim_first_msg_from_root(root); - msg != 0; - msg = msg->next) - { - str8_list_push(arena, &out->errors, msg->string); - } - } - } - - // dump - if(in->dump) ProfScope("dump") - { - String8List dump = {0}; - - // EXE - if(out->good_parse) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "EXE INFO:\n")); - { - str8_list_pushf(arena, &dump, "HASH: %016llX\n", exe_hash); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // MSF - if(in->dump_msf) - { - if(msf != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "MSF:\n")); - - str8_list_pushf(arena, &dump, " block_size=%llu\n", msf->block_size); - str8_list_pushf(arena, &dump, " block_count=%llu\n", msf->block_count); - str8_list_pushf(arena, &dump, " stream_count=%llu\n", msf->stream_count); - - String8 *stream_ptr = msf->streams; - U64 stream_count = msf->stream_count; - for(U64 i = 0; i < stream_count; i += 1, stream_ptr += 1) - { - str8_list_pushf(arena, &dump, " stream[%u].size=%llu\n", - i, stream_ptr->size); - } - - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - - // DBI - if(in->dump_sym) - { - if(sym != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "DBI SYM:\n")); - cv_stringize_sym_parsed(arena, &dump, sym); - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - - // TPI - if(in->dump_tpi_hash) - { - if(tpi_hash != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "TPI HASH:\n")); - pdb_stringize_tpi_hash(arena, &dump, tpi_hash); - str8_list_push(arena, &dump, str8_lit("\n")); - } - - if(ipi_hash != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "IPI HASH:\n")); - pdb_stringize_tpi_hash(arena, &dump, ipi_hash); - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - - // LEAF - if(in->dump_leaf) - { - if(tpi_leaf != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "TPI LEAF:\n")); - cv_stringize_leaf_parsed(arena, &dump, tpi_leaf); - str8_list_push(arena, &dump, str8_lit("\n")); - } - - if(ipi_leaf != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "IPI LEAF:\n")); - cv_stringize_leaf_parsed(arena, &dump, ipi_leaf); - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - - // BINARY SECTIONS - if(in->dump_coff_sections) - { - if(coff_sections != 0) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "COFF SECTIONS:\n")); - COFF_SectionHeader *section_ptr = coff_sections->sections; - for(U64 i = 0; i < coff_section_count; i += 1, section_ptr += 1) - { - // TODO(allen): probably should pull this out into a separate stringize path - // for the coff section type - char *first = (char*)section_ptr->name; - char *opl = first + sizeof(section_ptr->name); - String8 name = str8_cstring_capped(first, opl); - str8_list_pushf(arena, &dump, " %.*s:\n", str8_varg(name)); - str8_list_pushf(arena, &dump, " vsize=%u\n", section_ptr->vsize); - str8_list_pushf(arena, &dump, " voff =0x%x\n", section_ptr->voff); - str8_list_pushf(arena, &dump, " fsize=%u\n", section_ptr->fsize); - str8_list_pushf(arena, &dump, " foff =0x%x\n", section_ptr->foff); - str8_list_pushf(arena, &dump, " relocs_foff=0x%x\n", section_ptr->relocs_foff); - str8_list_pushf(arena, &dump, " lines_foff =0x%x\n", section_ptr->lines_foff); - str8_list_pushf(arena, &dump, " reloc_count=%u\n", section_ptr->reloc_count); - str8_list_pushf(arena, &dump, " line_count =%u\n", section_ptr->line_count); - // TODO(allen): better flags - str8_list_pushf(arena, &dump, " flags=%x\n", section_ptr->flags); - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - } - - // UNITS - if(comp_units != 0) - { - B32 dump_sym = in->dump_sym; - B32 dump_c13 = in->dump_c13; - - B32 dump_units = (dump_sym || dump_c13); - - if(dump_units) - { - PDB_CompUnit **unit_ptr = comp_units->units; - for(U64 i = 0; i < comp_unit_count; i += 1, unit_ptr += 1) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n")); - String8 name = (*unit_ptr)->obj_name; - String8 group_name = (*unit_ptr)->group_name; - str8_list_pushf(arena, &dump, "[%llu] %.*s\n(%.*s):\n", - i, str8_varg(name), str8_varg(group_name)); - if(dump_sym) - { - cv_stringize_sym_parsed(arena, &dump, sym_for_unit[i]); - } - if(dump_c13) - { - cv_stringize_c13_parsed(arena, &dump, c13_for_unit[i]); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - } - - // UNIT CONTRIBUTIONS - if(comp_unit_contributions != 0) - { - if(in->dump_contributions) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "UNIT CONTRIBUTIONS:\n")); - PDB_CompUnitContribution *contrib_ptr = comp_unit_contributions->contributions; - for(U64 i = 0; i < comp_unit_contribution_count; i += 1, contrib_ptr += 1) - { - str8_list_pushf(arena, &dump, - " { mod = %5u; voff_first = %08llx; voff_opl = %08llx; }\n", - contrib_ptr->mod, contrib_ptr->voff_first, contrib_ptr->voff_opl); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - - // rjf: dump table diagnostics - if(in->dump_table_diagnostics) - { - str8_list_push(arena, &dump, - str8_lit("################################" - "################################\n" - "TABLE DIAGNOSTICS:\n")); - struct - { - String8 name; - U64 bucket_count; - U64 value_count; - U64 collision_count; - } - table_info[] = - { - {str8_lit("p2r_ctx fwd_map"), p2r_ctx?p2r_ctx->fwd_map.buckets_count:0, p2r_ctx?p2r_ctx->fwd_map.pair_count:0, p2r_ctx?p2r_ctx->fwd_map.bucket_collision_count:0}, - {str8_lit("p2r_ctx frame_proc_map"), p2r_ctx?p2r_ctx->frame_proc_map.buckets_count:0, p2r_ctx?p2r_ctx->frame_proc_map.pair_count:0, p2r_ctx?p2r_ctx->frame_proc_map.bucket_collision_count:0}, - {str8_lit("p2r_ctx known_globals"), p2r_ctx?p2r_ctx->known_globals.buckets_count:0, p2r_ctx?p2r_ctx->known_globals.global_count:0, p2r_ctx?p2r_ctx->known_globals.bucket_collision_count:0}, - {str8_lit("p2r_ctx link_names"), p2r_ctx?p2r_ctx->link_names.buckets_count:0, p2r_ctx?p2r_ctx->link_names.link_name_count:0, p2r_ctx?p2r_ctx->link_names.bucket_collision_count:0}, - {str8_lit("rdim_root unit_map"), out->root->unit_map.buckets_count, out->root->unit_map.pair_count, out->root->unit_map.bucket_collision_count}, - {str8_lit("rdim_root symbol_map"), out->root->symbol_map.buckets_count, out->root->symbol_map.pair_count, out->root->symbol_map.bucket_collision_count}, - {str8_lit("rdim_root scope_map"), out->root->scope_map.buckets_count, out->root->scope_map.pair_count, out->root->scope_map.bucket_collision_count}, - {str8_lit("rdim_root local_map"), out->root->local_map.buckets_count, out->root->local_map.pair_count, out->root->local_map.bucket_collision_count}, - {str8_lit("rdim_root type_from_id_map"), out->root->type_from_id_map.buckets_count, out->root->type_from_id_map.pair_count, out->root->type_from_id_map.bucket_collision_count}, - {str8_lit("rdim_root construct_map"), out->root->construct_map.buckets_count, out->root->construct_map.pair_count, out->root->construct_map.bucket_collision_count}, - }; - for(U64 idx = 0; idx < ArrayCount(table_info); idx += 1) - { - str8_list_pushf(arena, &dump, "%S: %I64u values in %I64u buckets, with %I64u collisions (%f fill)\n", - table_info[idx].name, - table_info[idx].value_count, - table_info[idx].bucket_count, - table_info[idx].collision_count, - (F64)table_info[idx].value_count / (F64)table_info[idx].bucket_count); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - out->dump = dump; - } - -#endif - scratch_end(scratch); return out; } diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb.h b/src/raddbgi_from_pdb/raddbgi_from_pdb.h index d2ac7334..1cb9f460 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb.h +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb.h @@ -75,176 +75,6 @@ struct P2R_LinkNameMap U64 link_name_count; }; -#if 0 - -//////////////////////////////// -//~ rjf: PDB Type & Symbol Info Translation Helper Types - -//- rjf: typeid forward reference map - -typedef struct P2R_FwdNode P2R_FwdNode; -struct P2R_FwdNode -{ - P2R_FwdNode *next; - CV_TypeId key; - CV_TypeId val; -}; - -typedef struct P2R_FwdMap P2R_FwdMap; -struct P2R_FwdMap -{ - P2R_FwdNode **buckets; - U64 buckets_count; - U64 bucket_collision_count; - U64 pair_count; -}; - -//- rjf: type revisit lists - -typedef struct P2R_TypeRev P2R_TypeRev; -struct P2R_TypeRev -{ - P2R_TypeRev *next; - RDIM_Type *owner_type; - CV_TypeId field_itype; -}; - -//- rjf: frame proc maps - -typedef struct P2R_FrameProcData P2R_FrameProcData; -struct P2R_FrameProcData -{ - U32 frame_size; - CV_FrameprocFlags flags; -}; - -typedef struct P2R_FrameProcNode P2R_FrameProcNode; -struct P2R_FrameProcNode -{ - P2R_FrameProcNode *next; - RDIM_Symbol *key; - P2R_FrameProcData data; -}; - -typedef struct P2R_FrameProcMap P2R_FrameProcMap; -struct P2R_FrameProcMap -{ - P2R_FrameProcNode **buckets; - U64 buckets_count; - U64 bucket_collision_count; - U64 pair_count; -}; - -//- rjf: scopes - -typedef struct P2R_ScopeNode P2R_ScopeNode; -struct P2R_ScopeNode -{ - P2R_ScopeNode *next; - RDIM_Scope *scope; - RDIM_Symbol *symbol; -}; - -//- rjf: known global map - -typedef struct P2R_KnownGlobalNode P2R_KnownGlobalNode; -struct P2R_KnownGlobalNode -{ - P2R_KnownGlobalNode *next; - String8 key_name; - U64 key_voff; - U64 hash; -}; - -typedef struct P2R_KnownGlobalSet P2R_KnownGlobalSet; -struct P2R_KnownGlobalSet -{ - P2R_KnownGlobalNode **buckets; - U64 buckets_count; - U64 bucket_collision_count; - U64 global_count; -}; - -typedef struct P2R_CtxParams P2R_CtxParams; -struct P2R_CtxParams -{ - RDI_Arch arch; - PDB_TpiHashParsed *tpi_hash; - CV_LeafParsed *tpi_leaf; - PDB_CoffSectionArray *sections; - U64 fwd_map_bucket_count; - U64 frame_proc_map_bucket_count; - U64 known_global_map_bucket_count; - U64 link_name_map_bucket_count; -}; - -typedef struct P2R_TypesSymbolsParams P2R_TypesSymbolsParams; -struct P2R_TypesSymbolsParams -{ - CV_SymParsed *sym; - CV_SymParsed **sym_for_unit; - U64 unit_count; -}; - -typedef struct P2R_LinkNameNode P2R_LinkNameNode; -struct P2R_LinkNameNode -{ - P2R_LinkNameNode *next; - U64 voff; - String8 name; -}; - -typedef struct P2R_LinkNameMap P2R_LinkNameMap; -struct P2R_LinkNameMap -{ - P2R_LinkNameNode **buckets; - U64 buckets_count; - U64 bucket_collision_count; - U64 link_name_count; -}; - -typedef struct P2R_Ctx P2R_Ctx; -struct P2R_Ctx -{ - Arena *arena; - - // INPUT data - RDI_Arch arch; - U64 addr_size; - PDB_TpiHashParsed *hash; - CV_LeafParsed *leaf; - COFF_SectionHeader *sections; - U64 section_count; - - // OUTPUT data - RDIM_Root *root; - - // TEMPORARY STATE - P2R_FwdMap fwd_map; - P2R_TypeRev *member_revisit_first; - P2R_TypeRev *member_revisit_last; - P2R_TypeRev *enum_revisit_first; - P2R_TypeRev *enum_revisit_last; - P2R_FrameProcMap frame_proc_map; - P2R_ScopeNode *scope_stack; - P2R_ScopeNode *scope_node_free; - P2R_KnownGlobalSet known_globals; - P2R_LinkNameMap link_names; -}; - -//////////////////////////////// -//~ Conversion Output Type - -typedef struct P2R_Out P2R_Out; -struct P2R_Out -{ - B32 good_parse; - RDIM_Root *root; - String8List dump; - String8List errors; -}; -#endif - //////////////////////////////// //~ rjf: Basic Helpers @@ -283,112 +113,4 @@ internal void p2r_location_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkLis internal P2R_ConvertOut *p2r_convert(Arena *arena, P2R_ConvertIn *in); -#if 0 - -//////////////////////////////// -//~ rjf: Conversion Implementation Helpers - -//- rjf: pdb conversion context creation -internal P2R_Ctx *p2r_ctx_alloc(P2R_CtxParams *params, RDIM_Root *out_root); - -//- rjf: pdb types and symbols -internal void p2r_types_and_symbols(P2R_Ctx *pdb_ctx, P2R_TypesSymbolsParams *params); - -//- rjf: decoding helpers -internal U32 p2r_u32_from_numeric(P2R_Ctx *ctx, CV_NumericParsed *num); -internal COFF_SectionHeader* p2r_sec_header_from_sec_num(P2R_Ctx *ctx, U32 sec_num); - -//- rjf: type info -// -// TODO(allen): explain the overarching pattern of PDB type info translation here -// 1. main passes (out of order necessity) & after -// 2. resolve forward -// 3. cons type info -// 4. "resolve itype" -// 5. equipping members & enumerates -// 6. equipping source coordinates - -// type info construction passes -internal void p2r_type_cons_main_passes(P2R_Ctx *ctx); -internal CV_TypeId p2r_type_resolve_fwd(P2R_Ctx *ctx, CV_TypeId itype); -internal RDIM_Type* p2r_type_resolve_itype(P2R_Ctx *ctx, CV_TypeId itype); -internal void p2r_type_equip_members(P2R_Ctx *ctx, RDIM_Type *owern_type, CV_TypeId field_itype); -internal void p2r_type_equip_enumerates(P2R_Ctx *ctx, RDIM_Type *owner_type, CV_TypeId field_itype); - -// type info construction helpers -internal RDIM_Type* p2r_type_cons_basic(P2R_Ctx *ctx, CV_TypeId itype); -internal RDIM_Type* p2r_type_cons_leaf_record(P2R_Ctx *ctx, CV_TypeId itype); -internal RDIM_Type* p2r_type_resolve_and_check(P2R_Ctx *ctx, CV_TypeId itype); -internal void p2r_type_resolve_arglist(Arena *arena, RDIM_TypeList *out, - P2R_Ctx *ctx, CV_TypeId arglist_itype); - -// type info resolution helpers -internal RDIM_Type* p2r_type_from_name(P2R_Ctx *ctx, String8 name); - -// type fwd map -internal void p2r_type_fwd_map_set(Arena *arena, P2R_FwdMap *map, - CV_TypeId key, CV_TypeId val); -internal CV_TypeId p2r_type_fwd_map_get(P2R_FwdMap *map, CV_TypeId key); - -//- rjf: symbol info - -// symbol info construction -internal U64 p2r_hash_from_local_user_id(U64 sym_hash, U64 id); -internal U64 p2r_hash_from_scope_user_id(U64 sym_hash, U64 id); -internal U64 p2r_hash_from_symbol_user_id(U64 sym_hash, U64 id); -internal void p2r_symbol_cons(P2R_Ctx *ctx, CV_SymParsed *sym, U32 sym_unique_id); -internal void p2r_gather_link_names(P2R_Ctx *ctx, CV_SymParsed *sym); - -// "frameproc" map -internal void p2r_symbol_frame_proc_write(P2R_Ctx *ctx,RDIM_Symbol *key, - P2R_FrameProcData *data); -internal P2R_FrameProcData* p2r_symbol_frame_proc_read(P2R_Ctx *ctx, RDIM_Symbol *key); - -// scope stack -internal void p2r_symbol_push_scope(P2R_Ctx *ctx, RDIM_Scope *scope, RDIM_Symbol *symbol); -internal void p2r_symbol_pop_scope(P2R_Ctx *ctx); -internal void p2r_symbol_clear_scope_stack(P2R_Ctx *ctx); - -#define p2r_symbol_current_scope(ctx) ((ctx)->scope_stack == 0)?0:((ctx)->scope_stack->scope) -#define p2r_symbol_current_symbol(ctx) ((ctx)->scope_stack == 0)?0:((ctx)->scope_stack->symbol) - -// PDB/C++ name parsing helper -internal U64 p2r_end_of_cplusplus_container_name(String8 str); - -// global deduplication -internal U64 p2r_known_global_hash(String8 name, U64 voff); - -internal B32 p2r_known_global_lookup(P2R_KnownGlobalSet *set, String8 name, U64 voff); -internal void p2r_known_global_insert(Arena *arena, P2R_KnownGlobalSet *set, - String8 name, U64 voff); - - -// location info helpers -internal RDIM_Location* p2r_location_from_addr_reg_off(P2R_Ctx *ctx, - RDI_RegisterCode reg_code, - U32 reg_byte_size, - U32 reg_byte_pos, - S64 offset, - B32 extra_indirection); - -internal CV_EncodedFramePtrReg p2r_cv_encoded_fp_reg_from_proc(P2R_Ctx *ctx, - RDIM_Symbol *proc, - B32 param_base); - -internal RDI_RegisterCode p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, - CV_EncodedFramePtrReg encoded_reg); - -internal void p2r_location_over_lvar_addr_range(P2R_Ctx *ctx, - RDIM_LocationSet *locset, - RDIM_Location *location, - CV_LvarAddrRange *range, - CV_LvarAddrGap *gaps, U64 gap_count); - -// link names -internal void p2r_link_name_save(Arena *arena, P2R_LinkNameMap *map, - U64 voff, String8 name); -internal String8 p2r_link_name_find(P2R_LinkNameMap *map, U64 voff); - -#endif - #endif // RDI_FROM_PDB_H