mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 23:08:08 +00:00
checkpoint on rdi_from_dwarf pass, start addressing O(N lg N) hashing problem for type content, use sibling tags, etc.; remove test inputs from data/, just rely on local folder (filled via data server)
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
bias = (bias^x)&7;
|
||||
x -= bias;
|
||||
x *= 2;
|
||||
x *= x;
|
||||
x += bias;
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
/*
|
||||
* Program to run in debugger organized to provide tests for
|
||||
* single threaded stepping, breakpoints, evaluation.
|
||||
*/
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Complex Types
|
||||
|
||||
#include <complex.h>
|
||||
|
||||
void
|
||||
c_type_coverage_eval_tests(void){
|
||||
#if _WIN32
|
||||
_Fcomplex x = _FCbuild(0.f, 1.f);
|
||||
_Dcomplex y = _Cbuild(0.f, -1.f);
|
||||
|
||||
#else
|
||||
float complex x = 0.f + 1.f*I;
|
||||
double complex y = 0.0 - 1.0*I;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Reuse Type Names From Another Module
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct Basics{
|
||||
double a;
|
||||
float b;
|
||||
unsigned long long c;
|
||||
long long d;
|
||||
unsigned int e;
|
||||
int f;
|
||||
unsigned short g;
|
||||
short h;
|
||||
unsigned char i;
|
||||
char j;
|
||||
|
||||
int z;
|
||||
} Basics;
|
||||
|
||||
typedef struct Basics_Stdint{
|
||||
double x1;
|
||||
float x2;
|
||||
uint64_t x3;
|
||||
int64_t x4;
|
||||
uint32_t x5;
|
||||
int32_t x6;
|
||||
uint16_t x7;
|
||||
int16_t x8;
|
||||
uint8_t x9;
|
||||
int8_t x0;
|
||||
} Basics_Stdint;
|
||||
|
||||
typedef struct Pair{
|
||||
int i;
|
||||
float f;
|
||||
} Pair;
|
||||
|
||||
void
|
||||
c_versions_of_same_types(void){
|
||||
Basics basics = { 1.5f, 1.50000000000001, -1, 1, -2, 2, -4, 4, -8, 8, };
|
||||
Basics_Stdint basics_stdint = { 1.5f, 1.50000000000001, -1, 1, -2, 2, -4, 4, -8, 8, };
|
||||
Pair memory_[] = {
|
||||
{100, 1.f},
|
||||
{101, 2.f},
|
||||
{102, 4.f},
|
||||
{103, 8.f},
|
||||
{104, 16.f},
|
||||
{105, 32.f},
|
||||
};
|
||||
|
||||
int x = memory_[3].i + basics.f;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(rjf): Bitfields
|
||||
|
||||
typedef struct TypeWithBitfield TypeWithBitfield;
|
||||
struct TypeWithBitfield
|
||||
{
|
||||
int v : 14;
|
||||
int w : 4;
|
||||
int x : 32;
|
||||
int y : 4;
|
||||
int z : 10;
|
||||
};
|
||||
|
||||
typedef struct BitfieldType64 BitfieldType64;
|
||||
struct BitfieldType64
|
||||
{
|
||||
uint64_t size : 63;
|
||||
uint64_t is_free : 1;
|
||||
};
|
||||
|
||||
static int mut_xarray[4] = {100, 101, 102, 103};
|
||||
static float mut_farray[4] = {100.5f, 101.5f, 102.5f, 103.5f};
|
||||
|
||||
void
|
||||
c_type_with_bitfield_usage(void)
|
||||
{
|
||||
TypeWithBitfield b = {0};
|
||||
b.v = 100;
|
||||
b.w = 6;
|
||||
b.x = 434512;
|
||||
b.y = 7;
|
||||
b.z = 12;
|
||||
int x = (b.v + b.x);
|
||||
int y = (b.y - b.z);
|
||||
int z = (b.w) + 5;
|
||||
BitfieldType64 b64 = {0};
|
||||
b64.size = 524288;
|
||||
b64.is_free = 1;
|
||||
int abc = mut_xarray[0];
|
||||
mut_xarray[0] += 1;
|
||||
abc += mut_xarray[0];
|
||||
abc += mut_xarray[1];
|
||||
abc += mut_xarray[2];
|
||||
float f = mut_farray[0] + mut_farray[1] + mut_farray[2] + mut_farray[3];
|
||||
int w = 0;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
/*
|
||||
* Program to run in debugger organized to provide tests for
|
||||
* single threaded stepping, breakpoints, evaluation.
|
||||
*/
|
||||
|
||||
void c_type_coverage_eval_tests(void);
|
||||
void c_type_with_bitfield_usage(void);
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
/*
|
||||
** Make sure we have an inlined function
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define FORCE_INLINE __forceinline
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
# define FORCE_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
# error need force inline for this compiler
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Inline Stepping
|
||||
|
||||
unsigned int fixed_frac_bits = 5;
|
||||
static unsigned int bias = 7;
|
||||
|
||||
static FORCE_INLINE unsigned int
|
||||
fixed_mul(unsigned int a, unsigned int b){
|
||||
unsigned int c = (((a - bias)*(b - bias)) >> fixed_frac_bits) + bias;
|
||||
return(c);
|
||||
}
|
||||
|
||||
static FORCE_INLINE unsigned int
|
||||
multi_file_inlinesite(unsigned int x){
|
||||
// force compiler to generate annotations for code that's inside another file
|
||||
#include "inline_body.cpp"
|
||||
return x >> fixed_frac_bits;
|
||||
}
|
||||
|
||||
static unsigned int test_value = 0;
|
||||
|
||||
unsigned int
|
||||
inline_stepping_tests(void){
|
||||
bias = 15;
|
||||
|
||||
// NOTE(nick): Interesting that CL does not generate inline site symbols in order of apperance here unlike clang.
|
||||
|
||||
// CL:
|
||||
// BinaryAnnotations: CodeLengthAndCodeOffset d 0
|
||||
// BinaryAnnotation Length: 4 bytes (1 bytes padding)
|
||||
//
|
||||
// Clang:
|
||||
// BinaryAnnotations: LineOffset 1 CodeLength d
|
||||
// BinaryAnnotation Length: 4 bytes (0 bytes padding)
|
||||
unsigned int x = fixed_mul(5001, 7121);
|
||||
|
||||
// CL:
|
||||
// BinaryAnnotations: CodeOffsetAndLineOffset d File 0 CodeOffsetAndLineOffset 22 LineOffset 1e
|
||||
// CodeLengthAndCodeOffset 2 3
|
||||
// BinaryAnnotation Length: 12 bytes (1 bytes padding)
|
||||
//
|
||||
// Clang:
|
||||
// BinaryAnnotations: File 18 LineOffset ffffffe6 CodeOffset d CodeOffsetAndLineOffset 22
|
||||
// File 0 LineOffset 1e CodeOffset 3 CodeLength 2
|
||||
// BinaryAnnotation Length: 16 bytes (0 bytes padding)
|
||||
unsigned int z = multi_file_inlinesite(x);
|
||||
return(z);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e2b10fe04ef539796a329790987f781e645707a737e32db863f3e49a1766bf5a
|
||||
size 4763648
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:446e9b14f298e3824edccf61d857108d6100a3c1a3a5dcd7fa7d52fe5a1d6a8d
|
||||
size 2768548
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7ac765d8dfa6d3a3830b3efc76d8b52f6dd201004e9fead477138ac7b4d1015a
|
||||
size 264704
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#if _WIN32
|
||||
#define export_function extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define export_function extern "C"
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
# define thread_var __declspec(thread)
|
||||
#else
|
||||
# define thread_var __thread
|
||||
#endif
|
||||
|
||||
typedef struct OnlyInModule OnlyInModule;
|
||||
struct OnlyInModule
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
char *name;
|
||||
};
|
||||
|
||||
typedef struct Basics Basics;
|
||||
struct Basics
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
int d;
|
||||
};
|
||||
|
||||
static OnlyInModule only_in_module_global =
|
||||
{
|
||||
1, 2, 3, "foobar",
|
||||
};
|
||||
|
||||
thread_var float tls_a = 1.015625f;
|
||||
thread_var int tls_b = -100;
|
||||
|
||||
export_function void
|
||||
dll_tls_eval_test(void)
|
||||
{
|
||||
tls_a *= 1.5f;
|
||||
tls_b *= -2;
|
||||
only_in_module_global.x += 1;
|
||||
only_in_module_global.y += 2;
|
||||
only_in_module_global.z += 3;
|
||||
}
|
||||
|
||||
export_function void
|
||||
dll_type_eval_tests(void)
|
||||
{
|
||||
Basics basics1 = {1, 2, 3, 4};
|
||||
Basics basics2 = {4, 5, 6, 7};
|
||||
OnlyInModule only_in_module = {123, 456, 789, "this type is only in the module!"};
|
||||
int x = 0;
|
||||
(void)x;
|
||||
}
|
||||
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bc2f8b6f96c6bea013dbebcd6f6d84c0f015a361a62bf9158785687402b84311
|
||||
size 6942720
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:73c47bf20d8d12057fa9e4d12873620f6c860b1bc5d4f831b4925f03e9f7c0b4
|
||||
size 5518096
|
||||
@@ -1,119 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
static int important_s32 = 0;
|
||||
static float important_f32 = 0;
|
||||
|
||||
#if _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_something_with_intermediate_values(void)
|
||||
{
|
||||
static int another_important_s32 = 0;
|
||||
static float another_important_f32 = 0;
|
||||
|
||||
another_important_s32 = (int)important_f32;
|
||||
another_important_f32 = (float)important_s32;
|
||||
|
||||
#if _WIN32
|
||||
char buffer[256] = "Hello, World!\n";
|
||||
buffer[0] += important_s32 + another_important_s32;
|
||||
buffer[1] += (int)another_important_f32 * important_f32;
|
||||
OutputDebugStringA(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
store_important_s32(int *ptr)
|
||||
{
|
||||
important_s32 = *ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
store_important_f32(float *ptr)
|
||||
{
|
||||
important_f32 = *ptr;
|
||||
}
|
||||
|
||||
void
|
||||
optimized_build_eval_tests(void)
|
||||
{
|
||||
int simple_sum = 0;
|
||||
for(int i = 0; i < 10000; i += 1)
|
||||
{
|
||||
simple_sum += i;
|
||||
}
|
||||
store_important_s32(&simple_sum);
|
||||
|
||||
do_something_with_intermediate_values();
|
||||
|
||||
static struct {float x, y;} vec2s[] =
|
||||
{
|
||||
{ 10.f, 76.f },
|
||||
{ 40.f, 50.f },
|
||||
{ -230.f, 20.f },
|
||||
{ 27.f, 27.f },
|
||||
{ 57.f, -57.f },
|
||||
{ -37.f, 97.f },
|
||||
{ 99.f, 67.f },
|
||||
{ 99.f, 37.f },
|
||||
{ 99.f, 57.f },
|
||||
};
|
||||
{
|
||||
struct{float x, y;}sum = {0};
|
||||
int count = sizeof(vec2s)/sizeof(vec2s[0]);
|
||||
for(int i = 0; i < count; i += 1)
|
||||
{
|
||||
sum.x += vec2s[i].x;
|
||||
sum.y += vec2s[i].y;
|
||||
}
|
||||
struct{float x, y;}avg = {sum.x/count, sum.y/count};
|
||||
float f32 = avg.x * avg.y;
|
||||
store_important_f32(&f32);
|
||||
}
|
||||
|
||||
do_something_with_intermediate_values();
|
||||
|
||||
int factorial = 1;
|
||||
for(int i = 10; i > 0; i -= 1)
|
||||
{
|
||||
factorial *= i;
|
||||
}
|
||||
store_important_s32(&factorial);
|
||||
|
||||
do_something_with_intermediate_values();
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Struct Parameters Eval
|
||||
|
||||
struct OptimizedBasics{
|
||||
char a;
|
||||
unsigned char b;
|
||||
short c;
|
||||
unsigned short d;
|
||||
int e;
|
||||
unsigned int f;
|
||||
long long g;
|
||||
unsigned long long h;
|
||||
float i;
|
||||
double j;
|
||||
};
|
||||
|
||||
static void
|
||||
optimized_struct_parameter_helper(int *ptr, OptimizedBasics basics)
|
||||
{
|
||||
basics.a += *ptr;
|
||||
basics.a += 1;
|
||||
basics.a += 1;
|
||||
}
|
||||
|
||||
void
|
||||
optimized_struct_parameters_eval_tests(void)
|
||||
{
|
||||
int x = 10;
|
||||
OptimizedBasics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001};
|
||||
optimized_struct_parameter_helper(&x, basics);
|
||||
}
|
||||
@@ -930,6 +930,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
//- rjf: find all offsets of top-level tag trees across all units
|
||||
//
|
||||
U64Array *unit_info_root_tag_offs = 0;
|
||||
U64 *unit_tag_counts__first_pass = 0; // only includes roots + any descendants of roots who *don't* have a 'sibling' attribute
|
||||
U64 total_root_tag_count = 0;
|
||||
U64 *total_root_tag_count_ptr = &total_root_tag_count;
|
||||
lane_sync_u64(&total_root_tag_count_ptr, 0);
|
||||
@@ -938,8 +939,10 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
unit_info_root_tag_offs = push_array(scratch.arena, U64Array, unit_count);
|
||||
unit_tag_counts__first_pass = push_array(scratch.arena, U64, unit_count);
|
||||
}
|
||||
lane_sync_u64(&unit_info_root_tag_offs, 0);
|
||||
lane_sync_u64(&unit_tag_counts__first_pass, 0);
|
||||
typedef struct D2R_UnitTagTreeOffChunkNode D2R_UnitTagTreeOffChunkNode;
|
||||
struct D2R_UnitTagTreeOffChunkNode
|
||||
{
|
||||
@@ -1001,6 +1004,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
//- rjf: reading the next tag
|
||||
DW2_Tag tag = {0};
|
||||
off += dw2_read_tag(scratch3.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag);
|
||||
unit_tag_counts__first_pass[unit_idx] += 1;
|
||||
|
||||
//- rjf: look for sibling attribute fast path
|
||||
DW2_Attrib *sibling_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Sibling);
|
||||
@@ -1104,6 +1108,190 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
lane_sync_u64(&sub_unit_works_count, 0);
|
||||
lane_sync_u64(&sub_unit_works, 0);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: predict the total number of tags in all units
|
||||
//
|
||||
U64 total_tag_count_estimate = 1;
|
||||
{
|
||||
U64 tag_size_estimate = 32;
|
||||
for EachIndex(unit_idx, unit_count)
|
||||
{
|
||||
total_tag_count_estimate += dim_1u64(unit_info_tag_ranges[unit_idx]) / tag_size_estimate;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: hash all tags / attributes related to type info in all works,
|
||||
// for combining into type content hashes later. type content hashes
|
||||
// require combining a tree of several tag hashes - this just does the
|
||||
// tag hash portion.
|
||||
//
|
||||
// record into (off -> hash) map.
|
||||
//
|
||||
U64 tag_hash_slots_count = total_tag_count_estimate/8 + 1;
|
||||
D2R_TagHashNode **tag_hash_slots = 0;
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
tag_hash_slots = push_array(scratch.arena, D2R_TagHashNode *, tag_hash_slots_count);
|
||||
}
|
||||
lane_sync_u64(&tag_hash_slots, 0);
|
||||
ProfScope("hash all tags / attributes related to type info in all works, for combining into type content hashes later")
|
||||
{
|
||||
U64 work_take_idx_ = 0;
|
||||
U64 *work_take_idx_ptr = &work_take_idx_;
|
||||
lane_sync_u64(&work_take_idx_ptr, 0);
|
||||
for(;;)
|
||||
{
|
||||
//- rjf: take next work
|
||||
U64 work_idx = ins_atomic_u64_inc_eval(work_take_idx_ptr) - 1;
|
||||
if(work_idx >= sub_unit_works_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ProfBegin("hash work");
|
||||
|
||||
//- rjf: unpack work
|
||||
U64 unit_idx = sub_unit_works[work_idx].unit_idx;
|
||||
Rng1U64 unit_root_tag_idx_range = sub_unit_works[work_idx].root_tag_idx_range;
|
||||
|
||||
//- rjf: unpack unit info
|
||||
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[unit_idx];
|
||||
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
|
||||
|
||||
//- rjf: hash all relevant tags
|
||||
for(U64 root_tag_idx = unit_root_tag_idx_range.min;
|
||||
root_tag_idx < unit_root_tag_idx_range.max;
|
||||
root_tag_idx += 1)
|
||||
{
|
||||
U64 root_tag_start_off = unit_info_root_tag_offs[unit_idx].v[root_tag_idx];
|
||||
S64 depth = 0;
|
||||
for(U64 off = root_tag_start_off; contains_1u64(unit_info_tag_range, off) && (depth > 0 || off == root_tag_start_off);)
|
||||
{
|
||||
Temp tag_scratch = scratch_begin(&scratch.arena, 1);
|
||||
U64 start_off = off;
|
||||
|
||||
// rjf: read tag
|
||||
DW2_Tag tag = {0};
|
||||
off += dw2_read_tag(tag_scratch.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, off, &tag);
|
||||
|
||||
// rjf: determine if we need this tag's hash
|
||||
B32 need_tag_hash = (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_SubProgram ||
|
||||
tag.kind == DW_TagKind_Typedef ||
|
||||
tag.kind == DW_TagKind_UnionType ||
|
||||
tag.kind == DW_TagKind_PtrToMemberType ||
|
||||
tag.kind == DW_TagKind_SetType ||
|
||||
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 ||
|
||||
tag.kind == DW_TagKind_Namespace);
|
||||
|
||||
// rjf: hash <:= tag kind
|
||||
U64 hash = 0;
|
||||
if(need_tag_hash)
|
||||
{
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
|
||||
}
|
||||
|
||||
// rjf: hash <:= non-reference attributes
|
||||
if(need_tag_hash) for(DW2_AttribNode *n = tag.attribs.first; n != 0; n = n->next)
|
||||
{
|
||||
if(n->v.val.kind != DW_FormKind_RefAddr &&
|
||||
n->v.val.kind != DW_FormKind_Ref1 &&
|
||||
n->v.val.kind != DW_FormKind_Ref2 &&
|
||||
n->v.val.kind != DW_FormKind_Ref4 &&
|
||||
n->v.val.kind != DW_FormKind_Ref8 &&
|
||||
n->v.val.kind != DW_FormKind_RefUData &&
|
||||
n->v.val.kind != DW_FormKind_RefSup4 &&
|
||||
n->v.val.kind != DW_FormKind_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));
|
||||
if(n->v.val.string.size != 0)
|
||||
{
|
||||
hash = u64_hash_from_seed_str8(hash, n->v.val.string);
|
||||
}
|
||||
else if(n->v.val.addr != 0)
|
||||
{
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.u128));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: store
|
||||
if(need_tag_hash)
|
||||
{
|
||||
U64 off_hash = u64_hash_from_str8(str8_struct(&start_off));
|
||||
U64 slot_idx = off_hash%tag_hash_slots_count;
|
||||
D2R_TagHashNode *n = push_array(scratch.arena, D2R_TagHashNode, 1);
|
||||
n->info_off = start_off;
|
||||
n->hash = hash;
|
||||
for(B32 inserted = 0; !inserted;)
|
||||
{
|
||||
U64 slot_head_val = (U64)ins_atomic_u64_eval(&tag_hash_slots[slot_idx]);
|
||||
n->next = (D2R_TagHashNode *)slot_head_val;
|
||||
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&tag_hash_slots[slot_idx], (U64)n, slot_head_val))
|
||||
{
|
||||
inserted = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: tree nav
|
||||
if(tag.has_children)
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
if(tag.kind == DW_TagKind_Null)
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
|
||||
scratch_end(tag_scratch);
|
||||
if(off == start_off)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProfEnd();
|
||||
}
|
||||
lane_sync();
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: build built-in types
|
||||
//
|
||||
@@ -1128,18 +1316,6 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
lane_sync_u64(&builtin_type_from_kind_map, 0);
|
||||
#define d2r_type_from_builtin_kind(k) ((RDI_TypeKind_FirstBuiltIn <= (k) && (k) <= RDI_TypeKind_LastBuiltIn) ? builtin_type_from_kind_map[k - RDI_TypeKind_FirstBuiltIn] : builtin_type_from_kind_map[RDI_TypeKind_Void])
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: predict the total number of tags in all units
|
||||
//
|
||||
U64 total_tag_count_estimate = 1;
|
||||
{
|
||||
U64 tag_size_estimate = 32;
|
||||
for EachIndex(unit_idx, unit_count)
|
||||
{
|
||||
total_tag_count_estimate += dim_1u64(unit_info_tag_ranges[unit_idx]) / tag_size_estimate;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: gather all unique, to-be-deduplicated tags across all units (types, namespaces)
|
||||
//
|
||||
@@ -1245,11 +1421,14 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
// functions are not deduplicated, and even if types defined
|
||||
// within many functions match structurally, we consider them
|
||||
// unique, given that they have different definition sites &
|
||||
// names (fully qualified) still.
|
||||
// names (fully qualified) still. (technically, if two UDTs
|
||||
// match structurally, we could even dedup members - so two
|
||||
// UDT records, w/ different decl sites/names/etc., but point
|
||||
// at the same members)
|
||||
//
|
||||
// (2) namespaced by a type - we do *not* want to deduplicate. the
|
||||
// root-level type will already be deduplicated, so we'll only
|
||||
// produce it once, and that'll catch all sub-types etc.
|
||||
// (2) namespaced by a type - we *do* want to deduplicate. the
|
||||
// root-level type will be deduplicated, but children are
|
||||
// fragmentary - see (3).
|
||||
//
|
||||
// (3) namespaced by a namespace - we *do* want to deduplicate. the
|
||||
// children of a namespace are functionally top-level, and even
|
||||
@@ -1257,8 +1436,12 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
// debug info for each unit will contain fragmentary parts of it,
|
||||
// since presumably unused pieces of the namespace will be stripped.
|
||||
// thus, we need to visit namespace children as if they're top-level.
|
||||
//
|
||||
B32 children_should_be_deduped = 0;
|
||||
if(tag.kind == DW_TagKind_Namespace)
|
||||
if(tag.kind == DW_TagKind_Namespace ||
|
||||
tag.kind == DW_TagKind_ClassType ||
|
||||
tag.kind == DW_TagKind_StructureType ||
|
||||
tag.kind == DW_TagKind_UnionType)
|
||||
{
|
||||
children_should_be_deduped = 1;
|
||||
}
|
||||
@@ -1381,7 +1564,10 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: hash all tags we need to deduplicate & gather
|
||||
//- rjf: produce tree hash for all tags we need to deduplicate & gather
|
||||
//
|
||||
// the tree hash is formed by combining the tag hashes for all dependency tags
|
||||
//
|
||||
U64 total_tag_count_this_work = 0;
|
||||
for(D2R_TagNode *tag_n = first_tag_to_dedup; tag_n != 0; tag_n = tag_n->next)
|
||||
{
|
||||
@@ -1412,14 +1598,31 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
||||
{
|
||||
next = 0;
|
||||
U64 t_off = t->off;
|
||||
U64 off_hash = u64_hash_from_str8(str8_struct(&t->off));
|
||||
|
||||
// rjf: record this task in our seen task table
|
||||
{
|
||||
U64 off_hash = u64_hash_from_str8(str8_struct(&t->off));
|
||||
U64 slot_idx = off_hash%seen_task_slots_count;
|
||||
SLLStackPush(seen_task_slots[slot_idx], t);
|
||||
}
|
||||
|
||||
// rjf: find tag hash for this task
|
||||
U64 tag_hash = 0;
|
||||
{
|
||||
U64 slot_idx = off_hash%tag_hash_slots_count;
|
||||
for(D2R_TagHashNode *n = tag_hash_slots[slot_idx]; n != 0; n = n->next)
|
||||
{
|
||||
if(n->info_off == t_off)
|
||||
{
|
||||
tag_hash = n->hash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: combine tag hash into tree hash
|
||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag_hash));
|
||||
|
||||
// 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];
|
||||
|
||||
@@ -4,6 +4,17 @@
|
||||
#ifndef RDI_FROM_DWARF_H
|
||||
#define RDI_FROM_DWARF_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tag Hash Cache Types
|
||||
|
||||
typedef struct D2R_TagHashNode D2R_TagHashNode;
|
||||
struct D2R_TagHashNode
|
||||
{
|
||||
D2R_TagHashNode *next;
|
||||
U64 info_off;
|
||||
U64 hash;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unique Tag Tree Deduplication Types
|
||||
|
||||
|
||||
@@ -1279,7 +1279,7 @@ t_entry_point(CmdLine *cmdline)
|
||||
{
|
||||
String8 binary_dir_path = get_process_info()->binary_path;
|
||||
String8 root_dir_path = str8_chop_last_slash(binary_dir_path);
|
||||
g_input_data_dir = str8f(scratch.arena, "%S/data/test_inputs", root_dir_path);
|
||||
g_input_data_dir = str8f(scratch.arena, "%S/local/test_inputs", root_dir_path);
|
||||
}
|
||||
|
||||
// setup output directory
|
||||
|
||||
Reference in New Issue
Block a user