mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
d2r2: deduper fixes/simplification, first half of structured namespace support
This commit is contained in:
@@ -583,7 +583,7 @@ dw2_reference_info_off_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal *v)
|
|||||||
case DW_Form_Ref4:
|
case DW_Form_Ref4:
|
||||||
case DW_Form_Ref8:
|
case DW_Form_Ref8:
|
||||||
{
|
{
|
||||||
result = v->u128.u64[0];
|
result = ctx->unit_base_info_off + v->u128.u64[0];
|
||||||
}break;
|
}break;
|
||||||
// TODO(rjf): DW_Form_RefAddr, DW_Form_RefUData, DW_Form_RefSig8, DW_Form_RefSup8, etc.
|
// TODO(rjf): DW_Form_RefAddr, DW_Form_RefUData, DW_Form_RefSig8, DW_Form_RefSup8, etc.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ struct DW2_ParseCtx
|
|||||||
DW_Ext ext;
|
DW_Ext ext;
|
||||||
U64 addr_size;
|
U64 addr_size;
|
||||||
U64 unit_base_addr;
|
U64 unit_base_addr;
|
||||||
|
U64 unit_base_info_off;
|
||||||
DW2_AbbrevMap *abbrev_map;
|
DW2_AbbrevMap *abbrev_map;
|
||||||
DW2_OffsetTable *rnglists_table;
|
DW2_OffsetTable *rnglists_table;
|
||||||
DW2_OffsetTable *str_offsets_table;
|
DW2_OffsetTable *str_offsets_table;
|
||||||
|
|||||||
@@ -563,6 +563,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
ctx->version = hdr->version;
|
ctx->version = hdr->version;
|
||||||
ctx->format = hdr->format;
|
ctx->format = hdr->format;
|
||||||
ctx->addr_size = hdr->addr_size;
|
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];
|
ctx->abbrev_map = abbrev_map_from_unit_idx_table[unit_idx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1489,89 +1490,55 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Temp work_scratch = scratch_begin(&scratch.arena, 1);
|
||||||
|
|
||||||
//- rjf: unpack work
|
//- rjf: unpack work
|
||||||
U64 origin_unit_idx = sub_unit_works[work_idx].unit_idx;
|
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;
|
Rng1U64 origin_unit_root_tag_idx_range = sub_unit_works[work_idx].root_tag_idx_range;
|
||||||
|
|
||||||
//- rjf: unpack unit info
|
//- 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];
|
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
|
//- rjf: gather all tags which we want to deduplicate
|
||||||
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)
|
typedef struct D2R2_TagNode D2R2_TagNode;
|
||||||
|
struct D2R2_TagNode
|
||||||
{
|
{
|
||||||
S64 origin_unit_depth = 1;
|
D2R2_TagNode *next;
|
||||||
for(U64 off = unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx];
|
D2R2_UniqueTagKind kind;
|
||||||
off < origin_unit_info_tag_range.max && (origin_unit_depth > 1 || off == unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx]);)
|
U64 info_off;
|
||||||
{
|
U64 container_ancestor_info_off;
|
||||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
U64 hash_seed;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
TypeTagTask start_task = {0, origin_unit_idx, off};
|
D2R2_TagNode *first_tag_to_dedup = 0;
|
||||||
TypeTagTask *top_task = &start_task;
|
D2R2_TagNode *last_tag_to_dedup = 0;
|
||||||
TypeTagTask *free_task = 0;
|
for(U64 root_tag_idx = origin_unit_root_tag_idx_range.min;
|
||||||
U64 seen_task_slots_count = 16;
|
root_tag_idx < origin_unit_root_tag_idx_range.max;
|
||||||
TypeTagTask **seen_task_slots = push_array(scratch2.arena, TypeTagTask *, seen_task_slots_count);
|
root_tag_idx += 1)
|
||||||
for(TypeTagTask *t = top_task, *next = 0; t != 0; t = next)
|
|
||||||
{
|
{
|
||||||
next = 0;
|
U64 root_tag_start_off = unit_info_root_tag_offs[origin_unit_idx].v[root_tag_idx];
|
||||||
U64 t_off = t->off;
|
typedef struct D2R2_ParentTagNode D2R2_ParentTagNode;
|
||||||
|
struct D2R2_ParentTagNode
|
||||||
// rjf: record this task in our seen task table
|
|
||||||
{
|
{
|
||||||
U64 hash = u64_hash_from_str8(str8_struct(&t->off));
|
D2R2_ParentTagNode *next;
|
||||||
U64 slot_idx = hash%seen_task_slots_count;
|
DW_TagKind tag_kind;
|
||||||
SLLStackPush(seen_task_slots[slot_idx], t);
|
U64 info_off;
|
||||||
}
|
U64 hash_seed;
|
||||||
|
};
|
||||||
// rjf: unpack unit
|
D2R2_ParentTagNode *top_parent = 0;
|
||||||
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[t->unit_idx];
|
D2R2_ParentTagNode *free_parent = 0;
|
||||||
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[t->unit_idx];
|
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);)
|
||||||
// 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;)
|
|
||||||
{
|
{
|
||||||
U64 t_start_off = t_off;
|
Temp tag_scratch = scratch_begin(&work_scratch.arena, 1);
|
||||||
|
U64 start_off = off;
|
||||||
|
|
||||||
// rjf: read tag
|
// rjf: read tag
|
||||||
DW2_Tag tag = {0};
|
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
|
// rjf: is this one of the tags we'd like to dedup? -> gather
|
||||||
B32 should_skip_tag = (tag.kind == DW_TagKind_LexicalBlock ||
|
if(tag.kind == DW_TagKind_ArrayType ||
|
||||||
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 ||
|
|
||||||
tag.kind == DW_TagKind_ClassType ||
|
tag.kind == DW_TagKind_ClassType ||
|
||||||
tag.kind == DW_TagKind_EnumerationType ||
|
tag.kind == DW_TagKind_EnumerationType ||
|
||||||
tag.kind == DW_TagKind_PointerType ||
|
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_DynamicType ||
|
||||||
tag.kind == DW_TagKind_AtomicType ||
|
tag.kind == DW_TagKind_AtomicType ||
|
||||||
tag.kind == DW_TagKind_ImmutableType ||
|
tag.kind == DW_TagKind_ImmutableType ||
|
||||||
tag.kind == DW_TagKind_Namespace);
|
tag.kind == DW_TagKind_Namespace)
|
||||||
tag_has_children = tag.has_children;
|
|
||||||
tag_ends_children = (tag.kind == DW_TagKind_Null);
|
|
||||||
if(is_deduped_tag_tree)
|
|
||||||
{
|
{
|
||||||
tree_root_tag_kind = tag.kind;
|
U64 container_ancestor_info_off = 0;
|
||||||
if(tag.kind == DW_TagKind_Namespace)
|
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;
|
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;
|
hash_should_include_children = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: is type -> combine tag's content into hash
|
// rjf: if we want to combine this tag into the hash -> combine
|
||||||
if(!should_skip_tag && is_deduped_tag_tree)
|
if(!should_skip_tag)
|
||||||
{
|
{
|
||||||
// rjf: combine tag's kind
|
// rjf: combine tag's kind
|
||||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.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_hash = u64_hash_from_str8(str8_struct(&ref_info_off));
|
||||||
U64 off_slot_idx = off_hash%seen_task_slots_count;
|
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)
|
if(t->off == ref_info_off)
|
||||||
{
|
{
|
||||||
@@ -1697,15 +1785,16 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
// rjf: if we've not seen -> descend
|
// rjf: if we've not seen -> descend
|
||||||
if(!already_seen)
|
if(!already_seen)
|
||||||
{
|
{
|
||||||
TypeTagTask *dependency_task = free_task;
|
TagTask *dependency_task = free_task;
|
||||||
if(dependency_task != 0)
|
if(dependency_task != 0)
|
||||||
{
|
{
|
||||||
SLLStackPop(free_task);
|
SLLStackPop(free_task);
|
||||||
}
|
}
|
||||||
else
|
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;
|
next = dependency_task;
|
||||||
dependency_task->off = ref_info_off;
|
dependency_task->off = ref_info_off;
|
||||||
dependency_task->unit_idx = t->unit_idx;
|
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
|
// rjf: tree nav if we need to
|
||||||
if(is_deduped_tag_tree && hash_should_include_children && tag.has_children)
|
if(hash_should_include_children)
|
||||||
|
{
|
||||||
|
if(tag.has_children)
|
||||||
{
|
{
|
||||||
depth += 1;
|
depth += 1;
|
||||||
}
|
}
|
||||||
|
if(tag.kind == DW_TagKind_Null)
|
||||||
// rjf: zero tag kind -> ascend
|
|
||||||
if(is_deduped_tag_tree && tag.kind == DW_TagKind_Null && depth > 0)
|
|
||||||
{
|
{
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
}
|
depth = Max(0, depth);
|
||||||
|
|
||||||
// rjf: no advancing? -> +1
|
|
||||||
if(t_off == t_start_off)
|
|
||||||
{
|
|
||||||
t_off += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: depth == 0? -> done
|
|
||||||
if(depth == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
scratch_end(tag_scratch);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: if offset not advanced -> increment
|
|
||||||
if(off == start_off)
|
|
||||||
{
|
|
||||||
off += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: atomically gather this hash if not already gathered
|
//- rjf: atomically gather this hash if not already gathered
|
||||||
if(is_deduped_tag_tree)
|
|
||||||
{
|
{
|
||||||
B32 gathered = 0;
|
B32 gathered = 0;
|
||||||
U64 slot_idx = hash%unique_tag_slots_count;
|
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->kind = unique_tag_kind;
|
||||||
n->hash = hash;
|
n->hash = hash;
|
||||||
n->info_off = start_off;
|
n->info_off = start_off;
|
||||||
|
n->container_ancestor_info_off = container_ancestor_info_off;
|
||||||
U64 new_head_val = (U64)n;
|
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))
|
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
|
//- 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
|
// later references to this type, we can redirect to the deduplicated type with
|
||||||
// the right hash later.
|
// the right hash later.
|
||||||
if(is_deduped_tag_tree)
|
|
||||||
{
|
{
|
||||||
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
|
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;
|
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
scratch_end(dedup_root_scratch);
|
||||||
//- 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(scratch2);
|
scratch_end(work_scratch);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lane_sync();
|
lane_sync();
|
||||||
}
|
}
|
||||||
@@ -2938,6 +2975,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
|
|
||||||
// rjf: unpack type
|
// rjf: unpack type
|
||||||
RDIM_Type *type = 0;
|
RDIM_Type *type = 0;
|
||||||
|
if(type_attrib != &dw2_attrib_nil)
|
||||||
{
|
{
|
||||||
// rjf: attrib -> info off / unit idx
|
// rjf: attrib -> info off / unit idx
|
||||||
U64 type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
|
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];
|
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
|
||||||
|
|
||||||
//- rjf: produce all unit symbols in this work
|
//- 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;
|
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)
|
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];
|
U64 root_tag_start_off = unit_info_root_tag_offs[unit_idx].v[root_tag_idx];
|
||||||
S64 depth = 1;
|
S64 depth = 1;
|
||||||
for(U64 off = root_tag_start_off; off < unit_info_tag_range.max && (depth > 1 || off == root_tag_start_off);)
|
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,
|
//- rjf: iterate each frame base location case, or once if there are none,
|
||||||
// and convert the location in that context
|
// and convert the location in that context
|
||||||
RDIM_LocationCase nil_framebase_loc_case = {0, {0}, {0, max_U64}};
|
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 != 0;
|
||||||
framebase_loc_n = framebase_loc_n->next)
|
framebase_loc_n = framebase_loc_n->next)
|
||||||
{
|
{
|
||||||
@@ -4161,6 +4203,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
//- rjf: produce symbols from tag
|
//- rjf: produce symbols from tag
|
||||||
//
|
//
|
||||||
|
RDIM_Symbol *new_symbol = 0;
|
||||||
RDIM_Scope *new_scope_open = 0;
|
RDIM_Scope *new_scope_open = 0;
|
||||||
switch(tag.kind)
|
switch(tag.kind)
|
||||||
{
|
{
|
||||||
@@ -4179,13 +4222,14 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
root_scope->symbol = procedure;
|
root_scope->symbol = procedure;
|
||||||
root_scope->voff_ranges = ranges;
|
root_scope->voff_ranges = ranges;
|
||||||
dst_artifacts->scopes.scope_voff_count += 2*ranges.count;
|
dst_artifacts->scopes.scope_voff_count += 2*ranges.count;
|
||||||
|
new_symbol = procedure;
|
||||||
new_scope_open = root_scope;
|
new_scope_open = root_scope;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: inline site
|
//- rjf: inline site
|
||||||
case DW_TagKind_InlinedSubroutine:
|
case DW_TagKind_InlinedSubroutine:
|
||||||
{
|
{
|
||||||
|
// TODO(rjf)
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: variables
|
//- rjf: variables
|
||||||
@@ -4199,9 +4243,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
dst_symbols = &dst_artifacts->thread_variables;
|
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;
|
var_chunk_count = 8;
|
||||||
}
|
}
|
||||||
RDIM_Symbol *var = rdim_symbol_chunk_list_push(arena, dst_symbols, var_chunk_count);
|
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->name = name;
|
||||||
var->link_name = link_name;
|
var->link_name = link_name;
|
||||||
var->type = type;
|
var->type = type;
|
||||||
if(top_scope != 0)
|
|
||||||
{
|
|
||||||
var->container_scope = top_scope->scope;
|
|
||||||
}
|
|
||||||
var->location_cases = location_cases;
|
var->location_cases = location_cases;
|
||||||
|
new_symbol = var;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: lexical blocks (scopes)
|
//- 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_parent->scope != 0)
|
||||||
if(top_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);
|
SLLQueuePush_N(parent->first_child, parent->last_child, new_scope_open, next_sibling);
|
||||||
new_scope_open->parent_scope = parent;
|
new_scope_open->parent_scope = parent;
|
||||||
if(new_scope_open->symbol == 0)
|
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)
|
if(n != 0)
|
||||||
{
|
{
|
||||||
SLLStackPop(free_scope);
|
SLLStackPop(free_parent);
|
||||||
}
|
}
|
||||||
else
|
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)
|
if(framebase_attrib != &dw2_attrib_nil)
|
||||||
{
|
{
|
||||||
n->framebase_location_cases = framebase_location_cases;
|
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
|
//- 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;
|
D2R2_ParentNode *n = top_parent;
|
||||||
SLLStackPop(top_scope);
|
SLLStackPop(top_parent);
|
||||||
SLLStackPush(free_scope, n);
|
SLLStackPush(free_parent, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -4331,6 +4443,147 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
lane_sync();
|
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
|
//- rjf: fill result
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ struct D2R2_UniqueTagNode
|
|||||||
D2R2_UniqueTagKind kind;
|
D2R2_UniqueTagKind kind;
|
||||||
U64 hash;
|
U64 hash;
|
||||||
U64 info_off;
|
U64 info_off;
|
||||||
|
U64 container_ancestor_info_off;
|
||||||
U64 order_idx;
|
U64 order_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user