d2r2: deduper fixes/simplification, first half of structured namespace support

This commit is contained in:
Ryan Fleury
2026-05-04 15:41:23 -07:00
parent 8f65f466f5
commit aee299efe7
4 changed files with 670 additions and 415 deletions
+1 -1
View File
@@ -583,7 +583,7 @@ dw2_reference_info_off_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal *v)
case DW_Form_Ref4:
case DW_Form_Ref8:
{
result = v->u128.u64[0];
result = ctx->unit_base_info_off + v->u128.u64[0];
}break;
// TODO(rjf): DW_Form_RefAddr, DW_Form_RefUData, DW_Form_RefSig8, DW_Form_RefSup8, etc.
}
+1
View File
@@ -63,6 +63,7 @@ struct DW2_ParseCtx
DW_Ext ext;
U64 addr_size;
U64 unit_base_addr;
U64 unit_base_info_off;
DW2_AbbrevMap *abbrev_map;
DW2_OffsetTable *rnglists_table;
DW2_OffsetTable *str_offsets_table;
+429 -176
View File
@@ -563,6 +563,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
ctx->version = hdr->version;
ctx->format = hdr->format;
ctx->addr_size = hdr->addr_size;
ctx->unit_base_info_off = unit_info_ranges->v[unit_idx].min;
ctx->abbrev_map = abbrev_map_from_unit_idx_table[unit_idx];
}
}
@@ -1489,89 +1490,55 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
{
break;
}
Temp work_scratch = scratch_begin(&scratch.arena, 1);
//- rjf: unpack work
U64 origin_unit_idx = sub_unit_works[work_idx].unit_idx;
Rng1U64 origin_unit_root_tag_idx_range = sub_unit_works[work_idx].root_tag_idx_range;
//- rjf: unpack unit info
DW2_ParseCtx *origin_unit_parse_ctx = &unit_parse_ctxs[origin_unit_idx];
Rng1U64 origin_unit_info_tag_range = unit_info_tag_ranges[origin_unit_idx];
//- rjf: hash all content from to-be-deduplicated tags in this unit; record if unique
for(U64 root_tag_idx = origin_unit_root_tag_idx_range.min; root_tag_idx < origin_unit_root_tag_idx_range.max; root_tag_idx += 1)
//- rjf: gather all tags which we want to deduplicate
typedef struct D2R2_TagNode D2R2_TagNode;
struct D2R2_TagNode
{
S64 origin_unit_depth = 1;
for(U64 off = unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx];
off < origin_unit_info_tag_range.max && (origin_unit_depth > 1 || off == unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx]);)
{
Temp scratch2 = scratch_begin(&scratch.arena, 1);
U64 start_off = off;
//- rjf: hash deduped tags - this requires a hash of not only flat tag
// attributes, but also a walk of all other tags this tag references,
// and a hash of them too. so we produce a list of tasks for
// parsing/hashing tags, in order to find the full comprehensive hash
// for each tag.
//
// importantly, doing this can cause cycles in principle, so we also
// record which tags we visited, & order them, so we can just hash the
// order index, instead of doing a full recursion.
//
B32 is_deduped_tag_tree = 0;
DW_TagKind tree_root_tag_kind = DW_TagKind_Null;
D2R2_UniqueTagKind unique_tag_kind = D2R2_UniqueTagKind_Type;
B32 tag_has_children = 0;
B32 tag_ends_children = 0;
U64 hash = 0;
{
typedef struct TypeTagTask TypeTagTask;
struct TypeTagTask
{
TypeTagTask *next;
U64 unit_idx;
U64 off;
U64 order_idx;
D2R2_TagNode *next;
D2R2_UniqueTagKind kind;
U64 info_off;
U64 container_ancestor_info_off;
U64 hash_seed;
};
TypeTagTask start_task = {0, origin_unit_idx, off};
TypeTagTask *top_task = &start_task;
TypeTagTask *free_task = 0;
U64 seen_task_slots_count = 16;
TypeTagTask **seen_task_slots = push_array(scratch2.arena, TypeTagTask *, seen_task_slots_count);
for(TypeTagTask *t = top_task, *next = 0; t != 0; t = next)
D2R2_TagNode *first_tag_to_dedup = 0;
D2R2_TagNode *last_tag_to_dedup = 0;
for(U64 root_tag_idx = origin_unit_root_tag_idx_range.min;
root_tag_idx < origin_unit_root_tag_idx_range.max;
root_tag_idx += 1)
{
next = 0;
U64 t_off = t->off;
// rjf: record this task in our seen task table
U64 root_tag_start_off = unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx];
typedef struct D2R2_ParentTagNode D2R2_ParentTagNode;
struct D2R2_ParentTagNode
{
U64 hash = u64_hash_from_str8(str8_struct(&t->off));
U64 slot_idx = hash%seen_task_slots_count;
SLLStackPush(seen_task_slots[slot_idx], t);
}
// rjf: unpack unit
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[t->unit_idx];
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[t->unit_idx];
// rjf: read/hash the full tag tree at `t_off`; kick off additional
// tasks for referenced dependency types
U64 depth = 0;
for(;unit_info_tag_range.min <= t_off && t_off < unit_info_tag_range.max;)
D2R2_ParentTagNode *next;
DW_TagKind tag_kind;
U64 info_off;
U64 hash_seed;
};
D2R2_ParentTagNode *top_parent = 0;
D2R2_ParentTagNode *free_parent = 0;
S64 depth = 0;
for(U64 off = root_tag_start_off; contains_1u64(origin_unit_info_tag_range, off) && (depth > 0 || off == root_tag_start_off);)
{
U64 t_start_off = t_off;
Temp tag_scratch = scratch_begin(&work_scratch.arena, 1);
U64 start_off = off;
// rjf: read tag
DW2_Tag tag = {0};
t_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, t_off, &tag);
off += dw2_read_tag(tag_scratch.arena, origin_unit_parse_ctx, raw->sec[DW_Section_Info].data, off, &tag);
// rjf: determine if tag should be skipped
B32 should_skip_tag = (tag.kind == DW_TagKind_LexicalBlock ||
tag.kind == DW_TagKind_Variable);
// rjf: record top-level info about this tag tree
if(t_start_off == t->off && t == &start_task)
{
is_deduped_tag_tree = (tag.kind == DW_TagKind_ArrayType ||
// rjf: is this one of the tags we'd like to dedup? -> gather
if(tag.kind == DW_TagKind_ArrayType ||
tag.kind == DW_TagKind_ClassType ||
tag.kind == DW_TagKind_EnumerationType ||
tag.kind == DW_TagKind_PointerType ||
@@ -1598,28 +1565,149 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
tag.kind == DW_TagKind_DynamicType ||
tag.kind == DW_TagKind_AtomicType ||
tag.kind == DW_TagKind_ImmutableType ||
tag.kind == DW_TagKind_Namespace);
tag_has_children = tag.has_children;
tag_ends_children = (tag.kind == DW_TagKind_Null);
if(is_deduped_tag_tree)
tag.kind == DW_TagKind_Namespace)
{
tree_root_tag_kind = tag.kind;
if(tag.kind == DW_TagKind_Namespace)
U64 container_ancestor_info_off = 0;
for EachNode(n, D2R2_ParentTagNode, top_parent)
{
unique_tag_kind = D2R2_UniqueTagKind_Namespace;
if(n->tag_kind == DW_TagKind_StructureType ||
n->tag_kind == DW_TagKind_UnionType ||
n->tag_kind == DW_TagKind_ClassType ||
n->tag_kind == DW_TagKind_SubProgram ||
n->tag_kind == DW_TagKind_LexicalBlock ||
n->tag_kind == DW_TagKind_Namespace)
{
container_ancestor_info_off = n->info_off;
break;
}
}
D2R2_TagNode *n = push_array(work_scratch.arena, D2R2_TagNode, 1);
n->kind = (tag.kind == DW_TagKind_Namespace ? D2R2_UniqueTagKind_Namespace : D2R2_UniqueTagKind_Type);
n->info_off = start_off;
n->container_ancestor_info_off = container_ancestor_info_off;
n->hash_seed = top_parent ? top_parent->hash_seed : 0;
SLLQueuePush(first_tag_to_dedup, last_tag_to_dedup, n);
}
// rjf: compute hash seed for this tag
U64 hash_seed = (top_parent ? top_parent->hash_seed : 0);
if(tag.kind == DW_TagKind_SubProgram ||
tag.kind == DW_TagKind_StructureType ||
tag.kind == DW_TagKind_UnionType ||
tag.kind == DW_TagKind_ClassType ||
tag.kind == DW_TagKind_Namespace)
{
DW2_Attrib *name_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Name);
if(name_attrib != &dw2_attrib_nil)
{
hash_seed = u64_hash_from_str8(name_attrib->val.string);
}
}
// rjf: update depth / parent stack
if(tag.has_children)
{
depth += 1;
D2R2_ParentTagNode *n = free_parent;
if(n != 0)
{
SLLStackPop(free_parent);
}
else
{
n = push_array(work_scratch.arena, D2R2_ParentTagNode, 1);
}
SLLStackPush(top_parent, n);
n->tag_kind = tag.kind;
n->info_off = start_off;
n->hash_seed = hash_seed;
}
if(tag.kind == DW_TagKind_Null)
{
depth -= 1;
depth = Max(0, depth);
if(top_parent != 0)
{
D2R2_ParentTagNode *popped = top_parent;
SLLStackPop(top_parent);
SLLStackPush(free_parent, popped);
}
}
scratch_end(tag_scratch);
if(off == start_off)
{
break;
}
}
}
// rjf: determine if we want to consider tag children as part of the content hash
//- rjf: hash all tags we need to deduplicate & gather
for(D2R2_TagNode *tag_n = first_tag_to_dedup; tag_n != 0; tag_n = tag_n->next)
{
Temp dedup_root_scratch = scratch_begin(&scratch.arena, 1);
U64 start_off = tag_n->info_off;
D2R2_UniqueTagKind unique_tag_kind = tag_n->kind;
U64 container_ancestor_info_off = tag_n->container_ancestor_info_off;
U64 hash_seed = tag_n->hash_seed;
//- rjf: hash all tags & dependency tag trees
U64 hash = hash_seed;
{
typedef struct TagTask TagTask;
struct TagTask
{
TagTask *next;
U64 unit_idx;
U64 off;
U64 order_idx;
};
TagTask start_task = {0, origin_unit_idx, start_off};
TagTask *top_task = &start_task;
TagTask *free_task = 0;
U64 seen_task_slots_count = 16;
TagTask **seen_task_slots = push_array(dedup_root_scratch.arena, TagTask *, seen_task_slots_count);
for(TagTask *t = top_task, *next = 0; t != 0; t = next)
{
next = 0;
U64 t_off = t->off;
// rjf: record this task in our seen task table
{
U64 hash = u64_hash_from_str8(str8_struct(&t->off));
U64 slot_idx = hash%seen_task_slots_count;
SLLStackPush(seen_task_slots[slot_idx], t);
}
// rjf: unpack unit
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[t->unit_idx];
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[t->unit_idx];
// rjf: read/hash the full tag tree at `t_off`; kick off additional
// tasks for referenced dependency types
S64 depth = 0;
B32 hash_should_include_children = 1;
if(tree_root_tag_kind == DW_TagKind_Namespace)
for(;unit_info_tag_range.min <= t_off && t_off < unit_info_tag_range.max && (depth > 0 || t_off == t->off);)
{
Temp tag_scratch = scratch_begin(&dedup_root_scratch.arena, 1);
U64 t_start_off = t_off;
// rjf: read tag
DW2_Tag tag = {0};
t_off += dw2_read_tag(tag_scratch.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, t_off, &tag);
// rjf: determine if tag should be skipped from hashing
B32 should_skip_tag = (tag.kind == DW_TagKind_LexicalBlock ||
tag.kind == DW_TagKind_Variable);
// rjf: determine if we want to consider tag children as part of the content hash
if(t_start_off == t->off && tag.kind == DW_TagKind_Namespace)
{
hash_should_include_children = 0;
}
// rjf: is type -> combine tag's content into hash
if(!should_skip_tag && is_deduped_tag_tree)
// rjf: if we want to combine this tag into the hash -> combine
if(!should_skip_tag)
{
// rjf: combine tag's kind
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
@@ -1677,7 +1765,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
{
U64 off_hash = u64_hash_from_str8(str8_struct(&ref_info_off));
U64 off_slot_idx = off_hash%seen_task_slots_count;
for(TypeTagTask *t = seen_task_slots[off_slot_idx]; t != 0; t = t->next)
for(TagTask *t = seen_task_slots[off_slot_idx]; t != 0; t = t->next)
{
if(t->off == ref_info_off)
{
@@ -1697,15 +1785,16 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
// rjf: if we've not seen -> descend
if(!already_seen)
{
TypeTagTask *dependency_task = free_task;
TagTask *dependency_task = free_task;
if(dependency_task != 0)
{
SLLStackPop(free_task);
}
else
{
dependency_task = push_array(scratch2.arena, TypeTagTask, 1);
dependency_task = push_array(dedup_root_scratch.arena, TagTask, 1);
}
dependency_task->next = next;
next = dependency_task;
dependency_task->off = ref_info_off;
dependency_task->unit_idx = t->unit_idx;
@@ -1723,59 +1812,25 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
}
}
// rjf: is type tag tree, has children -> descend
if(is_deduped_tag_tree && hash_should_include_children && tag.has_children)
// rjf: tree nav if we need to
if(hash_should_include_children)
{
if(tag.has_children)
{
depth += 1;
}
// rjf: zero tag kind -> ascend
if(is_deduped_tag_tree && tag.kind == DW_TagKind_Null && depth > 0)
if(tag.kind == DW_TagKind_Null)
{
depth -= 1;
}
// rjf: no advancing? -> +1
if(t_off == t_start_off)
{
t_off += 1;
}
// rjf: depth == 0? -> done
if(depth == 0)
{
break;
depth = Max(0, depth);
}
}
// rjf: is this the starter task? -> advance base reading offset
//
// NOTE(rjf): in the case of functions, we need to apply the entire type
// discovery/hashing/gathering work to children of functions - *but* we
// also need to hash other children of functions. so, in that case, we
// only advance past the function root tag once we're done hashing all
// children we want - but, we still need to parse the children of the
// function again, in order to find types etc. contained within functions.
//
if(t == &start_task && tree_root_tag_kind == DW_TagKind_SubProgram && t->off == start_off)
{
off = t_off;
}
else if(t == &start_task)
{
off = t_off;
scratch_end(tag_scratch);
}
}
}
//- rjf: if offset not advanced -> increment
if(off == start_off)
{
off += 1;
}
//- rjf: atomically gather this hash if not already gathered
if(is_deduped_tag_tree)
{
B32 gathered = 0;
U64 slot_idx = hash%unique_tag_slots_count;
@@ -1856,6 +1911,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
n->kind = unique_tag_kind;
n->hash = hash;
n->info_off = start_off;
n->container_ancestor_info_off = container_ancestor_info_off;
U64 new_head_val = (U64)n;
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unique_tag_slots[slot_idx], new_head_val, slot_head_val))
{
@@ -1872,7 +1928,6 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
//- rjf: atomically record this (info_off -> hash) mapping, so that when we have
// later references to this type, we can redirect to the deduplicated type with
// the right hash later.
if(is_deduped_tag_tree)
{
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_maps[origin_unit_idx].slots_count;
@@ -1889,28 +1944,10 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
}
}
}
//- rjf: navigate tree in origin unit - only if we are not iterating
// a type tree. the type tree will have already been processed, because
// we needed to hash all of the content. but for non-type tag trees,
// we need to descend and parse their contents, since they may contain
// types themselves.
//
if(!is_deduped_tag_tree)
{
if(tag_has_children)
{
origin_unit_depth += 1;
}
if(tag_ends_children)
{
origin_unit_depth -= 1;
}
scratch_end(dedup_root_scratch);
}
scratch_end(scratch2);
}
}
scratch_end(work_scratch);
}
lane_sync();
}
@@ -2938,6 +2975,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
// rjf: unpack type
RDIM_Type *type = 0;
if(type_attrib != &dw2_attrib_nil)
{
// rjf: attrib -> info off / unit idx
U64 type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
@@ -3239,18 +3277,22 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
//- rjf: produce all unit symbols in this work
typedef struct D2R2_ScopeNode D2R2_ScopeNode;
struct D2R2_ScopeNode
{
D2R2_ScopeNode *next;
RDIM_Scope *scope;
RDIM_LocationCaseList framebase_location_cases;
};
D2R2_ScopeNode *top_scope = 0;
D2R2_ScopeNode *free_scope = 0;
U64 chunk_count = 256;
for(U64 root_tag_idx = root_tag_idx_range.min; root_tag_idx < root_tag_idx_range.max; root_tag_idx += 1)
{
typedef struct D2R2_ParentNode D2R2_ParentNode;
struct D2R2_ParentNode
{
D2R2_ParentNode *next;
DW_TagKind tag_kind;
U64 info_off;
RDIM_Scope *scope;
RDIM_Type *container_type;
RDIM_Namespace *container_namespace;
RDIM_LocationCaseList framebase_location_cases;
};
D2R2_ParentNode *top_parent = 0;
D2R2_ParentNode *free_parent = 0;
U64 root_tag_start_off = unit_info_root_tag_offs[unit_idx].v[root_tag_idx];
S64 depth = 1;
for(U64 off = root_tag_start_off; off < unit_info_tag_range.max && (depth > 1 || off == root_tag_start_off);)
@@ -3466,7 +3508,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
//- rjf: iterate each frame base location case, or once if there are none,
// and convert the location in that context
RDIM_LocationCase nil_framebase_loc_case = {0, {0}, {0, max_U64}};
for(RDIM_LocationCase *framebase_loc_n = top_scope ? top_scope->framebase_location_cases.first : &nil_framebase_loc_case;
for(RDIM_LocationCase *framebase_loc_n = top_parent ? top_parent->framebase_location_cases.first : &nil_framebase_loc_case;
framebase_loc_n != 0;
framebase_loc_n = framebase_loc_n->next)
{
@@ -4161,6 +4203,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
////////////////////////
//- rjf: produce symbols from tag
//
RDIM_Symbol *new_symbol = 0;
RDIM_Scope *new_scope_open = 0;
switch(tag.kind)
{
@@ -4179,13 +4222,14 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
root_scope->symbol = procedure;
root_scope->voff_ranges = ranges;
dst_artifacts->scopes.scope_voff_count += 2*ranges.count;
new_symbol = procedure;
new_scope_open = root_scope;
}break;
//- rjf: inline site
case DW_TagKind_InlinedSubroutine:
{
// TODO(rjf)
}break;
//- rjf: variables
@@ -4199,9 +4243,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
{
dst_symbols = &dst_artifacts->thread_variables;
}
else if(top_scope != 0)
else if(top_parent != 0 && top_parent->scope != 0)
{
dst_symbols = &top_scope->scope->locals;
dst_symbols = &top_parent->scope->locals;
var_chunk_count = 8;
}
RDIM_Symbol *var = rdim_symbol_chunk_list_push(arena, dst_symbols, var_chunk_count);
@@ -4210,11 +4254,8 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
var->name = name;
var->link_name = link_name;
var->type = type;
if(top_scope != 0)
{
var->container_scope = top_scope->scope;
}
var->location_cases = location_cases;
new_symbol = var;
}break;
//- rjf: lexical blocks (scopes)
@@ -4228,14 +4269,30 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
}
////////////////////////
//- rjf: push scopes
//- rjf: equip new symbols with container info
//
if(new_scope_open)
if(new_symbol != 0 && top_parent != 0)
{
// rjf: insert scope to parent
if(top_scope != 0)
if(top_parent->scope != 0)
{
RDIM_Scope *parent = top_scope->scope;
new_symbol->container_scope = top_parent->scope;
}
else if(top_parent->container_type != 0)
{
new_symbol->container_type = top_parent->container_type;
}
else if(top_parent->container_namespace != 0)
{
new_symbol->container_namespace = top_parent->container_namespace;
}
}
////////////////////////
//- rjf: insert new scopes to their parent
//
if(new_scope_open && top_parent != 0 && top_parent->scope != 0)
{
RDIM_Scope *parent = top_parent->scope;
SLLQueuePush_N(parent->first_child, parent->last_child, new_scope_open, next_sibling);
new_scope_open->parent_scope = parent;
if(new_scope_open->symbol == 0)
@@ -4244,36 +4301,91 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
}
}
// rjf: push new scope to stack
D2R2_ScopeNode *n = free_scope;
////////////////////////
//- rjf: gather container info for new tag parents
//
RDIM_Type *container_type = 0;
RDIM_Namespace *container_namespace = 0;
if(tag.has_children)
{
// rjf: info offset -> hash
U64 hash = 0;
{
UnitDedupedTagMap *unit_deduped_tag_map = &unit_deduped_tag_maps[unit_idx];
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_map->slots_count;
for EachNode(n, UnitDedupedTagNode, unit_deduped_tag_map->slots[info_off_slot_idx])
{
if(n->src_info_off == start_off)
{
hash = n->dst_hash;
break;
}
}
}
// rjf: map hash -> unique tag node
D2R2_UniqueTagNode *tag_node = 0;
{
U64 slot_idx = hash%unique_tag_slots_count;
for(D2R2_UniqueTagNode *n = unique_tag_slots[slot_idx]; n != 0; n = n->next)
{
if(n->hash == hash)
{
tag_node = n;
break;
}
}
}
// rjf: map tag node -> type/namespace
if(tag_node != 0) switch(tag_node->kind)
{
default:{}break;
case D2R2_UniqueTagKind_Type: {container_type = type_from_idx_map[tag_node->order_idx];}break;
case D2R2_UniqueTagKind_Namespace:{container_namespace = namespace_from_idx_map[tag_node->order_idx];}break;
}
}
////////////////////////
//- rjf: push tag parents
//
if(tag.has_children)
{
// rjf: push new parent to stack
D2R2_ParentNode *n = free_parent;
if(n != 0)
{
SLLStackPop(free_scope);
SLLStackPop(free_parent);
}
else
{
n = push_array(scratch.arena, D2R2_ScopeNode, 1);
n = push_array(scratch.arena, D2R2_ParentNode, 1);
}
n->scope = new_scope_open;
n->tag_kind = tag.kind;
n->info_off = start_off;
n->scope = new_scope_open ? new_scope_open : top_parent ? top_parent->scope : 0;
n->container_type = new_scope_open ? 0 : container_type;
n->container_namespace = new_scope_open ? 0 : container_namespace;
if(framebase_attrib != &dw2_attrib_nil)
{
n->framebase_location_cases = framebase_location_cases;
}
else if(top_scope != 0)
else if(top_parent != 0)
{
n->framebase_location_cases = top_scope->framebase_location_cases;
n->framebase_location_cases = top_parent->framebase_location_cases;
}
SLLStackPush(top_scope, n);
SLLStackPush(top_parent, n);
}
////////////////////////
//- rjf: pop scopes
//
if(tag.kind == DW_TagKind_Null && top_scope != 0)
if(tag.kind == DW_TagKind_Null && top_parent != 0)
{
D2R2_ScopeNode *n = top_scope;
SLLStackPop(top_scope);
SLLStackPush(free_scope, n);
D2R2_ParentNode *n = top_parent;
SLLStackPop(top_parent);
SLLStackPush(free_parent, n);
}
////////////////////////
@@ -4331,6 +4443,147 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
lane_sync();
}
////////////////////////////
//- rjf: upgrade all types with namespacing info
//
ProfScope("upgrade all types with namespacing info")
{
Rng1U64 range = lane_range(type_count);
for EachInRange(type_idx, range)
{
D2R2_UniqueTagNode *type_tag_node = type_tag_nodes[type_idx];
U64 container_ancestor_info_off = type_tag_node->container_ancestor_info_off;
RDIM_Type *dst_type = type_from_idx_map[type_idx];
if(dst_type == 0)
{
continue;
}
RDIM_UDT *dst_udt = dst_type->udt;
if(dst_udt == 0)
{
continue;
}
// rjf: find container types/namespaces
RDIM_Type *container_type = 0;
RDIM_Namespace *container_namespace = 0;
{
U64 info_off = container_ancestor_info_off;
U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off);
U64 unit_idx = unit_num > 0 ? unit_num-1 : 0;
// rjf: info off -> hash
U64 hash = 0;
{
UnitDedupedTagMap *unit_deduped_tag_map = &unit_deduped_tag_maps[unit_idx];
U64 info_off_hash = u64_hash_from_str8(str8_struct(&info_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_map->slots_count;
for(UnitDedupedTagNode *n = unit_deduped_tag_map->slots[info_off_slot_idx]; n != 0; n = n->next)
{
if(n->src_info_off == info_off)
{
hash = n->dst_hash;
break;
}
}
}
// rjf: hash -> type
{
U64 unique_type_tag_slot_idx = hash%unique_tag_slots_count;
for(D2R2_UniqueTagNode *n = unique_tag_slots[unique_type_tag_slot_idx]; n != 0; n = n->next)
{
if(n->hash == hash)
{
if(n->kind == D2R2_UniqueTagKind_Type)
{
container_type = type_from_idx_map[n->order_idx];
}
else if(n->kind == D2R2_UniqueTagKind_Namespace)
{
container_namespace = namespace_from_idx_map[n->order_idx];
}
break;
}
}
}
}
// rjf: fill
dst_udt->container_type = container_type;
dst_udt->container_namespace = container_namespace;
}
}
lane_sync();
////////////////////////////
//- rjf: upgrade all namespaces with namespacing info
//
ProfScope("upgrade all namespaces with namespacing info")
{
Rng1U64 range = lane_range(namespace_count);
for EachInRange(namespace_idx, range)
{
D2R2_UniqueTagNode *unique_tag_node = namespace_tag_nodes[namespace_idx];
U64 container_ancestor_info_off = unique_tag_node->container_ancestor_info_off;
RDIM_Namespace *dst_namespace = namespace_from_idx_map[namespace_idx];
if(dst_namespace == 0)
{
continue;
}
// rjf: find container types/namespaces
RDIM_Type *container_type = 0;
RDIM_Namespace *container_namespace = 0;
{
U64 info_off = container_ancestor_info_off;
U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off);
U64 unit_idx = unit_num > 0 ? unit_num-1 : 0;
// rjf: info off -> hash
U64 hash = 0;
{
UnitDedupedTagMap *unit_deduped_tag_map = &unit_deduped_tag_maps[unit_idx];
U64 info_off_hash = u64_hash_from_str8(str8_struct(&info_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_map->slots_count;
for(UnitDedupedTagNode *n = unit_deduped_tag_map->slots[info_off_slot_idx]; n != 0; n = n->next)
{
if(n->src_info_off == info_off)
{
hash = n->dst_hash;
break;
}
}
}
// rjf: hash -> type
{
U64 unique_type_tag_slot_idx = hash%unique_tag_slots_count;
for(D2R2_UniqueTagNode *n = unique_tag_slots[unique_type_tag_slot_idx]; n != 0; n = n->next)
{
if(n->hash == hash)
{
if(n->kind == D2R2_UniqueTagKind_Type)
{
container_type = type_from_idx_map[n->order_idx];
}
else if(n->kind == D2R2_UniqueTagKind_Namespace)
{
container_namespace = namespace_from_idx_map[n->order_idx];
}
break;
}
}
}
}
// rjf: fill
dst_namespace->parent_type = container_type;
dst_namespace->parent_namespace = container_namespace;
}
}
lane_sync();
////////////////////////////
//- rjf: fill result
//
+1
View File
@@ -22,6 +22,7 @@ struct D2R2_UniqueTagNode
D2R2_UniqueTagKind kind;
U64 hash;
U64 info_off;
U64 container_ancestor_info_off;
U64 order_idx;
};