mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
d2r2: function type info; fix reg+off location info for signed offsets, function type deduplicating / construction / referencing, etc.
This commit is contained in:
+1
-1
@@ -1121,7 +1121,7 @@ typedef RDI_U64 RDI_Location;
|
||||
#define RDI_Location_RegOffShift 32
|
||||
#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))
|
||||
#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)
|
||||
#define rdi_regoff_from_location(l) (RDI_S64)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)
|
||||
#define rdi_regoff_from_location(l) (RDI_S64)(RDI_S32)(RDI_S16)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)
|
||||
#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||
#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||
#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||
|
||||
+2
-2
@@ -956,8 +956,8 @@ rb_thread_entry_point(void *p)
|
||||
{
|
||||
bake_params = push_array(arena, RDIM_BakeParams, 1);
|
||||
rdim_bake_params_concat_in_place(bake_params, &pdb_bake_params);
|
||||
rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params);
|
||||
// rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2);
|
||||
// rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params);
|
||||
rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2);
|
||||
for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params)
|
||||
{
|
||||
rdim_bake_params_concat_in_place(bake_params, &n->v);
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
// [x] container can also be a unit, so you can also go from procedure/global/tvar -> unit
|
||||
// [x] *OR*, because we can guarantee that the units themselves will be sorted from lowest -> highest in all symbol tables, we can simply binary search the unit table (small) with a symbol's index to find its corresponding unit. that way, no need to duplicate e.g. namespaces and so on across units. and actually, we have to do this, because containers can be types, and those cannot be unit-locked.
|
||||
//
|
||||
// [ ] symbols only store their *partly-qualified name*, e.g. `x` for A::B::C::x
|
||||
// [ ] default name maps look up *partly-qualified names*
|
||||
// [ ] to match a *fully qualified name*, there needs to be a second kind of different lookup - instead of string-matching, we need to match against the *fully qualified names*. the maps must be built by hashing the *fully qualified name*, but redirecting to the symbol with the *partially qualified name*. this is to allow fully-qualified lookups, but avoid storing fully-qualified names.
|
||||
// [x] symbols only store their *partly-qualified name*, e.g. `x` for A::B::C::x
|
||||
// [x] default name maps look up *partly-qualified names*
|
||||
// [x] to match a *fully qualified name*, there needs to be a second kind of different lookup - instead of string-matching, we need to match against the *fully qualified names*. the maps must be built by hashing the *fully qualified name*, but redirecting to the symbol with the *partially qualified name*. this is to allow fully-qualified lookups, but avoid storing fully-qualified names.
|
||||
//
|
||||
//- urgent fixes
|
||||
// [ ] (use msvc assert as an example) show fastfail exception info (code, name, etc.) - comes from ExceptionInformation @fastfail
|
||||
|
||||
+1
-1
@@ -1116,7 +1116,7 @@ RDI_LocationSetElementMemberTable:
|
||||
`#define RDI_Location_RegOffShift 32`;
|
||||
`#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))`;
|
||||
`#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)`;
|
||||
`#define rdi_regoff_from_location(l) (RDI_S64)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)`;
|
||||
`#define rdi_regoff_from_location(l) (RDI_S64)(RDI_S32)(RDI_S16)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)`;
|
||||
`#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||
`#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||
`#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||
|
||||
+1
-1
@@ -1073,7 +1073,7 @@ lane_sync(); if(flags & (1ull<<(kind))) ProfScope(rdi_name_title_from_dump_subse
|
||||
S64 reg_off = rdi_regoff_from_location(location);
|
||||
String8 reg_code_string = rdi_string_from_reg_code(scratch.arena, tli->arch, reg_code);
|
||||
dumpf(" reg: %S\n", reg_code_string);
|
||||
dumpf(" reg_off: 0x%I64x\n", reg_off);
|
||||
dumpf(" reg_off: %I64d (0x%x)\n", reg_off, (U16)reg_off);
|
||||
}break;
|
||||
case RDI_LocationKind_ValReg:
|
||||
{
|
||||
|
||||
@@ -1377,6 +1377,10 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
DW2_Tag tag = {0};
|
||||
t_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, t_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)
|
||||
{
|
||||
@@ -1388,6 +1392,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
tag.kind == DW_TagKind_StringType ||
|
||||
tag.kind == DW_TagKind_StructureType ||
|
||||
tag.kind == DW_TagKind_SubroutineType ||
|
||||
tag.kind == DW_TagKind_SubProgram ||
|
||||
tag.kind == DW_TagKind_Typedef ||
|
||||
tag.kind == DW_TagKind_UnionType ||
|
||||
tag.kind == DW_TagKind_PtrToMemberType ||
|
||||
@@ -1409,7 +1414,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
}
|
||||
|
||||
// rjf: is type -> combine tag's content into hash
|
||||
if(is_type_tag_tree)
|
||||
if(!should_skip_tag && is_type_tag_tree)
|
||||
{
|
||||
// rjf: combine tag's kind
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
|
||||
@@ -1427,7 +1432,18 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
n->v.val.kind != DW_Form_Ref8 &&
|
||||
n->v.val.kind != DW_Form_RefUData &&
|
||||
n->v.val.kind != DW_Form_RefSup4 &&
|
||||
n->v.val.kind != DW_Form_RefSig8)
|
||||
n->v.val.kind != DW_Form_RefSig8 &&
|
||||
((tag.kind != DW_TagKind_SubProgram &&
|
||||
tag.kind != DW_TagKind_FormalParameter) ||
|
||||
(n->v.attrib_kind != DW_AttribKind_Name &&
|
||||
n->v.attrib_kind != DW_AttribKind_DeclFile &&
|
||||
n->v.attrib_kind != DW_AttribKind_DeclLine &&
|
||||
n->v.attrib_kind != DW_AttribKind_Prototyped &&
|
||||
n->v.attrib_kind != DW_AttribKind_External &&
|
||||
n->v.attrib_kind != DW_AttribKind_FrameBase &&
|
||||
n->v.attrib_kind != DW_AttribKind_Location &&
|
||||
n->v.attrib_kind != DW_AttribKind_LowPc &&
|
||||
n->v.attrib_kind != DW_AttribKind_HighPc)))
|
||||
{
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.kind));
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.u128));
|
||||
@@ -1638,26 +1654,40 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
TypeDepChain *next;
|
||||
U64 type_idx;
|
||||
};
|
||||
TypeDepChain **type_dep_chains = 0;
|
||||
U64 *type_dep_chains_counts = 0;
|
||||
ProfScope("gather per-type dependency chains")
|
||||
{
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
type_dep_chains = push_array(scratch.arena, TypeDepChain *, type_count);
|
||||
type_dep_chains_counts = push_array(scratch.arena, U64, type_count);
|
||||
}
|
||||
lane_sync_u64(&type_dep_chains, 0);
|
||||
lane_sync_u64(&type_dep_chains_counts, 0);
|
||||
Rng1U64 range = lane_range(type_count);
|
||||
for EachInRange(root_type_idx, range)
|
||||
{
|
||||
for(U64 hash = type_tag_nodes[root_type_idx]->hash, next_hash = 0;
|
||||
hash != 0;
|
||||
hash = next_hash)
|
||||
typedef struct TypeChainTask TypeChainTask;
|
||||
struct TypeChainTask
|
||||
{
|
||||
TypeChainTask *next;
|
||||
U64 hash;
|
||||
};
|
||||
TypeChainTask start_task = {0, type_tag_nodes[root_type_idx]->hash};
|
||||
TypeChainTask *top_task = &start_task;
|
||||
TypeChainTask *free_task = 0;
|
||||
TypeChainTask *last_t = 0;
|
||||
for(TypeChainTask *t = top_task; t != 0; (last_t = t, t = t->next))
|
||||
{
|
||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||
|
||||
// rjf: recycle old tasks
|
||||
if(last_t != 0)
|
||||
{
|
||||
SLLStackPush(free_task, last_t);
|
||||
}
|
||||
|
||||
// rjf: unpack task
|
||||
U64 hash = t->hash;
|
||||
|
||||
// rjf: hash -> unique type tag node
|
||||
UniqueTypeTagNode *type_tag_node = 0;
|
||||
{
|
||||
@@ -1681,12 +1711,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
unit_idx = type_tag_node->unit_idx;
|
||||
}
|
||||
|
||||
// rjf: record this type in the dependency chain
|
||||
// rjf: record this type in the dependency chain count
|
||||
if(type_tag_node != 0)
|
||||
{
|
||||
TypeDepChain *c = push_array(scratch.arena, TypeDepChain, 1);
|
||||
c->type_idx = type_tag_node->order_idx;
|
||||
SLLStackPush(type_dep_chains[root_type_idx], c);
|
||||
type_dep_chains_counts[root_type_idx] += 1;
|
||||
}
|
||||
|
||||
@@ -1695,12 +1722,20 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
|
||||
|
||||
// rjf: parse this type's tag
|
||||
U64 read_off = info_off;
|
||||
DW2_Tag tag = {0};
|
||||
dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, info_off, &tag);
|
||||
read_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, read_off, &tag);
|
||||
|
||||
// rjf: find direct type, if one exists
|
||||
U64 direct_type_info_off = 0;
|
||||
U64 direct_type_unit_idx = 0;
|
||||
// rjf: find direct types from this type tag
|
||||
typedef struct DirectTypeNode DirectTypeNode;
|
||||
struct DirectTypeNode
|
||||
{
|
||||
DirectTypeNode *next;
|
||||
U64 info_off;
|
||||
U64 unit_idx;
|
||||
};
|
||||
DirectTypeNode *first_direct_type = 0;
|
||||
DirectTypeNode *last_direct_type = 0;
|
||||
switch(tag.kind)
|
||||
{
|
||||
default:{}break;
|
||||
@@ -1713,40 +1748,116 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
case DW_TagKind_ArrayType:
|
||||
case DW_TagKind_SubrangeType:
|
||||
case DW_TagKind_Typedef:
|
||||
case DW_TagKind_SubProgram:
|
||||
case DW_TagKind_SubroutineType:
|
||||
{
|
||||
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
|
||||
direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||
direct_type_unit_idx = unit_idx;
|
||||
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
||||
// rjf: gather direct type
|
||||
{
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
|
||||
if(0 < new_unit_num && new_unit_num <= unit_count)
|
||||
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
|
||||
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||
U64 direct_type_unit_idx = unit_idx;
|
||||
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
||||
{
|
||||
direct_type_unit_idx = new_unit_num-1;
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
|
||||
if(0 < new_unit_num && new_unit_num <= unit_count)
|
||||
{
|
||||
direct_type_unit_idx = new_unit_num-1;
|
||||
}
|
||||
}
|
||||
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
|
||||
n->info_off = direct_type_info_off;
|
||||
n->unit_idx = direct_type_unit_idx;
|
||||
SLLQueuePush(first_direct_type, last_direct_type, n);
|
||||
}
|
||||
|
||||
// rjf: functions -> gather parameters
|
||||
if(tag.has_children && (tag.kind == DW_TagKind_SubProgram || tag.kind == DW_TagKind_SubroutineType))
|
||||
{
|
||||
S64 depth = 1;
|
||||
for(;depth > 0 && contains_1u64(unit_info_tag_range, read_off);)
|
||||
{
|
||||
U64 start_read_off = read_off;
|
||||
|
||||
// rjf: read child tag
|
||||
DW2_Tag child_tag = {0};
|
||||
read_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, read_off, &child_tag);
|
||||
|
||||
// rjf: formal parameters -> gather direct types
|
||||
if(child_tag.kind == DW_TagKind_FormalParameter)
|
||||
{
|
||||
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&child_tag, DW_AttribKind_Type);
|
||||
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||
U64 direct_type_unit_idx = unit_idx;
|
||||
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
||||
{
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
|
||||
if(0 < new_unit_num && new_unit_num <= unit_count)
|
||||
{
|
||||
direct_type_unit_idx = new_unit_num-1;
|
||||
}
|
||||
}
|
||||
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
|
||||
n->info_off = direct_type_info_off;
|
||||
n->unit_idx = direct_type_unit_idx;
|
||||
SLLQueuePush(first_direct_type, last_direct_type, n);
|
||||
}
|
||||
|
||||
// rjf: tree navigations
|
||||
if(tag.has_children)
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
if(tag.kind == DW_TagKind_Null)
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
|
||||
if(read_off == start_read_off)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: look up hash for direct type
|
||||
U64 direct_type_hash = 0;
|
||||
// rjf: for each dependency type, look up their hash, + spawn new tasks for them
|
||||
for EachNode(n, DirectTypeNode, first_direct_type)
|
||||
{
|
||||
U64 off_hash = u64_hash_from_str8(str8_struct(&direct_type_info_off));
|
||||
U64 off_slot_idx = off_hash%unit_type_maps[direct_type_unit_idx].slots_count;
|
||||
for(UnitTypeNode *n = unit_type_maps[direct_type_unit_idx].slots[off_slot_idx]; n != 0; n = n->next)
|
||||
U64 direct_type_info_off = n->info_off;
|
||||
U64 direct_type_unit_idx = n->unit_idx;
|
||||
|
||||
// rjf: direct type info offset -> hash
|
||||
U64 direct_type_hash = 0;
|
||||
{
|
||||
if(n->src_info_off == direct_type_info_off)
|
||||
U64 off_hash = u64_hash_from_str8(str8_struct(&direct_type_info_off));
|
||||
U64 off_slot_idx = off_hash%unit_type_maps[direct_type_unit_idx].slots_count;
|
||||
for(UnitTypeNode *n = unit_type_maps[direct_type_unit_idx].slots[off_slot_idx]; n != 0; n = n->next)
|
||||
{
|
||||
direct_type_hash = n->dst_hash;
|
||||
break;
|
||||
if(n->src_info_off == direct_type_info_off)
|
||||
{
|
||||
direct_type_hash = n->dst_hash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: spawn task
|
||||
TypeChainTask *new_task = free_task;
|
||||
if(new_task != 0)
|
||||
{
|
||||
SLLStackPop(free_task);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_task = push_array(scratch.arena, TypeChainTask, 1);
|
||||
}
|
||||
new_task->hash = direct_type_hash;
|
||||
t->next = new_task;
|
||||
}
|
||||
|
||||
// rjf: iterate to direct type's hash
|
||||
next_hash = direct_type_hash;
|
||||
|
||||
scratch_end(scratch2);
|
||||
}
|
||||
}
|
||||
@@ -1940,9 +2051,116 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
dst_type->direct_type = direct_type;
|
||||
dst_type->byte_size = (direct_type != 0 ? direct_type->byte_size : bitsize/8);
|
||||
}break;
|
||||
case DW_TagKind_SubProgram:
|
||||
case DW_TagKind_SubroutineType:
|
||||
{
|
||||
// rjf: build type
|
||||
dst_type = rdim_type_chunk_list_push(arena, &lane_types, lane_types_chunk_count);
|
||||
dst_type->kind = RDI_TypeKind_Function;
|
||||
dst_type->name = name;
|
||||
dst_type->direct_type = direct_type;
|
||||
dst_type->byte_size = arch_addr_size;
|
||||
|
||||
// rjf: gather all parameter types
|
||||
typedef struct ParamNode ParamNode;
|
||||
struct ParamNode
|
||||
{
|
||||
ParamNode *next;
|
||||
U64 type_unit_idx;
|
||||
U64 type_info_off;
|
||||
};
|
||||
ParamNode *first_param = 0;
|
||||
ParamNode *last_param = 0;
|
||||
U64 param_count = 0;
|
||||
{
|
||||
U64 tag_children_off = info_off + tag_info_size;
|
||||
S64 depth = 1;
|
||||
for(U64 off = tag_children_off; depth > 0 && contains_1u64(unit_info_tag_range, off);)
|
||||
{
|
||||
U64 start_off = off;
|
||||
|
||||
// rjf: read child tag
|
||||
DW2_Tag child_tag = {0};
|
||||
off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, off, &child_tag);
|
||||
|
||||
// rjf: gather parameters
|
||||
if(child_tag.kind == DW_TagKind_FormalParameter)
|
||||
{
|
||||
DW2_Attrib *type_attrib = dw2_attrib_from_kind(&child_tag, DW_AttribKind_Type);
|
||||
ParamNode *n = push_array(scratch2.arena, ParamNode, 1);
|
||||
n->type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||
n->type_unit_idx = unit_idx;
|
||||
SLLQueuePush(first_param, last_param, n);
|
||||
if(!contains_1u64(unit_info_tag_range, n->type_info_off))
|
||||
{
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, n->type_info_off);
|
||||
n->type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
||||
}
|
||||
param_count += 1;
|
||||
}
|
||||
|
||||
// rjf: navigate tree
|
||||
if(child_tag.kind == DW_TagKind_Null)
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
if(child_tag.has_children)
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
if(off == start_off)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: tighten parameter types
|
||||
dst_type->count = (RDI_U32)param_count; // TODO(rjf): @u64_to_u32
|
||||
dst_type->param_types = push_array(arena, RDIM_Type *, dst_type->count);
|
||||
{
|
||||
U64 param_idx = 0;
|
||||
for(ParamNode *n = first_param; n != 0; n = n->next, param_idx += 1)
|
||||
{
|
||||
U64 param_type_info_off = n->type_info_off;
|
||||
U64 param_type_unit_idx = n->type_unit_idx;
|
||||
|
||||
// rjf: map info_off/unit_idx -> hash
|
||||
U64 param_type_hash = 0;
|
||||
{
|
||||
UnitTypeMap *direct_type_unit_type_map = &unit_type_maps[param_type_unit_idx];
|
||||
U64 info_off_hash = u64_hash_from_str8(str8_struct(¶m_type_info_off));
|
||||
U64 info_off_slot_idx = info_off_hash%direct_type_unit_type_map->slots_count;
|
||||
for(UnitTypeNode *n = direct_type_unit_type_map->slots[info_off_slot_idx]; n != 0; n = n->next)
|
||||
{
|
||||
if(n->src_info_off == param_type_info_off)
|
||||
{
|
||||
param_type_hash = n->dst_hash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: map hash -> type
|
||||
RDIM_Type *param_type = 0;
|
||||
{
|
||||
U64 unique_type_tag_slot_idx = param_type_hash%unique_type_tag_slots_count;
|
||||
for(UniqueTypeTagNode *n = unique_type_tag_slots[unique_type_tag_slot_idx]; n != 0; n = n->next)
|
||||
{
|
||||
if(n->hash == param_type_hash)
|
||||
{
|
||||
param_type = type_from_idx_map[n->order_idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: store
|
||||
dst_type->param_types[param_idx] = param_type;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case DW_TagKind_Typedef:
|
||||
{
|
||||
@@ -2458,14 +2676,23 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
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);
|
||||
// rjf: functions need to get their type info from themselves; the type attrib
|
||||
// only references the return type. so, in that case, we'll use the procedure's
|
||||
// own info offset / unit index, rather than the type attribute's.
|
||||
U64 type_info_off = start_off;
|
||||
U64 type_unit_idx = unit_idx;
|
||||
if(!contains_1u64(unit_info_tag_range, type_info_off))
|
||||
|
||||
// rjf: attrib -> (info_off, unit_idx)
|
||||
if(tag.kind != DW_TagKind_SubProgram)
|
||||
{
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, type_info_off);
|
||||
type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
||||
type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
|
||||
type_unit_idx = unit_idx;
|
||||
if(!contains_1u64(unit_info_tag_range, type_info_off))
|
||||
{
|
||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, type_info_off);
|
||||
type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: (info_off, unit_idx) -> hash
|
||||
@@ -3137,6 +3364,93 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
{
|
||||
loc.kind = val_stack_top && val_stack_top->v.is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream;
|
||||
loc.bytecode = dst_bytecode;
|
||||
|
||||
// rjf: gather first few bytecodes for pattern matching
|
||||
RDI_EvalOp beginning_ops[5] = {0};
|
||||
RDIM_EvalBytecodeOp *beginning_nodes[5] = {0};
|
||||
{
|
||||
U64 idx = 0;
|
||||
for EachNode(n, RDIM_EvalBytecodeOp, dst_bytecode.first_op)
|
||||
{
|
||||
if(idx >= ArrayCount(beginning_ops))
|
||||
{
|
||||
break;
|
||||
}
|
||||
beginning_ops[idx] = n->op;
|
||||
beginning_nodes[idx] = n;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: match simple register offsets
|
||||
if(loc.kind == RDI_LocationKind_AddrBytecodeStream &&
|
||||
beginning_ops[0] == RDI_EvalOp_RegRead &&
|
||||
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU16) &&
|
||||
beginning_ops[2] == RDI_EvalOp_TruncSigned &&
|
||||
beginning_ops[3] == RDI_EvalOp_Add &&
|
||||
beginning_ops[4] == RDI_EvalOp_Stop)
|
||||
{
|
||||
U8 rdi_reg_code = (beginning_nodes[0]->p&0x0000FF)>>0;
|
||||
U8 byte_size = (beginning_nodes[0]->p&0x00FF00)>>8;
|
||||
U8 byte_off = (beginning_nodes[0]->p&0xFF0000)>>16;
|
||||
if(byte_off == 0 && byte_size == unit_parse_ctx->addr_size)
|
||||
{
|
||||
loc.kind = RDI_LocationKind_AddrRegPlusOff;
|
||||
loc.reg_code = rdi_reg_code;
|
||||
loc.offset = beginning_nodes[1]->p;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: match simple module offsets
|
||||
if(beginning_ops[0] == RDI_EvalOp_ModuleOff && beginning_ops[1] == RDI_EvalOp_Stop)
|
||||
{
|
||||
U64 voff = beginning_nodes[0]->p;
|
||||
loc.kind = RDI_LocationKind_ModuleOff;
|
||||
loc.offset = voff;
|
||||
}
|
||||
else if(((beginning_ops[0] == RDI_EvalOp_ModuleOff &&
|
||||
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU16 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU32 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU64)) ||
|
||||
(beginning_ops[1] == RDI_EvalOp_ModuleOff &&
|
||||
(beginning_ops[0] == RDI_EvalOp_ConstU8 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU16 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU32 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU64))) &&
|
||||
beginning_ops[2] == RDI_EvalOp_Add &&
|
||||
beginning_ops[3] == RDI_EvalOp_Stop)
|
||||
{
|
||||
U64 voff = beginning_nodes[0]->p + beginning_nodes[1]->p;
|
||||
loc.kind = RDI_LocationKind_ModuleOff;
|
||||
loc.offset = voff;
|
||||
}
|
||||
|
||||
// rjf: match simple TLS offsets
|
||||
if(beginning_ops[0] == RDI_EvalOp_TLSOff && beginning_ops[1] == RDI_EvalOp_Stop)
|
||||
{
|
||||
U64 toff = beginning_nodes[0]->p;
|
||||
loc.kind = RDI_LocationKind_TLSOff;
|
||||
loc.offset = toff;
|
||||
}
|
||||
else if(((beginning_ops[0] == RDI_EvalOp_TLSOff &&
|
||||
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU16 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU32 ||
|
||||
beginning_ops[1] == RDI_EvalOp_ConstU64)) ||
|
||||
(beginning_ops[1] == RDI_EvalOp_TLSOff &&
|
||||
(beginning_ops[0] == RDI_EvalOp_ConstU8 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU16 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU32 ||
|
||||
beginning_ops[0] == RDI_EvalOp_ConstU64))) &&
|
||||
beginning_ops[2] == RDI_EvalOp_Add &&
|
||||
beginning_ops[3] == RDI_EvalOp_Stop)
|
||||
{
|
||||
U64 toff = beginning_nodes[0]->p + beginning_nodes[1]->p;
|
||||
loc.kind = RDI_LocationKind_TLSOff;
|
||||
loc.offset = toff;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: collect
|
||||
@@ -3174,9 +3488,11 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
{
|
||||
RDIM_Scope *root_scope = rdim_scope_chunk_list_push(arena, &dst_unit->scopes, chunk_count);
|
||||
RDIM_Symbol *procedure = rdim_symbol_chunk_list_push(arena, &dst_unit->procedures, chunk_count);
|
||||
procedure->name = name;
|
||||
procedure->link_name = link_name;
|
||||
procedure->root_scope = root_scope;
|
||||
procedure->name = name;
|
||||
procedure->link_name = link_name;
|
||||
procedure->type = type;
|
||||
procedure->root_scope = root_scope;
|
||||
procedure->location_cases = framebase_location_cases;
|
||||
root_scope->symbol = procedure;
|
||||
root_scope->voff_ranges = ranges;
|
||||
dst_unit->scopes.scope_voff_count += 2;
|
||||
|
||||
Reference in New Issue
Block a user