mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-12 23:31:38 -07:00
p2r2 more progress; src file line sequence equipping, sketch out symbol conversion - we unfortunately cannot currently easily subdivide units! we need to pull out the few 'record-range' concepts and make them flat first, e.g. proc base address for inline sites, frameproc info, etc.
This commit is contained in:
+1
-1
@@ -47,7 +47,7 @@ commands =
|
||||
{
|
||||
//- rjf: [raddbg]
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build radbin telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build radbin release telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [raddbg wsl]
|
||||
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
@@ -660,7 +660,7 @@ p2r2_convert_thread_entry_point(void *p)
|
||||
String8Array *lane_file_paths = p2r2_shared->lane_file_paths;
|
||||
U64Array *lane_file_paths_hashes = p2r2_shared->lane_file_paths_hashes;
|
||||
|
||||
//////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: build unified collection & map for source files
|
||||
//
|
||||
{
|
||||
@@ -1089,6 +1089,26 @@ p2r2_convert_thread_entry_point(void *p)
|
||||
lane_sync();
|
||||
RDIM_LineTableChunkList all_line_tables = p2r2_shared->all_line_tables;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: equip source files with line sequences
|
||||
//
|
||||
ProfScope("equip source files with line sequences") if(lane_idx() == 0)
|
||||
{
|
||||
for(RDIM_LineTableChunkNode *line_table_chunk_n = all_line_tables.first;
|
||||
line_table_chunk_n != 0;
|
||||
line_table_chunk_n = line_table_chunk_n->next)
|
||||
{
|
||||
for EachIndex(chunk_line_table_idx, line_table_chunk_n->count)
|
||||
{
|
||||
RDIM_LineTable *line_table = &line_table_chunk_n->v[chunk_line_table_idx];
|
||||
for(RDIM_LineSequenceNode *s = line_table->first_seq; s != 0; s = s->next)
|
||||
{
|
||||
rdim_src_file_push_line_sequence(arena, &all_src_files__sequenceless, s->v.src_file, &s->v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: types pass 1: produce type forward resolution map
|
||||
//
|
||||
@@ -2104,6 +2124,682 @@ p2r2_convert_thread_entry_point(void *p)
|
||||
RDIM_Type **basic_type_ptrs = p2r2_shared->basic_type_ptrs;
|
||||
RDIM_TypeChunkList all_types = p2r2_shared->all_types;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: types pass 4: build UDTs
|
||||
//
|
||||
ProfScope("types pass 4: build UDTs")
|
||||
{
|
||||
#define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < tpi_leaf->itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0)
|
||||
|
||||
//- rjf: set up
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
p2r2_shared->lanes_udts = push_array(arena, RDIM_UDTChunkList, lane_count());
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//- rjf: do wide fill
|
||||
{
|
||||
U64 udts_chunk_cap = 1024;
|
||||
RDIM_UDTChunkList *udts = &p2r2_shared->lanes_udts[lane_idx()];
|
||||
Rng1U64 range = lane_range(itype_opl);
|
||||
for EachInRange(idx, range)
|
||||
{
|
||||
//- rjf: skip basics
|
||||
CV_TypeId itype = (CV_TypeId)idx;
|
||||
if(itype < itype_first) { continue; }
|
||||
|
||||
//- rjf: grab type for this itype - skip if empty
|
||||
RDIM_Type *dst_type = itype_type_ptrs[itype];
|
||||
if(dst_type == 0) { continue; }
|
||||
|
||||
//- rjf: unpack itype leaf range - skip if out-of-range
|
||||
CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-tpi_leaf->itype_first];
|
||||
CV_LeafKind kind = range->hdr.kind;
|
||||
U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind);
|
||||
U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2;
|
||||
U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2;
|
||||
if(range->off+range->hdr.size > tpi_leaf->data.size ||
|
||||
range->off+2+header_struct_size > tpi_leaf->data.size ||
|
||||
range->hdr.size < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: build UDT
|
||||
CV_TypeId field_itype = 0;
|
||||
switch(kind)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
////////////////////////
|
||||
//- rjf: structs/unions/classes -> equip members
|
||||
//
|
||||
case CV_LeafKind_CLASS:
|
||||
case CV_LeafKind_STRUCTURE:
|
||||
{
|
||||
CV_LeafStruct *lf = (CV_LeafStruct *)itype_leaf_first;
|
||||
if(lf->props & CV_TypeProp_FwdRef)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_itype = lf->field_itype;
|
||||
}goto equip_members;
|
||||
case CV_LeafKind_UNION:
|
||||
{
|
||||
CV_LeafUnion *lf = (CV_LeafUnion *)itype_leaf_first;
|
||||
if(lf->props & CV_TypeProp_FwdRef)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_itype = lf->field_itype;
|
||||
}goto equip_members;
|
||||
case CV_LeafKind_CLASS2:
|
||||
case CV_LeafKind_STRUCT2:
|
||||
{
|
||||
CV_LeafStruct2 *lf = (CV_LeafStruct2 *)itype_leaf_first;
|
||||
if(lf->props & CV_TypeProp_FwdRef)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_itype = lf->field_itype;
|
||||
}goto equip_members;
|
||||
equip_members:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
//- rjf: grab UDT info
|
||||
RDIM_UDT *dst_udt = dst_type->udt;
|
||||
if(dst_udt == 0)
|
||||
{
|
||||
dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap);
|
||||
dst_udt->self_type = dst_type;
|
||||
}
|
||||
|
||||
//- rjf: gather all fields
|
||||
typedef struct FieldListTask FieldListTask;
|
||||
struct FieldListTask
|
||||
{
|
||||
FieldListTask *next;
|
||||
CV_TypeId itype;
|
||||
};
|
||||
FieldListTask start_fl_task = {0, field_itype};
|
||||
FieldListTask *fl_todo_stack = &start_fl_task;
|
||||
FieldListTask *fl_done_stack = 0;
|
||||
for(;fl_todo_stack != 0;)
|
||||
{
|
||||
//- rjf: take & unpack task
|
||||
FieldListTask *fl_task = fl_todo_stack;
|
||||
SLLStackPop(fl_todo_stack);
|
||||
SLLStackPush(fl_done_stack, fl_task);
|
||||
CV_TypeId field_list_itype = fl_task->itype;
|
||||
|
||||
//- rjf: skip bad itypes
|
||||
if(field_list_itype < tpi_leaf->itype_first || tpi_leaf->itype_opl <= field_list_itype)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: field list itype -> range
|
||||
CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-tpi_leaf->itype_first];
|
||||
|
||||
//- rjf: skip bad headers
|
||||
if(range->off+range->hdr.size > tpi_leaf->data.size ||
|
||||
range->hdr.size < 2 ||
|
||||
range->hdr.kind != CV_LeafKind_FIELDLIST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: loop over all fields
|
||||
{
|
||||
U8 *field_list_first = tpi_leaf->data.str+range->off+2;
|
||||
U8 *field_list_opl = field_list_first+range->hdr.size-2;
|
||||
for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl;
|
||||
read_ptr < field_list_opl;
|
||||
read_ptr = next_read_ptr)
|
||||
{
|
||||
// rjf: unpack field
|
||||
CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr;
|
||||
U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind);
|
||||
U8 *field_leaf_first = read_ptr+2;
|
||||
U8 *field_leaf_opl = field_list_opl;
|
||||
next_read_ptr = field_leaf_opl;
|
||||
|
||||
// rjf: skip out-of-bounds fields
|
||||
if(field_leaf_first+field_leaf_header_size > field_list_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// rjf: process field
|
||||
switch(field_kind)
|
||||
{
|
||||
//- rjf: unhandled/invalid cases
|
||||
default:
|
||||
{
|
||||
// TODO(rjf): log
|
||||
}break;
|
||||
|
||||
//- rjf: INDEX
|
||||
case CV_LeafKind_INDEX:
|
||||
{
|
||||
// rjf: unpack leaf
|
||||
CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first;
|
||||
CV_TypeId new_itype = lf->itype;
|
||||
|
||||
// rjf: bump next read pointer past header
|
||||
next_read_ptr = (U8 *)(lf+1);
|
||||
|
||||
// rjf: determine if index itype is new
|
||||
B32 is_new = 1;
|
||||
for(FieldListTask *t = fl_done_stack; t != 0; t = t->next)
|
||||
{
|
||||
if(t->itype == new_itype)
|
||||
{
|
||||
is_new = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: if new -> push task to follow new itype
|
||||
if(is_new)
|
||||
{
|
||||
FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1);
|
||||
SLLStackPush(fl_todo_stack, new_task);
|
||||
new_task->itype = new_itype;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: MEMBER
|
||||
case CV_LeafKind_MEMBER:
|
||||
{
|
||||
// TODO(rjf): log on bad offset
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafMember *lf = (CV_LeafMember *)field_leaf_first;
|
||||
U8 *offset_ptr = (U8 *)(lf+1);
|
||||
CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl);
|
||||
U64 offset64 = cv_u64_from_numeric(&offset);
|
||||
U8 *name_ptr = offset_ptr + offset.encoded_size;
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_DataField;
|
||||
mem->name = name;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
mem->off = (U32)offset64;
|
||||
}break;
|
||||
|
||||
//- rjf: STMEMBER
|
||||
case CV_LeafKind_STMEMBER:
|
||||
{
|
||||
// TODO(rjf): handle attribs
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafStMember *lf = (CV_LeafStMember *)field_leaf_first;
|
||||
U8 *name_ptr = (U8 *)(lf+1);
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_StaticData;
|
||||
mem->name = name;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
}break;
|
||||
|
||||
//- rjf: METHOD
|
||||
case CV_LeafKind_METHOD:
|
||||
{
|
||||
// rjf: unpack leaf
|
||||
CV_LeafMethod *lf = (CV_LeafMethod *)field_leaf_first;
|
||||
U8 *name_ptr = (U8 *)(lf+1);
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
//- rjf: method list itype -> range
|
||||
CV_RecRange *method_list_range = &tpi_leaf->leaf_ranges.ranges[lf->list_itype-tpi_leaf->itype_first];
|
||||
|
||||
//- rjf: skip bad method lists
|
||||
if(method_list_range->off+method_list_range->hdr.size > tpi_leaf->data.size ||
|
||||
method_list_range->hdr.size < 2 ||
|
||||
method_list_range->hdr.kind != CV_LeafKind_METHODLIST)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//- rjf: loop through all methods & emit members
|
||||
U8 *method_list_first = tpi_leaf->data.str + method_list_range->off + 2;
|
||||
U8 *method_list_opl = method_list_first + method_list_range->hdr.size-2;
|
||||
for(U8 *method_read_ptr = method_list_first, *next_method_read_ptr = method_list_opl;
|
||||
method_read_ptr < method_list_opl;
|
||||
method_read_ptr = next_method_read_ptr)
|
||||
{
|
||||
CV_LeafMethodListMember *method = (CV_LeafMethodListMember*)method_read_ptr;
|
||||
CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(method->attribs);
|
||||
RDIM_Type *method_type = p2r_type_ptr_from_itype(method->itype);
|
||||
next_method_read_ptr = (U8 *)(method+1);
|
||||
|
||||
// TODO(allen): PROBLEM
|
||||
// We only get offsets for virtual functions (the "vbaseoff") from
|
||||
// "Intro" and "PureIntro". In C++ inheritance, when we have a chain
|
||||
// of inheritance (let's just talk single inheritance for now) the
|
||||
// first class in the chain that introduces a new virtual function
|
||||
// has this "Intro" method. If a later class in the chain redefines
|
||||
// the virtual function it only has a "Virtual" method which does
|
||||
// not update the offset. There is a "Virtual" and "PureVirtual"
|
||||
// variant of "Virtual". The "Pure" in either case means there
|
||||
// is no concrete procedure. When there is no "Pure" the method
|
||||
// should have a corresponding procedure symbol id.
|
||||
//
|
||||
// The issue is we will want to mark all of our virtual methods as
|
||||
// virtual and give them an offset, but that means we have to do
|
||||
// some extra figuring to propogate offsets from "Intro" methods
|
||||
// to "Virtual" methods in inheritance trees. That is - IF we want
|
||||
// to start preserving the offsets of virtuals. There is room in
|
||||
// the method struct to make this work, but for now I've just
|
||||
// decided to drop this information. It is not urgently useful to
|
||||
// us and greatly complicates matters.
|
||||
|
||||
// rjf: read vbaseoff
|
||||
U32 vbaseoff = 0;
|
||||
if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro)
|
||||
{
|
||||
if(next_method_read_ptr+4 <= method_list_opl)
|
||||
{
|
||||
vbaseoff = *(U32 *)next_method_read_ptr;
|
||||
}
|
||||
next_method_read_ptr += 4;
|
||||
}
|
||||
|
||||
// rjf: emit method
|
||||
switch(prop)
|
||||
{
|
||||
default:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_Method;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
case CV_MethodProp_Static:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_StaticMethod;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
case CV_MethodProp_Virtual:
|
||||
case CV_MethodProp_PureVirtual:
|
||||
case CV_MethodProp_Intro:
|
||||
case CV_MethodProp_PureIntro:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_VirtualMethod;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
}break;
|
||||
|
||||
//- rjf: ONEMETHOD
|
||||
case CV_LeafKind_ONEMETHOD:
|
||||
{
|
||||
// TODO(rjf): handle attribs
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafOneMethod *lf = (CV_LeafOneMethod *)field_leaf_first;
|
||||
CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(lf->attribs);
|
||||
U8 *vbaseoff_ptr = (U8 *)(lf+1);
|
||||
U8 *vbaseoff_opl_ptr = vbaseoff_ptr;
|
||||
U32 vbaseoff = 0;
|
||||
if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro)
|
||||
{
|
||||
vbaseoff = *(U32 *)(vbaseoff_ptr);
|
||||
vbaseoff_opl_ptr += sizeof(U32);
|
||||
}
|
||||
U8 *name_ptr = vbaseoff_opl_ptr;
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
RDIM_Type *method_type = p2r_type_ptr_from_itype(lf->itype);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit method
|
||||
switch(prop)
|
||||
{
|
||||
default:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_Method;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
|
||||
case CV_MethodProp_Static:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_StaticMethod;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
|
||||
case CV_MethodProp_Virtual:
|
||||
case CV_MethodProp_PureVirtual:
|
||||
case CV_MethodProp_Intro:
|
||||
case CV_MethodProp_PureIntro:
|
||||
{
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_VirtualMethod;
|
||||
mem->name = name;
|
||||
mem->type = method_type;
|
||||
}break;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: NESTTYPE
|
||||
case CV_LeafKind_NESTTYPE:
|
||||
{
|
||||
// rjf: unpack leaf
|
||||
CV_LeafNestType *lf = (CV_LeafNestType *)field_leaf_first;
|
||||
U8 *name_ptr = (U8 *)(lf+1);
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_NestedType;
|
||||
mem->name = name;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
}break;
|
||||
|
||||
//- rjf: NESTTYPEEX
|
||||
case CV_LeafKind_NESTTYPEEX:
|
||||
{
|
||||
// TODO(rjf): handle attribs
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafNestTypeEx *lf = (CV_LeafNestTypeEx *)field_leaf_first;
|
||||
U8 *name_ptr = (U8 *)(lf+1);
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_NestedType;
|
||||
mem->name = name;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
}break;
|
||||
|
||||
//- rjf: BCLASS
|
||||
case CV_LeafKind_BCLASS:
|
||||
{
|
||||
// TODO(rjf): log on bad offset
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafBClass *lf = (CV_LeafBClass *)field_leaf_first;
|
||||
U8 *offset_ptr = (U8 *)(lf+1);
|
||||
CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl);
|
||||
U64 offset64 = cv_u64_from_numeric(&offset);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = offset_ptr+offset.encoded_size;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_Base;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
mem->off = (U32)offset64;
|
||||
}break;
|
||||
|
||||
//- rjf: VBCLASS/IVBCLASS
|
||||
case CV_LeafKind_VBCLASS:
|
||||
case CV_LeafKind_IVBCLASS:
|
||||
{
|
||||
// TODO(rjf): log on bad offsets
|
||||
// TODO(rjf): handle attribs
|
||||
// TODO(rjf): offsets?
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafVBClass *lf = (CV_LeafVBClass *)field_leaf_first;
|
||||
U8 *num1_ptr = (U8 *)(lf+1);
|
||||
CV_NumericParsed num1 = cv_numeric_from_data_range(num1_ptr, field_leaf_opl);
|
||||
U8 *num2_ptr = num1_ptr + num1.encoded_size;
|
||||
CV_NumericParsed num2 = cv_numeric_from_data_range(num2_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past header
|
||||
next_read_ptr = (U8 *)(lf+1);
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt);
|
||||
mem->kind = RDI_MemberKind_VirtualBase;
|
||||
mem->type = p2r_type_ptr_from_itype(lf->itype);
|
||||
}break;
|
||||
|
||||
//- rjf: VFUNCTAB
|
||||
case CV_LeafKind_VFUNCTAB:
|
||||
{
|
||||
CV_LeafVFuncTab *lf = (CV_LeafVFuncTab *)field_leaf_first;
|
||||
|
||||
// rjf: bump next read pointer past header
|
||||
next_read_ptr = (U8 *)(lf+1);
|
||||
|
||||
// NOTE(rjf): currently no-op this case
|
||||
(void)lf;
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: align-up next field
|
||||
next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
////////////////////////
|
||||
//- rjf: enums -> equip enumerates
|
||||
//
|
||||
case CV_LeafKind_ENUM:
|
||||
{
|
||||
CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first;
|
||||
if(lf->props & CV_TypeProp_FwdRef)
|
||||
{
|
||||
break;
|
||||
}
|
||||
field_itype = lf->field_itype;
|
||||
}goto equip_enum_vals;
|
||||
equip_enum_vals:;
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
//- rjf: grab UDT info
|
||||
RDIM_UDT *dst_udt = dst_type->udt;
|
||||
if(dst_udt == 0)
|
||||
{
|
||||
dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap);
|
||||
dst_udt->self_type = dst_type;
|
||||
}
|
||||
|
||||
//- rjf: gather all fields
|
||||
typedef struct FieldListTask FieldListTask;
|
||||
struct FieldListTask
|
||||
{
|
||||
FieldListTask *next;
|
||||
CV_TypeId itype;
|
||||
};
|
||||
FieldListTask start_fl_task = {0, field_itype};
|
||||
FieldListTask *fl_todo_stack = &start_fl_task;
|
||||
FieldListTask *fl_done_stack = 0;
|
||||
for(;fl_todo_stack != 0;)
|
||||
{
|
||||
//- rjf: take & unpack task
|
||||
FieldListTask *fl_task = fl_todo_stack;
|
||||
SLLStackPop(fl_todo_stack);
|
||||
SLLStackPush(fl_done_stack, fl_task);
|
||||
CV_TypeId field_list_itype = fl_task->itype;
|
||||
|
||||
//- rjf: skip bad itypes
|
||||
if(field_list_itype < tpi_leaf->itype_first || tpi_leaf->itype_opl <= field_list_itype)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: field list itype -> range
|
||||
CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-tpi_leaf->itype_first];
|
||||
|
||||
//- rjf: skip bad headers
|
||||
if(range->off+range->hdr.size > tpi_leaf->data.size ||
|
||||
range->hdr.size < 2 ||
|
||||
range->hdr.kind != CV_LeafKind_FIELDLIST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: loop over all fields
|
||||
{
|
||||
U8 *field_list_first = tpi_leaf->data.str+range->off+2;
|
||||
U8 *field_list_opl = field_list_first+range->hdr.size-2;
|
||||
for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl;
|
||||
read_ptr < field_list_opl;
|
||||
read_ptr = next_read_ptr)
|
||||
{
|
||||
// rjf: unpack field
|
||||
CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr;
|
||||
U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind);
|
||||
U8 *field_leaf_first = read_ptr+2;
|
||||
U8 *field_leaf_opl = field_leaf_first+range->hdr.size-2;
|
||||
next_read_ptr = field_leaf_opl;
|
||||
|
||||
// rjf: skip out-of-bounds fields
|
||||
if(field_leaf_first+field_leaf_header_size > field_list_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// rjf: process field
|
||||
switch(field_kind)
|
||||
{
|
||||
//- rjf: unhandled/invalid cases
|
||||
default:
|
||||
{
|
||||
// TODO(rjf): log
|
||||
}break;
|
||||
|
||||
//- rjf: INDEX
|
||||
case CV_LeafKind_INDEX:
|
||||
{
|
||||
// rjf: unpack leaf
|
||||
CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first;
|
||||
CV_TypeId new_itype = lf->itype;
|
||||
|
||||
// rjf: determine if index itype is new
|
||||
B32 is_new = 1;
|
||||
for(FieldListTask *t = fl_done_stack; t != 0; t = t->next)
|
||||
{
|
||||
if(t->itype == new_itype)
|
||||
{
|
||||
is_new = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: if new -> push task to follow new itype
|
||||
if(is_new)
|
||||
{
|
||||
FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1);
|
||||
SLLStackPush(fl_todo_stack, new_task);
|
||||
new_task->itype = new_itype;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: ENUMERATE
|
||||
case CV_LeafKind_ENUMERATE:
|
||||
{
|
||||
// TODO(rjf): attribs
|
||||
|
||||
// rjf: unpack leaf
|
||||
CV_LeafEnumerate *lf = (CV_LeafEnumerate *)field_leaf_first;
|
||||
U8 *val_ptr = (U8 *)(lf+1);
|
||||
CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, field_leaf_opl);
|
||||
U64 val64 = cv_u64_from_numeric(&val);
|
||||
U8 *name_ptr = val_ptr + val.encoded_size;
|
||||
String8 name = str8_cstring_capped(name_ptr, field_leaf_opl);
|
||||
|
||||
// rjf: bump next read pointer past variable length parts
|
||||
next_read_ptr = name.str+name.size+1;
|
||||
|
||||
// rjf: emit member
|
||||
RDIM_UDTEnumVal *enum_val = rdim_udt_push_enum_val(arena, udts, dst_udt);
|
||||
enum_val->name = name;
|
||||
enum_val->val = val64;
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: align-up next field
|
||||
next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef p2r_type_ptr_from_itype
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: produce symbols from all streams
|
||||
//
|
||||
ProfScope("produce symbols from all streams")
|
||||
{
|
||||
//- rjf: set up
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
p2r2_shared->lanes_procedures = push_array(arena, RDIM_SymbolChunkList, lane_count());
|
||||
p2r2_shared->lanes_global_variables = push_array(arena, RDIM_SymbolChunkList, lane_count());
|
||||
p2r2_shared->lanes_thread_variables = push_array(arena, RDIM_SymbolChunkList, lane_count());
|
||||
p2r2_shared->lanes_constants = push_array(arena, RDIM_SymbolChunkList, lane_count());
|
||||
p2r2_shared->lanes_scopes = push_array(arena, RDIM_ScopeChunkList, lane_count());
|
||||
p2r2_shared->lanes_inline_sites = push_array(arena, RDIM_InlineSiteChunkList, lane_count());
|
||||
p2r2_shared->lanes_typedefs = push_array(arena, RDIM_TypeChunkList, lane_count());
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//- rjf: wide fill
|
||||
for(P2R2_UnitSymBlock *lane_block = lane_sym_blocks[lane_idx()].first;
|
||||
lane_block != 0;
|
||||
lane_block = lane_block->next)
|
||||
{
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: join all lane symbols
|
||||
//
|
||||
{
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
//-
|
||||
//-
|
||||
|
||||
@@ -92,6 +92,23 @@ struct P2R2_Shared
|
||||
RDIM_Type **itype_type_ptrs;
|
||||
RDIM_Type **basic_type_ptrs;
|
||||
RDIM_TypeChunkList all_types;
|
||||
|
||||
RDIM_UDTChunkList *lanes_udts;
|
||||
|
||||
RDIM_SymbolChunkList *lanes_procedures;
|
||||
RDIM_SymbolChunkList *lanes_global_variables;
|
||||
RDIM_SymbolChunkList *lanes_thread_variables;
|
||||
RDIM_SymbolChunkList *lanes_constants;
|
||||
RDIM_ScopeChunkList *lanes_scopes;
|
||||
RDIM_InlineSiteChunkList *lanes_inline_sites;
|
||||
RDIM_TypeChunkList *lanes_typedefs;
|
||||
|
||||
RDIM_SymbolChunkList all_procedures;
|
||||
RDIM_SymbolChunkList all_global_variables;
|
||||
RDIM_SymbolChunkList all_thread_variables;
|
||||
RDIM_SymbolChunkList all_constants;
|
||||
RDIM_ScopeChunkList all_scopes;
|
||||
RDIM_InlineSiteChunkList all_inline_sites;
|
||||
};
|
||||
|
||||
global P2R2_Shared *p2r2_shared = 0;
|
||||
|
||||
Reference in New Issue
Block a user