mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
d2r2 type deduplication: further work on type content hashing; correct .debug_str_offsets handling; sketch out type dependency chain build
This commit is contained in:
+14
-16
@@ -758,34 +758,32 @@ rng1u64_array_from_list(Arena *arena, Rng1U64List *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
rng_1u64_array_bsearch(Rng1U64Array arr, U64 value)
|
rng1u64_array_num_from_value__binary_search(Rng1U64Array *array, U64 value)
|
||||||
{
|
{
|
||||||
if(arr.count > 0 && arr.v[0].min < value && value < arr.v[arr.count-1].max)
|
U64 result = 0;
|
||||||
|
if(array->count > 0 && array->v[0].min <= value && value < array->v[array->count-1].max)
|
||||||
{
|
{
|
||||||
U64 l = 0;
|
U64 min_idx = 0;
|
||||||
U64 r = arr.count - 1;
|
U64 max_idx = array->count - 1;
|
||||||
for(; l <= r; )
|
for(;min_idx <= max_idx;)
|
||||||
{
|
{
|
||||||
U64 m = l + (r - l) / 2;
|
U64 mid_idx = min_idx + (max_idx - min_idx) / 2;
|
||||||
if(contains_1u64(arr.v[m], value))
|
if(contains_1u64(array->v[mid_idx], value))
|
||||||
{
|
{
|
||||||
return m;
|
result = mid_idx+1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(arr.v[m].min < value)
|
else if(array->v[mid_idx].min < value)
|
||||||
{
|
{
|
||||||
l = m + 1;
|
min_idx = mid_idx + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = m - 1;
|
max_idx = mid_idx - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(arr.count == 1 && contains_1u64(arr.v[0], value))
|
return result;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return max_U64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ internal void rng1u64_list_push_node(Rng1U64List *list, Rng1U64Node *n);
|
|||||||
internal Rng1U64Node * rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng);
|
internal Rng1U64Node * rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng);
|
||||||
internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat);
|
internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat);
|
||||||
internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list);
|
internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list);
|
||||||
internal U64 rng_1u64_array_bsearch(Rng1U64Array arr, U64 value);
|
internal U64 rng1u64_array_num_from_value__binary_search(Rng1U64Array *array, U64 value);
|
||||||
|
|
||||||
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
|
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
|
||||||
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
|
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
|
||||||
|
|||||||
+139
-139
@@ -245,9 +245,9 @@ internal U64
|
|||||||
dw_reg_count_from_arch(Arch arch)
|
dw_reg_count_from_arch(Arch arch)
|
||||||
{
|
{
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
default: { NotImplemented; } // fall-through
|
default: { NotImplemented; } // fall-through
|
||||||
case Arch_Null: return 0;
|
case Arch_Null: return 0;
|
||||||
case Arch_x64: return DW_RegX64_Last;
|
case Arch_x64: return DW_RegX64_Last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,9 +269,9 @@ internal U64
|
|||||||
dw_sp_from_arch(Arch arch)
|
dw_sp_from_arch(Arch arch)
|
||||||
{
|
{
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
default: NotImplemented;
|
default: NotImplemented;
|
||||||
case Arch_Null: return 0;
|
case Arch_Null: return 0;
|
||||||
case Arch_x64: return DW_RegX64_Rsp;
|
case Arch_x64: return DW_RegX64_Rsp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +280,11 @@ internal U64
|
|||||||
dw_size_from_format(DW_Format format)
|
dw_size_from_format(DW_Format format)
|
||||||
{
|
{
|
||||||
U64 result = 0;
|
U64 result = 0;
|
||||||
switch (format) {
|
switch(format)
|
||||||
case DW_Format_Null: break;
|
{
|
||||||
case DW_Format_32Bit: result = 4; break;
|
case DW_Format_Null:{}break;
|
||||||
case DW_Format_64Bit: result = 8; break;
|
case DW_Format_32Bit:{result = 4;}break;
|
||||||
default: InvalidPath; break;
|
case DW_Format_64Bit:{result = 8;}break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -389,11 +389,11 @@ dw_operand_count_from_expr_op(DW_ExprOp op)
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _OPER_COUNT;
|
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _OPER_COUNT;
|
||||||
DW_Expr_V3_XList
|
DW_Expr_V3_XList
|
||||||
DW_Expr_V4_XList
|
DW_Expr_V4_XList
|
||||||
DW_Expr_V5_XList
|
DW_Expr_V5_XList
|
||||||
DW_Expr_GNU_XList
|
DW_Expr_GNU_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -404,11 +404,11 @@ dw_pop_count_from_expr_op(DW_ExprOp op)
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _POP_COUNT;
|
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _POP_COUNT;
|
||||||
DW_Expr_V3_XList
|
DW_Expr_V3_XList
|
||||||
DW_Expr_V4_XList
|
DW_Expr_V4_XList
|
||||||
DW_Expr_V5_XList
|
DW_Expr_V5_XList
|
||||||
DW_Expr_GNU_XList
|
DW_Expr_GNU_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -419,11 +419,11 @@ dw_push_count_from_expr_op(DW_ExprOp op)
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _PUSH_COUNT;
|
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _PUSH_COUNT;
|
||||||
DW_Expr_V3_XList
|
DW_Expr_V3_XList
|
||||||
DW_Expr_V4_XList
|
DW_Expr_V4_XList
|
||||||
DW_Expr_V5_XList
|
DW_Expr_V5_XList
|
||||||
DW_Expr_GNU_XList
|
DW_Expr_GNU_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -433,12 +433,12 @@ dw_operand_types_from_expr_opcode(DW_ExprOp op)
|
|||||||
{
|
{
|
||||||
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, _OPER_TYPE0, _OPER_TYPE1) case _ID: { local_persist DW_ExprOperandType t[] = { DW_ExprOperandType_##_OPER_TYPE0, DW_ExprOperandType_##_OPER_TYPE1 }; return t; }
|
#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, _OPER_TYPE0, _OPER_TYPE1) case _ID: { local_persist DW_ExprOperandType t[] = { DW_ExprOperandType_##_OPER_TYPE0, DW_ExprOperandType_##_OPER_TYPE1 }; return t; }
|
||||||
switch (op) {
|
switch (op) {
|
||||||
DW_Expr_V3_XList
|
DW_Expr_V3_XList
|
||||||
DW_Expr_V4_XList
|
DW_Expr_V4_XList
|
||||||
DW_Expr_V5_XList
|
DW_Expr_V5_XList
|
||||||
DW_Expr_GNU_XList
|
DW_Expr_GNU_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -450,7 +450,7 @@ dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode)
|
|||||||
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; }
|
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; }
|
||||||
DW_CFA_Kind_XList
|
DW_CFA_Kind_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -460,21 +460,21 @@ dw_is_cfa_expr_opcode_invalid(DW_ExprOp opcode)
|
|||||||
{
|
{
|
||||||
B32 is_invalid = 0;
|
B32 is_invalid = 0;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_ExprOp_Addrx:
|
case DW_ExprOp_Addrx:
|
||||||
case DW_ExprOp_Call2:
|
case DW_ExprOp_Call2:
|
||||||
case DW_ExprOp_Call4:
|
case DW_ExprOp_Call4:
|
||||||
case DW_ExprOp_CallRef:
|
case DW_ExprOp_CallRef:
|
||||||
case DW_ExprOp_ConstType:
|
case DW_ExprOp_ConstType:
|
||||||
case DW_ExprOp_Constx:
|
case DW_ExprOp_Constx:
|
||||||
case DW_ExprOp_Convert:
|
case DW_ExprOp_Convert:
|
||||||
case DW_ExprOp_DerefType:
|
case DW_ExprOp_DerefType:
|
||||||
case DW_ExprOp_RegvalType:
|
case DW_ExprOp_RegvalType:
|
||||||
case DW_ExprOp_Reinterpret:
|
case DW_ExprOp_Reinterpret:
|
||||||
case DW_ExprOp_PushObjectAddress:
|
case DW_ExprOp_PushObjectAddress:
|
||||||
case DW_ExprOp_CallFrameCfa: {
|
case DW_ExprOp_CallFrameCfa: {
|
||||||
is_invalid = 1;
|
is_invalid = 1;
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return is_invalid;
|
return is_invalid;
|
||||||
}
|
}
|
||||||
@@ -484,14 +484,14 @@ dw_is_new_row_cfa_opcode(DW_CFA_Opcode opcode)
|
|||||||
{
|
{
|
||||||
B32 is_new_row_op = 0;
|
B32 is_new_row_op = 0;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_CFA_SetLoc:
|
case DW_CFA_SetLoc:
|
||||||
case DW_CFA_AdvanceLoc:
|
case DW_CFA_AdvanceLoc:
|
||||||
case DW_CFA_AdvanceLoc1:
|
case DW_CFA_AdvanceLoc1:
|
||||||
case DW_CFA_AdvanceLoc2:
|
case DW_CFA_AdvanceLoc2:
|
||||||
case DW_CFA_AdvanceLoc4: {
|
case DW_CFA_AdvanceLoc4: {
|
||||||
is_new_row_op = 1;
|
is_new_row_op = 1;
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return is_new_row_op;
|
return is_new_row_op;
|
||||||
}
|
}
|
||||||
@@ -503,7 +503,7 @@ dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode)
|
|||||||
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; }
|
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; }
|
||||||
DW_CFA_Kind_XList
|
DW_CFA_Kind_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: { NotImplemented; } break;
|
default: { NotImplemented; } break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -512,9 +512,9 @@ internal String8
|
|||||||
dw_string_from_format(DW_Format format)
|
dw_string_from_format(DW_Format format)
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case DW_Format_Null: return str8_lit("NULL");
|
case DW_Format_Null: return str8_lit("NULL");
|
||||||
case DW_Format_32Bit: return str8_lit("DWARF32");
|
case DW_Format_32Bit: return str8_lit("DWARF32");
|
||||||
case DW_Format_64Bit: return str8_lit("DWARF64");
|
case DW_Format_64Bit: return str8_lit("DWARF64");
|
||||||
}
|
}
|
||||||
return str8_zero();
|
return str8_zero();
|
||||||
}
|
}
|
||||||
@@ -810,7 +810,7 @@ dw_string_from_cfa_opcode(DW_CFA_Opcode opcode)
|
|||||||
#define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME));
|
#define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME));
|
||||||
DW_CFA_Kind_XList
|
DW_CFA_Kind_XList
|
||||||
#undef X
|
#undef X
|
||||||
default: InvalidPath; break;
|
default: InvalidPath; break;
|
||||||
}
|
}
|
||||||
return str8_zero();
|
return str8_zero();
|
||||||
}
|
}
|
||||||
@@ -965,78 +965,78 @@ internal B32
|
|||||||
dw_form_match(DW_Form a, DW_Form b)
|
dw_form_match(DW_Form a, DW_Form b)
|
||||||
{
|
{
|
||||||
B32 is_match = 0;
|
B32 is_match = 0;
|
||||||
|
|
||||||
if (a.kind == b.kind) {
|
if (a.kind == b.kind) {
|
||||||
switch (a.kind) {
|
switch (a.kind) {
|
||||||
case DW_Form_Null: {} break;
|
case DW_Form_Null: {} break;
|
||||||
|
|
||||||
case DW_Form_Addr: { is_match = str8_match(a.addr, b.addr, 0); } break;
|
case DW_Form_Addr: { is_match = str8_match(a.addr, b.addr, 0); } break;
|
||||||
case DW_Form_String: { is_match = str8_match(a.string, b.string, 0); } break;
|
case DW_Form_String: { is_match = str8_match(a.string, b.string, 0); } break;
|
||||||
case DW_Form_ExprLoc: { is_match = str8_match(a.exprloc, b.exprloc, 0); } break;
|
case DW_Form_ExprLoc: { is_match = str8_match(a.exprloc, b.exprloc, 0); } break;
|
||||||
|
|
||||||
case DW_Form_Block:
|
case DW_Form_Block:
|
||||||
case DW_Form_Block1:
|
case DW_Form_Block1:
|
||||||
case DW_Form_Block2:
|
case DW_Form_Block2:
|
||||||
case DW_Form_Block4: {
|
case DW_Form_Block4: {
|
||||||
is_match = str8_match(a.block, b.block, 0);
|
is_match = str8_match(a.block, b.block, 0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_Data1:
|
case DW_Form_Data1:
|
||||||
case DW_Form_Data2:
|
case DW_Form_Data2:
|
||||||
case DW_Form_Data4:
|
case DW_Form_Data4:
|
||||||
case DW_Form_Data8:
|
case DW_Form_Data8:
|
||||||
case DW_Form_Data16: {
|
case DW_Form_Data16: {
|
||||||
is_match = str8_match(a.data, b.data, 0);
|
is_match = str8_match(a.data, b.data, 0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_Flag: { is_match = a.flag == b.flag; } break;
|
case DW_Form_Flag: { is_match = a.flag == b.flag; } break;
|
||||||
case DW_Form_SData: { is_match = a.sdata == b.sdata; } break;
|
case DW_Form_SData: { is_match = a.sdata == b.sdata; } break;
|
||||||
case DW_Form_UData: { is_match = a.udata == b.udata; } break;
|
case DW_Form_UData: { is_match = a.udata == b.udata; } break;
|
||||||
|
|
||||||
case DW_Form_RefAddr:
|
case DW_Form_RefAddr:
|
||||||
case DW_Form_Ref1:
|
case DW_Form_Ref1:
|
||||||
case DW_Form_Ref2:
|
case DW_Form_Ref2:
|
||||||
case DW_Form_Ref4:
|
case DW_Form_Ref4:
|
||||||
case DW_Form_Ref8:
|
case DW_Form_Ref8:
|
||||||
case DW_Form_RefUData:
|
case DW_Form_RefUData:
|
||||||
case DW_Form_GNU_RefAlt: {
|
case DW_Form_GNU_RefAlt: {
|
||||||
is_match = a.ref == b.ref;
|
is_match = a.ref == b.ref;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_Indirect: { NotImplemented; } break;
|
case DW_Form_Indirect: { NotImplemented; } break;
|
||||||
|
|
||||||
case DW_Form_SecOffset:
|
case DW_Form_SecOffset:
|
||||||
case DW_Form_LineStrp:
|
case DW_Form_LineStrp:
|
||||||
case DW_Form_GNU_StrpAlt: {
|
case DW_Form_GNU_StrpAlt: {
|
||||||
is_match = a.sec_offset == b.sec_offset;
|
is_match = a.sec_offset == b.sec_offset;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_ImplicitConst: { is_match = a.implicit_const, b.implicit_const; } break;
|
case DW_Form_ImplicitConst: { is_match = a.implicit_const, b.implicit_const; } break;
|
||||||
|
|
||||||
case DW_Form_Strx:
|
case DW_Form_Strx:
|
||||||
case DW_Form_Strx1:
|
case DW_Form_Strx1:
|
||||||
case DW_Form_Strx2:
|
case DW_Form_Strx2:
|
||||||
case DW_Form_Strx3:
|
case DW_Form_Strx3:
|
||||||
case DW_Form_Strx4:
|
case DW_Form_Strx4:
|
||||||
case DW_Form_Addrx:
|
case DW_Form_Addrx:
|
||||||
case DW_Form_Addrx1:
|
case DW_Form_Addrx1:
|
||||||
case DW_Form_Addrx2:
|
case DW_Form_Addrx2:
|
||||||
case DW_Form_Addrx3:
|
case DW_Form_Addrx3:
|
||||||
case DW_Form_Addrx4:
|
case DW_Form_Addrx4:
|
||||||
case DW_Form_RngListx:
|
case DW_Form_RngListx:
|
||||||
case DW_Form_LocListx: {
|
case DW_Form_LocListx: {
|
||||||
is_match = a.xval == b.xval;
|
is_match = a.xval == b.xval;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_StrpSup: { is_match = a.strp_sup == b.strp_sup; } break;
|
case DW_Form_StrpSup: { is_match = a.strp_sup == b.strp_sup; } break;
|
||||||
|
|
||||||
case DW_Form_RefSup4: { NotImplemented; } break;
|
case DW_Form_RefSup4: { NotImplemented; } break;
|
||||||
case DW_Form_RefSup8: { NotImplemented; } break;
|
case DW_Form_RefSup8: { NotImplemented; } break;
|
||||||
|
|
||||||
default: { InvalidPath; } break;
|
default: { InvalidPath; } break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_match;
|
return is_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1044,20 +1044,20 @@ internal U64
|
|||||||
dw_length_from_std_opcode(DW_StdOpcode opcode)
|
dw_length_from_std_opcode(DW_StdOpcode opcode)
|
||||||
{
|
{
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_StdOpcode_ExtendedOpcode: return 0;
|
case DW_StdOpcode_ExtendedOpcode: return 0;
|
||||||
case DW_StdOpcode_Copy: return 0;
|
case DW_StdOpcode_Copy: return 0;
|
||||||
case DW_StdOpcode_AdvancePc: return 1;
|
case DW_StdOpcode_AdvancePc: return 1;
|
||||||
case DW_StdOpcode_AdvanceLine: return 1;
|
case DW_StdOpcode_AdvanceLine: return 1;
|
||||||
case DW_StdOpcode_SetFile: return 1;
|
case DW_StdOpcode_SetFile: return 1;
|
||||||
case DW_StdOpcode_SetColumn: return 1;
|
case DW_StdOpcode_SetColumn: return 1;
|
||||||
case DW_StdOpcode_NegateStmt: return 0;
|
case DW_StdOpcode_NegateStmt: return 0;
|
||||||
case DW_StdOpcode_SetBasicBlock: return 0;
|
case DW_StdOpcode_SetBasicBlock: return 0;
|
||||||
case DW_StdOpcode_ConstAddPc: return 0;
|
case DW_StdOpcode_ConstAddPc: return 0;
|
||||||
case DW_StdOpcode_FixedAdvancePc: return 1;
|
case DW_StdOpcode_FixedAdvancePc: return 1;
|
||||||
case DW_StdOpcode_SetPrologueEnd: return 0;
|
case DW_StdOpcode_SetPrologueEnd: return 0;
|
||||||
case DW_StdOpcode_SetEpilogueBegin: return 0;
|
case DW_StdOpcode_SetEpilogueBegin: return 0;
|
||||||
case DW_StdOpcode_SetIsa: return 1;
|
case DW_StdOpcode_SetIsa: return 1;
|
||||||
default: InvalidPath; break;
|
default: InvalidPath; break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2072,16 +2072,16 @@ dw_cu_from_info_off(Arena *arena, DW_Raw *input, DW_ListUnitInput lu_input, U64
|
|||||||
U64 loclists_sec_off = dw_interp_sec_offset(loclists_base_attrib->form );
|
U64 loclists_sec_off = dw_interp_sec_offset(loclists_base_attrib->form );
|
||||||
|
|
||||||
// map section offset to unit index
|
// map section offset to unit index
|
||||||
U64 addr_lu_idx = rng_1u64_array_bsearch(lu_input.addr_ranges, addr_sec_off );
|
U64 addr_lu_num = rng1u64_array_num_from_value__binary_search(&lu_input.addr_ranges, addr_sec_off );
|
||||||
U64 str_offsets_lu_idx = rng_1u64_array_bsearch(lu_input.str_offset_ranges, str_offsets_sec_off);
|
U64 str_offsets_lu_num = rng1u64_array_num_from_value__binary_search(&lu_input.str_offset_ranges, str_offsets_sec_off);
|
||||||
U64 rnglists_lu_idx = rng_1u64_array_bsearch(lu_input.rnglist_ranges, rnglists_sec_off );
|
U64 rnglists_lu_num = rng1u64_array_num_from_value__binary_search(&lu_input.rnglist_ranges, rnglists_sec_off );
|
||||||
U64 loclists_lu_idx = rng_1u64_array_bsearch(lu_input.loclist_ranges, loclists_sec_off );
|
U64 loclists_lu_num = rng1u64_array_num_from_value__binary_search(&lu_input.loclist_ranges, loclists_sec_off );
|
||||||
|
|
||||||
// map index to unit
|
// map index to unit
|
||||||
DW_ListUnit *addr_lu = addr_lu_idx < lu_input.addr_count ? &lu_input.addrs[addr_lu_idx] : 0;
|
DW_ListUnit *addr_lu = 0 < (addr_lu_num && addr_lu_num <= lu_input.addr_count) ? &lu_input.addrs[addr_lu_num-1] : 0;
|
||||||
DW_ListUnit *str_offsets_lu = str_offsets_lu_idx < lu_input.str_offset_count ? &lu_input.str_offsets[str_offsets_lu_idx] : 0;
|
DW_ListUnit *str_offsets_lu = 0 < (str_offsets_lu_num && str_offsets_lu_num <= lu_input.str_offset_count) ? &lu_input.str_offsets[str_offsets_lu_num-1] : 0;
|
||||||
DW_ListUnit *rnglists_lu = rnglists_lu_idx < lu_input.rnglist_count ? &lu_input.rnglists[rnglists_lu_idx] : 0;
|
DW_ListUnit *rnglists_lu = 0 < (rnglists_lu_num && rnglists_lu_num <= lu_input.rnglist_count) ? &lu_input.rnglists[rnglists_lu_num-1] : 0;
|
||||||
DW_ListUnit *loclists_lu = loclists_lu_idx < lu_input.loclist_count ? &lu_input.loclists[loclists_lu_idx] : 0;
|
DW_ListUnit *loclists_lu = 0 < (loclists_lu_num && loclists_lu_num <= lu_input.loclist_count) ? &lu_input.loclists[loclists_lu_num-1] : 0;
|
||||||
|
|
||||||
// find compile unit base address
|
// find compile unit base address
|
||||||
DW_Attrib *low_pc_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LowPc);
|
DW_Attrib *low_pc_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LowPc);
|
||||||
|
|||||||
@@ -399,8 +399,19 @@ dw2_read_form_val(DW2_ParseCtx *ctx, String8 data, U64 off, DW_FormKind form_kin
|
|||||||
case DW_Form_Strx3:
|
case DW_Form_Strx3:
|
||||||
case DW_Form_Strx4:
|
case DW_Form_Strx4:
|
||||||
case DW_Form_Strx:
|
case DW_Form_Strx:
|
||||||
|
if(ctx->str_offsets_table != 0)
|
||||||
{
|
{
|
||||||
// TODO(rjf)
|
U64 entry_idx = val.u128.u64[0];
|
||||||
|
if(entry_idx < ctx->str_offsets_table->entries_count)
|
||||||
|
{
|
||||||
|
U64 entry_size = ctx->str_offsets_table->entry_size;
|
||||||
|
U64 entry_off = entry_idx * entry_size;
|
||||||
|
U64 string_data_off = 0;
|
||||||
|
MemoryCopy(&string_data_off, (U8 *)ctx->str_offsets_table->entries + entry_off, entry_size);
|
||||||
|
String8 string_section_data = ctx->raw->sec[DW_Section_Str].data;
|
||||||
|
val.string = str8_cstring_capped(string_section_data.str + string_data_off,
|
||||||
|
string_section_data.str + string_section_data.size);
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
case DW_Form_LineStrp:
|
case DW_Form_LineStrp:
|
||||||
{
|
{
|
||||||
@@ -545,6 +556,25 @@ dw2_attrib_from_kind(DW2_Tag *tag, DW_AttribKind kind)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
dw2_reference_info_off_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal *v)
|
||||||
|
{
|
||||||
|
U64 result = 0;
|
||||||
|
switch(v->kind)
|
||||||
|
{
|
||||||
|
default:{}break;
|
||||||
|
case DW_Form_Ref1:
|
||||||
|
case DW_Form_Ref2:
|
||||||
|
case DW_Form_Ref4:
|
||||||
|
case DW_Form_Ref8:
|
||||||
|
{
|
||||||
|
result = v->u128.u64[0];
|
||||||
|
}break;
|
||||||
|
// TODO(rjf): DW_Form_RefAddr, DW_Form_RefUData, DW_Form_RefSig8, DW_Form_RefSup8, etc.
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Line Table Parsing
|
//~ rjf: Line Table Parsing
|
||||||
|
|
||||||
@@ -831,3 +861,42 @@ dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 of
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Offset Table Parsing (.debug_str_offsets)
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out)
|
||||||
|
{
|
||||||
|
U64 start_off = off;
|
||||||
|
{
|
||||||
|
// rjf: read data length / format
|
||||||
|
U64 unit_data_length = 0;
|
||||||
|
DW_Format format = DW_Format_Null;
|
||||||
|
off += dw2_read_initial_length(data, off, &unit_data_length, &format);
|
||||||
|
U64 unit_data_off_opl = off + unit_data_length;
|
||||||
|
|
||||||
|
// rjf: read version
|
||||||
|
DW_Version version = DW_Version_Null;
|
||||||
|
off += str8_deserial_read_struct(data, off, &version);
|
||||||
|
|
||||||
|
// rjf: version 5: read rest (this section only exists in 5+)
|
||||||
|
if(version == DW_Version_5)
|
||||||
|
{
|
||||||
|
// rjf: skip padding
|
||||||
|
off += sizeof(U16);
|
||||||
|
|
||||||
|
// rjf: fill table info
|
||||||
|
out->format = format;
|
||||||
|
out->version = version;
|
||||||
|
out->entry_size = dw_size_from_format(format);
|
||||||
|
out->entries_count = (unit_data_off_opl - off) / out->entry_size;
|
||||||
|
out->entries = data.str + off;
|
||||||
|
|
||||||
|
// rjf: skip table
|
||||||
|
off = unit_data_off_opl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
U64 bytes_read = (off - start_off);
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ struct DW2_AbbrevMap
|
|||||||
U64 slots_count;
|
U64 slots_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Offset Table (.debug_str_offsets)
|
||||||
|
|
||||||
|
typedef struct DW2_StrOffsetsTable DW2_StrOffsetsTable;
|
||||||
|
struct DW2_StrOffsetsTable
|
||||||
|
{
|
||||||
|
DW_Format format;
|
||||||
|
DW_Version version;
|
||||||
|
U64 entry_size;
|
||||||
|
U64 entries_count;
|
||||||
|
void *entries;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Parsing Context Bundle
|
//~ rjf: Parsing Context Bundle
|
||||||
|
|
||||||
@@ -49,6 +62,7 @@ struct DW2_ParseCtx
|
|||||||
DW_Format format;
|
DW_Format format;
|
||||||
U64 addr_size;
|
U64 addr_size;
|
||||||
DW2_AbbrevMap *abbrev_map;
|
DW2_AbbrevMap *abbrev_map;
|
||||||
|
DW2_StrOffsetsTable *str_offsets_table;
|
||||||
String8 unit_dir;
|
String8 unit_dir;
|
||||||
String8 unit_file;
|
String8 unit_file;
|
||||||
};
|
};
|
||||||
@@ -210,10 +224,16 @@ internal U64 dw2_read_form_val(DW2_ParseCtx *ctx, String8 data, U64 off, DW_Form
|
|||||||
|
|
||||||
internal U64 dw2_read_tag(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out);
|
internal U64 dw2_read_tag(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out);
|
||||||
internal DW2_Attrib *dw2_attrib_from_kind(DW2_Tag *tag, DW_AttribKind kind);
|
internal DW2_Attrib *dw2_attrib_from_kind(DW2_Tag *tag, DW_AttribKind kind);
|
||||||
|
internal U64 dw2_reference_info_off_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal *v);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Line Table Parsing
|
//~ rjf: Line Table Parsing
|
||||||
|
|
||||||
internal U64 dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_LineTableHeader *out);
|
internal U64 dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_LineTableHeader *out);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Offset Table Parsing (.debug_str_offsets)
|
||||||
|
|
||||||
|
internal U64 dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out);
|
||||||
|
|
||||||
#endif // DWARF_PARSE_2_H
|
#endif // DWARF_PARSE_2_H
|
||||||
|
|||||||
@@ -2415,7 +2415,8 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task)
|
|||||||
if (obj_sect_header->vsize == 0) {
|
if (obj_sect_header->vsize == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sect_number = rng_1u64_array_bsearch(task->image_section_virt_ranges, obj_sect_header->voff);
|
U64 sect_num = rng1u64_array_num_from_value__binary_search(&task->image_section_virt_ranges, obj_sect_header->voff);
|
||||||
|
sect_number = sect_num-1;
|
||||||
Assert(sect_number < task->image_section_virt_ranges.count);
|
Assert(sect_number < task->image_section_virt_ranges.count);
|
||||||
sect_data = str8_zero();
|
sect_data = str8_zero();
|
||||||
sect_off = obj_sect_header->voff - task->image_section_virt_ranges.v[sect_number].min;
|
sect_off = obj_sect_header->voff - task->image_section_virt_ranges.v[sect_number].min;
|
||||||
@@ -2424,7 +2425,8 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task)
|
|||||||
if (obj_sect_header->fsize == 0) {
|
if (obj_sect_header->fsize == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sect_number = rng_1u64_array_bsearch(task->image_section_file_ranges, obj_sect_header->foff);
|
U64 sect_num = rng1u64_array_num_from_value__binary_search(&task->image_section_file_ranges, obj_sect_header->foff);
|
||||||
|
sect_number = sect_num-1;
|
||||||
Assert(sect_number < task->image_section_file_ranges.count);
|
Assert(sect_number < task->image_section_file_ranges.count);
|
||||||
sect_data = str8_substr(task->image_data, rng_1u64(obj_sect_header->foff, obj_sect_header->foff + obj_sect_header->fsize));
|
sect_data = str8_substr(task->image_data, rng_1u64(obj_sect_header->foff, obj_sect_header->foff + obj_sect_header->fsize));
|
||||||
sect_off = obj_sect_header->foff - task->image_section_file_ranges.v[sect_number].min;
|
sect_off = obj_sect_header->foff - task->image_section_file_ranges.v[sect_number].min;
|
||||||
|
|||||||
@@ -1,25 +1,6 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Helpers
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
d2r2_hash_from_seed_tag(U64 seed, DW2_Tag *tag)
|
|
||||||
{
|
|
||||||
U64 result = seed;
|
|
||||||
result = u64_hash_from_seed_str8(result, str8_struct(&tag->kind));
|
|
||||||
for EachNode(n, DW2_AttribNode, tag->attribs.first)
|
|
||||||
{
|
|
||||||
DW2_Attrib *attrib = &n->v;
|
|
||||||
result = u64_hash_from_seed_str8(result, str8_struct(&attrib->attrib_kind));
|
|
||||||
result = u64_hash_from_seed_str8(result, str8_struct(&attrib->val.kind));
|
|
||||||
result = u64_hash_from_seed_str8(result, attrib->val.string);
|
|
||||||
result = u64_hash_from_seed_str8(result, str8_struct(&attrib->val.u128));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Main Conversion Entry Point (New)
|
//~ rjf: Main Conversion Entry Point (New)
|
||||||
|
|
||||||
@@ -276,6 +257,86 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
lane_sync();
|
lane_sync();
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: parse all string offsets tables
|
||||||
|
//
|
||||||
|
// in an incredible twist of fate, DWARF decided to decouple these from
|
||||||
|
// compilation units. compilation units *do* contain a
|
||||||
|
// DW_AttribKind_StrOffsetsBase attribute. but this base offset does *not*
|
||||||
|
// point to the beginning of a table in .debug_str_offsets! it instead points
|
||||||
|
// PAST THE INITIAL VARIABLE-WIDTH LENGTH AND FORMAT ENCODING! this means
|
||||||
|
// you can't actually use the StrOffsetsBase attribute for ANYTHING other
|
||||||
|
// than correllating a unit to its associated string offset table - but you
|
||||||
|
// *necessarily needed to have parsed that table beforehand*, completely
|
||||||
|
// independently from units.
|
||||||
|
//
|
||||||
|
// so, we have to parse all the string offset tables up-front, then
|
||||||
|
// *binary search* their ranges to determine which unit has which table.
|
||||||
|
//
|
||||||
|
// of course, in practice, it's perhaps likely/expected that these match
|
||||||
|
// one-to-one with units, and in the same order, because that is what is
|
||||||
|
// most natural for generators. but, the format does not *guarantee this*,
|
||||||
|
// and instead specced something far more arbitrary.
|
||||||
|
//
|
||||||
|
// thank you, again, DWARF.
|
||||||
|
//
|
||||||
|
U64 str_offsets_tables_count = 0;
|
||||||
|
DW2_StrOffsetsTable *str_offsets_tables = 0;
|
||||||
|
Rng1U64 *str_offsets_tables_ranges = 0;
|
||||||
|
ProfScope("parse all string offsets tables") if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||||
|
|
||||||
|
//- rjf: gather all tables (loose)
|
||||||
|
typedef struct TableNode TableNode;
|
||||||
|
struct TableNode
|
||||||
|
{
|
||||||
|
TableNode *next;
|
||||||
|
DW2_StrOffsetsTable v;
|
||||||
|
Rng1U64 range;
|
||||||
|
};
|
||||||
|
TableNode *first_table = 0;
|
||||||
|
TableNode *last_table = 0;
|
||||||
|
U64 table_count = 0;
|
||||||
|
for(U64 off = 0; off < raw->sec[DW_Section_StrOffsets].data.size;)
|
||||||
|
{
|
||||||
|
U64 start_off = off;
|
||||||
|
DW2_StrOffsetsTable table = {0};
|
||||||
|
off += dw2_read_str_offsets_table(raw->sec[DW_Section_StrOffsets].data, off, &table);
|
||||||
|
if(table.entries != 0)
|
||||||
|
{
|
||||||
|
TableNode *n = push_array(scratch2.arena, TableNode, 1);
|
||||||
|
SLLQueuePush(first_table, last_table, n);
|
||||||
|
n->v = table;
|
||||||
|
n->range = r1u64(start_off, off);
|
||||||
|
table_count += 1;
|
||||||
|
}
|
||||||
|
if(off == start_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: tighten
|
||||||
|
str_offsets_tables_count = table_count;
|
||||||
|
str_offsets_tables = push_array(scratch.arena, DW2_StrOffsetsTable, str_offsets_tables_count);
|
||||||
|
str_offsets_tables_ranges = push_array(scratch.arena, Rng1U64, str_offsets_tables_count);
|
||||||
|
{
|
||||||
|
U64 idx = 0;
|
||||||
|
for EachNode(n, TableNode, first_table)
|
||||||
|
{
|
||||||
|
str_offsets_tables[idx] = n->v;
|
||||||
|
str_offsets_tables_ranges[idx] = n->range;
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch2);
|
||||||
|
}
|
||||||
|
lane_sync_u64(&str_offsets_tables_count, 0);
|
||||||
|
lane_sync_u64(&str_offsets_tables, 0);
|
||||||
|
lane_sync_u64(&str_offsets_tables_ranges, 0);
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: build per-unit parsing contexts
|
//- rjf: build per-unit parsing contexts
|
||||||
//
|
//
|
||||||
@@ -301,7 +362,58 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
lane_sync();
|
lane_sync();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: parse each unit's root-level tag
|
//- rjf: do initial parse of each unit's root-level tag
|
||||||
|
//
|
||||||
|
// an incredible NOTE: this is actually not sufficient. because this tag parse
|
||||||
|
// is what informs us which .debug_str_offsets table each unit should be associated
|
||||||
|
// with (via the StrOffsetsBase attribute), we actually don't have the right string
|
||||||
|
// offset table *before* we parse this, which means we can't resolve some of the
|
||||||
|
// string attribute values.
|
||||||
|
//
|
||||||
|
// so, in another incredible twist of fate, we actually must do this *twice*. first,
|
||||||
|
// to find *just the StrOffsetsBase*, and then, to actually fully resolve everything.
|
||||||
|
//
|
||||||
|
DW2_Tag *unit_root_tags__pre_str_offsets = 0;
|
||||||
|
{
|
||||||
|
if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
unit_root_tags__pre_str_offsets = push_array(scratch.arena, DW2_Tag, unit_count);
|
||||||
|
}
|
||||||
|
lane_sync_u64(&unit_root_tags__pre_str_offsets, 0);
|
||||||
|
Rng1U64 range = lane_range(unit_count);
|
||||||
|
for EachInRange(unit_idx, range)
|
||||||
|
{
|
||||||
|
dw2_read_tag(scratch.arena, &unit_parse_ctxs[unit_idx], raw->sec[DW_Section_Info].data, unit_info_tag_ranges[unit_idx].min, &unit_root_tags__pre_str_offsets[unit_idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: look up string offset tables for each unit (.debug_str_offsets);
|
||||||
|
// equip to per-unit parsing contexts
|
||||||
|
//
|
||||||
|
{
|
||||||
|
Rng1U64Array str_offsets_tables_ranges_array = {str_offsets_tables_ranges, str_offsets_tables_count};
|
||||||
|
Rng1U64 range = lane_range(unit_count);
|
||||||
|
for EachInRange(unit_idx, range)
|
||||||
|
{
|
||||||
|
DW2_Tag *unit_root_tag = &unit_root_tags__pre_str_offsets[unit_idx];
|
||||||
|
DW2_Attrib *str_offsets_base_off_attrib = dw2_attrib_from_kind(unit_root_tag, DW_AttribKind_StrOffsetsBase);
|
||||||
|
U64 str_offsets_base_off = str_offsets_base_off_attrib->val.u128.u64[0];
|
||||||
|
U64 str_offsets_table_num = rng1u64_array_num_from_value__binary_search(&str_offsets_tables_ranges_array, str_offsets_base_off);
|
||||||
|
if(0 < str_offsets_table_num && str_offsets_table_num <= str_offsets_tables_ranges_array.count)
|
||||||
|
{
|
||||||
|
DW2_StrOffsetsTable *table = &str_offsets_tables[str_offsets_table_num-1];
|
||||||
|
unit_parse_ctxs[unit_idx].str_offsets_table = table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: do parse of each unit's root tag AFTER finding the right .debug_str_offsets table
|
||||||
|
//
|
||||||
|
// (excellent work everyone - thank you for reminding me why RDI is necessary)
|
||||||
//
|
//
|
||||||
DW2_Tag *unit_root_tags = 0;
|
DW2_Tag *unit_root_tags = 0;
|
||||||
{
|
{
|
||||||
@@ -888,9 +1000,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
U64 total_tag_count_estimate = 1;
|
U64 total_tag_count_estimate = 1;
|
||||||
{
|
{
|
||||||
U64 tag_size_estimate = 32;
|
U64 tag_size_estimate = 32;
|
||||||
for EachIndex(unit_idx, unit_info_ranges->count)
|
for EachIndex(unit_idx, unit_count)
|
||||||
{
|
{
|
||||||
total_tag_count_estimate += dim_1u64(unit_info_ranges->v[unit_idx]) / tag_size_estimate;
|
total_tag_count_estimate += dim_1u64(unit_info_tag_ranges[unit_idx]) / tag_size_estimate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,6 +1033,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
UniqueTypeTagNode **unique_type_tag_slots = 0;
|
UniqueTypeTagNode **unique_type_tag_slots = 0;
|
||||||
U64 unique_type_tag_slots_count = total_tag_count_estimate/8 + 1;
|
U64 unique_type_tag_slots_count = total_tag_count_estimate/8 + 1;
|
||||||
UnitTypeMap *unit_type_maps = 0;
|
UnitTypeMap *unit_type_maps = 0;
|
||||||
|
ProfScope("gather all unique type tags across all units")
|
||||||
{
|
{
|
||||||
if(lane_idx() == 0)
|
if(lane_idx() == 0)
|
||||||
{
|
{
|
||||||
@@ -935,167 +1048,231 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
//- rjf: take next unit
|
//- rjf: take next unit
|
||||||
U64 unit_idx = ins_atomic_u64_inc_eval(unit_take_idx_ptr) - 1;
|
U64 origin_unit_idx = ins_atomic_u64_inc_eval(unit_take_idx_ptr) - 1;
|
||||||
if(unit_idx >= unit_count)
|
if(origin_unit_idx >= unit_count)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: unpack unit
|
//- rjf: unpack unit info
|
||||||
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[unit_idx];
|
Rng1U64 origin_unit_info_tag_range = unit_info_tag_ranges[origin_unit_idx];
|
||||||
Rng1U64 unit_info_range = unit_info_ranges->v[unit_idx];
|
|
||||||
|
|
||||||
//- rjf: set up type map for this unit
|
//- rjf: set up type map for this unit
|
||||||
unit_type_maps[unit_idx].slots_count = dim_1u64(unit_info_range) / 256 + 1;
|
unit_type_maps[origin_unit_idx].slots_count = dim_1u64(origin_unit_info_tag_range) / 256 + 1;
|
||||||
unit_type_maps[unit_idx].slots = push_array(scratch.arena, UnitTypeNode *, unit_type_maps[unit_idx].slots_count);
|
unit_type_maps[origin_unit_idx].slots = push_array(scratch.arena, UnitTypeNode *, unit_type_maps[origin_unit_idx].slots_count);
|
||||||
|
|
||||||
//- rjf: find all type tags in this unit
|
//- rjf: hash all type content from tags in this unit; record if unique
|
||||||
for(U64 off = unit_info_range.min; off < unit_info_range.max;)
|
for(U64 off = origin_unit_info_tag_range.min; off < origin_unit_info_tag_range.max;)
|
||||||
{
|
{
|
||||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||||
U64 start_off = off;
|
U64 start_off = off;
|
||||||
|
|
||||||
// rjf: read next tag
|
//- rjf: hash type tags - this requires a hash of not only type tags'
|
||||||
DW2_Tag tag = {0};
|
// attributes, but also a walk of all other type tags this tag references,
|
||||||
off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, off, &tag);
|
// 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 type tag.
|
||||||
|
//
|
||||||
|
B32 is_type_tag_tree = 0;
|
||||||
|
U64 hash = 0;
|
||||||
|
{
|
||||||
|
typedef struct TypeTagTask TypeTagTask;
|
||||||
|
struct TypeTagTask
|
||||||
|
{
|
||||||
|
TypeTagTask *next;
|
||||||
|
U64 unit_idx;
|
||||||
|
U64 off;
|
||||||
|
};
|
||||||
|
TypeTagTask start_task = {0, origin_unit_idx, off};
|
||||||
|
TypeTagTask *first_task = &start_task;
|
||||||
|
TypeTagTask *last_task = first_task;
|
||||||
|
TypeTagTask *free_task = 0;
|
||||||
|
for(TypeTagTask *t = first_task; t != 0; t = t->next)
|
||||||
|
{
|
||||||
|
U64 t_off = t->off;
|
||||||
|
|
||||||
|
// rjf: unpack unit
|
||||||
|
Rng1U64 unit_info_range = unit_info_ranges->v[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_range.min <= t_off && t_off < unit_info_range.max;)
|
||||||
|
{
|
||||||
|
U64 t_start_off = t_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);
|
||||||
|
|
||||||
|
// rjf: record top-level info about this tag tree
|
||||||
|
if(t_start_off == t->off && t == &start_task)
|
||||||
|
{
|
||||||
|
is_type_tag_tree = (tag.kind == DW_TagKind_ArrayType || tag.kind == DW_TagKind_ClassType ||
|
||||||
|
tag.kind == DW_TagKind_EnumerationType || tag.kind == DW_TagKind_PointerType ||
|
||||||
|
tag.kind == DW_TagKind_ReferenceType || tag.kind == DW_TagKind_StringType ||
|
||||||
|
tag.kind == DW_TagKind_StructureType || tag.kind == DW_TagKind_SubroutineType ||
|
||||||
|
tag.kind == DW_TagKind_Typedef || tag.kind == DW_TagKind_UnionType ||
|
||||||
|
tag.kind == DW_TagKind_PtrToMemberType || tag.kind == DW_TagKind_SetType ||
|
||||||
|
tag.kind == DW_TagKind_SubrangeType || tag.kind == DW_TagKind_BaseType ||
|
||||||
|
tag.kind == DW_TagKind_ConstType || tag.kind == DW_TagKind_FileType ||
|
||||||
|
tag.kind == DW_TagKind_PackedType || tag.kind == DW_TagKind_VolatileType ||
|
||||||
|
tag.kind == DW_TagKind_RestrictType || tag.kind == DW_TagKind_InterfaceType ||
|
||||||
|
tag.kind == DW_TagKind_UnspecifiedType || tag.kind == DW_TagKind_SharedType ||
|
||||||
|
tag.kind == DW_TagKind_RValueReferenceType || tag.kind == DW_TagKind_CoarrayType ||
|
||||||
|
tag.kind == DW_TagKind_DynamicType || tag.kind == DW_TagKind_AtomicType ||
|
||||||
|
tag.kind == DW_TagKind_ImmutableType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: is type -> combine tag's content into hash
|
||||||
|
if(is_type_tag_tree)
|
||||||
|
{
|
||||||
|
// rjf: combine tag's kind
|
||||||
|
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
|
||||||
|
|
||||||
|
// rjf: combine non-reference attributes (references could be different,
|
||||||
|
// because of deduping, but they could match ultimately). for any
|
||||||
|
// referenced dependency types, kick them off
|
||||||
|
for(DW2_AttribNode *n = tag.attribs.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->v.val.kind != DW_Form_RefAddr &&
|
||||||
|
n->v.val.kind != DW_Form_Ref1 &&
|
||||||
|
n->v.val.kind != DW_Form_Ref2 &&
|
||||||
|
n->v.val.kind != DW_Form_Ref4 &&
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
hash = u64_hash_from_seed_str8(hash, n->v.val.string);
|
||||||
|
}
|
||||||
|
if(n->v.attrib_kind == DW_AttribKind_Type)
|
||||||
|
{
|
||||||
|
TypeTagTask *dependency_task = free_task;
|
||||||
|
if(dependency_task != 0)
|
||||||
|
{
|
||||||
|
SLLStackPop(free_task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dependency_task = push_array(scratch2.arena, TypeTagTask, 1);
|
||||||
|
}
|
||||||
|
dependency_task->off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &n->v.val);
|
||||||
|
dependency_task->unit_idx = t->unit_idx;
|
||||||
|
if(!contains_1u64(unit_info_range, dependency_task->off))
|
||||||
|
{
|
||||||
|
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(unit_info_ranges, dependency_task->off);
|
||||||
|
if(0 < new_unit_num && new_unit_num <= unit_count)
|
||||||
|
{
|
||||||
|
dependency_task->unit_idx = new_unit_num-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: is type tag tree, has children -> descend
|
||||||
|
if(is_type_tag_tree && tag.has_children)
|
||||||
|
{
|
||||||
|
depth += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: zero tag kind -> ascend
|
||||||
|
if(is_type_tag_tree && tag.kind == DW_TagKind_Null && depth > 0)
|
||||||
|
{
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: no advancing? -> +1
|
||||||
|
if(t_off == t_start_off)
|
||||||
|
{
|
||||||
|
t_off += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: depth == 0? -> done
|
||||||
|
if(depth == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: is this the starter task? -> advance base reading offset
|
||||||
|
if(t == &start_task)
|
||||||
|
{
|
||||||
|
off = t_off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rjf: if offset not advanced -> increment
|
//- rjf: if offset not advanced -> increment
|
||||||
if(off == start_off)
|
if(off == start_off)
|
||||||
{
|
{
|
||||||
off += 1;
|
off += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: if type tag -> read full tree, hash, gather
|
//- rjf: atomically gather this hash if not already gathered
|
||||||
switch(tag.kind)
|
if(is_type_tag_tree)
|
||||||
{
|
{
|
||||||
default:{}break;
|
B32 gathered = 0;
|
||||||
case DW_TagKind_ArrayType:
|
U64 slot_idx = hash%unique_type_tag_slots_count;
|
||||||
case DW_TagKind_ClassType:
|
for(;!gathered;)
|
||||||
case DW_TagKind_EnumerationType:
|
|
||||||
case DW_TagKind_PointerType:
|
|
||||||
case DW_TagKind_ReferenceType:
|
|
||||||
case DW_TagKind_StringType:
|
|
||||||
case DW_TagKind_StructureType:
|
|
||||||
case DW_TagKind_SubroutineType:
|
|
||||||
case DW_TagKind_Typedef:
|
|
||||||
case DW_TagKind_UnionType:
|
|
||||||
case DW_TagKind_PtrToMemberType:
|
|
||||||
case DW_TagKind_SetType:
|
|
||||||
case DW_TagKind_SubrangeType:
|
|
||||||
case DW_TagKind_BaseType:
|
|
||||||
case DW_TagKind_ConstType:
|
|
||||||
case DW_TagKind_FileType:
|
|
||||||
case DW_TagKind_PackedType:
|
|
||||||
case DW_TagKind_VolatileType:
|
|
||||||
case DW_TagKind_RestrictType:
|
|
||||||
case DW_TagKind_InterfaceType:
|
|
||||||
case DW_TagKind_UnspecifiedType:
|
|
||||||
case DW_TagKind_SharedType:
|
|
||||||
case DW_TagKind_RValueReferenceType:
|
|
||||||
case DW_TagKind_CoarrayType:
|
|
||||||
case DW_TagKind_DynamicType:
|
|
||||||
case DW_TagKind_AtomicType:
|
|
||||||
case DW_TagKind_ImmutableType:
|
|
||||||
{
|
{
|
||||||
// rjf: form hash from top-level tag
|
// rjf: read existing slot head pointer *before* we lookup / insert
|
||||||
U64 hash = d2r2_hash_from_seed_tag(5381, &tag);
|
U64 slot_head_val = ins_atomic_u64_eval(&unique_type_tag_slots[slot_idx]);
|
||||||
|
|
||||||
// rjf: if this tag has children -> hash all children, combine into `hash`
|
// rjf: determine if this hash has been gathered
|
||||||
if(tag.has_children)
|
for(UniqueTypeTagNode *n = (UniqueTypeTagNode *)slot_head_val; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
U64 depth = 1;
|
if(n->hash == hash)
|
||||||
for(;off < unit_info_range.max && depth > 0;)
|
|
||||||
{
|
{
|
||||||
Temp temp = temp_begin(scratch2.arena);
|
gathered = 1;
|
||||||
U64 start_off_2 = off;
|
break;
|
||||||
|
|
||||||
// rjf: read descendant tag
|
|
||||||
DW2_Tag descendant_tag = {0};
|
|
||||||
off += dw2_read_tag(temp.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, off, &descendant_tag);
|
|
||||||
|
|
||||||
// rjf: if offset not advanced -> increment
|
|
||||||
if(off == start_off_2)
|
|
||||||
{
|
|
||||||
off += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: combine hash of descendant tag to main hash
|
|
||||||
hash = d2r2_hash_from_seed_tag(hash, &descendant_tag);
|
|
||||||
|
|
||||||
// rjf: navigate the tree
|
|
||||||
if(descendant_tag.kind == DW_TagKind_Null)
|
|
||||||
{
|
|
||||||
depth -= 1;
|
|
||||||
}
|
|
||||||
else if(descendant_tag.has_children)
|
|
||||||
{
|
|
||||||
depth += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_end(temp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: atomically gather this hash if not already gathered
|
// rjf: if this hash has *not* been gathered, try an insert. we:
|
||||||
|
//
|
||||||
|
// 1. allocate/fill a node
|
||||||
|
// 2. set it up to point to the old head
|
||||||
|
// 3. compare/exchange the old head with the new head - IFF the head matches what we expect from above
|
||||||
|
// 4. if we fail, another thread has touched this slot, we pop the allocated node & try again
|
||||||
|
// (we may find that another thread has filled this hash, so we'll just be done)
|
||||||
|
//
|
||||||
|
if(!gathered)
|
||||||
{
|
{
|
||||||
B32 gathered = 0;
|
Temp insert_temp = temp_begin(scratch.arena);
|
||||||
U64 slot_idx = hash%unique_type_tag_slots_count;
|
UniqueTypeTagNode *n = push_array(scratch.arena, UniqueTypeTagNode, 1);
|
||||||
for(;!gathered;)
|
n->next = (UniqueTypeTagNode *)slot_head_val;
|
||||||
|
n->hash = hash;
|
||||||
|
n->unit_idx = origin_unit_idx;
|
||||||
|
n->info_off = start_off;
|
||||||
|
U64 new_head_val = (U64)n;
|
||||||
|
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unique_type_tag_slots[slot_idx], new_head_val, slot_head_val))
|
||||||
{
|
{
|
||||||
// rjf: read existing slot head pointer *before* we lookup / insert
|
gathered = 1;
|
||||||
U64 slot_head_val = ins_atomic_u64_eval(&unique_type_tag_slots[slot_idx]);
|
}
|
||||||
|
else
|
||||||
// rjf: determine if this hash has been gathered
|
{
|
||||||
for(UniqueTypeTagNode *n = (UniqueTypeTagNode *)slot_head_val; n != 0; n = n->next)
|
temp_end(insert_temp);
|
||||||
{
|
|
||||||
if(n->hash == hash)
|
|
||||||
{
|
|
||||||
gathered = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: if this hash has *not* been gathered, try an insert. we:
|
|
||||||
//
|
|
||||||
// 1. allocate/fill a node
|
|
||||||
// 2. set it up to point to the old head
|
|
||||||
// 3. compare/exchange the old head with the new head - IFF the head matches what we expect from above
|
|
||||||
// 4. if we fail, another thread has touched this slot, we pop the allocated node & try again
|
|
||||||
// (we may find that another thread has filled this hash, so we'll just be done)
|
|
||||||
//
|
|
||||||
if(!gathered)
|
|
||||||
{
|
|
||||||
Temp insert_temp = temp_begin(scratch.arena);
|
|
||||||
UniqueTypeTagNode *n = push_array(scratch.arena, UniqueTypeTagNode, 1);
|
|
||||||
n->next = (UniqueTypeTagNode *)slot_head_val;
|
|
||||||
n->hash = hash;
|
|
||||||
n->unit_idx = unit_idx;
|
|
||||||
n->info_off = start_off;
|
|
||||||
U64 new_head_val = (U64)n;
|
|
||||||
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unique_type_tag_slots[slot_idx], slot_head_val, new_head_val))
|
|
||||||
{
|
|
||||||
gathered = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp_end(insert_temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// rjf: 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.
|
//- rjf: record this (info_off -> hash) mapping, so that when we have
|
||||||
{
|
// later references to this type, we can redirect to the deduplicated
|
||||||
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
|
// type with the right hash later.
|
||||||
U64 info_off_slot_idx = info_off_hash%unit_type_maps[unit_idx].slots_count;
|
if(is_type_tag_tree)
|
||||||
UnitTypeNode *n = push_array(scratch.arena, UnitTypeNode, 1);
|
{
|
||||||
n->src_info_off = start_off;
|
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
|
||||||
n->dst_hash = hash;
|
U64 info_off_slot_idx = info_off_hash%unit_type_maps[origin_unit_idx].slots_count;
|
||||||
SLLStackPush(unit_type_maps[unit_idx].slots[info_off_slot_idx], n);
|
UnitTypeNode *n = push_array(scratch.arena, UnitTypeNode, 1);
|
||||||
}
|
n->src_info_off = start_off;
|
||||||
}break;
|
n->dst_hash = hash;
|
||||||
|
SLLStackPush(unit_type_maps[origin_unit_idx].slots[info_off_slot_idx], n);
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_end(scratch2);
|
scratch_end(scratch2);
|
||||||
@@ -1104,6 +1281,93 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
lane_sync();
|
lane_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: produce [0...n) -> unique-tag-node mapping for all types
|
||||||
|
//
|
||||||
|
U64 type_count = 0;
|
||||||
|
UniqueTypeTagNode **type_tag_nodes = 0;
|
||||||
|
ProfScope("produce [0...n) -> hash mapping for all types") if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
for EachIndex(slot_idx, unique_type_tag_slots_count)
|
||||||
|
{
|
||||||
|
for EachNode(n, UniqueTypeTagNode, unique_type_tag_slots[slot_idx])
|
||||||
|
{
|
||||||
|
type_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type_tag_nodes = push_array(scratch.arena, UniqueTypeTagNode *, type_count);
|
||||||
|
U64 idx = 0;
|
||||||
|
for EachIndex(slot_idx, unique_type_tag_slots_count)
|
||||||
|
{
|
||||||
|
for EachNode(n, UniqueTypeTagNode, unique_type_tag_slots[slot_idx])
|
||||||
|
{
|
||||||
|
type_tag_nodes[idx] = n;
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync_u64(&type_count, 0);
|
||||||
|
lane_sync_u64(&type_tag_nodes, 0);
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: gather per-type dependency chains
|
||||||
|
//
|
||||||
|
typedef struct TypeDepChain TypeDepChain;
|
||||||
|
struct TypeDepChain
|
||||||
|
{
|
||||||
|
TypeDepChain *next;
|
||||||
|
U64 hash;
|
||||||
|
};
|
||||||
|
TypeDepChain **type_dep_chains = 0;
|
||||||
|
ProfScope("gather per-type dependency chains")
|
||||||
|
{
|
||||||
|
if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
type_dep_chains = push_array(scratch.arena, TypeDepChain *, type_count);
|
||||||
|
}
|
||||||
|
lane_sync_u64(&type_dep_chains, 0);
|
||||||
|
Rng1U64 range = lane_range(type_count);
|
||||||
|
for EachInRange(type_idx, range)
|
||||||
|
{
|
||||||
|
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||||
|
|
||||||
|
// rjf: unpack type's tag node
|
||||||
|
UniqueTypeTagNode *type_tag_node = type_tag_nodes[type_idx];
|
||||||
|
U64 info_off = type_tag_node->info_off;
|
||||||
|
U64 unit_idx = type_tag_node->unit_idx;
|
||||||
|
|
||||||
|
// rjf: unpack unit
|
||||||
|
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[unit_idx];
|
||||||
|
Rng1U64 unit_info_range = unit_info_ranges->v[unit_idx];
|
||||||
|
|
||||||
|
// rjf: parse this type's tag
|
||||||
|
DW2_Tag tag = {0};
|
||||||
|
dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, info_off, &tag);
|
||||||
|
|
||||||
|
// rjf: find direct type, if one exists
|
||||||
|
switch(tag.kind)
|
||||||
|
{
|
||||||
|
default:{}break;
|
||||||
|
case DW_TagKind_PointerType:
|
||||||
|
case DW_TagKind_ReferenceType:
|
||||||
|
case DW_TagKind_RValueReferenceType:
|
||||||
|
case DW_TagKind_RestrictType:
|
||||||
|
case DW_TagKind_VolatileType:
|
||||||
|
case DW_TagKind_ConstType:
|
||||||
|
case DW_TagKind_ArrayType:
|
||||||
|
case DW_TagKind_SubrangeType:
|
||||||
|
case DW_TagKind_Typedef:
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: fill result
|
//- rjf: fill result
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ struct D2R2_ConvertParams
|
|||||||
B32 deterministic;
|
B32 deterministic;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Helpers
|
|
||||||
|
|
||||||
internal U64 d2r2_hash_from_seed_tag(U64 seed, DW2_Tag *tag);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Main Conversion Entry Point (New)
|
//~ rjf: Main Conversion Entry Point (New)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user