mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-26 05:25:00 -07:00
merge
This commit is contained in:
Binary file not shown.
+3
-2
@@ -46,9 +46,10 @@ load_paths =
|
||||
commands =
|
||||
{
|
||||
//- rjf: fkey command slots (change locally but do not commit)
|
||||
.f1 = { .win = "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 raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "build textperf release telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f3 = { .win = "pushd build && textperf.exe --capture && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 15
|
||||
# define BUILD_VERSION_PATCH 16
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
|
||||
+105
-7
@@ -480,7 +480,9 @@ internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0
|
||||
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Miscellaneous Ops
|
||||
//~ rjf: Color Operations
|
||||
|
||||
//- rjf: hsv <-> rgb
|
||||
|
||||
internal Vec3F32
|
||||
hsv_from_rgb(Vec3F32 rgb)
|
||||
@@ -567,16 +569,102 @@ rgba_from_hsva(Vec4F32 hsva)
|
||||
return rgba;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
rgba_from_u32(U32 hex)
|
||||
//- rjf: srgb <-> linear
|
||||
|
||||
internal Vec3F32
|
||||
linear_from_srgb(Vec3F32 srgb)
|
||||
{
|
||||
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
|
||||
((hex&0x00ff0000)>>16)/255.f,
|
||||
((hex&0x0000ff00)>> 8)/255.f,
|
||||
((hex&0x000000ff)>> 0)/255.f);
|
||||
Vec3F32 result;
|
||||
for EachElement(idx, srgb.v)
|
||||
{
|
||||
result.v[idx] = (srgb.v[idx] < 0.0404482362771082f ? srgb.v[idx] / 12.92f : pow_f32((srgb.v[idx] + 0.055f) / 1.055f, 2.4f));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec3F32
|
||||
srgb_from_linear(Vec3F32 linear)
|
||||
{
|
||||
Vec3F32 result;
|
||||
for EachElement(idx, linear.v)
|
||||
{
|
||||
result.v[idx] = (0 <= linear.v[idx] && linear.v[idx] < 0.00313066844250063) ? linear.v[idx]*12.92f : 1.05f * pow_f32(linear.v[idx], 1.f/2.4f) - 0.055f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
linear_from_srgba(Vec4F32 srgba)
|
||||
{
|
||||
Vec4F32 result;
|
||||
result.xyz = linear_from_srgb(srgba.xyz);
|
||||
result.w = srgba.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
srgba_from_linear(Vec4F32 linear)
|
||||
{
|
||||
Vec4F32 result;
|
||||
result.xyz = srgb_from_linear(linear.xyz);
|
||||
result.w = linear.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: oklab <-> linear
|
||||
|
||||
internal Vec3F32
|
||||
oklab_from_linear(Vec3F32 linear)
|
||||
{
|
||||
F32 l = (0.4122214708f * linear.x + 0.5363325363f * linear.y + 0.0514459929f * linear.z);
|
||||
F32 m = (0.2119034982f * linear.x + 0.6806995451f * linear.y + 0.1073969566f * linear.z);
|
||||
F32 s = (0.0883024619f * linear.x + 0.2817188376f * linear.y + 0.6299787005f * linear.z);
|
||||
F32 l_ = cbrt_f32(l);
|
||||
F32 m_ = cbrt_f32(m);
|
||||
F32 s_ = cbrt_f32(s);
|
||||
Vec3F32 result;
|
||||
result.x = 0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_;
|
||||
result.y = 1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_;
|
||||
result.z = 0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec3F32
|
||||
linear_from_oklab(Vec3F32 oklab)
|
||||
{
|
||||
F32 l_ = oklab.x + 0.3963377774f * oklab.y + 0.2158037573f * oklab.z;
|
||||
F32 m_ = oklab.x - 0.1055613458f * oklab.y - 0.0638541728f * oklab.z;
|
||||
F32 s_ = oklab.x - 0.0894841775f * oklab.y - 1.2914855480f * oklab.z;
|
||||
F32 l = l_*l_*l_;
|
||||
F32 m = m_*m_*m_;
|
||||
F32 s = s_*s_*s_;
|
||||
Vec3F32 result;
|
||||
result.x = +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
|
||||
result.y = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
|
||||
result.z = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
oklab_from_lineara(Vec4F32 lineara)
|
||||
{
|
||||
Vec4F32 result;
|
||||
result.xyz = oklab_from_linear(lineara.xyz);
|
||||
result.w = lineara.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
lineara_from_oklab(Vec4F32 oklab)
|
||||
{
|
||||
Vec4F32 result;
|
||||
result.xyz = linear_from_oklab(oklab.xyz);
|
||||
result.w = oklab.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: rgba <-> u32
|
||||
|
||||
internal U32
|
||||
u32_from_rgba(Vec4F32 rgba)
|
||||
{
|
||||
@@ -588,6 +676,16 @@ u32_from_rgba(Vec4F32 rgba)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
rgba_from_u32(U32 hex)
|
||||
{
|
||||
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
|
||||
((hex&0x00ff0000)>>16)/255.f,
|
||||
((hex&0x0000ff00)>> 8)/255.f,
|
||||
((hex&0x000000ff)>> 0)/255.f);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: List Type Functions
|
||||
|
||||
|
||||
+19
-3
@@ -379,6 +379,7 @@ struct Rng1S64Array
|
||||
#define abs_s64(v) (S64)llabs(v)
|
||||
|
||||
#define sqrt_f32(v) sqrtf(v)
|
||||
#define cbrt_f32(v) cbrtf(v)
|
||||
#define mod_f32(a, b) fmodf((a), (b))
|
||||
#define pow_f32(b, e) powf((b), (e))
|
||||
#define ceil_f32(v) ceilf(v)
|
||||
@@ -396,6 +397,7 @@ struct Rng1S64Array
|
||||
#define tan_f32(v) tanf(radians_from_turns_f32(v))
|
||||
|
||||
#define sqrt_f64(v) sqrt(v)
|
||||
#define cbrt_f64(v) cbrt(v)
|
||||
#define mod_f64(a, b) fmod((a), (b))
|
||||
#define pow_f64(b, e) pow((b), (e))
|
||||
#define ceil_f64(v) ceil(v)
|
||||
@@ -651,15 +653,29 @@ internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b);
|
||||
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Miscellaneous Ops
|
||||
//~ rjf: Color Operations
|
||||
|
||||
//- rjf: hsv <-> rgb
|
||||
internal Vec3F32 hsv_from_rgb(Vec3F32 rgb);
|
||||
internal Vec3F32 rgb_from_hsv(Vec3F32 hsv);
|
||||
internal Vec4F32 hsva_from_rgba(Vec4F32 rgba);
|
||||
internal Vec4F32 rgba_from_hsva(Vec4F32 hsva);
|
||||
internal Vec4F32 rgba_from_u32(U32 hex);
|
||||
internal U32 u32_from_rgba(Vec4F32 rgba);
|
||||
|
||||
//- rjf: srgb <-> linear
|
||||
internal Vec3F32 linear_from_srgb(Vec3F32 srgb);
|
||||
internal Vec3F32 srgb_from_linear(Vec3F32 linear);
|
||||
internal Vec4F32 linear_from_srgba(Vec4F32 srgba);
|
||||
internal Vec4F32 srgba_from_linear(Vec4F32 linear);
|
||||
|
||||
//- rjf: oklab <-> linear
|
||||
internal Vec3F32 oklab_from_linear(Vec3F32 linear);
|
||||
internal Vec3F32 linear_from_oklab(Vec3F32 oklab);
|
||||
internal Vec4F32 oklab_from_lineara(Vec4F32 lineara);
|
||||
internal Vec4F32 lineara_from_oklab(Vec4F32 oklab);
|
||||
|
||||
//- rjf: rgba <-> u32
|
||||
internal U32 u32_from_rgba(Vec4F32 rgba);
|
||||
internal Vec4F32 rgba_from_u32(U32 hex);
|
||||
#define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f }
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
+56
-20
@@ -242,7 +242,7 @@ str8_cstring_capped_reverse(void *raw_start, void *raw_cap)
|
||||
for(; ptr > start; )
|
||||
{
|
||||
ptr -= 1;
|
||||
|
||||
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
break;
|
||||
@@ -427,23 +427,53 @@ str8_chop(String8 str, U64 amt){
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_skip_chop_whitespace(String8 string){
|
||||
str8_skip_chop_whitespace(String8 string)
|
||||
{
|
||||
U8 *first = string.str;
|
||||
U8 *opl = first + string.size;
|
||||
for (;first < opl; first += 1){
|
||||
if (!char_is_space(*first)){
|
||||
for(;first < opl; first += 1)
|
||||
{
|
||||
if(!char_is_space(*first))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (;opl > first;){
|
||||
for(;opl > first;)
|
||||
{
|
||||
opl -= 1;
|
||||
if (!char_is_space(*opl)){
|
||||
if(!char_is_space(*opl))
|
||||
{
|
||||
opl += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String8 result = str8_range(first, opl);
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_skip_chop_slashes(String8 string)
|
||||
{
|
||||
U8 *first = string.str;
|
||||
U8 *opl = first + string.size;
|
||||
for(;first < opl; first += 1)
|
||||
{
|
||||
if(!char_is_slash(*first))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(;opl > first;)
|
||||
{
|
||||
opl -= 1;
|
||||
if(!char_is_slash(*opl))
|
||||
{
|
||||
opl += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String8 result = str8_range(first, opl);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -619,7 +649,7 @@ internal String8
|
||||
str8_from_memory_size(Arena *arena, U64 size)
|
||||
{
|
||||
String8 result;
|
||||
|
||||
|
||||
if(size < KB(1))
|
||||
{
|
||||
result = push_str8f(arena, "%llu Bytes", size);
|
||||
@@ -640,7 +670,7 @@ str8_from_memory_size(Arena *arena, U64 size)
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -648,7 +678,7 @@ internal String8
|
||||
str8_from_count(Arena *arena, U64 count)
|
||||
{
|
||||
String8 result;
|
||||
|
||||
|
||||
if(count < 1 * 1000)
|
||||
{
|
||||
result = push_str8f(arena, "%llu", count);
|
||||
@@ -689,7 +719,7 @@ str8_from_count(Arena *arena, U64 count)
|
||||
result = push_str8f(arena, "%lluB", count / 1000000000, frac);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1114,6 +1144,13 @@ str8_list_from_flags(Arena *arena, String8List *list,
|
||||
////////////////////////////////
|
||||
//~ rjf; String Arrays
|
||||
|
||||
internal String8Array
|
||||
str8_array_zero(void)
|
||||
{
|
||||
String8Array result = {0};
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8Array
|
||||
str8_array_from_list(Arena *arena, String8List *list)
|
||||
{
|
||||
@@ -1827,10 +1864,10 @@ try_guid_from_string(String8 string, Guid *guid_out)
|
||||
String8 data4_hi_str = list.first->next->next->next->string;
|
||||
String8 data4_lo_str = list.first->next->next->next->next->string;
|
||||
if(str8_is_integer(data1_str, 16) &&
|
||||
str8_is_integer(data2_str, 16) &&
|
||||
str8_is_integer(data3_str, 16) &&
|
||||
str8_is_integer(data4_hi_str, 16) &&
|
||||
str8_is_integer(data4_lo_str, 16))
|
||||
str8_is_integer(data2_str, 16) &&
|
||||
str8_is_integer(data3_str, 16) &&
|
||||
str8_is_integer(data4_hi_str, 16) &&
|
||||
str8_is_integer(data4_lo_str, 16))
|
||||
{
|
||||
U64 data1 = u64_from_str8(data1_str, 16);
|
||||
U64 data2 = u64_from_str8(data2_str, 16);
|
||||
@@ -1838,10 +1875,10 @@ try_guid_from_string(String8 string, Guid *guid_out)
|
||||
U64 data4_hi = u64_from_str8(data4_hi_str, 16);
|
||||
U64 data4_lo = u64_from_str8(data4_lo_str, 16);
|
||||
if(data1 <= max_U32 &&
|
||||
data2 <= max_U16 &&
|
||||
data3 <= max_U16 &&
|
||||
data4_hi <= max_U16 &&
|
||||
data4_lo <= 0xffffffffffff)
|
||||
data2 <= max_U16 &&
|
||||
data3 <= max_U16 &&
|
||||
data4_hi <= max_U16 &&
|
||||
data4_lo <= 0xffffffffffff)
|
||||
{
|
||||
guid_out->data1 = (U32)data1;
|
||||
guid_out->data2 = (U16)data2;
|
||||
@@ -2370,4 +2407,3 @@ str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out)
|
||||
*block_out = str8_substr(string, range);
|
||||
return block_out->size;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ internal String8 str8_skip(String8 str, U64 amt);
|
||||
internal String8 str8_postfix(String8 str, U64 size);
|
||||
internal String8 str8_chop(String8 str, U64 amt);
|
||||
internal String8 str8_skip_chop_whitespace(String8 string);
|
||||
internal String8 str8_skip_chop_slashes(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Formatting & Copying
|
||||
@@ -287,6 +288,7 @@ internal void str8_list_from_flags(Arena *arena, String8List *list, U32
|
||||
////////////////////////////////
|
||||
//~ rjf; String Arrays
|
||||
|
||||
internal String8Array str8_array_zero(void);
|
||||
internal String8Array str8_array_from_list(Arena *arena, String8List *list);
|
||||
internal String8Array str8_array_reserve(Arena *arena, U64 count);
|
||||
|
||||
|
||||
+15
-9
@@ -4,17 +4,17 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Kinds
|
||||
|
||||
@table(name display_string)
|
||||
@table(name code_name display_string)
|
||||
CTRL_EntityKindTable:
|
||||
{
|
||||
{Root "Root" }
|
||||
{Machine "Machine" }
|
||||
{Process "Process" }
|
||||
{Thread "Thread" }
|
||||
{Module "Module" }
|
||||
{EntryPoint "Entry Point" }
|
||||
{DebugInfoPath "Debug Info Path" }
|
||||
{PendingThreadName "Pending Thread Name" }
|
||||
{Root root "Root" }
|
||||
{Machine machine "Machine" }
|
||||
{Process process "Process" }
|
||||
{Thread thread "Thread" }
|
||||
{Module module "Module" }
|
||||
{EntryPoint entry_point "Entry Point" }
|
||||
{DebugInfoPath debug_info_path "Debug Info Path" }
|
||||
{PendingThreadName pending_thread_name "Pending Thread Name" }
|
||||
}
|
||||
|
||||
@enum CTRL_EntityKind:
|
||||
@@ -24,6 +24,12 @@ CTRL_EntityKindTable:
|
||||
COUNT,
|
||||
}
|
||||
|
||||
@data(String8) ctrl_entity_kind_code_name_table:
|
||||
{
|
||||
`{0}`,
|
||||
@expand(CTRL_EntityKindTable a) `str8_lit_comp("$(a.code_name)")`
|
||||
}
|
||||
|
||||
@data(String8) ctrl_entity_kind_display_string_table:
|
||||
{
|
||||
`{0}`,
|
||||
|
||||
+428
-309
@@ -43,6 +43,21 @@ ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind)
|
||||
return cause;
|
||||
}
|
||||
|
||||
internal CTRL_ExceptionKind
|
||||
ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind)
|
||||
{
|
||||
CTRL_ExceptionKind result = CTRL_ExceptionKind_Null;
|
||||
switch(kind)
|
||||
{
|
||||
default:{}break;
|
||||
case DMN_ExceptionKind_MemoryRead: {result = CTRL_ExceptionKind_MemoryRead;}break;
|
||||
case DMN_ExceptionKind_MemoryWrite: {result = CTRL_ExceptionKind_MemoryWrite;}break;
|
||||
case DMN_ExceptionKind_MemoryExecute: {result = CTRL_ExceptionKind_MemoryExecute;}break;
|
||||
case DMN_ExceptionKind_CppThrow: {result = CTRL_ExceptionKind_CppThrow;}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ctrl_string_from_event_kind(CTRL_EventKind kind)
|
||||
{
|
||||
@@ -91,6 +106,21 @@ ctrl_string_from_msg_kind(CTRL_MsgKind kind)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_EntityKind
|
||||
ctrl_entity_kind_from_string(String8 string)
|
||||
{
|
||||
CTRL_EntityKind result = CTRL_EntityKind_Null;
|
||||
for EachNonZeroEnumVal(CTRL_EntityKind, k)
|
||||
{
|
||||
if(str8_match(ctrl_entity_kind_code_name_table[k], string, 0))
|
||||
{
|
||||
result = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Machine/Handle Pair Type Functions
|
||||
|
||||
@@ -136,6 +166,37 @@ ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src)
|
||||
return dst;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ctrl_string_from_handle(Arena *arena, CTRL_Handle handle)
|
||||
{
|
||||
String8 result = push_str8f(arena, "$0x%I64x$0x%I64x", handle.machine_id, handle.dmn_handle.u64[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_Handle
|
||||
ctrl_handle_from_string(String8 string)
|
||||
{
|
||||
CTRL_Handle handle = {0};
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U8 split = '$';
|
||||
String8List parts = str8_split(scratch.arena, string, &split, 1, 0);
|
||||
if(parts.first && parts.first->next)
|
||||
{
|
||||
CTRL_MachineID machine_id = 0;
|
||||
DMN_Handle dmn_handle = {0};
|
||||
if(try_u64_from_str8_c_rules(parts.first->string, &machine_id) &&
|
||||
try_u64_from_str8_c_rules(parts.first->next->string, &dmn_handle.u64[0]))
|
||||
{
|
||||
handle.machine_id = machine_id;
|
||||
handle.dmn_handle = dmn_handle;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Type Functions
|
||||
|
||||
@@ -201,7 +262,6 @@ ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src)
|
||||
dst->env_string_list = str8_list_copy(arena, &src->env_string_list);
|
||||
dst->traps = ctrl_trap_list_copy(arena, &src->traps);
|
||||
dst->user_bps = ctrl_user_breakpoint_list_copy(arena, &src->user_bps);
|
||||
dst->meta_evals = *deep_copy_from_struct(arena, CTRL_MetaEvalArray, &src->meta_evals);
|
||||
}
|
||||
|
||||
//- rjf: list building
|
||||
@@ -332,10 +392,6 @@ ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs)
|
||||
str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->condition.size);
|
||||
str8_serial_push_data(scratch.arena, &msgs_srlzed, bp->condition.str, bp->condition.size);
|
||||
}
|
||||
|
||||
// rjf: write meta-eval-info array
|
||||
String8 meta_evals_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEvalArray, &msg->meta_evals);
|
||||
str8_serial_push_string(scratch.arena, &msgs_srlzed, meta_evals_srlzed);
|
||||
}
|
||||
}
|
||||
String8 string = str8_serial_end(arena, &msgs_srlzed);
|
||||
@@ -459,12 +515,6 @@ ctrl_msg_list_from_serialized_string(Arena *arena, String8 string)
|
||||
bp->condition.str = push_array_no_zero(arena, U8, bp->condition.size);
|
||||
read_off += str8_deserial_read(string, read_off, bp->condition.str, bp->condition.size, 1);
|
||||
}
|
||||
|
||||
// rjf: read meta-eval-info array
|
||||
String8 meta_evals_data = str8_skip(string, read_off);
|
||||
U64 meta_evals_size = 0;
|
||||
msg->meta_evals = *struct_from_serialized(arena, CTRL_MetaEvalArray, meta_evals_data, .advance_out = &meta_evals_size);
|
||||
read_off += meta_evals_size;
|
||||
}
|
||||
}
|
||||
return msgs;
|
||||
@@ -639,95 +689,100 @@ ctrl_entity_store_release(CTRL_EntityStore *cache)
|
||||
//- rjf: string allocation/deletion
|
||||
|
||||
internal U64
|
||||
ctrl_name_bucket_idx_from_string_size(U64 size)
|
||||
ctrl_name_bucket_num_from_string_size(U64 size)
|
||||
{
|
||||
U64 size_rounded = u64_up_to_pow2(size+1);
|
||||
size_rounded = ClampBot((1<<4), size_rounded);
|
||||
U64 bucket_idx = 0;
|
||||
switch(size_rounded)
|
||||
U64 bucket_num = 0;
|
||||
if(size > 0)
|
||||
{
|
||||
case 1<<4: {bucket_idx = 0;}break;
|
||||
case 1<<5: {bucket_idx = 1;}break;
|
||||
case 1<<6: {bucket_idx = 2;}break;
|
||||
case 1<<7: {bucket_idx = 3;}break;
|
||||
case 1<<8: {bucket_idx = 4;}break;
|
||||
case 1<<9: {bucket_idx = 5;}break;
|
||||
case 1<<10:{bucket_idx = 6;}break;
|
||||
default:{bucket_idx = ArrayCount(((CTRL_EntityStore *)0)->free_string_chunks)-1;}break;
|
||||
for EachElement(idx, ctrl_entity_string_bucket_chunk_sizes)
|
||||
{
|
||||
if(size <= ctrl_entity_string_bucket_chunk_sizes[idx])
|
||||
{
|
||||
bucket_num = idx+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bucket_idx;
|
||||
return bucket_num;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string)
|
||||
{
|
||||
if(string.size == 0) {return str8_zero();}
|
||||
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
|
||||
CTRL_EntityStringChunkNode *node = store->free_string_chunks[bucket_idx];
|
||||
|
||||
// rjf: pull from bucket free list
|
||||
if(node != 0)
|
||||
//- rjf: allocate node
|
||||
CTRL_EntityStringChunkNode *node = 0;
|
||||
{
|
||||
if(bucket_idx == ArrayCount(store->free_string_chunks)-1)
|
||||
U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size);
|
||||
if(bucket_num == ArrayCount(ctrl_entity_string_bucket_chunk_sizes))
|
||||
{
|
||||
node = 0;
|
||||
CTRL_EntityStringChunkNode *prev = 0;
|
||||
for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_idx];
|
||||
n != 0;
|
||||
prev = n, n = n->next)
|
||||
CTRL_EntityStringChunkNode *best_node = 0;
|
||||
CTRL_EntityStringChunkNode *best_node_prev = 0;
|
||||
U64 best_node_size = max_U64;
|
||||
{
|
||||
if(n->size >= string.size)
|
||||
for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_num-1], *prev = 0; n != 0; (prev = n, n = n->next))
|
||||
{
|
||||
if(prev == 0)
|
||||
if(n->size >= string.size && n->size < best_node_size)
|
||||
{
|
||||
store->free_string_chunks[bucket_idx] = n->next;
|
||||
best_node = n;
|
||||
best_node_prev = prev;
|
||||
best_node_size = n->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = n->next;
|
||||
}
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(best_node != 0)
|
||||
{
|
||||
node = best_node;
|
||||
if(best_node_prev)
|
||||
{
|
||||
best_node_prev->next = best_node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
store->free_string_chunks[bucket_num-1] = best_node->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 chunk_size = u64_up_to_pow2(string.size);
|
||||
node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, chunk_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(bucket_num != 0)
|
||||
{
|
||||
SLLStackPop(store->free_string_chunks[bucket_idx]);
|
||||
node = store->free_string_chunks[bucket_num-1];
|
||||
if(node != 0)
|
||||
{
|
||||
SLLStackPop(store->free_string_chunks[bucket_num-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, ctrl_entity_string_bucket_chunk_sizes[bucket_num-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: no found node -> allocate new
|
||||
if(node == 0)
|
||||
//- rjf: fill node
|
||||
String8 result = {0};
|
||||
if(node != 0)
|
||||
{
|
||||
U64 chunk_size = 0;
|
||||
if(bucket_idx < ArrayCount(store->free_string_chunks)-1)
|
||||
{
|
||||
chunk_size = 1<<(bucket_idx+4);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk_size = u64_up_to_pow2(string.size);
|
||||
}
|
||||
U8 *chunk_memory = push_array(store->arena, U8, chunk_size);
|
||||
node = (CTRL_EntityStringChunkNode *)chunk_memory;
|
||||
node->size = chunk_size;
|
||||
result.str = (U8 *)node;
|
||||
result.size = string.size;
|
||||
MemoryCopy(result.str, string.str, result.size);
|
||||
}
|
||||
|
||||
// rjf: fill string & return
|
||||
String8 allocated_string = str8((U8 *)node, string.size);
|
||||
MemoryCopy((U8 *)node, string.str, string.size);
|
||||
return allocated_string;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_entity_string_release(CTRL_EntityStore *store, String8 string)
|
||||
{
|
||||
if(string.size == 0) {return;}
|
||||
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
|
||||
CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str;
|
||||
node->size = u64_up_to_pow2(string.size);
|
||||
SLLStackPush(store->free_string_chunks[bucket_idx], node);
|
||||
U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size);
|
||||
if(1 <= bucket_num && bucket_num <= ArrayCount(rd_name_bucket_chunk_sizes))
|
||||
{
|
||||
U64 bucket_idx = bucket_num-1;
|
||||
CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str;
|
||||
SLLStackPush(store->free_string_chunks[bucket_idx], node);
|
||||
node->size = u64_up_to_pow2(string.size);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: entity construction/deletion
|
||||
@@ -1305,7 +1360,6 @@ ctrl_init(void)
|
||||
ctrl_state->ctrl_thread_entity_store = ctrl_entity_store_alloc();
|
||||
ctrl_state->dmn_event_arena = arena_alloc();
|
||||
ctrl_state->user_entry_point_arena = arena_alloc();
|
||||
ctrl_state->user_meta_eval_arena = arena_alloc();
|
||||
ctrl_state->dbg_dir_arena = arena_alloc();
|
||||
for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)0; k < CTRL_ExceptionCodeKind_COUNT; k = (CTRL_ExceptionCodeKind)(k+1))
|
||||
{
|
||||
@@ -1370,6 +1424,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
|
||||
//- rjf: try to read from cache
|
||||
B32 is_good = 0;
|
||||
B32 process_node_exists = 0;
|
||||
B32 is_stale = 1;
|
||||
OS_MutexScopeR(process_stripe->rw_mutex)
|
||||
{
|
||||
@@ -1377,6 +1432,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
{
|
||||
if(ctrl_handle_match(n->handle, process))
|
||||
{
|
||||
process_node_exists = 1;
|
||||
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
|
||||
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
|
||||
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
|
||||
@@ -1395,7 +1451,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
}
|
||||
|
||||
//- rjf: not good -> create process cache node if necessary
|
||||
if(!is_good)
|
||||
if(!is_good && !process_node_exists)
|
||||
{
|
||||
OS_MutexScopeW(process_stripe->rw_mutex)
|
||||
{
|
||||
@@ -2994,44 +3050,118 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle threa
|
||||
internal CTRL_CallStack
|
||||
ctrl_call_stack_from_unwind(Arena *arena, DI_Scope *di_scope, CTRL_Entity *process, CTRL_Unwind *base_unwind)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Arch arch = process->arch;
|
||||
CTRL_CallStack result = {0};
|
||||
result.concrete_frame_count = base_unwind->frames.count;
|
||||
result.total_frame_count = result.concrete_frame_count;
|
||||
result.frames = push_array(arena, CTRL_CallStackFrame, result.concrete_frame_count);
|
||||
for(U64 idx = 0; idx < result.concrete_frame_count; idx += 1)
|
||||
{
|
||||
CTRL_UnwindFrame *src = &base_unwind->frames.v[idx];
|
||||
CTRL_CallStackFrame *dst = &result.frames[idx];
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
|
||||
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff);
|
||||
|
||||
// rjf: fill concrete frame info
|
||||
dst->regs = src->regs;
|
||||
dst->rdi = rdi;
|
||||
dst->procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx);
|
||||
|
||||
// rjf: push inline frames
|
||||
for(RDI_Scope *s = scope;
|
||||
s->inline_site_idx != 0;
|
||||
s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx))
|
||||
typedef struct FrameNode FrameNode;
|
||||
struct FrameNode
|
||||
{
|
||||
RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx);
|
||||
CTRL_CallStackInlineFrame *inline_frame = push_array(arena, CTRL_CallStackInlineFrame, 1);
|
||||
DLLPushFront(dst->first_inline_frame, dst->last_inline_frame, inline_frame);
|
||||
inline_frame->inline_site = site;
|
||||
dst->inline_frame_count += 1;
|
||||
result.inline_frame_count += 1;
|
||||
result.total_frame_count += 1;
|
||||
FrameNode *next;
|
||||
CTRL_CallStackFrame v;
|
||||
};
|
||||
|
||||
//- rjf: gather all frames
|
||||
FrameNode *first_frame = 0;
|
||||
FrameNode *last_frame = 0;
|
||||
U64 frame_count = 0;
|
||||
for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1)
|
||||
{
|
||||
// rjf: unpack
|
||||
CTRL_UnwindFrame *src = &base_unwind->frames.v[base_frame_idx];
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
|
||||
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff);
|
||||
|
||||
// rjf: build inline frames (minus parent & inline depth)
|
||||
FrameNode *first_inline_frame = 0;
|
||||
FrameNode *last_inline_frame = 0;
|
||||
U64 inline_frame_count = 0;
|
||||
for(RDI_Scope *s = scope;
|
||||
s->inline_site_idx != 0;
|
||||
s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx))
|
||||
{
|
||||
FrameNode *dst_inline = push_array(scratch.arena, FrameNode, 1);
|
||||
if(first_inline_frame == 0)
|
||||
{
|
||||
first_inline_frame = dst_inline;
|
||||
}
|
||||
last_inline_frame = dst_inline;
|
||||
SLLQueuePush(first_frame, last_frame, dst_inline);
|
||||
dst_inline->v.unwind_count = base_frame_idx;
|
||||
dst_inline->v.regs = src->regs;
|
||||
dst_inline->v.rdi = rdi;
|
||||
dst_inline->v.inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx);
|
||||
frame_count += 1;
|
||||
inline_frame_count += 1;
|
||||
}
|
||||
|
||||
// rjf: build concrete frame
|
||||
FrameNode *dst_base = push_array(scratch.arena, FrameNode, 1);
|
||||
SLLQueuePush(first_frame, last_frame, dst_base);
|
||||
dst_base->v.unwind_count = base_frame_idx;
|
||||
dst_base->v.regs = src->regs;
|
||||
dst_base->v.rdi = rdi;
|
||||
dst_base->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx);
|
||||
frame_count += 1;
|
||||
|
||||
// rjf: hook up inline frames to point to concrete frame, and to account for inline depth
|
||||
U64 inline_frame_idx = 0;
|
||||
for(FrameNode *inline_frame = first_inline_frame; inline_frame != 0; inline_frame = inline_frame->next, inline_frame_idx += 1)
|
||||
{
|
||||
inline_frame->v.parent_num = frame_count;
|
||||
inline_frame->v.inline_depth = inline_frame_count - inline_frame_idx;
|
||||
if(inline_frame == last_inline_frame)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: package
|
||||
result.count = frame_count;
|
||||
result.frames = push_array(arena, CTRL_CallStackFrame, result.count);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(FrameNode *n = first_frame; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
MemoryCopyStruct(&result.frames[idx], &n->v);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_CallStackFrame *
|
||||
ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth)
|
||||
{
|
||||
CTRL_CallStackFrame *f = 0;
|
||||
{
|
||||
U64 base_frame_idx = 0;
|
||||
for(U64 idx = 0; idx < call_stack->count; idx += 1)
|
||||
{
|
||||
if(call_stack->frames[idx].parent_num == 0)
|
||||
{
|
||||
if(base_frame_idx == unwind_count)
|
||||
{
|
||||
f = &call_stack->frames[idx];
|
||||
break;
|
||||
}
|
||||
base_frame_idx += 1;
|
||||
}
|
||||
}
|
||||
if(f != 0 && call_stack->frames + inline_depth < f)
|
||||
{
|
||||
f -= inline_depth;
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Halting All Attached Processes
|
||||
|
||||
@@ -3242,8 +3372,6 @@ ctrl_thread__entry_point(void *p)
|
||||
//- rjf: unpack per-message parameterizations & store
|
||||
{
|
||||
MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters);
|
||||
arena_clear(ctrl_state->user_meta_eval_arena);
|
||||
ctrl_state->user_meta_evals = *deep_copy_from_struct(ctrl_state->user_meta_eval_arena, CTRL_MetaEvalArray, &msg->meta_evals);
|
||||
}
|
||||
|
||||
//- rjf: process message
|
||||
@@ -3331,11 +3459,11 @@ ctrl_thread__entry_point(void *p)
|
||||
//- rjf: breakpoint resolution
|
||||
|
||||
internal void
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
{
|
||||
if(user_bps->first == 0) { return; }
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
DI_Scope *di_scope = eval_scope->di_scope;
|
||||
CTRL_Entity *module_entity = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, module);
|
||||
CTRL_Entity *debug_info_path_entity = ctrl_entity_child_from_kind(module_entity, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {debug_info_path_entity->string, debug_info_path_entity->timestamp};
|
||||
@@ -3399,45 +3527,37 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle proc
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: symbol:voff-based breakpoints
|
||||
case CTRL_UserBreakpointKind_SymbolNameAndOffset:
|
||||
//- rjf: expression-based breakpoints
|
||||
case CTRL_UserBreakpointKind_Expression:
|
||||
{
|
||||
String8 symbol_name = bp->string;
|
||||
U64 voff = bp->u64;
|
||||
RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures);
|
||||
RDI_ParsedNameMap map = {0};
|
||||
rdi_parsed_from_name_map(rdi, mapptr, &map);
|
||||
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size);
|
||||
if(node != 0)
|
||||
String8 expr = bp->string;
|
||||
E_Value value = e_value_from_string(expr);
|
||||
if(value.u64 != 0)
|
||||
{
|
||||
U32 id_count = 0;
|
||||
U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count);
|
||||
for(U32 match_i = 0; match_i < id_count; match_i += 1)
|
||||
{
|
||||
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, ids[match_i]);
|
||||
U64 proc_voff = rdi_first_voff_from_procedure(rdi, procedure);
|
||||
U64 proc_vaddr = proc_voff + base_vaddr;
|
||||
DMN_Trap trap = {process.dmn_handle, proc_vaddr + voff, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
di_scope_close(di_scope);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
{
|
||||
for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next)
|
||||
{
|
||||
CTRL_UserBreakpoint *bp = &n->v;
|
||||
if(bp->kind == CTRL_UserBreakpointKind_VirtualAddress)
|
||||
if(bp->kind == CTRL_UserBreakpointKind_Expression)
|
||||
{
|
||||
DMN_Trap trap = {process.dmn_handle, bp->u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
String8 expr = bp->string;
|
||||
E_Value value = e_value_from_string(expr);
|
||||
if(value.u64 != 0)
|
||||
{
|
||||
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4404,42 +4524,134 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
//- rjf: meta evaluations
|
||||
case CTRL_EvalSpaceKind_Meta:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 meta_eval_idx = space.u64s[0];
|
||||
if(meta_eval_idx < ctrl_state->user_meta_evals.count)
|
||||
{
|
||||
CTRL_MetaEval *meval = &ctrl_state->user_meta_evals.v[meta_eval_idx];
|
||||
|
||||
// rjf: copy meta evaluation to scratch arena, to form range of legal reads
|
||||
arena_push(scratch.arena, 0, 64);
|
||||
String8 meval_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEval, meval);
|
||||
U64 pos_min = arena_pos(scratch.arena);
|
||||
CTRL_MetaEval *meval_read = struct_from_serialized(scratch.arena, CTRL_MetaEval, meval_srlzed);
|
||||
U64 pos_opl = arena_pos(scratch.arena);
|
||||
|
||||
// rjf: rebase all pointer values in meta evaluation to be relative to base pointer
|
||||
struct_rebase_ptrs(CTRL_MetaEval, meval_read, meval_read);
|
||||
|
||||
// rjf: perform actual read
|
||||
Rng1U64 legal_range = r1u64(0, pos_opl-pos_min);
|
||||
if(contains_1u64(legal_range, range.min))
|
||||
{
|
||||
result = 1;
|
||||
U64 range_dim = dim_1u64(range);
|
||||
U64 bytes_to_read = Min(range_dim, (legal_range.max - range.min));
|
||||
MemoryCopy(out, ((U8 *)meval_read) + range.min, bytes_to_read);
|
||||
if(bytes_to_read < range_dim)
|
||||
{
|
||||
MemoryZero((U8 *)out + bytes_to_read, range_dim - bytes_to_read);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
|
||||
}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: control thread eval scopes
|
||||
|
||||
internal CTRL_EvalScope *
|
||||
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
|
||||
{
|
||||
CTRL_EvalScope *scope = push_array(arena, CTRL_EvalScope, 1);
|
||||
scope->di_scope = di_scope_open();
|
||||
|
||||
// rjf: unpack thread
|
||||
Arch arch = thread->arch;
|
||||
U64 thread_rip_vaddr = dmn_rip_from_thread(thread->handle.dmn_handle);
|
||||
CTRL_Entity *process = ctrl_process_from_entity(thread);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||
U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr);
|
||||
|
||||
// rjf: gather evaluation modules
|
||||
U64 eval_modules_count = Max(1, ctrl_state->ctrl_thread_entity_store->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &di_rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
{
|
||||
U64 eval_module_idx = 0;
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first;
|
||||
process != &ctrl_entity_nil;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
for(CTRL_Entity *mod = process->first;
|
||||
mod != &ctrl_entity_nil;
|
||||
mod = mod->next)
|
||||
{
|
||||
if(mod->kind != CTRL_EntityKind_Module) { continue; }
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
eval_modules[eval_module_idx].arch = arch;
|
||||
eval_modules[eval_module_idx].rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, max_U64);
|
||||
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
|
||||
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
|
||||
if(mod == module)
|
||||
{
|
||||
eval_modules_primary = &eval_modules[eval_module_idx];
|
||||
}
|
||||
eval_module_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: build eval type context
|
||||
{
|
||||
E_TypeCtx *ctx = &scope->type_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
}
|
||||
e_select_type_ctx(&scope->type_ctx);
|
||||
|
||||
// rjf: build eval parse context
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = &scope->parse_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->ip_thread_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->ip_thread_space.u64_0 = (U64)thread;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
}
|
||||
e_select_parse_ctx(&scope->parse_ctx);
|
||||
|
||||
// rjf: build eval IR context
|
||||
{
|
||||
E_IRCtx *ctx = &scope->ir_ctx;
|
||||
ctx->macro_map = push_array(arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(arena, 512);
|
||||
ctx->lookup_rule_map = push_array(arena, E_LookupRuleMap, 1);
|
||||
ctx->lookup_rule_map[0] = e_lookup_rule_map_make(arena, 512);
|
||||
ctx->irgen_rule_map = push_array(arena, E_IRGenRuleMap, 1);
|
||||
ctx->irgen_rule_map[0] = e_irgen_rule_map_make(arena, 512);
|
||||
ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1);
|
||||
ctx->auto_hook_map[0] = e_auto_hook_map_make(arena, 512);
|
||||
}
|
||||
e_select_ir_ctx(&scope->ir_ctx);
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
{
|
||||
E_InterpretCtx *ctx = &scope->interpret_ctx;
|
||||
ctx->space_rw_user_data = ctrl_state->ctrl_thread_entity_store;
|
||||
ctx->space_read = ctrl_eval_space_read;
|
||||
ctx->primary_space = eval_modules_primary->space;
|
||||
ctx->reg_arch = eval_modules_primary->arch;
|
||||
ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->reg_space.u64_0 = (U64)thread;
|
||||
ctx->module_base = push_array(arena, U64, 1);
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->tls_base = push_array(arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&scope->interpret_ctx);
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_thread__eval_scope_end(CTRL_EvalScope *scope)
|
||||
{
|
||||
di_scope_close(scope->di_scope);
|
||||
}
|
||||
|
||||
//- rjf: log flusher
|
||||
|
||||
internal void
|
||||
@@ -4771,25 +4983,30 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
//- rjf: gather all initial breakpoints
|
||||
//
|
||||
DMN_TrapChunkList user_traps = {0};
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next)
|
||||
CTRL_Entity *thread = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, target_thread);
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
|
||||
// rjf: resolve module-dependent user bps
|
||||
for(CTRL_Entity *module = process->first; module != &ctrl_entity_nil; module = module->next)
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next)
|
||||
{
|
||||
if(module->kind != CTRL_EntityKind_Module) { continue; }
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, process->handle, module->handle, &msg->user_bps, &user_traps);
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
|
||||
// rjf: resolve module-dependent user bps
|
||||
for(CTRL_Entity *module = process->first; module != &ctrl_entity_nil; module = module->next)
|
||||
{
|
||||
if(module->kind != CTRL_EntityKind_Module) { continue; }
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, process->handle, module->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
|
||||
// rjf: push virtual-address user breakpoints per-process
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, process->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
|
||||
// rjf: push virtual-address user breakpoints per-process
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, process->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -5053,39 +5270,48 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
}break;
|
||||
case DMN_EventKind_CreateProcess:
|
||||
{
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: create_process -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &ctrl_entity_nil);
|
||||
{
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: create_process -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
}
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}break;
|
||||
case DMN_EventKind_LoadModule:
|
||||
{
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: load_module -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
CTRL_Entity *thread = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, ctrl_handle_make(CTRL_MachineID_Local, event->thread));
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
|
||||
{
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: load_module -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
}
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}break;
|
||||
}
|
||||
|
||||
@@ -5406,118 +5632,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
// rjf: evaluate hit stop conditions
|
||||
if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions")
|
||||
{
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
|
||||
// rjf: gather evaluation modules
|
||||
U64 eval_modules_count = Max(1, ctrl_state->ctrl_thread_entity_store->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_Module *eval_modules = push_array(temp.arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &di_rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
{
|
||||
U64 eval_module_idx = 0;
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first;
|
||||
process != &ctrl_entity_nil;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
for(CTRL_Entity *mod = process->first;
|
||||
mod != &ctrl_entity_nil;
|
||||
mod = mod->next)
|
||||
{
|
||||
if(mod->kind != CTRL_EntityKind_Module) { continue; }
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
eval_modules[eval_module_idx].arch = arch;
|
||||
eval_modules[eval_module_idx].rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
|
||||
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
|
||||
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
|
||||
if(mod == module)
|
||||
{
|
||||
eval_modules_primary = &eval_modules[eval_module_idx];
|
||||
}
|
||||
eval_module_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: loop through all conditions, check all
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, thread);
|
||||
for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next)
|
||||
{
|
||||
// rjf: build eval type context
|
||||
E_TypeCtx type_ctx = zero_struct;
|
||||
{
|
||||
E_TypeCtx *ctx = &type_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
}
|
||||
e_select_type_ctx(&type_ctx);
|
||||
|
||||
// rjf: build eval parse context
|
||||
E_ParseCtx parse_ctx = zero_struct;
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = &parse_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->ip_thread_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->ip_thread_space.u64_0 = (U64)thread;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(temp.arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(temp.arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
}
|
||||
e_select_parse_ctx(&parse_ctx);
|
||||
|
||||
// rjf: build eval IR context
|
||||
E_IRCtx ir_ctx = zero_struct;
|
||||
{
|
||||
E_IRCtx *ctx = &ir_ctx;
|
||||
ctx->macro_map = push_array(temp.arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(temp.arena, 512);
|
||||
E_TypeKey meval_type_key = e_type_key_cons_base(type(CTRL_MetaEval));
|
||||
for EachIndex(idx, ctrl_state->user_meta_evals.count)
|
||||
{
|
||||
E_Space space = e_space_make(CTRL_EvalSpaceKind_Meta);
|
||||
E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, 0);
|
||||
expr->space = space;
|
||||
expr->mode = E_Mode_Offset;
|
||||
expr->type_key = meval_type_key;
|
||||
e_string2expr_map_insert(temp.arena, ctx->macro_map, ctrl_state->user_meta_evals.v[idx].label, expr);
|
||||
}
|
||||
}
|
||||
e_select_ir_ctx(&ir_ctx);
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
E_InterpretCtx interpret_ctx = zero_struct;
|
||||
{
|
||||
E_InterpretCtx *ctx = &interpret_ctx;
|
||||
ctx->space_rw_user_data = ctrl_state->ctrl_thread_entity_store;
|
||||
ctx->space_read = ctrl_eval_space_read;
|
||||
ctx->primary_space = eval_modules_primary->space;
|
||||
ctx->reg_arch = eval_modules_primary->arch;
|
||||
ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->reg_space.u64_0 = (U64)thread;
|
||||
ctx->module_base = push_array(temp.arena, U64, 1);
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->frame_base = push_array(temp.arena, U64, 1);
|
||||
ctx->tls_base = push_array(temp.arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&interpret_ctx, type_ctx.primary_module->rdi, type_ctx.ip_voff);
|
||||
|
||||
// rjf: evaluate
|
||||
E_Eval eval = zero_struct;
|
||||
ProfScope("evaluate expression")
|
||||
@@ -5540,7 +5657,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
di_scope_close(di_scope);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}
|
||||
|
||||
// rjf: gather trap net hits
|
||||
@@ -5848,6 +5965,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread);
|
||||
event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process);
|
||||
event->exception_code = stop_event->code;
|
||||
event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind);
|
||||
event->vaddr_rng = r1u64(stop_event->address, stop_event->address);
|
||||
event->rip_vaddr = stop_event->instruction_pointer;
|
||||
ctrl_c2u_push_events(&evts);
|
||||
@@ -5922,6 +6040,7 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread);
|
||||
event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process);
|
||||
event->exception_code = stop_event->code;
|
||||
event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind);
|
||||
event->vaddr_rng = r1u64(stop_event->address, stop_event->address);
|
||||
event->rip_vaddr = stop_event->instruction_pointer;
|
||||
}
|
||||
|
||||
+43
-246
@@ -12,229 +12,6 @@ typedef U64 CTRL_MachineID;
|
||||
|
||||
#define CTRL_MachineID_Local (1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Meta Evaluation Types
|
||||
|
||||
//- rjf: auto-checkbox b32s
|
||||
|
||||
typedef struct CTRL_CheckB32 CTRL_CheckB32;
|
||||
struct CTRL_CheckB32
|
||||
{
|
||||
B32 b32;
|
||||
};
|
||||
|
||||
struct_members(CTRL_CheckB32)
|
||||
{
|
||||
member_lit_comp(CTRL_CheckB32, type(B32), b32),
|
||||
};
|
||||
struct_type(CTRL_CheckB32);
|
||||
|
||||
//- rjf: styled string types
|
||||
|
||||
ptr_type(CTRL_PlainString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPlainText,.count_delimiter_name = str8_lit_comp("size"));
|
||||
ptr_type(CTRL_CodeString8__str_ptr_type, type(U8), .flags = TypeFlag_IsCodeText, .count_delimiter_name = str8_lit_comp("size"));
|
||||
ptr_type(CTRL_PathString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPathText, .count_delimiter_name = str8_lit_comp("size"));
|
||||
Member CTRL_PlainString8__members[] =
|
||||
{
|
||||
member_lit_comp(String8, &CTRL_PlainString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
|
||||
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
|
||||
};
|
||||
Member CTRL_CodeString8__members[] =
|
||||
{
|
||||
member_lit_comp(String8, &CTRL_CodeString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
|
||||
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
|
||||
};
|
||||
Member CTRL_PathString8__members[] =
|
||||
{
|
||||
member_lit_comp(String8, &CTRL_PathString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
|
||||
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
|
||||
};
|
||||
named_struct_type(CTRL_PlainString8, String8, .name = str8_lit_comp("string"));
|
||||
named_struct_type(CTRL_CodeString8, String8, .name = str8_lit_comp("string"));
|
||||
named_struct_type(CTRL_PathString8, String8, .name = str8_lit_comp("string"));
|
||||
|
||||
//- rjf: meta evaluation callstack types
|
||||
|
||||
typedef struct CTRL_MetaEvalFrame CTRL_MetaEvalFrame;
|
||||
struct CTRL_MetaEvalFrame
|
||||
{
|
||||
U64 vaddr;
|
||||
U64 inline_depth;
|
||||
};
|
||||
ptr_type(CTRL_MetaEvalFrame__vaddr_type, type(void), .flags = TypeFlag_IsExternal, .size = sizeof(U64));
|
||||
struct_members(CTRL_MetaEvalFrame)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEvalFrame, &CTRL_MetaEvalFrame__vaddr_type, vaddr),
|
||||
member_lit_comp(CTRL_MetaEvalFrame, type(U64), inline_depth),
|
||||
};
|
||||
struct_type(CTRL_MetaEvalFrame, .name = str8_lit_comp("callstack_frame"));
|
||||
typedef struct CTRL_MetaEvalFrameArray CTRL_MetaEvalFrameArray;
|
||||
struct CTRL_MetaEvalFrameArray
|
||||
{
|
||||
U64 count;
|
||||
CTRL_MetaEvalFrame *v;
|
||||
};
|
||||
ptr_type(CTRL_MetaEvalFrameArray__v_ptr_type, type(CTRL_MetaEvalFrame), .count_delimiter_name = str8_lit_comp("count"));
|
||||
struct_members(CTRL_MetaEvalFrameArray)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEvalFrameArray, type(U64), count, .pretty_name = str8_lit_comp("Frame Count")),
|
||||
{str8_lit_comp("v"), str8_lit_comp("Frame Addresses"), &CTRL_MetaEvalFrameArray__v_ptr_type, OffsetOf(CTRL_MetaEvalFrameArray, v)},
|
||||
};
|
||||
struct_type(CTRL_MetaEvalFrameArray, .name = str8_lit_comp("callstack_frames"));
|
||||
|
||||
//- rjf: meta evaluation instance types
|
||||
|
||||
typedef struct CTRL_MetaEval CTRL_MetaEval;
|
||||
struct CTRL_MetaEval
|
||||
{
|
||||
#define CTRL_MetaEval_MemberXList \
|
||||
X(B32, enabled, "Enabled")\
|
||||
X(B32, frozen, "Frozen")\
|
||||
X(U64, hit_count, "Hit Count")\
|
||||
X(U64, id, "ID")\
|
||||
X(Rng1U64, vaddr_range, "Address Range")\
|
||||
X(U32, color, "Color")\
|
||||
X(CTRL_CheckB32, debug_subprocesses,"Debug Subprocesses")\
|
||||
Y(String8, type(CTRL_CodeString8), label, "Label")\
|
||||
Y(String8, type(CTRL_PathString8), exe, "Executable Path")\
|
||||
Y(String8, type(CTRL_PathString8), dbg, "Debug Info Path")\
|
||||
Y(String8, type(CTRL_PlainString8), args, "Arguments")\
|
||||
Y(String8, type(CTRL_PathString8), working_directory, "Working Directory")\
|
||||
Y(String8, type(CTRL_CodeString8), entry_point, "Custom Entry Point")\
|
||||
Y(String8, type(CTRL_PathString8), stdout_path, "Standard Output Path")\
|
||||
Y(String8, type(CTRL_PathString8), stderr_path, "Standard Error Path")\
|
||||
Y(String8, type(CTRL_PathString8), stdin_path, "Standard Input Path")\
|
||||
Y(String8, type(CTRL_PathString8), source_location, "Source Location")\
|
||||
Y(String8, type(CTRL_CodeString8), function_location, "Function Location")\
|
||||
Y(String8, type(CTRL_CodeString8), address_location, "Address Location")\
|
||||
Y(String8, type(CTRL_PathString8), source_path, "Source Path")\
|
||||
Y(String8, type(CTRL_PathString8), destination_path, "Destination Path")\
|
||||
Y(String8, type(CTRL_CodeString8), type, "Type")\
|
||||
Y(String8, type(CTRL_CodeString8), view_rule, "View Rule")\
|
||||
Y(String8, type(CTRL_CodeString8), condition, "Condition")\
|
||||
X(CTRL_MetaEvalFrameArray, callstack, "Call Stack")
|
||||
#define X(T, name, pretty_name) T name;
|
||||
#define Y(T, ti, name, pretty_name) T name;
|
||||
CTRL_MetaEval_MemberXList
|
||||
#undef X
|
||||
#undef Y
|
||||
};
|
||||
struct_members(CTRL_MetaEval)
|
||||
{
|
||||
#define X(T, name, pretty_name_) member_lit_comp(CTRL_MetaEval, type(T), name, .pretty_name = str8_lit_comp(pretty_name_)),
|
||||
#define Y(T, ti, name, pretty_name_) member_lit_comp(CTRL_MetaEval, (ti), name, .pretty_name = str8_lit_comp(pretty_name_)),
|
||||
CTRL_MetaEval_MemberXList
|
||||
#undef X
|
||||
#undef Y
|
||||
};
|
||||
struct_type(CTRL_MetaEval);
|
||||
|
||||
//- rjf: filters on main meta evaluation bundle
|
||||
|
||||
struct_members(CTRL_BreakpointMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(B32), enabled, .pretty_name = str8_lit_comp("Enabled")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U64), hit_count, .pretty_name = str8_lit_comp("Hit Count")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), condition, .pretty_name = str8_lit_comp("Condition")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), function_location, .pretty_name = str8_lit_comp("Function Location")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_TargetMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PlainString8),args, .pretty_name = str8_lit_comp("Arguments")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), working_directory, .pretty_name = str8_lit_comp("Working Directory")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), entry_point, .pretty_name = str8_lit_comp("Custom Entry Point")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdout_path, .pretty_name = str8_lit_comp("Standard Output Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stderr_path, .pretty_name = str8_lit_comp("Standard Error Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdin_path, .pretty_name = str8_lit_comp("Standard Input Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CheckB32), debug_subprocesses, .pretty_name = str8_lit_comp("Debug Subprocesses")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_PinMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Expression")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_FilePathMapMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_path, .pretty_name = str8_lit_comp("Source Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), destination_path, .pretty_name = str8_lit_comp("Destination Path")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_AutoViewRuleMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), type, .pretty_name = str8_lit_comp("Type")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), view_rule, .pretty_name = str8_lit_comp("View Rule")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_MachineMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_ProcessMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_ModuleMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), dbg, .pretty_name = str8_lit_comp("Debug Info Path")),
|
||||
member_lit_comp(CTRL_MetaEval, type(Rng1U64), vaddr_range, .pretty_name = str8_lit_comp("Address Range")),
|
||||
};
|
||||
|
||||
struct_members(CTRL_ThreadMetaEval)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
|
||||
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
|
||||
member_lit_comp(CTRL_MetaEval, type(CTRL_MetaEvalFrameArray), callstack, .pretty_name = str8_lit_comp("Call Stack")),
|
||||
};
|
||||
|
||||
named_struct_type(CTRL_BreakpointMetaEval, CTRL_MetaEval, .name = str8_lit_comp("breakpoint"));
|
||||
named_struct_type(CTRL_TargetMetaEval, CTRL_MetaEval, .name = str8_lit_comp("target"));
|
||||
named_struct_type(CTRL_PinMetaEval, CTRL_MetaEval, .name = str8_lit_comp("pin"));
|
||||
named_struct_type(CTRL_FilePathMapMetaEval, CTRL_MetaEval, .name = str8_lit_comp("file_path_map"));
|
||||
named_struct_type(CTRL_AutoViewRuleMetaEval,CTRL_MetaEval, .name = str8_lit_comp("auto_view_rule"));
|
||||
named_struct_type(CTRL_MachineMetaEval, CTRL_MetaEval, .name = str8_lit_comp("machine"));
|
||||
named_struct_type(CTRL_ProcessMetaEval, CTRL_MetaEval, .name = str8_lit_comp("process"));
|
||||
named_struct_type(CTRL_ModuleMetaEval, CTRL_MetaEval, .name = str8_lit_comp("module"));
|
||||
named_struct_type(CTRL_ThreadMetaEval, CTRL_MetaEval, .name = str8_lit_comp("thread"));
|
||||
|
||||
//- rjf: meta evaluation array
|
||||
|
||||
typedef struct CTRL_MetaEvalArray CTRL_MetaEvalArray;
|
||||
struct CTRL_MetaEvalArray
|
||||
{
|
||||
CTRL_MetaEval *v;
|
||||
U64 count;
|
||||
};
|
||||
ptr_type(CTRL_MetaEvalArray__v_ptr_type, type(CTRL_BreakpointMetaEval), .count_delimiter_name = str8_lit_comp("count"));
|
||||
struct_members(CTRL_MetaEvalArray)
|
||||
{
|
||||
{str8_lit_comp("v"), {0}, &CTRL_MetaEvalArray__v_ptr_type, OffsetOf(CTRL_MetaEvalArray, v)},
|
||||
member_lit_comp(CTRL_MetaEvalArray, type(U64), count),
|
||||
};
|
||||
struct_type(CTRL_MetaEvalArray);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Handle Types
|
||||
|
||||
@@ -340,6 +117,18 @@ struct CTRL_EntityStringChunkNode
|
||||
U64 size;
|
||||
};
|
||||
|
||||
read_only global U64 ctrl_entity_string_bucket_chunk_sizes[] =
|
||||
{
|
||||
16,
|
||||
64,
|
||||
256,
|
||||
1024,
|
||||
4096,
|
||||
16384,
|
||||
65536,
|
||||
0xffffffffffffffffull,
|
||||
};
|
||||
|
||||
typedef struct CTRL_EntityStore CTRL_EntityStore;
|
||||
struct CTRL_EntityStore
|
||||
{
|
||||
@@ -349,7 +138,7 @@ struct CTRL_EntityStore
|
||||
CTRL_EntityHashSlot *hash_slots;
|
||||
CTRL_EntityHashNode *hash_node_free;
|
||||
U64 hash_slots_count;
|
||||
CTRL_EntityStringChunkNode *free_string_chunks[8];
|
||||
CTRL_EntityStringChunkNode *free_string_chunks[ArrayCount(ctrl_entity_string_bucket_chunk_sizes)];
|
||||
U64 entity_kind_counts[CTRL_EntityKind_COUNT];
|
||||
Arena *entity_kind_lists_arenas[CTRL_EntityKind_COUNT];
|
||||
U64 entity_kind_lists_gens[CTRL_EntityKind_COUNT];
|
||||
@@ -404,32 +193,23 @@ struct CTRL_Unwind
|
||||
////////////////////////////////
|
||||
//~ rjf: Call Stack Types
|
||||
|
||||
typedef struct CTRL_CallStackInlineFrame CTRL_CallStackInlineFrame;
|
||||
struct CTRL_CallStackInlineFrame
|
||||
{
|
||||
CTRL_CallStackInlineFrame *next;
|
||||
CTRL_CallStackInlineFrame *prev;
|
||||
RDI_InlineSite *inline_site;
|
||||
};
|
||||
|
||||
typedef struct CTRL_CallStackFrame CTRL_CallStackFrame;
|
||||
struct CTRL_CallStackFrame
|
||||
{
|
||||
CTRL_CallStackInlineFrame *first_inline_frame;
|
||||
CTRL_CallStackInlineFrame *last_inline_frame;
|
||||
U64 inline_frame_count;
|
||||
U64 parent_num;
|
||||
U64 unwind_count;
|
||||
U64 inline_depth;
|
||||
void *regs;
|
||||
RDI_Parsed *rdi;
|
||||
RDI_Procedure *procedure;
|
||||
RDI_InlineSite *inline_site;
|
||||
};
|
||||
|
||||
typedef struct CTRL_CallStack CTRL_CallStack;
|
||||
struct CTRL_CallStack
|
||||
{
|
||||
CTRL_CallStackFrame *frames;
|
||||
U64 concrete_frame_count;
|
||||
U64 inline_frame_count;
|
||||
U64 total_frame_count;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -483,8 +263,7 @@ typedef enum CTRL_UserBreakpointKind
|
||||
{
|
||||
CTRL_UserBreakpointKind_Null,
|
||||
CTRL_UserBreakpointKind_FileNameAndLineColNumber,
|
||||
CTRL_UserBreakpointKind_SymbolNameAndOffset,
|
||||
CTRL_UserBreakpointKind_VirtualAddress,
|
||||
CTRL_UserBreakpointKind_Expression,
|
||||
CTRL_UserBreakpointKind_COUNT
|
||||
}
|
||||
CTRL_UserBreakpointKind;
|
||||
@@ -573,7 +352,6 @@ struct CTRL_Msg
|
||||
String8 stdin_path;
|
||||
CTRL_TrapList traps;
|
||||
CTRL_UserBreakpointList user_bps;
|
||||
CTRL_MetaEvalArray meta_evals;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MsgNode CTRL_MsgNode;
|
||||
@@ -857,6 +635,19 @@ struct CTRL_DbgDirNode
|
||||
U64 module_direct_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Control Thread Evaluation Scopes
|
||||
|
||||
typedef struct CTRL_EvalScope CTRL_EvalScope;
|
||||
struct CTRL_EvalScope
|
||||
{
|
||||
DI_Scope *di_scope;
|
||||
E_TypeCtx type_ctx;
|
||||
E_ParseCtx parse_ctx;
|
||||
E_IRCtx ir_ctx;
|
||||
E_InterpretCtx interpret_ctx;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Wakeup Hook Function Types
|
||||
|
||||
@@ -909,8 +700,6 @@ struct CTRL_State
|
||||
DMN_EventNode *free_dmn_event_node;
|
||||
Arena *user_entry_point_arena;
|
||||
String8List user_entry_points;
|
||||
Arena *user_meta_eval_arena;
|
||||
CTRL_MetaEvalArray user_meta_evals;
|
||||
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
|
||||
U64 process_counter;
|
||||
Arena *dbg_dir_arena;
|
||||
@@ -949,8 +738,10 @@ read_only global CTRL_Entity ctrl_entity_nil =
|
||||
internal U64 ctrl_hash_from_string(String8 string);
|
||||
internal U64 ctrl_hash_from_handle(CTRL_Handle handle);
|
||||
internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
|
||||
internal CTRL_ExceptionKind ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind);
|
||||
internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind);
|
||||
internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind);
|
||||
internal CTRL_EntityKind ctrl_entity_kind_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions
|
||||
@@ -960,6 +751,7 @@ internal CTRL_Handle ctrl_handle_make(CTRL_MachineID machine_id, DMN_Handle dmn_
|
||||
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
|
||||
internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair);
|
||||
internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src);
|
||||
internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Type Functions
|
||||
@@ -1015,7 +807,7 @@ internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
|
||||
internal void ctrl_entity_store_release(CTRL_EntityStore *store);
|
||||
|
||||
//- rjf: string allocation/deletion
|
||||
internal U64 ctrl_name_bucket_idx_from_string_size(U64 size);
|
||||
internal U64 ctrl_name_bucket_num_from_string_size(U64 size);
|
||||
internal String8 ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string);
|
||||
internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string);
|
||||
|
||||
@@ -1120,6 +912,7 @@ internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *sto
|
||||
//~ rjf: Call Stack Building Functions
|
||||
|
||||
internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, DI_Scope *di_scope, CTRL_Entity *process, CTRL_Unwind *base_unwind);
|
||||
internal CTRL_CallStackFrame *ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Halting All Attached Processes
|
||||
@@ -1153,8 +946,8 @@ internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
|
||||
internal void ctrl_thread__entry_point(void *p);
|
||||
|
||||
//- rjf: breakpoint resolution
|
||||
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
|
||||
//- rjf: module lifetime open/close work
|
||||
internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path);
|
||||
@@ -1166,6 +959,10 @@ internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_
|
||||
//- rjf: eval helpers
|
||||
internal B32 ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 vaddr_range);
|
||||
|
||||
//- rjf: control thread eval scopes
|
||||
internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread);
|
||||
internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope);
|
||||
|
||||
//- rjf: log flusher
|
||||
internal void ctrl_thread__flush_info_log(String8 string);
|
||||
internal void ctrl_thread__end_and_flush_info_log(void);
|
||||
|
||||
@@ -4,6 +4,19 @@
|
||||
//- GENERATED CODE
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
String8 ctrl_entity_kind_code_name_table[9] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("root"),
|
||||
str8_lit_comp("machine"),
|
||||
str8_lit_comp("process"),
|
||||
str8_lit_comp("thread"),
|
||||
str8_lit_comp("module"),
|
||||
str8_lit_comp("entry_point"),
|
||||
str8_lit_comp("debug_info_path"),
|
||||
str8_lit_comp("pending_thread_name"),
|
||||
};
|
||||
|
||||
String8 ctrl_entity_kind_display_string_table[9] =
|
||||
{
|
||||
{0},
|
||||
|
||||
@@ -64,6 +64,7 @@ CTRL_ExceptionCodeKind_COUNT,
|
||||
} CTRL_ExceptionCodeKind;
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 ctrl_entity_kind_code_name_table[9];
|
||||
extern String8 ctrl_entity_kind_display_string_table[9];
|
||||
extern U32 ctrl_exception_code_kind_code_table[38];
|
||||
extern String8 ctrl_exception_code_kind_display_string_table[38];
|
||||
|
||||
@@ -4,53 +4,52 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Built-In Command Tables
|
||||
|
||||
@table(name ui_vis ipc_docs_vis q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags )
|
||||
// / | | | \___ _________________________________/ | | | | |
|
||||
// / | | | \ / | | | | |
|
||||
D_CmdTable: // | | | | | | | | | |
|
||||
@table(name ui_vis ipc_docs_vis q_expr q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_floating q_required canonical_icon string display_name desc search_tags ctx_filter)
|
||||
// / | | | | \___ _________________________________/ | | | | | |
|
||||
// / | | | | \ / | | | | | |
|
||||
D_CmdTable: // | | | | | | | | | | | |
|
||||
{
|
||||
//- rjf: low-level target control operations
|
||||
{LaunchAndRun 1 1 Entity null Target Null 0 0 0 0 0 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" }
|
||||
{LaunchAndInit 1 1 Entity null Target Null 0 0 0 0 0 1 PlayStepForward "launch_and_init" "Launch and Initialize" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" }
|
||||
{Kill 1 1 Process null Nil Process 0 0 0 0 0 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" }
|
||||
{KillAll 1 1 Null null Nil Null 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" }
|
||||
{Detach 1 1 Process null Nil Process 0 0 0 0 0 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" }
|
||||
{Continue 1 1 Null null Nil Null 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" }
|
||||
{StepIntoInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" }
|
||||
{StepOverInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" }
|
||||
{StepIntoLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" }
|
||||
{StepOverLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" }
|
||||
{StepOut 1 1 Null null Nil Null 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" }
|
||||
{Halt 1 1 Null null Nil Null 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" }
|
||||
{SoftHaltRefresh 1 1 Null null Nil Null 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" }
|
||||
{SetThreadIP 0 1 Vaddr null Nil Null 0 0 0 0 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" }
|
||||
{LaunchAndRun 1 1 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" "" }
|
||||
{LaunchAndStepInto 1 1 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 PlayStepForward "launch_and_step_into" "Launch and Step Into" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" "" }
|
||||
{Kill 1 1 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" "" }
|
||||
{KillAll 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" "" }
|
||||
{Detach 1 1 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" "" }
|
||||
{Continue 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" "" }
|
||||
{StepIntoInst 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" "" }
|
||||
{StepOverInst 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" "" }
|
||||
{StepIntoLine 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" "" }
|
||||
{StepOverLine 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" "" }
|
||||
{StepOut 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" "" }
|
||||
{Halt 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" "" }
|
||||
{SoftHaltRefresh 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" "" }
|
||||
{SetThreadIP 0 1 "" Vaddr null Nil Null 0 0 0 0 1 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" "" }
|
||||
|
||||
//- rjf: high-level composite target control operations
|
||||
{RunToLine 0 1 Null null Nil Null 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" }
|
||||
{RunToAddress 1 1 Vaddr null Nil Null 0 0 0 0 1 1 PlayStepForward "run_to_address" "Run To Address" "Runs until a particular address is hit." "" }
|
||||
{Run 1 1 Null null Nil Null 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" }
|
||||
{Restart 1 1 Null null Nil Null 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" }
|
||||
{StepInto 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" }
|
||||
{StepOver 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" }
|
||||
{RunToLine 0 1 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" "$text_pt," }
|
||||
{Run 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" "" }
|
||||
{Restart 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" "" }
|
||||
{StepInto 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" "" }
|
||||
{StepOver 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" "" }
|
||||
|
||||
//- rjf: debug control context management operations
|
||||
{FreezeThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" }
|
||||
{ThawThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" }
|
||||
{FreezeProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" }
|
||||
{ThawProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" }
|
||||
{FreezeMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" }
|
||||
{ThawMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" }
|
||||
{FreezeLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" }
|
||||
{ThawLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" }
|
||||
{FreezeEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "freeze_entity" "Freeze Entity" "Freezes an entity." "" }
|
||||
{ThawEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "thaw_entity" "Thaw Entity" "Thaws an entity." "" }
|
||||
{FreezeThread 1 1 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" "" }
|
||||
{ThawThread 1 1 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" "" }
|
||||
{FreezeProcess 1 1 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" "" }
|
||||
{ThawProcess 1 1 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" "" }
|
||||
{FreezeMachine 0 1 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" "" }
|
||||
{ThawMachine 0 1 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" "" }
|
||||
{FreezeLocalMachine 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" "" }
|
||||
{ThawLocalMachine 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" "" }
|
||||
{FreezeEntity 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Unlocked "freeze_entity" "Freeze Entity" "Freezes an entity." "" "" }
|
||||
{ThawEntity 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Locked "thaw_entity" "Thaw Entity" "Thaws an entity." "" "" }
|
||||
|
||||
//- rjf: entity decoration
|
||||
{SetEntityColor 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" }
|
||||
{SetEntityName 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" }
|
||||
{SetEntityColor 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" "" }
|
||||
{SetEntityName 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" "" }
|
||||
|
||||
//- rjf: attaching
|
||||
{Attach 1 1 PID null Nil Null 0 0 0 0 0 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" }
|
||||
{Attach 1 1 "query:unattached_processes" PID null Nil Null 0 0 0 0 0 1 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" "" }
|
||||
}
|
||||
|
||||
@enum D_CmdKind:
|
||||
@@ -114,7 +113,6 @@ D_DevToggleTable:
|
||||
{eval_compiler_tooltips}
|
||||
{eval_watch_key_tooltips}
|
||||
{cmd_context_tooltips}
|
||||
{scratch_mouse_draw}
|
||||
{updating_indicator}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,16 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
#if !defined(XXH_IMPLEMENTATION)
|
||||
# define XXH_IMPLEMENTATION
|
||||
# define XXH_STATIC_LINKING_ONLY
|
||||
# include "third_party/xxHash/xxhash.h"
|
||||
#endif
|
||||
|
||||
internal U64
|
||||
d_hash_from_seed_string(U64 seed, String8 string)
|
||||
{
|
||||
U64 result = seed;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
U64 result = XXH3_64bits_withSeed(string.str, string.size, seed);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,7 +61,7 @@ d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src)
|
||||
for(U64 idx = 0; idx < dst.count; idx += 1)
|
||||
{
|
||||
dst.v[idx].file_path = push_str8_copy(arena, dst.v[idx].file_path);
|
||||
dst.v[idx].symbol_name = push_str8_copy(arena, dst.v[idx].symbol_name);
|
||||
dst.v[idx].vaddr_expr = push_str8_copy(arena, dst.v[idx].vaddr_expr);
|
||||
dst.v[idx].condition = push_str8_copy(arena, dst.v[idx].condition);
|
||||
}
|
||||
return dst;
|
||||
@@ -667,35 +669,102 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
|
||||
//- rjf: symbol lookups
|
||||
|
||||
internal String8
|
||||
d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 decorated)
|
||||
d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, U64 depth, B32 decorated)
|
||||
{
|
||||
String8 result = {0};
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
DI_Scope *scope = di_scope_open();
|
||||
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
|
||||
|
||||
//- rjf: try scopes
|
||||
if(result.size == 0)
|
||||
{
|
||||
// rjf: voff -> scope
|
||||
U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff);
|
||||
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx);
|
||||
U64 proc_idx = scope->proc_idx;
|
||||
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx);
|
||||
E_TypeKey type = e_type_key_ext(E_TypeKind_Function, procedure->type_idx, e_parse_ctx_module_idx_from_rdi(rdi));
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
|
||||
if(decorated && procedure->type_idx != 0)
|
||||
|
||||
// rjf: scope -> # of max possible inline depth
|
||||
U64 inline_site_count = 0;
|
||||
for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next)
|
||||
{
|
||||
String8List list = {0};
|
||||
e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0);
|
||||
str8_list_push(scratch.arena, &list, name);
|
||||
e_type_rhs_string_from_key(scratch.arena, type, &list, 0);
|
||||
result = str8_list_join(arena, &list, 0);
|
||||
RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx);
|
||||
s_idx_next = s->parent_scope_idx;
|
||||
if(s->inline_site_idx != 0)
|
||||
{
|
||||
inline_site_count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: depth in [1, max]? -> form name from inline site
|
||||
if(0 < depth && depth <= inline_site_count)
|
||||
{
|
||||
RDI_InlineSite *inline_site = 0;
|
||||
U64 s_inline_depth = inline_site_count;
|
||||
for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next)
|
||||
{
|
||||
RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx);
|
||||
s_idx_next = s->parent_scope_idx;
|
||||
if(s_inline_depth == depth)
|
||||
{
|
||||
inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx);
|
||||
break;
|
||||
}
|
||||
s_inline_depth -= 1;
|
||||
if(s_inline_depth == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(inline_site != 0)
|
||||
{
|
||||
E_TypeKey type = e_type_key_ext(E_TypeKind_Function, inline_site->type_idx, e_parse_ctx_module_idx_from_rdi(rdi));
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size);
|
||||
if(decorated && inline_site->type_idx != 0)
|
||||
{
|
||||
String8List list = {0};
|
||||
str8_list_pushf(scratch.arena, &list, "[inlined] ");
|
||||
e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0);
|
||||
str8_list_push(scratch.arena, &list, name);
|
||||
e_type_rhs_string_from_key(scratch.arena, type, &list, 0);
|
||||
result = str8_list_join(arena, &list, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = push_str8_copy(arena, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: depth == 0 or depth >= max? -> form name from scope procedure
|
||||
else
|
||||
{
|
||||
result = push_str8_copy(arena, name);
|
||||
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx);
|
||||
U64 proc_idx = scope->proc_idx;
|
||||
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx);
|
||||
E_TypeKey type = e_type_key_ext(E_TypeKind_Function, procedure->type_idx, e_parse_ctx_module_idx_from_rdi(rdi));
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
|
||||
if(decorated && procedure->type_idx != 0)
|
||||
{
|
||||
String8List list = {0};
|
||||
e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0);
|
||||
str8_list_push(scratch.arena, &list, name);
|
||||
e_type_rhs_string_from_key(scratch.arena, type, &list, 0);
|
||||
result = str8_list_join(arena, &list, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = push_str8_copy(arena, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: try global variables
|
||||
if(result.size == 0)
|
||||
{
|
||||
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff);
|
||||
@@ -704,6 +773,7 @@ d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 d
|
||||
U8 *name_ptr = rdi_string_from_idx(rdi, global_var->name_string_idx, &name_size);
|
||||
result = push_str8_copy(arena, str8(name_ptr, name_size));
|
||||
}
|
||||
|
||||
di_scope_close(scope);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
@@ -711,7 +781,7 @@ d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 d
|
||||
}
|
||||
|
||||
internal String8
|
||||
d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, B32 decorated)
|
||||
d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, U64 depth, B32 decorated)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
String8 result = {0};
|
||||
@@ -719,7 +789,7 @@ d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr,
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
U64 voff = ctrl_voff_from_vaddr(module, vaddr);
|
||||
result = d_symbol_name_from_dbgi_key_voff(arena, &dbgi_key, voff, decorated);
|
||||
result = d_symbol_name_from_dbgi_key_voff(arena, &dbgi_key, voff, depth, decorated);
|
||||
}
|
||||
ProfEnd();
|
||||
return result;
|
||||
@@ -1595,6 +1665,7 @@ d_init(void)
|
||||
d_state->arena = arena;
|
||||
d_state->cmds_arena = arena_alloc();
|
||||
d_state->output_log_key = hs_hash_from_data(str8_lit("output_log_key"));
|
||||
hs_submit_data(d_state->output_log_key, 0, str8_zero());
|
||||
d_state->ctrl_entity_store = ctrl_entity_store_alloc();
|
||||
d_state->ctrl_stop_arena = arena_alloc();
|
||||
d_state->view_rule_spec_table_size = 1024;
|
||||
@@ -1628,13 +1699,12 @@ d_init(void)
|
||||
}
|
||||
|
||||
internal D_EventList
|
||||
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64], CTRL_MetaEvalArray *meta_evals)
|
||||
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64])
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
D_EventList result = {0};
|
||||
d_state->frame_index += 1;
|
||||
d_state->frame_eval_memread_endt_us = os_now_microseconds() + 1000;
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: sync with ctrl thread
|
||||
@@ -1831,8 +1901,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Breakpoint *bp = &breakpoints->v[idx];
|
||||
str8_list_push(scratch.arena, &strings, bp->file_path);
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt));
|
||||
str8_list_push(scratch.arena, &strings, bp->symbol_name);
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->vaddr));
|
||||
str8_list_push(scratch.arena, &strings, bp->vaddr_expr);
|
||||
str8_list_push(scratch.arena, &strings, bp->condition);
|
||||
}
|
||||
}
|
||||
@@ -1872,35 +1941,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: sync with di parsers
|
||||
//
|
||||
ProfScope("sync with di parsers")
|
||||
{
|
||||
DI_EventList events = di_p2u_pop_events(scratch.arena, 0);
|
||||
for(DI_EventNode *n = events.first; n != 0; n = n->next)
|
||||
{
|
||||
DI_Event *event = &n->v;
|
||||
switch(event->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case DI_EventKind_ConversionStarted:
|
||||
{
|
||||
RD_Entity *task = rd_entity_alloc(rd_entity_root(), RD_EntityKind_ConversionTask);
|
||||
rd_entity_equip_name(task, event->string);
|
||||
}break;
|
||||
case DI_EventKind_ConversionEnded:
|
||||
{
|
||||
RD_Entity *task = rd_entity_from_name_and_kind(event->string, RD_EntityKind_ConversionTask);
|
||||
if(!rd_entity_is_nil(task))
|
||||
{
|
||||
rd_entity_mark_for_deletion(task);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: process top-level commands
|
||||
//
|
||||
@@ -1927,7 +1967,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
|
||||
//- rjf: low-level target control operations
|
||||
case D_CmdKind_LaunchAndRun:
|
||||
case D_CmdKind_LaunchAndInit:
|
||||
case D_CmdKind_LaunchAndStepInto:
|
||||
{
|
||||
// rjf: get list of targets to launch
|
||||
D_TargetArray *targets_to_launch = ¶ms->targets;
|
||||
@@ -1998,7 +2038,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->debug_subprocesses = target->debug_subprocesses;
|
||||
msg->env_inherit = 1;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
str8_list_push(scratch.arena, &msg->entry_points, custom_entry_point_name);
|
||||
msg->env_string_list = env;
|
||||
}
|
||||
@@ -2008,7 +2047,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
need_run = 1;
|
||||
run_kind = D_RunKind_Run;
|
||||
run_thread = &ctrl_entity_nil;
|
||||
run_flags = (cmd->kind == D_CmdKind_LaunchAndInit) ? CTRL_RunFlag_StopOnEntryPoint : 0;
|
||||
run_flags = (cmd->kind == D_CmdKind_LaunchAndStepInto) ? CTRL_RunFlag_StopOnEntryPoint : 0;
|
||||
}
|
||||
|
||||
// rjf: no targets -> error
|
||||
@@ -2031,7 +2070,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->exit_code = 1;
|
||||
msg->entity = process->handle;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
}
|
||||
}break;
|
||||
case D_CmdKind_KillAll:
|
||||
@@ -2040,7 +2078,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->kind = CTRL_MsgKind_KillAll;
|
||||
msg->exit_code = 1;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
}break;
|
||||
case D_CmdKind_Detach:
|
||||
{
|
||||
@@ -2055,7 +2092,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->kind = CTRL_MsgKind_Detach;
|
||||
msg->entity = process->handle;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
}
|
||||
}break;
|
||||
case D_CmdKind_Continue:
|
||||
@@ -2203,15 +2239,15 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
{
|
||||
run_extra_bps.count = 1;
|
||||
run_extra_bps.v = push_array(scratch.arena, D_Breakpoint, 1);
|
||||
run_extra_bps.v[0].file_path = params->file_path;
|
||||
run_extra_bps.v[0].pt = params->cursor;
|
||||
d_cmd(D_CmdKind_Run);
|
||||
}break;
|
||||
case D_CmdKind_RunToAddress:
|
||||
{
|
||||
run_extra_bps.count = 1;
|
||||
run_extra_bps.v = push_array(scratch.arena, D_Breakpoint, 1);
|
||||
run_extra_bps.v[0].vaddr = params->vaddr;
|
||||
if(params->file_path.size != 0)
|
||||
{
|
||||
run_extra_bps.v[0].file_path = params->file_path;
|
||||
run_extra_bps.v[0].pt = params->cursor;
|
||||
}
|
||||
else if(params->vaddr != 0)
|
||||
{
|
||||
run_extra_bps.v[0].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr);
|
||||
}
|
||||
d_cmd(D_CmdKind_Run);
|
||||
}break;
|
||||
case D_CmdKind_Run:
|
||||
@@ -2255,7 +2291,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
else if(!d_ctrl_targets_running())
|
||||
{
|
||||
d_cmd(D_CmdKind_LaunchAndInit, .targets = *targets);
|
||||
d_cmd(D_CmdKind_LaunchAndStepInto, .targets = *targets);
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -2331,7 +2367,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->kind = CTRL_MsgKind_Attach;
|
||||
msg->entity_id = pid;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
@@ -2353,7 +2388,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
msg->entity = run_thread->handle;
|
||||
msg->parent = process->handle;
|
||||
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
|
||||
MemoryCopyStruct(&msg->meta_evals, meta_evals);
|
||||
MemoryCopyStruct(&msg->traps, &run_traps);
|
||||
D_BreakpointArray *bp_batches[] =
|
||||
{
|
||||
@@ -2382,20 +2416,11 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: virtual address location -> add breakpoint for address
|
||||
else if(bp->vaddr != 0)
|
||||
// rjf: virtual address expression -> add expression breakpoint
|
||||
else if(bp->vaddr_expr.size != 0)
|
||||
{
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_VirtualAddress};
|
||||
ctrl_user_bp.u64 = bp->vaddr;
|
||||
ctrl_user_bp.condition = bp->condition;
|
||||
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
|
||||
}
|
||||
|
||||
// rjf: symbol name location -> add breakpoint for symbol name
|
||||
else if(bp->symbol_name.size != 0)
|
||||
{
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_SymbolNameAndOffset};
|
||||
ctrl_user_bp.string = bp->symbol_name;
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_Expression};
|
||||
ctrl_user_bp.string = bp->vaddr_expr;
|
||||
ctrl_user_bp.condition = bp->condition;
|
||||
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ struct D_Breakpoint
|
||||
{
|
||||
String8 file_path;
|
||||
TxtPt pt;
|
||||
String8 symbol_name;
|
||||
U64 vaddr;
|
||||
String8 vaddr_expr;
|
||||
String8 condition;
|
||||
};
|
||||
|
||||
@@ -331,7 +330,6 @@ struct D_State
|
||||
// rjf: top-level state
|
||||
Arena *arena;
|
||||
U64 frame_index;
|
||||
U64 frame_eval_memread_endt_us;
|
||||
|
||||
// rjf: commands
|
||||
Arena *cmds_arena;
|
||||
@@ -433,8 +431,8 @@ internal CTRL_TrapList d_trap_net_from_thread__step_into_line(Arena *arena, CTRL
|
||||
//~ rjf: Debug Info Lookups
|
||||
|
||||
//- rjf: voff|vaddr -> symbol lookups
|
||||
internal String8 d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 decorated);
|
||||
internal String8 d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, B32 decorated);
|
||||
internal String8 d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, U64 depth, B32 decorated);
|
||||
internal String8 d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, U64 depth, B32 decorated);
|
||||
|
||||
//- rjf: symbol -> voff lookups
|
||||
internal U64 d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name);
|
||||
@@ -495,6 +493,6 @@ internal B32 d_next_cmd(D_Cmd **cmd);
|
||||
//~ rjf: Main Layer Top-Level Calls
|
||||
|
||||
internal void d_init(void);
|
||||
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64], CTRL_MetaEvalArray *meta_evals);
|
||||
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]);
|
||||
|
||||
#endif // DBG_ENGINE_CORE_H
|
||||
|
||||
@@ -10,7 +10,7 @@ typedef enum D_CmdKind
|
||||
{
|
||||
D_CmdKind_Null,
|
||||
D_CmdKind_LaunchAndRun,
|
||||
D_CmdKind_LaunchAndInit,
|
||||
D_CmdKind_LaunchAndStepInto,
|
||||
D_CmdKind_Kill,
|
||||
D_CmdKind_KillAll,
|
||||
D_CmdKind_Detach,
|
||||
@@ -24,7 +24,6 @@ D_CmdKind_Halt,
|
||||
D_CmdKind_SoftHaltRefresh,
|
||||
D_CmdKind_SetThreadIP,
|
||||
D_CmdKind_RunToLine,
|
||||
D_CmdKind_RunToAddress,
|
||||
D_CmdKind_Run,
|
||||
D_CmdKind_Restart,
|
||||
D_CmdKind_StepInto,
|
||||
@@ -78,7 +77,6 @@ global B32 DEV_draw_ui_box_heatmap = 0;
|
||||
global B32 DEV_eval_compiler_tooltips = 0;
|
||||
global B32 DEV_eval_watch_key_tooltips = 0;
|
||||
global B32 DEV_cmd_context_tooltips = 0;
|
||||
global B32 DEV_scratch_mouse_draw = 0;
|
||||
global B32 DEV_updating_indicator = 0;
|
||||
struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
|
||||
{
|
||||
@@ -89,7 +87,6 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
|
||||
{&DEV_eval_compiler_tooltips, str8_lit_comp("eval_compiler_tooltips")},
|
||||
{&DEV_eval_watch_key_tooltips, str8_lit_comp("eval_watch_key_tooltips")},
|
||||
{&DEV_cmd_context_tooltips, str8_lit_comp("cmd_context_tooltips")},
|
||||
{&DEV_scratch_mouse_draw, str8_lit_comp("scratch_mouse_draw")},
|
||||
{&DEV_updating_indicator, str8_lit_comp("updating_indicator")},
|
||||
};
|
||||
#endif // DBG_ENGINE_META_H
|
||||
|
||||
+8
-2
@@ -262,12 +262,14 @@ di_scope_open(void)
|
||||
scope = push_array_no_zero(di_tctx->arena, DI_Scope, 1);
|
||||
}
|
||||
MemoryZeroStruct(scope);
|
||||
DLLPushBack(di_tctx->first_scope, di_tctx->last_scope, scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
internal void
|
||||
di_scope_close(DI_Scope *scope)
|
||||
{
|
||||
DLLRemove(di_tctx->first_scope, di_tctx->last_scope, scope);
|
||||
for(DI_Touch *t = scope->first_touch, *next = 0; t != 0; t = next)
|
||||
{
|
||||
next = t->next;
|
||||
@@ -1349,7 +1351,6 @@ di_search_thread__entry_point(void *p)
|
||||
for(;;)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
|
||||
//- rjf: get next key, unpack
|
||||
U128 key = di_u2s_dequeue_req(thread_idx);
|
||||
@@ -1380,6 +1381,9 @@ di_search_thread__entry_point(void *p)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: begin debug info scope
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
|
||||
//- rjf: get all rdis
|
||||
U64 rdis_count = params.dbgi_keys.count;
|
||||
RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count);
|
||||
@@ -1428,6 +1432,9 @@ di_search_thread__entry_point(void *p)
|
||||
cancelled = (cancelled || out->cancelled);
|
||||
}
|
||||
|
||||
//- rjf: end debug info scope
|
||||
di_scope_close(di_scope);
|
||||
|
||||
//- rjf: list -> array
|
||||
DI_SearchItemArray items = {0};
|
||||
if(arena != 0 && !cancelled)
|
||||
@@ -1496,7 +1503,6 @@ di_search_thread__entry_point(void *p)
|
||||
}
|
||||
}
|
||||
|
||||
di_scope_close(di_scope);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +225,7 @@ typedef struct DI_Scope DI_Scope;
|
||||
struct DI_Scope
|
||||
{
|
||||
DI_Scope *next;
|
||||
DI_Scope *prev;
|
||||
DI_Touch *first_touch;
|
||||
DI_Touch *last_touch;
|
||||
};
|
||||
@@ -233,6 +234,8 @@ typedef struct DI_TCTX DI_TCTX;
|
||||
struct DI_TCTX
|
||||
{
|
||||
Arena *arena;
|
||||
DI_Scope *first_scope;
|
||||
DI_Scope *last_scope;
|
||||
DI_Scope *free_scope;
|
||||
DI_Touch *free_touch;
|
||||
};
|
||||
|
||||
@@ -1229,6 +1229,75 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
|
||||
cmd = str8_list_join(scratch.arena, &args, &join_params);
|
||||
}
|
||||
|
||||
//- rjf: determine if process needs a console
|
||||
B32 needs_console = 1;
|
||||
{
|
||||
String8 exe_path = params->cmd_line.first->string;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, exe_path);
|
||||
|
||||
// rjf: find PE offset
|
||||
U32 pe_offset = 0;
|
||||
{
|
||||
U64 dos_magic_off = 0;
|
||||
U16 dos_magic = 0;
|
||||
os_file_read_struct(file, dos_magic_off, &dos_magic);
|
||||
if(dos_magic == PE_DOS_MAGIC)
|
||||
{
|
||||
U64 pe_offset_off = OffsetOf(PE_DosHeader, coff_file_offset);
|
||||
os_file_read_struct(file, pe_offset_off, &pe_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get COFF header
|
||||
B32 got_coff_header = 0;
|
||||
U64 coff_header_off = 0;
|
||||
COFF_Header coff_header = {0};
|
||||
if(pe_offset > 0)
|
||||
{
|
||||
U64 pe_magic_off = pe_offset;
|
||||
U32 pe_magic = 0;
|
||||
os_file_read_struct(file, pe_magic_off, &pe_magic);
|
||||
if(pe_magic == PE_MAGIC)
|
||||
{
|
||||
coff_header_off = pe_magic_off + sizeof(pe_magic);
|
||||
if(os_file_read_struct(file, coff_header_off, &coff_header))
|
||||
{
|
||||
got_coff_header = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get subsystem from PE header following COFF header
|
||||
PE_WindowsSubsystem subsystem = 0;
|
||||
{
|
||||
U64 opt_header_off = coff_header_off + sizeof(coff_header);
|
||||
switch(coff_header.machine)
|
||||
{
|
||||
default:{}break;
|
||||
case COFF_MachineType_X64:
|
||||
{
|
||||
PE_OptionalHeader32Plus hdr = {0};
|
||||
os_file_read_struct(file, opt_header_off, &hdr);
|
||||
subsystem = hdr.subsystem;
|
||||
}break;
|
||||
case COFF_MachineType_X86:
|
||||
{
|
||||
PE_OptionalHeader32 hdr = {0};
|
||||
os_file_read_struct(file, opt_header_off, &hdr);
|
||||
subsystem = hdr.subsystem;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: determine if we need a console depending on the subsystem
|
||||
if(subsystem == PE_WindowsSubsystem_WINDOWS_GUI)
|
||||
{
|
||||
needs_console = 0;
|
||||
}
|
||||
|
||||
os_file_close(file);
|
||||
}
|
||||
|
||||
//- rjf: produce environment strings
|
||||
String8 env = {0};
|
||||
{
|
||||
@@ -1291,7 +1360,10 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
|
||||
inherit_handles = 1;
|
||||
}
|
||||
PROCESS_INFORMATION process_info = {0};
|
||||
AllocConsole();
|
||||
if(needs_console)
|
||||
{
|
||||
AllocConsole();
|
||||
}
|
||||
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, creation_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
|
||||
{
|
||||
// check if we are 32-bit app, and just close it immediately
|
||||
@@ -1315,7 +1387,10 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
|
||||
{
|
||||
MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP);
|
||||
}
|
||||
FreeConsole();
|
||||
if(needs_console)
|
||||
{
|
||||
FreeConsole();
|
||||
}
|
||||
|
||||
//- rjf: eliminate all handles which have stuck around from the AllocConsole
|
||||
{
|
||||
|
||||
+83
-37
@@ -45,9 +45,9 @@ dr_hash_from_string(String8 string)
|
||||
//~ rjf: Fancy String Type Functions
|
||||
|
||||
internal void
|
||||
dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str)
|
||||
dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str)
|
||||
{
|
||||
DR_FancyStringNode *n = push_array_no_zero(arena, DR_FancyStringNode, 1);
|
||||
DR_FStrNode *n = push_array_no_zero(arena, DR_FStrNode, 1);
|
||||
MemoryCopyStruct(&n->v, str);
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
list->node_count += 1;
|
||||
@@ -55,7 +55,38 @@ dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString
|
||||
}
|
||||
|
||||
internal void
|
||||
dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push)
|
||||
dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string)
|
||||
{
|
||||
DR_FStr fstr = {string, *params};
|
||||
if(!fnt_tag_match(fnt_tag_zero(), overrides->font))
|
||||
{
|
||||
fstr.params.font = overrides->font;
|
||||
}
|
||||
if(overrides->raster_flags != 0)
|
||||
{
|
||||
fstr.params.raster_flags = overrides->raster_flags;
|
||||
}
|
||||
if(overrides->color.x != 0 || overrides->color.y != 0 || overrides->color.z != 0 || overrides->color.w != 0)
|
||||
{
|
||||
fstr.params.color = overrides->color;
|
||||
}
|
||||
if(overrides->size != 0)
|
||||
{
|
||||
fstr.params.size = overrides->size;
|
||||
}
|
||||
if(overrides->underline_thickness != 0)
|
||||
{
|
||||
fstr.params.underline_thickness = overrides->underline_thickness;
|
||||
}
|
||||
if(overrides->strikethrough_thickness != 0)
|
||||
{
|
||||
fstr.params.strikethrough_thickness = overrides->strikethrough_thickness;
|
||||
}
|
||||
dr_fstrs_push(arena, list, &fstr);
|
||||
}
|
||||
|
||||
internal void
|
||||
dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push)
|
||||
{
|
||||
if(dst->last != 0 && to_push->first != 0)
|
||||
{
|
||||
@@ -71,34 +102,51 @@ dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList
|
||||
MemoryZeroStruct(to_push);
|
||||
}
|
||||
|
||||
internal DR_FStrList
|
||||
dr_fstrs_copy(Arena *arena, DR_FStrList *src)
|
||||
{
|
||||
DR_FStrList dst = {0};
|
||||
for(DR_FStrNode *src_n = src->first; src_n != 0; src_n = src_n->next)
|
||||
{
|
||||
DR_FStr fstr = src_n->v;
|
||||
fstr.string = push_str8_copy(arena, fstr.string);
|
||||
dr_fstrs_push(arena, &dst, &fstr);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
internal String8
|
||||
dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list)
|
||||
dr_string_from_fstrs(Arena *arena, DR_FStrList *list)
|
||||
{
|
||||
String8 result = {0};
|
||||
result.size = list->total_size;
|
||||
result.str = push_array_no_zero(arena, U8, result.size);
|
||||
U64 idx = 0;
|
||||
for(DR_FancyStringNode *n = list->first; n != 0; n = n->next)
|
||||
for(DR_FStrNode *n = list->first; n != 0; n = n->next)
|
||||
{
|
||||
MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size);
|
||||
idx += n->v.string.size;
|
||||
if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font))
|
||||
{
|
||||
MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size);
|
||||
idx += n->v.string.size;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DR_FancyRunList
|
||||
dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs)
|
||||
internal DR_FRunList
|
||||
dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
DR_FancyRunList run_list = {0};
|
||||
DR_FRunList run_list = {0};
|
||||
F32 base_align_px = 0;
|
||||
for(DR_FancyStringNode *n = strs->first; n != 0; n = n->next)
|
||||
for(DR_FStrNode *n = strs->first; n != 0; n = n->next)
|
||||
{
|
||||
DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
|
||||
dst_n->v.run = fnt_push_run_from_string(arena, n->v.font, n->v.size, base_align_px, tab_size_px, flags, n->v.string);
|
||||
dst_n->v.color = n->v.color;
|
||||
dst_n->v.underline_thickness = n->v.underline_thickness;
|
||||
dst_n->v.strikethrough_thickness = n->v.strikethrough_thickness;
|
||||
DR_FRunNode *dst_n = push_array(arena, DR_FRunNode, 1);
|
||||
dst_n->v.run = fnt_push_run_from_string(arena, n->v.params.font, n->v.params.size, base_align_px, tab_size_px, n->v.params.raster_flags, n->v.string);
|
||||
dst_n->v.color = n->v.params.color;
|
||||
dst_n->v.underline_thickness = n->v.params.underline_thickness;
|
||||
dst_n->v.strikethrough_thickness = n->v.params.strikethrough_thickness;
|
||||
dst_n->v.icon = (fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font));
|
||||
SLLQueuePush(run_list.first, run_list.last, dst_n);
|
||||
run_list.node_count += 1;
|
||||
run_list.dim.x += dst_n->v.run.dim.x;
|
||||
@@ -109,20 +157,14 @@ dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_Rast
|
||||
return run_list;
|
||||
}
|
||||
|
||||
internal DR_FancyRunList
|
||||
dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src)
|
||||
internal Vec2F32
|
||||
dr_dim_from_fstrs(DR_FStrList *fstrs)
|
||||
{
|
||||
DR_FancyRunList dst = {0};
|
||||
for(DR_FancyRunNode *src_n = src->first; src_n != 0; src_n = src_n->next)
|
||||
{
|
||||
DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
|
||||
SLLQueuePush(dst.first, dst.last, dst_n);
|
||||
MemoryCopyStruct(&dst_n->v, &src_n->v);
|
||||
dst_n->v.run.pieces = fnt_piece_array_copy(arena, &src_n->v.run.pieces);
|
||||
dst.node_count += 1;
|
||||
}
|
||||
dst.dim = src->dim;
|
||||
return dst;
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
DR_FRunList fruns = dr_fruns_from_fstrs(scratch.arena, 0, fstrs);
|
||||
Vec2F32 dim = fruns.dim;
|
||||
scratch_end(scratch);
|
||||
return dim;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -131,7 +173,7 @@ dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src)
|
||||
// (Frame boundaries)
|
||||
|
||||
internal void
|
||||
dr_begin_frame(void)
|
||||
dr_begin_frame(FNT_Tag icon_font)
|
||||
{
|
||||
if(dr_thread_ctx == 0)
|
||||
{
|
||||
@@ -143,6 +185,7 @@ dr_begin_frame(void)
|
||||
arena_pop_to(dr_thread_ctx->arena, dr_thread_ctx->arena_frame_start_pos);
|
||||
dr_thread_ctx->free_bucket_selection = 0;
|
||||
dr_thread_ctx->top_bucket = 0;
|
||||
dr_thread_ctx->icon_font = icon_font;
|
||||
}
|
||||
|
||||
internal void
|
||||
@@ -455,7 +498,7 @@ dr_sub_bucket(DR_Bucket *bucket)
|
||||
//- rjf: text
|
||||
|
||||
internal void
|
||||
dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run)
|
||||
dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
@@ -467,9 +510,9 @@ dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run
|
||||
B32 trailer_found = 0;
|
||||
Vec4F32 last_color = {0};
|
||||
U64 byte_off = 0;
|
||||
for(DR_FancyRunNode *n = list->first; n != 0; n = n->next)
|
||||
for(DR_FRunNode *n = list->first; n != 0; n = n->next)
|
||||
{
|
||||
DR_FancyRun *fr = &n->v;
|
||||
DR_FRun *fr = &n->v;
|
||||
Rng1F32 pixel_range = {0};
|
||||
{
|
||||
pixel_range.min = 100000;
|
||||
@@ -558,7 +601,7 @@ dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run
|
||||
}
|
||||
|
||||
internal void
|
||||
dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
|
||||
dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
|
||||
{
|
||||
for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next)
|
||||
{
|
||||
@@ -573,9 +616,9 @@ dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x
|
||||
F32 advance = 0;
|
||||
F32 ascent = 0;
|
||||
F32 descent = 0;
|
||||
for(DR_FancyRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
|
||||
for(DR_FRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
|
||||
{
|
||||
DR_FancyRun *fr = &fr_n->v;
|
||||
DR_FRun *fr = &fr_n->v;
|
||||
FNT_Run *run = &fr->run;
|
||||
ascent = run->ascent;
|
||||
descent = run->descent;
|
||||
@@ -589,7 +632,10 @@ dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x
|
||||
pixel_range.min = Min(pre_advance, pixel_range.min);
|
||||
pixel_range.max = Max(post_advance, pixel_range.max);
|
||||
}
|
||||
byte_off += piece->decode_size;
|
||||
if(!fr->icon)
|
||||
{
|
||||
byte_off += piece->decode_size;
|
||||
}
|
||||
advance += piece->advance;
|
||||
}
|
||||
}
|
||||
|
||||
+41
-30
@@ -7,54 +7,62 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Fancy String Types
|
||||
|
||||
typedef struct DR_FancyString DR_FancyString;
|
||||
struct DR_FancyString
|
||||
typedef struct DR_FStrParams DR_FStrParams;
|
||||
struct DR_FStrParams
|
||||
{
|
||||
FNT_Tag font;
|
||||
String8 string;
|
||||
FNT_RasterFlags raster_flags;
|
||||
Vec4F32 color;
|
||||
F32 size;
|
||||
F32 underline_thickness;
|
||||
F32 strikethrough_thickness;
|
||||
};
|
||||
|
||||
typedef struct DR_FancyStringNode DR_FancyStringNode;
|
||||
struct DR_FancyStringNode
|
||||
typedef struct DR_FStr DR_FStr;
|
||||
struct DR_FStr
|
||||
{
|
||||
DR_FancyStringNode *next;
|
||||
DR_FancyString v;
|
||||
String8 string;
|
||||
DR_FStrParams params;
|
||||
};
|
||||
|
||||
typedef struct DR_FancyStringList DR_FancyStringList;
|
||||
struct DR_FancyStringList
|
||||
typedef struct DR_FStrNode DR_FStrNode;
|
||||
struct DR_FStrNode
|
||||
{
|
||||
DR_FancyStringNode *first;
|
||||
DR_FancyStringNode *last;
|
||||
DR_FStrNode *next;
|
||||
DR_FStr v;
|
||||
};
|
||||
|
||||
typedef struct DR_FStrList DR_FStrList;
|
||||
struct DR_FStrList
|
||||
{
|
||||
DR_FStrNode *first;
|
||||
DR_FStrNode *last;
|
||||
U64 node_count;
|
||||
U64 total_size;
|
||||
};
|
||||
|
||||
typedef struct DR_FancyRun DR_FancyRun;
|
||||
struct DR_FancyRun
|
||||
typedef struct DR_FRun DR_FRun;
|
||||
struct DR_FRun
|
||||
{
|
||||
FNT_Run run;
|
||||
Vec4F32 color;
|
||||
F32 underline_thickness;
|
||||
F32 strikethrough_thickness;
|
||||
B32 icon;
|
||||
};
|
||||
|
||||
typedef struct DR_FancyRunNode DR_FancyRunNode;
|
||||
struct DR_FancyRunNode
|
||||
typedef struct DR_FRunNode DR_FRunNode;
|
||||
struct DR_FRunNode
|
||||
{
|
||||
DR_FancyRunNode *next;
|
||||
DR_FancyRun v;
|
||||
DR_FRunNode *next;
|
||||
DR_FRun v;
|
||||
};
|
||||
|
||||
typedef struct DR_FancyRunList DR_FancyRunList;
|
||||
struct DR_FancyRunList
|
||||
typedef struct DR_FRunList DR_FRunList;
|
||||
struct DR_FRunList
|
||||
{
|
||||
DR_FancyRunNode *first;
|
||||
DR_FancyRunNode *last;
|
||||
DR_FRunNode *first;
|
||||
DR_FRunNode *last;
|
||||
U64 node_count;
|
||||
Vec2F32 dim;
|
||||
};
|
||||
@@ -91,6 +99,7 @@ struct DR_ThreadCtx
|
||||
{
|
||||
Arena *arena;
|
||||
U64 arena_frame_start_pos;
|
||||
FNT_Tag icon_font;
|
||||
DR_BucketSelectionNode *top_bucket;
|
||||
DR_BucketSelectionNode *free_bucket_selection;
|
||||
};
|
||||
@@ -108,19 +117,21 @@ internal U64 dr_hash_from_string(String8 string);
|
||||
////////////////////////////////
|
||||
//~ rjf: Fancy String Type Functions
|
||||
|
||||
internal void dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str);
|
||||
#define dr_fancy_string_list_push_new(arena, list, font_, size_, color_, string_, ...) dr_fancy_string_list_push((arena), (list), &(DR_FancyString){.font = (font_), .string = (string_), .color = (color_), .size = (size_), __VA_ARGS__})
|
||||
internal void dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push);
|
||||
internal String8 dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list);
|
||||
internal DR_FancyRunList dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs);
|
||||
internal DR_FancyRunList dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src);
|
||||
internal void dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str);
|
||||
internal void dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string);
|
||||
#define dr_fstrs_push_new(arena, list, params, string, ...) dr_fstrs_push_new_((arena), (list), (params), &(DR_FStrParams){.size = 0, __VA_ARGS__}, (string))
|
||||
internal void dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push);
|
||||
internal DR_FStrList dr_fstrs_copy(Arena *arena, DR_FStrList *src);
|
||||
internal String8 dr_string_from_fstrs(Arena *arena, DR_FStrList *list);
|
||||
internal DR_FRunList dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs);
|
||||
internal Vec2F32 dr_dim_from_fstrs(DR_FStrList *fstrs);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level API
|
||||
//
|
||||
// (Frame boundaries & bucket submission)
|
||||
|
||||
internal void dr_begin_frame(void);
|
||||
internal void dr_begin_frame(FNT_Tag icon_font);
|
||||
internal void dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket);
|
||||
|
||||
////////////////////////////////
|
||||
@@ -184,8 +195,8 @@ internal void dr_sub_bucket(DR_Bucket *bucket);
|
||||
//~ rjf: Draw Call Helpers
|
||||
|
||||
//- rjf: text
|
||||
internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run);
|
||||
internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
|
||||
internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run);
|
||||
internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
|
||||
internal void dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run);
|
||||
internal void dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string);
|
||||
|
||||
|
||||
+6
-1
@@ -71,7 +71,7 @@ E_TypeKindTable:
|
||||
{IncompleteEnum "enum" 0 }
|
||||
{Bitfield "bitfield" 0 }
|
||||
{Variadic "variadic" 0 }
|
||||
{Collection "collection" 0 }
|
||||
{Set "set" 0 }
|
||||
}
|
||||
|
||||
@table(name op_kind precedence string op_pre op_sep op_pos)
|
||||
@@ -116,6 +116,8 @@ E_ExprKindTable:
|
||||
|
||||
{ Ternary Null 0 "? " "" "?" ":"}
|
||||
|
||||
{ Call Null 0 "()" "(" "," ")"}
|
||||
|
||||
{ LeafBytecode Null 0 "bytecode" "" "" "" }
|
||||
{ LeafMember Null 0 "member" "" "" "" }
|
||||
{ LeafStringLiteral Null 0 "string_literal" "" "" "" }
|
||||
@@ -125,6 +127,7 @@ E_ExprKindTable:
|
||||
{ LeafF32 Null 0 "F32" "" "" "" }
|
||||
{ LeafIdent Null 0 "leaf_ident" "" "" "" }
|
||||
{ LeafOffset Null 0 "leaf_offset" "" "" "" }
|
||||
{ LeafValue Null 0 "leaf_value" "" "" "" }
|
||||
{ LeafFilePath Null 0 "leaf_filepath" "" "" "" }
|
||||
|
||||
{ TypeIdent Null 0 "type_ident" "" "" "" }
|
||||
@@ -133,6 +136,8 @@ E_ExprKindTable:
|
||||
{ Func Null 0 "function" "" "" "" }
|
||||
|
||||
{ Define Binary 13 "=" "" "=" "" }
|
||||
|
||||
{ Tag Null 0 "=>" "=>" "," "" }
|
||||
}
|
||||
|
||||
@table(name display_string)
|
||||
|
||||
+80
-86
@@ -7,26 +7,35 @@
|
||||
internal E_Eval
|
||||
e_eval_from_expr(Arena *arena, E_Expr *expr)
|
||||
{
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
|
||||
E_OpList oplist = e_oplist_from_irtree(arena, irtree.root);
|
||||
String8 bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
E_Interpretation interp = e_interpret(bytecode);
|
||||
E_Space zero_space = {0};
|
||||
E_Space space = (MemoryMatchStruct(&zero_space, &irtree.space) ? e_interpret_ctx->primary_space : irtree.space);
|
||||
E_ExprChain exprs = {expr, expr};
|
||||
E_Eval result = e_eval_from_exprs(arena, exprs);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_eval_from_exprs(Arena *arena, E_ExprChain exprs)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, exprs.last);
|
||||
E_LookupRuleTagPair lookup = e_lookup_rule_tag_pair_from_expr_irtree(exprs.last, &irtree);
|
||||
E_OpList oplist = e_oplist_from_irtree(arena, irtree.root);
|
||||
String8 bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
E_Interpretation interp = e_interpret(bytecode);
|
||||
E_Eval eval =
|
||||
{
|
||||
.value = interp.value,
|
||||
.mode = irtree.mode,
|
||||
.space = space,
|
||||
.expr = expr,
|
||||
.type_key = irtree.type_key,
|
||||
.code = interp.code,
|
||||
.value = interp.value,
|
||||
.space = interp.space,
|
||||
.exprs = exprs,
|
||||
.irtree = irtree,
|
||||
.lookup_rule_tag = lookup,
|
||||
.code = interp.code,
|
||||
};
|
||||
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
|
||||
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
|
||||
{
|
||||
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
|
||||
}
|
||||
ProfEnd();
|
||||
return eval;
|
||||
}
|
||||
|
||||
@@ -35,26 +44,39 @@ e_eval_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
E_TokenArray tokens = e_token_array_from_text(arena, string);
|
||||
E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens);
|
||||
E_Eval eval = e_eval_from_expr(arena, parse.expr);
|
||||
E_Eval eval = e_eval_from_exprs(arena, parse.exprs);
|
||||
e_msg_list_concat_in_place(&eval.msgs, &parse.msgs);
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_eval_from_stringf(Arena *arena, char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
E_Eval eval = e_eval_from_string(arena, string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_autoresolved_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
if(e_parse_ctx &&
|
||||
if(e_parse_state &&
|
||||
e_interpret_ctx &&
|
||||
e_parse_ctx->modules_count > 0 &&
|
||||
e_parse_state->ctx->modules_count > 0 &&
|
||||
e_interpret_ctx->module_base != 0 &&
|
||||
(e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S64)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U64)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S32)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U32))))
|
||||
(e_type_key_match(eval.irtree.type_key, e_type_key_basic(E_TypeKind_S64)) ||
|
||||
e_type_key_match(eval.irtree.type_key, e_type_key_basic(E_TypeKind_U64)) ||
|
||||
e_type_key_match(eval.irtree.type_key, e_type_key_basic(E_TypeKind_S32)) ||
|
||||
e_type_key_match(eval.irtree.type_key, e_type_key_basic(E_TypeKind_U32))))
|
||||
{
|
||||
U64 vaddr = eval.value.u64;
|
||||
U64 voff = vaddr - e_interpret_ctx->module_base[0];
|
||||
RDI_Parsed *rdi = e_parse_ctx->primary_module->rdi;
|
||||
RDI_Parsed *rdi = e_parse_state->ctx->primary_module->rdi;
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, voff);
|
||||
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff);
|
||||
RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff);
|
||||
@@ -63,7 +85,7 @@ e_autoresolved_eval_from_eval(E_Eval eval)
|
||||
if(string_idx == 0) { string_idx = gvar->name_string_idx; }
|
||||
if(string_idx != 0)
|
||||
{
|
||||
eval.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, e_type_key_basic(E_TypeKind_Void), 0);
|
||||
eval.irtree.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, e_type_key_basic(E_TypeKind_Void), 1, 0);
|
||||
}
|
||||
}
|
||||
return eval;
|
||||
@@ -72,7 +94,7 @@ e_autoresolved_eval_from_eval(E_Eval eval)
|
||||
internal E_Eval
|
||||
e_dynamically_typed_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
E_TypeKey type_key = eval.type_key;
|
||||
E_TypeKey type_key = eval.irtree.type_key;
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
if(e_type_state != 0 &&
|
||||
e_interpret_ctx != 0 &&
|
||||
@@ -85,7 +107,7 @@ e_dynamically_typed_eval_from_eval(E_Eval eval)
|
||||
E_TypeKind ptee_type_kind = e_type_kind_from_key(ptee_type_key);
|
||||
if(ptee_type_kind == E_TypeKind_Struct || ptee_type_kind == E_TypeKind_Class)
|
||||
{
|
||||
E_Type *ptee_type = e_type_from_key(scratch.arena, ptee_type_key);
|
||||
E_Type *ptee_type = e_type_from_key__cached(ptee_type_key);
|
||||
B32 has_vtable = 0;
|
||||
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
|
||||
{
|
||||
@@ -129,8 +151,8 @@ e_dynamically_typed_eval_from_eval(E_Eval eval)
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
|
||||
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
|
||||
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
|
||||
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 0);
|
||||
eval.type_key = ptr_to_derived_type_key;
|
||||
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0);
|
||||
eval.irtree.type_key = ptr_to_derived_type_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,13 +167,13 @@ internal E_Eval
|
||||
e_value_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
if(eval.mode == E_Mode_Offset)
|
||||
if(eval.irtree.mode == E_Mode_Offset)
|
||||
{
|
||||
E_TypeKey type_key = e_type_unwrap(eval.type_key);
|
||||
E_TypeKey type_key = e_type_unwrap(eval.irtree.type_key);
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
if(type_kind == E_TypeKind_Array)
|
||||
{
|
||||
eval.mode = E_Mode_Value;
|
||||
eval.irtree.mode = E_Mode_Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -162,13 +184,13 @@ e_value_eval_from_eval(E_Eval eval)
|
||||
type_byte_size <= sizeof(E_Value) &&
|
||||
e_space_read(eval.space, &eval.value, value_vaddr_range))
|
||||
{
|
||||
eval.mode = E_Mode_Value;
|
||||
eval.irtree.mode = E_Mode_Value;
|
||||
|
||||
// rjf: mask&shift, for bitfields
|
||||
if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64))
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *type = e_type_from_key(scratch.arena, type_key);
|
||||
E_Type *type = e_type_from_key__cached(type_key);
|
||||
U64 valid_bits_mask = 0;
|
||||
for(U64 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
@@ -176,7 +198,7 @@ e_value_eval_from_eval(E_Eval eval)
|
||||
}
|
||||
eval.value.u64 = eval.value.u64 >> type->off;
|
||||
eval.value.u64 = eval.value.u64 & valid_bits_mask;
|
||||
eval.type_key = type->direct_type_key;
|
||||
eval.irtree.type_key = type->direct_type_key;
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@@ -198,65 +220,37 @@ e_value_eval_from_eval(E_Eval eval)
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_element_eval_from_array_eval_index(E_Eval eval, U64 index)
|
||||
internal E_Value
|
||||
e_value_from_string(String8 string)
|
||||
{
|
||||
E_Eval result = {0};
|
||||
result.mode = eval.mode;
|
||||
result.space = eval.space;
|
||||
result.type_key = e_type_direct_from_key(eval.type_key);
|
||||
result.code = eval.code;
|
||||
result.msgs = eval.msgs;
|
||||
U64 element_size = e_type_byte_size_from_key(result.type_key);
|
||||
switch(eval.mode)
|
||||
{
|
||||
default:{}break;
|
||||
case E_Mode_Value:
|
||||
if(element_size <= sizeof(E_Value) &&
|
||||
index < sizeof(E_Value)/element_size)
|
||||
{
|
||||
MemoryCopy((U8 *)(&result.value.u512[0]),
|
||||
(U8 *)(&eval.value.u512[0]) + index*element_size,
|
||||
element_size);
|
||||
}break;
|
||||
case E_Mode_Offset:
|
||||
{
|
||||
result.value.u64 = eval.value.u64 + element_size*index;
|
||||
}break;
|
||||
}
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Eval eval = e_eval_from_string(scratch.arena, string);
|
||||
E_Eval value_eval = e_value_eval_from_eval(eval);
|
||||
E_Value result = value_eval.value;
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name)
|
||||
internal E_Value
|
||||
e_value_from_stringf(char *fmt, ...)
|
||||
{
|
||||
E_Eval result = {0};
|
||||
{
|
||||
E_Member member = e_type_member_from_key_name__cached(eval.type_key, member_name);
|
||||
if(member.kind != E_MemberKind_Null)
|
||||
{
|
||||
result.mode = eval.mode;
|
||||
result.space = eval.space;
|
||||
result.type_key = member.type_key;
|
||||
result.code = eval.code;
|
||||
result.msgs = eval.msgs;
|
||||
switch(eval.mode)
|
||||
{
|
||||
default:{}break;
|
||||
case E_Mode_Value:
|
||||
if(member.off < sizeof(eval.value))
|
||||
{
|
||||
U64 member_size = e_type_byte_size_from_key(member.type_key);
|
||||
MemoryCopy((U8 *)(&result.value.u512[0]),
|
||||
(U8 *)(&eval.value.u512[0]) + member.off,
|
||||
Min(member_size, sizeof(eval.value) - member.off));
|
||||
}break;
|
||||
case E_Mode_Offset:
|
||||
{
|
||||
result.value.u64 = eval.value.u64 + member.off;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
E_Value result = e_value_from_string(string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal E_Value
|
||||
e_value_from_expr(E_Expr *expr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Eval eval = e_eval_from_expr(scratch.arena, expr);
|
||||
E_Eval value_eval = e_value_eval_from_eval(eval);
|
||||
E_Value result = value_eval.value;
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
@@ -11,10 +11,10 @@ typedef struct E_Eval E_Eval;
|
||||
struct E_Eval
|
||||
{
|
||||
E_Value value;
|
||||
E_Mode mode;
|
||||
E_Space space;
|
||||
E_Expr *expr;
|
||||
E_TypeKey type_key;
|
||||
E_ExprChain exprs;
|
||||
E_IRTreeAndType irtree;
|
||||
E_LookupRuleTagPair lookup_rule_tag;
|
||||
E_InterpretationCode code;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
@@ -23,11 +23,14 @@ struct E_Eval
|
||||
//~ rjf: Bundled Evaluation Functions
|
||||
|
||||
internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr);
|
||||
internal E_Eval e_eval_from_exprs(Arena *arena, E_ExprChain exprs);
|
||||
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
|
||||
internal E_Eval e_eval_from_stringf(Arena *arena, char *fmt, ...);
|
||||
internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_value_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_element_eval_from_array_eval_index(E_Eval eval, U64 index);
|
||||
internal E_Eval e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name);
|
||||
internal E_Value e_value_from_string(String8 string);
|
||||
internal E_Value e_value_from_stringf(char *fmt, ...);
|
||||
internal E_Value e_value_from_expr(E_Expr *expr);
|
||||
|
||||
#endif // EVAL_BUNDLES_H
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helper Functions
|
||||
|
||||
#if !defined(XXH_IMPLEMENTATION)
|
||||
# define XXH_IMPLEMENTATION
|
||||
# define XXH_STATIC_LINKING_ONLY
|
||||
# include "third_party/xxHash/xxhash.h"
|
||||
#endif
|
||||
|
||||
internal U64
|
||||
e_hash_from_string(U64 seed, String8 string)
|
||||
{
|
||||
U64 result = seed;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
U64 result = XXH3_64bits_withSeed(string.str, string.size, seed);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,9 @@ typedef U64 E_SpaceKind;
|
||||
enum
|
||||
{
|
||||
E_SpaceKind_Null,
|
||||
E_SpaceKind_File,
|
||||
E_SpaceKind_FileSystem,
|
||||
E_SpaceKind_HashStoreKey,
|
||||
E_SpaceKind_FirstUserDefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -99,7 +99,11 @@ e_interpret(String8 bytecode)
|
||||
U64 stack_cap = 128; // TODO(rjf): scan bytecode; determine maximum stack depth
|
||||
E_Value *stack = push_array_no_zero(scratch.arena, E_Value, stack_cap);
|
||||
U64 stack_count = 0;
|
||||
E_Space selected_space = e_interpret_ctx->primary_space;
|
||||
E_Space selected_space = {0};
|
||||
if(bytecode.size != 0)
|
||||
{
|
||||
selected_space = e_interpret_ctx->primary_space;
|
||||
}
|
||||
|
||||
//- rjf: iterate bytecode & perform ops
|
||||
U8 *ptr = bytecode.str;
|
||||
@@ -115,7 +119,7 @@ e_interpret(String8 bytecode)
|
||||
}
|
||||
else switch(op)
|
||||
{
|
||||
case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
|
||||
case E_IRExtKind_SetSpace: {ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
|
||||
default:
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
@@ -853,6 +857,7 @@ e_interpret(String8 bytecode)
|
||||
{
|
||||
result.value = stack[0];
|
||||
}
|
||||
result.space = selected_space;
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef struct E_Interpretation E_Interpretation;
|
||||
struct E_Interpretation
|
||||
{
|
||||
E_Value value;
|
||||
E_Space space;
|
||||
E_InterpretationCode code;
|
||||
};
|
||||
|
||||
|
||||
+1856
-317
File diff suppressed because it is too large
Load Diff
+362
-6
@@ -42,6 +42,7 @@ struct E_IRNode
|
||||
E_IRNode *last;
|
||||
E_IRNode *next;
|
||||
RDI_EvalOp op;
|
||||
E_Space space;
|
||||
String8 string;
|
||||
E_Value value;
|
||||
};
|
||||
@@ -51,25 +52,325 @@ struct E_IRTreeAndType
|
||||
{
|
||||
E_IRNode *root;
|
||||
E_TypeKey type_key;
|
||||
E_Member member;
|
||||
E_Mode mode;
|
||||
E_Space space;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Context
|
||||
//~ rjf: Member/Index Lookup Hooks
|
||||
|
||||
typedef struct E_LookupInfo E_LookupInfo;
|
||||
struct E_LookupInfo
|
||||
{
|
||||
void *user_data;
|
||||
U64 named_expr_count;
|
||||
U64 idxed_expr_count;
|
||||
};
|
||||
|
||||
typedef struct E_LookupAccess E_LookupAccess;
|
||||
struct E_LookupAccess
|
||||
{
|
||||
E_IRTreeAndType irtree_and_type;
|
||||
};
|
||||
|
||||
#define E_LOOKUP_INFO_FUNCTION_SIG(name) E_LookupInfo name(Arena *arena, E_IRTreeAndType *lhs, E_Expr *tag, String8 filter)
|
||||
#define E_LOOKUP_INFO_FUNCTION_NAME(name) e_lookup_info_##name
|
||||
#define E_LOOKUP_INFO_FUNCTION_DEF(name) internal E_LOOKUP_INFO_FUNCTION_SIG(E_LOOKUP_INFO_FUNCTION_NAME(name))
|
||||
typedef E_LOOKUP_INFO_FUNCTION_SIG(E_LookupInfoFunctionType);
|
||||
E_LOOKUP_INFO_FUNCTION_DEF(default);
|
||||
|
||||
#define E_LOOKUP_ACCESS_FUNCTION_SIG(name) E_LookupAccess name(Arena *arena, E_ExprKind kind, E_Expr *lhs, E_Expr *rhs, E_Expr *tag, void *user_data)
|
||||
#define E_LOOKUP_ACCESS_FUNCTION_NAME(name) e_lookup_access_##name
|
||||
#define E_LOOKUP_ACCESS_FUNCTION_DEF(name) internal E_LOOKUP_ACCESS_FUNCTION_SIG(E_LOOKUP_ACCESS_FUNCTION_NAME(name))
|
||||
typedef E_LOOKUP_ACCESS_FUNCTION_SIG(E_LookupAccessFunctionType);
|
||||
E_LOOKUP_ACCESS_FUNCTION_DEF(default);
|
||||
|
||||
#define E_LOOKUP_RANGE_FUNCTION_SIG(name) void name(Arena *arena, E_Expr *lhs, E_Expr *tag, String8 filter, Rng1U64 idx_range, E_Expr **exprs, String8 *exprs_strings, void *user_data)
|
||||
#define E_LOOKUP_RANGE_FUNCTION_NAME(name) e_lookup_range_##name
|
||||
#define E_LOOKUP_RANGE_FUNCTION_DEF(name) internal E_LOOKUP_RANGE_FUNCTION_SIG(E_LOOKUP_RANGE_FUNCTION_NAME(name))
|
||||
typedef E_LOOKUP_RANGE_FUNCTION_SIG(E_LookupRangeFunctionType);
|
||||
E_LOOKUP_RANGE_FUNCTION_DEF(default);
|
||||
|
||||
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(U64 num, void *user_data)
|
||||
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name) e_lookup_id_from_num_##name
|
||||
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(name) internal E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name))
|
||||
typedef E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LookupIDFromNumFunctionType);
|
||||
E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(default);
|
||||
|
||||
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(U64 id, void *user_data)
|
||||
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name) e_lookup_num_from_id_##name
|
||||
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(name) internal E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name))
|
||||
typedef E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LookupNumFromIDFunctionType);
|
||||
E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(default);
|
||||
|
||||
typedef struct E_LookupRule E_LookupRule;
|
||||
struct E_LookupRule
|
||||
{
|
||||
String8 name;
|
||||
E_LookupInfoFunctionType *info;
|
||||
E_LookupAccessFunctionType *access;
|
||||
E_LookupRangeFunctionType *range;
|
||||
E_LookupIDFromNumFunctionType *id_from_num;
|
||||
E_LookupNumFromIDFunctionType *num_from_id;
|
||||
};
|
||||
|
||||
typedef struct E_LookupRuleNode E_LookupRuleNode;
|
||||
struct E_LookupRuleNode
|
||||
{
|
||||
E_LookupRuleNode *next;
|
||||
E_LookupRule v;
|
||||
};
|
||||
|
||||
typedef struct E_LookupRuleSlot E_LookupRuleSlot;
|
||||
struct E_LookupRuleSlot
|
||||
{
|
||||
E_LookupRuleNode *first;
|
||||
E_LookupRuleNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_LookupRuleMap E_LookupRuleMap;
|
||||
struct E_LookupRuleMap
|
||||
{
|
||||
E_LookupRuleSlot *slots;
|
||||
U64 slots_count;
|
||||
};
|
||||
|
||||
typedef struct E_LookupRuleTagPair E_LookupRuleTagPair;
|
||||
struct E_LookupRuleTagPair
|
||||
{
|
||||
E_LookupRule *rule;
|
||||
E_Expr *tag;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Generation Hooks
|
||||
|
||||
#define E_IRGEN_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr, E_Expr *tag)
|
||||
#define E_IRGEN_FUNCTION_NAME(name) e_irgen_##name
|
||||
#define E_IRGEN_FUNCTION_DEF(name) internal E_IRGEN_FUNCTION_SIG(E_IRGEN_FUNCTION_NAME(name))
|
||||
typedef E_IRGEN_FUNCTION_SIG(E_IRGenFunctionType);
|
||||
E_IRGEN_FUNCTION_DEF(default);
|
||||
|
||||
typedef struct E_IRGenRule E_IRGenRule;
|
||||
struct E_IRGenRule
|
||||
{
|
||||
String8 name;
|
||||
E_IRGenFunctionType *irgen;
|
||||
};
|
||||
|
||||
typedef struct E_IRGenRuleNode E_IRGenRuleNode;
|
||||
struct E_IRGenRuleNode
|
||||
{
|
||||
E_IRGenRuleNode *next;
|
||||
E_IRGenRule v;
|
||||
};
|
||||
|
||||
typedef struct E_IRGenRuleSlot E_IRGenRuleSlot;
|
||||
struct E_IRGenRuleSlot
|
||||
{
|
||||
E_IRGenRuleNode *first;
|
||||
E_IRGenRuleNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_IRGenRuleMap E_IRGenRuleMap;
|
||||
struct E_IRGenRuleMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_IRGenRuleSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Pattern -> Hook Key Data Structure (Auto View Rules)
|
||||
|
||||
typedef struct E_AutoHookNode E_AutoHookNode;
|
||||
struct E_AutoHookNode
|
||||
{
|
||||
E_AutoHookNode *hash_next;
|
||||
E_AutoHookNode *pattern_order_next;
|
||||
E_TypeKey type_key;
|
||||
String8List type_pattern_parts;
|
||||
E_ExprChain tag_exprs;
|
||||
};
|
||||
|
||||
typedef struct E_AutoHookSlot E_AutoHookSlot;
|
||||
struct E_AutoHookSlot
|
||||
{
|
||||
E_AutoHookNode *first;
|
||||
E_AutoHookNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_AutoHookMap E_AutoHookMap;
|
||||
struct E_AutoHookMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_AutoHookSlot *slots;
|
||||
E_AutoHookNode *first_pattern;
|
||||
E_AutoHookNode *last_pattern;
|
||||
};
|
||||
|
||||
typedef struct E_AutoHookParams E_AutoHookParams;
|
||||
struct E_AutoHookParams
|
||||
{
|
||||
E_TypeKey type_key;
|
||||
String8 type_pattern;
|
||||
String8 tag_expr_string;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Used Tag Map Data Structure
|
||||
|
||||
typedef struct E_UsedTagNode E_UsedTagNode;
|
||||
struct E_UsedTagNode
|
||||
{
|
||||
E_UsedTagNode *next;
|
||||
E_UsedTagNode *prev;
|
||||
E_Expr *tag;
|
||||
};
|
||||
|
||||
typedef struct E_UsedTagSlot E_UsedTagSlot;
|
||||
struct E_UsedTagSlot
|
||||
{
|
||||
E_UsedTagNode *first;
|
||||
E_UsedTagNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_UsedTagMap E_UsedTagMap;
|
||||
struct E_UsedTagMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_UsedTagSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Key -> Auto Hook Expr List Cache
|
||||
|
||||
typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode;
|
||||
struct E_TypeAutoHookCacheNode
|
||||
{
|
||||
E_TypeAutoHookCacheNode *next;
|
||||
E_TypeKey key;
|
||||
E_ExprList exprs;
|
||||
};
|
||||
|
||||
typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot;
|
||||
struct E_TypeAutoHookCacheSlot
|
||||
{
|
||||
E_TypeAutoHookCacheNode *first;
|
||||
E_TypeAutoHookCacheNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap;
|
||||
struct E_TypeAutoHookCacheMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_TypeAutoHookCacheSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Evaluated String ID Map
|
||||
|
||||
typedef struct E_StringIDNode E_StringIDNode;
|
||||
struct E_StringIDNode
|
||||
{
|
||||
E_StringIDNode *hash_next;
|
||||
E_StringIDNode *id_next;
|
||||
U64 id;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
typedef struct E_StringIDSlot E_StringIDSlot;
|
||||
struct E_StringIDSlot
|
||||
{
|
||||
E_StringIDNode *first;
|
||||
E_StringIDNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_StringIDMap E_StringIDMap;
|
||||
struct E_StringIDMap
|
||||
{
|
||||
U64 id_slots_count;
|
||||
E_StringIDSlot *id_slots;
|
||||
U64 hash_slots_count;
|
||||
E_StringIDSlot *hash_slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Context
|
||||
|
||||
typedef struct E_IRCtx E_IRCtx;
|
||||
struct E_IRCtx
|
||||
{
|
||||
E_String2ExprMap *macro_map;
|
||||
E_LookupRuleMap *lookup_rule_map;
|
||||
E_IRGenRuleMap *irgen_rule_map;
|
||||
E_AutoHookMap *auto_hook_map;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR State
|
||||
|
||||
typedef struct E_IRTreeAndTypeCacheNode E_IRTreeAndTypeCacheNode;
|
||||
struct E_IRTreeAndTypeCacheNode
|
||||
{
|
||||
E_IRTreeAndTypeCacheNode *next;
|
||||
E_Expr *expr;
|
||||
E_IRTreeAndType irtree_and_type;
|
||||
};
|
||||
|
||||
typedef struct E_IRTreeAndTypeCacheSlot E_IRTreeAndTypeCacheSlot;
|
||||
struct E_IRTreeAndTypeCacheSlot
|
||||
{
|
||||
E_IRTreeAndTypeCacheNode *first;
|
||||
E_IRTreeAndTypeCacheNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_IRState E_IRState;
|
||||
struct E_IRState
|
||||
{
|
||||
Arena *arena;
|
||||
U64 arena_eval_start_pos;
|
||||
|
||||
// rjf: ir context
|
||||
E_IRCtx *ctx;
|
||||
|
||||
// rjf: caches
|
||||
E_UsedTagMap *used_tag_map;
|
||||
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
|
||||
U64 irtree_and_type_cache_slots_count;
|
||||
E_IRTreeAndTypeCacheSlot *irtree_and_type_cache_slots;
|
||||
U64 string_id_gen;
|
||||
E_StringIDMap *string_id_map;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
local_persist read_only E_LookupRule e_lookup_rule__nil =
|
||||
{
|
||||
str8_lit_comp("nil"),
|
||||
E_LOOKUP_INFO_FUNCTION_NAME(default),
|
||||
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
|
||||
E_LOOKUP_RANGE_FUNCTION_NAME(default),
|
||||
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
|
||||
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
|
||||
};
|
||||
local_persist read_only E_LookupRule e_lookup_rule__default =
|
||||
{
|
||||
str8_lit_comp("default"),
|
||||
E_LOOKUP_INFO_FUNCTION_NAME(default),
|
||||
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
|
||||
E_LOOKUP_RANGE_FUNCTION_NAME(default),
|
||||
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
|
||||
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
|
||||
};
|
||||
local_persist read_only E_IRGenRule e_irgen_rule__default =
|
||||
{
|
||||
str8_lit_comp("default"),
|
||||
E_IRGEN_FUNCTION_NAME(default),
|
||||
};
|
||||
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
|
||||
thread_static E_IRCtx *e_ir_ctx = 0;
|
||||
thread_static E_IRState *e_ir_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expr Kind Enum Functions
|
||||
@@ -83,6 +384,39 @@ internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
|
||||
internal E_IRCtx *e_selected_ir_ctx(void);
|
||||
internal void e_select_ir_ctx(E_IRCtx *ctx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Lookups
|
||||
|
||||
internal E_LookupRuleMap e_lookup_rule_map_make(Arena *arena, U64 slots_count);
|
||||
internal void e_lookup_rule_map_insert(Arena *arena, E_LookupRuleMap *map, E_LookupRule *rule);
|
||||
#define e_lookup_rule_map_insert_new(arena, map, name_, ...) e_lookup_rule_map_insert((arena), (map), &(E_LookupRule){.name = (name_), __VA_ARGS__})
|
||||
|
||||
internal E_LookupRule *e_lookup_rule_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Gen Rules
|
||||
|
||||
internal E_IRGenRuleMap e_irgen_rule_map_make(Arena *arena, U64 slots_count);
|
||||
internal void e_irgen_rule_map_insert(Arena *arena, E_IRGenRuleMap *map, E_IRGenRule *rule);
|
||||
#define e_irgen_rule_map_insert_new(arena, map, name_, ...) e_irgen_rule_map_insert((arena), (map), &(E_IRGenRule){.name = (name_), __VA_ARGS__})
|
||||
|
||||
internal E_IRGenRule *e_irgen_rule_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Auto Hooks
|
||||
|
||||
internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count);
|
||||
internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params);
|
||||
#define e_auto_hook_map_insert_new(arena, map, ...) e_auto_hook_map_insert_new_((arena), (map), &(E_AutoHookParams){.type_key = zero_struct, __VA_ARGS__})
|
||||
internal E_ExprList e_auto_hook_tag_exprs_from_type_key(Arena *arena, E_TypeKey type_key);
|
||||
internal E_ExprList e_auto_hook_tag_exprs_from_type_key__cached(E_TypeKey type_key);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Evaluated String IDs
|
||||
|
||||
internal U64 e_id_from_string(String8 string);
|
||||
internal String8 e_string_from_id(U64 id);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR-ization Functions
|
||||
|
||||
@@ -101,6 +435,7 @@ internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
|
||||
|
||||
//- rjf: ir subtree building helpers
|
||||
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
|
||||
internal E_IRNode *e_irtree_leaf_u128(Arena *arena, U128 u128);
|
||||
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
|
||||
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
|
||||
@@ -108,18 +443,39 @@ internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l,
|
||||
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
|
||||
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
|
||||
internal E_IRNode *e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c);
|
||||
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_Space space, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
|
||||
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
|
||||
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Space from_space, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
|
||||
|
||||
//- rjf: rule tag poison checking
|
||||
internal B32 e_tag_is_poisoned(E_Expr *tag);
|
||||
internal void e_tag_poison(E_Expr *tag);
|
||||
internal void e_tag_unpoison(E_Expr *tag);
|
||||
|
||||
//- rjf: top-level irtree/type extraction
|
||||
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
|
||||
|
||||
//- rjf: irtree -> linear ops/bytecode
|
||||
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
|
||||
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out);
|
||||
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
|
||||
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
|
||||
|
||||
//- rjf: leaf-bytecode expression extensions
|
||||
internal E_Expr *e_expr_irext_member_access(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, String8 member_name);
|
||||
internal E_Expr *e_expr_irext_array_index(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, U64 index);
|
||||
internal E_Expr *e_expr_irext_deref(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree);
|
||||
internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_TypeKey type_key);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IRified Expression Cache
|
||||
|
||||
internal E_IRTreeAndType e_irtree_and_type_from_expr__cached(E_Expr *expr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression & IR-Tree => Lookup Rule
|
||||
|
||||
internal E_LookupRuleTagPair e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree);
|
||||
|
||||
#endif // EVAL_IR_H
|
||||
|
||||
+1193
-988
File diff suppressed because it is too large
Load Diff
+69
-14
@@ -52,6 +52,8 @@ struct E_Expr
|
||||
{
|
||||
E_Expr *first;
|
||||
E_Expr *last;
|
||||
E_Expr *first_tag;
|
||||
E_Expr *last_tag;
|
||||
E_Expr *next;
|
||||
E_Expr *prev;
|
||||
E_Expr *ref;
|
||||
@@ -62,9 +64,32 @@ struct E_Expr
|
||||
E_TypeKey type_key;
|
||||
E_Value value;
|
||||
String8 string;
|
||||
String8 qualifier;
|
||||
String8 bytecode;
|
||||
};
|
||||
|
||||
typedef struct E_ExprChain E_ExprChain;
|
||||
struct E_ExprChain
|
||||
{
|
||||
E_Expr *first;
|
||||
E_Expr *last;
|
||||
};
|
||||
|
||||
typedef struct E_ExprNode E_ExprNode;
|
||||
struct E_ExprNode
|
||||
{
|
||||
E_ExprNode *next;
|
||||
E_Expr *v;
|
||||
};
|
||||
|
||||
typedef struct E_ExprList E_ExprList;
|
||||
struct E_ExprList
|
||||
{
|
||||
E_ExprNode *first;
|
||||
E_ExprNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Map Types
|
||||
|
||||
@@ -128,6 +153,17 @@ struct E_String2ExprMap
|
||||
E_String2ExprMapSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Results
|
||||
|
||||
typedef struct E_Parse E_Parse;
|
||||
struct E_Parse
|
||||
{
|
||||
E_Token *last_token;
|
||||
E_ExprChain exprs;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Context
|
||||
|
||||
@@ -152,14 +188,33 @@ struct E_ParseCtx
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Results
|
||||
//~ rjf: Parse State (stateful thread-local caching mechanisms, not provided by user)
|
||||
|
||||
typedef struct E_Parse E_Parse;
|
||||
struct E_Parse
|
||||
typedef struct E_ParseCacheNode E_ParseCacheNode;
|
||||
struct E_ParseCacheNode
|
||||
{
|
||||
E_Token *last_token;
|
||||
E_Expr *expr;
|
||||
E_MsgList msgs;
|
||||
E_ParseCacheNode *next;
|
||||
String8 string;
|
||||
E_Parse parse;
|
||||
};
|
||||
|
||||
typedef struct E_ParseCacheSlot E_ParseCacheSlot;
|
||||
struct E_ParseCacheSlot
|
||||
{
|
||||
E_ParseCacheNode *first;
|
||||
E_ParseCacheNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_ParseState E_ParseState;
|
||||
struct E_ParseState
|
||||
{
|
||||
Arena *arena;
|
||||
U64 arena_eval_start_pos;
|
||||
E_ParseCtx *ctx;
|
||||
|
||||
// rjf: string -> parse cache
|
||||
E_ParseCacheSlot *parse_cache_slots;
|
||||
U64 parse_cache_slots_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -167,8 +222,8 @@ struct E_Parse
|
||||
|
||||
global read_only E_String2NumMap e_string2num_map_nil = {0};
|
||||
global read_only E_String2ExprMap e_string2expr_map_nil = {0};
|
||||
global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil};
|
||||
thread_static E_ParseCtx *e_parse_ctx = 0;
|
||||
global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil};
|
||||
thread_static E_ParseState *e_parse_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Map Functions
|
||||
@@ -218,13 +273,12 @@ internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
|
||||
internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child);
|
||||
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
|
||||
internal void e_expr_remove_child(E_Expr *parent, E_Expr *child);
|
||||
internal void e_expr_push_tag(E_Expr *parent, E_Expr *child);
|
||||
internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref);
|
||||
internal E_Expr *e_expr_ref_addr(Arena *arena, E_Expr *rhs);
|
||||
internal E_Expr *e_expr_ref_member_access(Arena *arena, E_Expr *lhs, String8 member_name);
|
||||
internal E_Expr *e_expr_ref_array_index(Arena *arena, E_Expr *lhs, U64 index);
|
||||
internal E_Expr *e_expr_ref_deref(Arena *arena, E_Expr *rhs);
|
||||
internal E_Expr *e_expr_ref_cast(Arena *arena, E_TypeKey type_key, E_Expr *rhs);
|
||||
internal E_Expr *e_expr_ref_bswap(Arena *arena, E_Expr *rhs);
|
||||
internal E_Expr *e_expr_copy(Arena *arena, E_Expr *src);
|
||||
internal void e_expr_list_push(Arena *arena, E_ExprList *list, E_Expr *expr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Tree -> String Conversions
|
||||
@@ -239,8 +293,9 @@ internal E_TypeKey e_leaf_type_from_name(String8 name);
|
||||
internal E_TypeKey e_type_from_expr(E_Expr *expr);
|
||||
internal void e_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, E_String2ExprMap *map, E_Expr *expr);
|
||||
internal E_Parse e_parse_type_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
internal E_Parse e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *tokens, S64 max_precedence);
|
||||
internal E_Parse e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *tokens, S64 max_precedence, U64 max_chain_count);
|
||||
internal E_Parse e_parse_expr_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
internal E_Expr *e_parse_expr_from_text(Arena *arena, String8 text);
|
||||
internal E_Parse e_parse_expr_from_text(Arena *arena, String8 text);
|
||||
internal E_Parse e_parse_expr_from_text__cached(String8 text);
|
||||
|
||||
#endif // EVAL_PARSE_H
|
||||
|
||||
+179
-65
@@ -250,6 +250,8 @@ e_select_type_ctx(E_TypeCtx *ctx)
|
||||
e_type_state->cons_key_slots = push_array(e_type_state->arena, E_ConsTypeSlot, e_type_state->cons_key_slots_count);
|
||||
e_type_state->member_cache_slots_count = 256;
|
||||
e_type_state->member_cache_slots = push_array(e_type_state->arena, E_MemberCacheSlot, e_type_state->member_cache_slots_count);
|
||||
e_type_state->type_cache_slots_count = 1024;
|
||||
e_type_state->type_cache_slots = push_array(e_type_state->arena, E_TypeCacheSlot, e_type_state->type_cache_slots_count);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -321,6 +323,8 @@ e_hash_from_cons_type_params(E_ConsTypeParams *params)
|
||||
params->direct_key.u32[2],
|
||||
(U32)((params->count & 0x00000000ffffffffull)>> 0),
|
||||
(U32)((params->count & 0xffffffff00000000ull)>> 32),
|
||||
(U32)((params->depth & 0x00000000ffffffffull)>> 0),
|
||||
(U32)((params->depth & 0xffffffff00000000ull)>> 32),
|
||||
};
|
||||
U64 hash = e_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer)));
|
||||
hash = e_hash_from_string(hash, params->name);
|
||||
@@ -334,7 +338,8 @@ e_cons_type_params_match(E_ConsTypeParams *l, E_ConsTypeParams *r)
|
||||
l->flags == r->flags &&
|
||||
str8_match(l->name, r->name, 0) &&
|
||||
e_type_key_match(l->direct_key, r->direct_key) &&
|
||||
l->count == r->count);
|
||||
l->count == r->count &&
|
||||
l->depth == r->depth);
|
||||
if(result && l->members != 0 && r->members != 0)
|
||||
{
|
||||
for(U64 idx = 0; idx < l->count; idx += 1)
|
||||
@@ -445,16 +450,16 @@ e_type_key_cons_(E_ConsTypeParams *params)
|
||||
//- rjf: constructed type helpers
|
||||
|
||||
internal E_TypeKey
|
||||
e_type_key_cons_array(E_TypeKey element_type_key, U64 count)
|
||||
e_type_key_cons_array(E_TypeKey element_type_key, U64 count, E_TypeFlags flags)
|
||||
{
|
||||
E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_Array, .direct_key = element_type_key, .count = count);
|
||||
E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_Array, .direct_key = element_type_key, .count = count, .flags = flags);
|
||||
return key;
|
||||
}
|
||||
|
||||
internal E_TypeKey
|
||||
e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, E_TypeFlags flags)
|
||||
e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags)
|
||||
{
|
||||
E_TypeKey key = e_type_key_cons(.arch = arch, .kind = E_TypeKind_Ptr, .flags = flags, .direct_key = element_type_key);
|
||||
E_TypeKey key = e_type_key_cons(.arch = arch, .kind = E_TypeKind_Ptr, .flags = flags, .direct_key = element_type_key, .count = count);
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -478,12 +483,12 @@ e_type_key_cons_base(Type *type)
|
||||
if(type->flags & TypeFlag_IsPlainText){ flags |= E_TypeFlag_IsPlainText; }
|
||||
if(type->flags & TypeFlag_IsCodeText) { flags |= E_TypeFlag_IsCodeText; }
|
||||
if(type->flags & TypeFlag_IsPathText) { flags |= E_TypeFlag_IsPathText; }
|
||||
result = e_type_key_cons_ptr(arch_from_context(), direct_type, flags);
|
||||
result = e_type_key_cons_ptr(arch_from_context(), direct_type, 1, flags);
|
||||
}break;
|
||||
case TypeKind_Array:
|
||||
{
|
||||
E_TypeKey direct_type = e_type_key_cons_base(type->direct);
|
||||
result = e_type_key_cons_array(direct_type, type->count);
|
||||
result = e_type_key_cons_array(direct_type, type->count, 0);
|
||||
}break;
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
@@ -492,7 +497,7 @@ e_type_key_cons_base(Type *type)
|
||||
for(U64 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
E_TypeKey member_type_key = e_type_key_cons_base(type->members[idx].type);
|
||||
e_member_list_push_new(scratch.arena, &members, .name = type->members[idx].name, .off = type->members[idx].value, .type_key = member_type_key, .pretty_name = type->members[idx].pretty_name);
|
||||
e_member_list_push_new(scratch.arena, &members, .name = type->members[idx].name, .off = type->members[idx].value, .type_key = member_type_key);
|
||||
}
|
||||
E_MemberArray members_array = e_member_array_from_list(scratch.arena, &members);
|
||||
result = e_type_key_cons(.arch = arch_from_context(),
|
||||
@@ -518,13 +523,12 @@ e_type_key_match(E_TypeKey l, E_TypeKey r)
|
||||
//- rjf: key -> info extraction
|
||||
|
||||
internal U64
|
||||
e_hash_from_type_key(E_TypeKey key)
|
||||
e_hash_from_type(E_Type *type)
|
||||
{
|
||||
U64 hash = 0;
|
||||
if(!e_type_key_match(e_type_key_zero(), key))
|
||||
if(type != &e_type_nil)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
String8List strings = {0};
|
||||
str8_serial_begin(scratch.arena, &strings);
|
||||
str8_serial_push_struct(scratch.arena, &strings, &type->kind);
|
||||
@@ -623,9 +627,12 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->name = push_str8_copy(arena, node->params.name);
|
||||
type->direct_type_key = node->params.direct_key;
|
||||
type->count = node->params.count;
|
||||
type->depth = node->params.depth;
|
||||
type->arch = node->params.arch;
|
||||
type->byte_size = node->byte_size;
|
||||
switch(type->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case E_TypeKind_Struct:
|
||||
case E_TypeKind_Union:
|
||||
case E_TypeKind_Class:
|
||||
@@ -700,6 +707,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = members_count;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
type->members = members;
|
||||
}
|
||||
|
||||
@@ -744,6 +752,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = enum_vals_count;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
type->enum_vals = enum_vals;
|
||||
type->direct_type_key = direct_type_key;
|
||||
}
|
||||
@@ -783,6 +792,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->flags = flags;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Ptr:
|
||||
case RDI_TypeKind_LRef:
|
||||
@@ -792,6 +802,8 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->kind = kind;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->byte_size = bit_size_from_arch(e_type_state->ctx->modules[rdi_idx].arch)/8;
|
||||
type->count = 1;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
|
||||
case RDI_TypeKind_Array:
|
||||
@@ -801,6 +813,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = rdi_type->constructed.count;
|
||||
type->byte_size = direct_type_byte_size * type->count;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Function:
|
||||
{
|
||||
@@ -816,6 +829,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
@@ -849,6 +863,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->owner_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
@@ -886,6 +901,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->byte_size = bit_size_from_arch(e_type_state->ctx->modules[rdi_idx].arch)/8;
|
||||
type->owner_type_key = owner_type_key;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
@@ -914,6 +930,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
//- rjf: bitfields
|
||||
@@ -937,6 +954,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->off = (U32)rdi_type->bitfield.off;
|
||||
type->count = (U64)rdi_type->bitfield.size;
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
//- rjf: incomplete types
|
||||
@@ -950,6 +968,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->arch = e_type_state->ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -977,6 +996,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
type->kind = E_TypeKind_Union;
|
||||
type->name = push_str8f(arena, "reg_%I64u_bit", reg_byte_count*8);
|
||||
type->byte_size = (U64)reg_byte_count;
|
||||
type->arch = (Arch)key.u32[0];
|
||||
|
||||
// rjf: build register type members
|
||||
E_MemberList members = {0};
|
||||
@@ -1045,7 +1065,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("u128s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U128), reg_byte_count/16);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U128), reg_byte_count/16, 0);
|
||||
}
|
||||
if(type->byte_size > 8 && type->byte_size%8 == 0)
|
||||
{
|
||||
@@ -1055,7 +1075,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("u64s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U64), reg_byte_count/8);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U64), reg_byte_count/8, 0);
|
||||
}
|
||||
if(type->byte_size > 4 && type->byte_size%4 == 0)
|
||||
{
|
||||
@@ -1065,7 +1085,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("u32s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U32), reg_byte_count/4);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U32), reg_byte_count/4, 0);
|
||||
}
|
||||
if(type->byte_size > 2 && type->byte_size%2 == 0)
|
||||
{
|
||||
@@ -1075,7 +1095,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("u16s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U16), reg_byte_count/2);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U16), reg_byte_count/2, 0);
|
||||
}
|
||||
if(type->byte_size > 1)
|
||||
{
|
||||
@@ -1085,7 +1105,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("u8s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), reg_byte_count);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), reg_byte_count, 0);
|
||||
}
|
||||
if(type->byte_size > 4 && type->byte_size%4 == 0)
|
||||
{
|
||||
@@ -1095,7 +1115,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("f32s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F32), reg_byte_count/4);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F32), reg_byte_count/4, 0);
|
||||
}
|
||||
if(type->byte_size > 8 && type->byte_size%8 == 0)
|
||||
{
|
||||
@@ -1105,7 +1125,7 @@ e_type_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *mem = &n->v;
|
||||
mem->kind = E_MemberKind_DataField;
|
||||
mem->name = str8_lit("f64s");
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F64), reg_byte_count/8);
|
||||
mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F64), reg_byte_count/8, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1179,10 +1199,8 @@ e_type_direct_from_key(E_TypeKey key)
|
||||
case E_TypeKeyKind_Ext:
|
||||
case E_TypeKeyKind_Cons:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
result = type->direct_type_key;
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
return result;
|
||||
@@ -1198,10 +1216,8 @@ e_type_owner_from_key(E_TypeKey key)
|
||||
case E_TypeKeyKind_Ext:
|
||||
case E_TypeKeyKind_Cons:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
result = type->owner_type_key;
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
return result;
|
||||
@@ -1340,21 +1356,18 @@ e_type_match(E_TypeKey l, E_TypeKey r)
|
||||
|
||||
case E_TypeKind_Array:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *lt = e_type_from_key(scratch.arena, l);
|
||||
E_Type *rt = e_type_from_key(scratch.arena, r);
|
||||
E_Type *lt = e_type_from_key__cached(l);
|
||||
E_Type *rt = e_type_from_key__cached(r);
|
||||
if(lt->count == rt->count && e_type_match(lt->direct_type_key, rt->direct_type_key))
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Function:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *lt = e_type_from_key(scratch.arena, l);
|
||||
E_Type *rt = e_type_from_key(scratch.arena, r);
|
||||
E_Type *lt = e_type_from_key__cached(l);
|
||||
E_Type *rt = e_type_from_key__cached(r);
|
||||
if(lt->count == rt->count && e_type_match(lt->direct_type_key, rt->direct_type_key))
|
||||
{
|
||||
B32 params_match = 1;
|
||||
@@ -1371,14 +1384,12 @@ e_type_match(E_TypeKey l, E_TypeKey r)
|
||||
}
|
||||
result = params_match;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Method:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_Type *lt = e_type_from_key(scratch.arena, l);
|
||||
E_Type *rt = e_type_from_key(scratch.arena, r);
|
||||
E_Type *lt = e_type_from_key__cached(l);
|
||||
E_Type *rt = e_type_from_key__cached(r);
|
||||
if(lt->count == rt->count &&
|
||||
e_type_match(lt->direct_type_key, rt->direct_type_key) &&
|
||||
e_type_match(lt->owner_type_key, rt->owner_type_key))
|
||||
@@ -1397,7 +1408,6 @@ e_type_match(E_TypeKey l, E_TypeKey r)
|
||||
}
|
||||
result = params_match;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
@@ -1412,7 +1422,6 @@ e_type_member_copy(Arena *arena, E_Member *src)
|
||||
E_Member *dst = push_array(arena, E_Member, 1);
|
||||
MemoryCopyStruct(dst, src);
|
||||
dst->name = push_str8_copy(arena, src->name);
|
||||
dst->pretty_name = push_str8_copy(arena, src->pretty_name);
|
||||
dst->inheritance_key_chain = e_type_key_list_copy(arena, &src->inheritance_key_chain);
|
||||
return dst;
|
||||
}
|
||||
@@ -1442,7 +1451,7 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key)
|
||||
E_MemberList members_list = {0};
|
||||
B32 members_need_offset_sort = 0;
|
||||
{
|
||||
E_Type *root_type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *root_type = e_type_from_key__cached(key);
|
||||
typedef struct Task Task;
|
||||
struct Task
|
||||
{
|
||||
@@ -1481,7 +1490,7 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key)
|
||||
t->inheritance_chain = e_type_key_list_copy(scratch.arena, &task->inheritance_chain);
|
||||
e_type_key_list_push(scratch.arena, &t->inheritance_chain, type->members[member_idx].type_key);
|
||||
t->type_key = type->members[member_idx].type_key;
|
||||
t->type = e_type_from_key(scratch.arena, type->members[member_idx].type_key);
|
||||
t->type = e_type_from_key__cached(type->members[member_idx].type_key);
|
||||
SLLQueuePush(first_task, last_task, t);
|
||||
members_need_offset_sort = 1;
|
||||
}
|
||||
@@ -1564,7 +1573,7 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key)
|
||||
E_Member *padding_member = &new_members.v[n->prev_member_idx+padding_idx+1];
|
||||
MemoryZeroStruct(padding_member);
|
||||
padding_member->kind = E_MemberKind_Padding;
|
||||
padding_member->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), n->size);
|
||||
padding_member->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), n->size, 0);
|
||||
padding_member->off = n->off;
|
||||
padding_member->name = push_str8f(arena, "[padding %I64u]", padding_idx);
|
||||
padding_idx += 1;
|
||||
@@ -1602,26 +1611,21 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
{
|
||||
default:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
str8_list_push(arena, out, push_str8_copy(arena, type->name));
|
||||
str8_list_push(arena, out, str8_lit(" "));
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Bitfield:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
e_type_lhs_string_from_key(arena, type->direct_type_key, out, prec, skip_return);
|
||||
str8_list_pushf(arena, out, ": %I64u", type->count);
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Modifier:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
E_TypeKey direct = type->direct_type_key;
|
||||
e_type_lhs_string_from_key(arena, direct, out, 1, skip_return);
|
||||
if(type->flags & E_TypeFlag_Const)
|
||||
@@ -1632,7 +1636,6 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
{
|
||||
str8_list_push(arena, out, str8_lit("volatile "));
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Variadic:
|
||||
@@ -1646,11 +1649,9 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
case E_TypeKind_Class:
|
||||
case E_TypeKind_Alias:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
str8_list_push(arena, out, push_str8_copy(arena, type->name));
|
||||
str8_list_push(arena, out, str8_lit(" "));
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_IncompleteStruct: keyword = str8_lit("struct"); goto fwd_udt;
|
||||
@@ -1659,13 +1660,11 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
case E_TypeKind_IncompleteClass: keyword = str8_lit("class"); goto fwd_udt;
|
||||
fwd_udt:;
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
str8_list_push(arena, out, keyword);
|
||||
str8_list_push(arena, out, str8_lit(" "));
|
||||
str8_list_push(arena, out, push_str8_copy(arena, type->name));
|
||||
str8_list_push(arena, out, str8_lit(" "));
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Array:
|
||||
@@ -1696,6 +1695,11 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
E_TypeKey direct = e_type_direct_from_key(key);
|
||||
e_type_lhs_string_from_key(arena, direct, out, 1, skip_return);
|
||||
str8_list_push(arena, out, str8_lit("*"));
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
if(type->count != 1)
|
||||
{
|
||||
str8_list_pushf(arena, out, ".%I64u", type->count);
|
||||
}
|
||||
}break;
|
||||
|
||||
case E_TypeKind_LRef:
|
||||
@@ -1714,11 +1718,10 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
|
||||
case E_TypeKind_MemberPtr:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
E_TypeKey direct = type->direct_type_key;
|
||||
e_type_lhs_string_from_key(arena, direct, out, 1, skip_return);
|
||||
E_Type *container = e_type_from_key(scratch.arena, type->owner_type_key);
|
||||
E_Type *container = e_type_from_key__cached(type->owner_type_key);
|
||||
if(container->kind != E_TypeKind_Null)
|
||||
{
|
||||
str8_list_push(arena, out, push_str8_copy(arena, container->name));
|
||||
@@ -1728,7 +1731,6 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
str8_list_push(arena, out, str8_lit("<unknown-class>"));
|
||||
}
|
||||
str8_list_push(arena, out, str8_lit("::*"));
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
@@ -1759,8 +1761,7 @@ e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
|
||||
case E_TypeKind_Array:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
if(prec == 1)
|
||||
{
|
||||
str8_list_push(arena, out, str8_lit(")"));
|
||||
@@ -1771,13 +1772,11 @@ e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
str8_list_push(arena, out, str8_lit("]"));
|
||||
E_TypeKey direct = e_type_direct_from_key(key);
|
||||
e_type_rhs_string_from_key(arena, direct, out, 2);
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
|
||||
case E_TypeKind_Function:
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_Type *type = e_type_from_key(scratch.arena, key);
|
||||
E_Type *type = e_type_from_key__cached(key);
|
||||
if(prec == 1)
|
||||
{
|
||||
str8_list_push(arena, out, str8_lit(")"));
|
||||
@@ -1806,7 +1805,6 @@ e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
|
||||
}
|
||||
E_TypeKey direct = e_type_direct_from_key(key);
|
||||
e_type_rhs_string_from_key(arena, direct, out, 2);
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
@@ -1846,9 +1844,74 @@ e_type_key_list_copy(Arena *arena, E_TypeKeyList *src)
|
||||
return dst;
|
||||
}
|
||||
|
||||
internal E_String2TypeKeyMap
|
||||
e_string2typekey_map_make(Arena *arena, U64 slots_count)
|
||||
{
|
||||
E_String2TypeKeyMap map = {0};
|
||||
map.slots_count = slots_count;
|
||||
map.slots = push_array(arena, E_String2TypeKeySlot, map.slots_count);
|
||||
return map;
|
||||
}
|
||||
|
||||
internal void
|
||||
e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key)
|
||||
{
|
||||
E_String2TypeKeyNode *n = push_array(arena, E_String2TypeKeyNode, 1);
|
||||
U64 hash = e_hash_from_string(5381, string);
|
||||
U64 slot_idx = hash%map->slots_count;
|
||||
SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n);
|
||||
n->string = push_str8_copy(arena, string);
|
||||
n->key = key;
|
||||
}
|
||||
|
||||
internal E_TypeKey
|
||||
e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string)
|
||||
{
|
||||
E_TypeKey key = zero_struct;
|
||||
U64 hash = e_hash_from_string(5381, string);
|
||||
U64 slot_idx = hash%map->slots_count;
|
||||
for(E_String2TypeKeyNode *n = map->slots[slot_idx].first; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(n->string, string, 0))
|
||||
{
|
||||
key = n->key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Lookups
|
||||
|
||||
internal E_Type *
|
||||
e_type_from_key__cached(E_TypeKey key)
|
||||
{
|
||||
E_Type *type = &e_type_nil;
|
||||
{
|
||||
U64 hash = e_hash_from_string(5381, str8_struct(&key));
|
||||
U64 slot_idx = hash%e_type_state->type_cache_slots_count;
|
||||
E_TypeCacheNode *node = 0;
|
||||
for(E_TypeCacheNode *n = e_type_state->type_cache_slots[slot_idx].first; n != 0; n = n->next)
|
||||
{
|
||||
if(e_type_key_match(key, n->key))
|
||||
{
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node == 0)
|
||||
{
|
||||
node = push_array(e_type_state->arena, E_TypeCacheNode, 1);
|
||||
node->key = key;
|
||||
node->type = e_type_from_key(e_type_state->arena, key);
|
||||
SLLQueuePush(e_type_state->type_cache_slots[slot_idx].first, e_type_state->type_cache_slots[slot_idx].last, node);
|
||||
}
|
||||
type = node->type;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
internal E_MemberCacheNode *
|
||||
e_member_cache_node_from_type_key(E_TypeKey key)
|
||||
{
|
||||
@@ -1872,6 +1935,8 @@ e_member_cache_node_from_type_key(E_TypeKey key)
|
||||
node->members = e_type_data_members_from_key(e_type_state->arena, key);
|
||||
node->member_hash_slots_count = node->members.count;
|
||||
node->member_hash_slots = push_array(e_type_state->arena, E_MemberHashSlot, node->member_hash_slots_count);
|
||||
node->member_filter_slots_count = 16;
|
||||
node->member_filter_slots = push_array(e_type_state->arena, E_MemberFilterSlot, node->member_filter_slots_count);
|
||||
for EachIndex(idx, node->members.count)
|
||||
{
|
||||
U64 hash = e_hash_from_string(5381, node->members.v[idx].name);
|
||||
@@ -1884,6 +1949,55 @@ e_member_cache_node_from_type_key(E_TypeKey key)
|
||||
return node;
|
||||
}
|
||||
|
||||
internal E_MemberArray
|
||||
e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter)
|
||||
{
|
||||
E_MemberArray members = {0};
|
||||
E_MemberCacheNode *node = e_member_cache_node_from_type_key(key);
|
||||
if(node != 0)
|
||||
{
|
||||
if(filter.size == 0)
|
||||
{
|
||||
members = node->members;
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 hash = e_hash_from_string(5381, filter);
|
||||
U64 slot_idx = hash%node->member_filter_slots_count;
|
||||
E_MemberFilterSlot *slot = &node->member_filter_slots[slot_idx];
|
||||
E_MemberFilterNode *filter_node = 0;
|
||||
for(E_MemberFilterNode *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(n->filter, filter, 0))
|
||||
{
|
||||
filter_node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(filter_node == 0)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
filter_node = push_array(e_type_state->arena, E_MemberFilterNode, 1);
|
||||
filter_node->filter = push_str8_copy(e_type_state->arena, filter);
|
||||
E_MemberList member_list__filtered = {0};
|
||||
for EachIndex(idx, node->members.count)
|
||||
{
|
||||
E_Member *member = &node->members.v[idx];
|
||||
FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, member->name);
|
||||
if(matches.count == matches.needle_part_count)
|
||||
{
|
||||
e_member_list_push(scratch.arena, &member_list__filtered, member);
|
||||
}
|
||||
}
|
||||
filter_node->members_filtered = e_member_array_from_list(e_type_state->arena, &member_list__filtered);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
members = filter_node->members_filtered;
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
internal E_MemberArray
|
||||
e_type_data_members_from_key__cached(E_TypeKey key)
|
||||
{
|
||||
|
||||
+82
-10
@@ -59,6 +59,7 @@ typedef enum E_MemberKind
|
||||
E_MemberKind_VirtualBase,
|
||||
E_MemberKind_NestedType,
|
||||
E_MemberKind_Padding,
|
||||
E_MemberKind_Query,
|
||||
E_MemberKind_COUNT
|
||||
}
|
||||
E_MemberKind;
|
||||
@@ -66,12 +67,13 @@ E_MemberKind;
|
||||
typedef U32 E_TypeFlags;
|
||||
enum
|
||||
{
|
||||
E_TypeFlag_Const = (1<<0),
|
||||
E_TypeFlag_Volatile = (1<<1),
|
||||
E_TypeFlag_External = (1<<2),
|
||||
E_TypeFlag_IsPlainText= (1<<3),
|
||||
E_TypeFlag_IsCodeText = (1<<4),
|
||||
E_TypeFlag_IsPathText = (1<<5),
|
||||
E_TypeFlag_Const = (1<<0),
|
||||
E_TypeFlag_Volatile = (1<<1),
|
||||
E_TypeFlag_External = (1<<2),
|
||||
E_TypeFlag_IsPlainText = (1<<3),
|
||||
E_TypeFlag_IsCodeText = (1<<4),
|
||||
E_TypeFlag_IsPathText = (1<<5),
|
||||
E_TypeFlag_EditableChildren = (1<<6),
|
||||
};
|
||||
|
||||
typedef struct E_Member E_Member;
|
||||
@@ -80,7 +82,6 @@ struct E_Member
|
||||
E_MemberKind kind;
|
||||
E_TypeKey type_key;
|
||||
String8 name;
|
||||
String8 pretty_name;
|
||||
U64 off;
|
||||
E_TypeKeyList inheritance_key_chain;
|
||||
};
|
||||
@@ -129,7 +130,9 @@ struct E_Type
|
||||
String8 name;
|
||||
U64 byte_size;
|
||||
U64 count;
|
||||
U64 depth;
|
||||
U32 off;
|
||||
Arch arch;
|
||||
E_TypeKey direct_type_key;
|
||||
E_TypeKey owner_type_key;
|
||||
E_TypeKey *param_type_keys;
|
||||
@@ -137,6 +140,31 @@ struct E_Type
|
||||
E_EnumVal *enum_vals;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String -> Type Key Map Data Structure
|
||||
|
||||
typedef struct E_String2TypeKeyNode E_String2TypeKeyNode;
|
||||
struct E_String2TypeKeyNode
|
||||
{
|
||||
E_String2TypeKeyNode *next;
|
||||
String8 string;
|
||||
E_TypeKey key;
|
||||
};
|
||||
|
||||
typedef struct E_String2TypeKeySlot E_String2TypeKeySlot;
|
||||
struct E_String2TypeKeySlot
|
||||
{
|
||||
E_String2TypeKeyNode *first;
|
||||
E_String2TypeKeyNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_String2TypeKeyMap E_String2TypeKeyMap;
|
||||
struct E_String2TypeKeyMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_String2TypeKeySlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Evaluation Context
|
||||
|
||||
@@ -151,6 +179,7 @@ struct E_ConsTypeParams
|
||||
String8 name;
|
||||
E_TypeKey direct_key;
|
||||
U64 count;
|
||||
U64 depth;
|
||||
E_Member *members;
|
||||
E_EnumVal *enum_vals;
|
||||
};
|
||||
@@ -172,6 +201,23 @@ struct E_ConsTypeSlot
|
||||
E_ConsTypeNode *last;
|
||||
};
|
||||
|
||||
//- rjf: unpacked type cache
|
||||
|
||||
typedef struct E_TypeCacheNode E_TypeCacheNode;
|
||||
struct E_TypeCacheNode
|
||||
{
|
||||
E_TypeCacheNode *next;
|
||||
E_TypeKey key;
|
||||
E_Type *type;
|
||||
};
|
||||
|
||||
typedef struct E_TypeCacheSlot E_TypeCacheSlot;
|
||||
struct E_TypeCacheSlot
|
||||
{
|
||||
E_TypeCacheNode *first;
|
||||
E_TypeCacheNode *last;
|
||||
};
|
||||
|
||||
//- rjf: member lookup cache types
|
||||
|
||||
typedef struct E_MemberHashNode E_MemberHashNode;
|
||||
@@ -188,6 +234,21 @@ struct E_MemberHashSlot
|
||||
E_MemberHashNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_MemberFilterNode E_MemberFilterNode;
|
||||
struct E_MemberFilterNode
|
||||
{
|
||||
E_MemberFilterNode *next;
|
||||
String8 filter;
|
||||
E_MemberArray members_filtered;
|
||||
};
|
||||
|
||||
typedef struct E_MemberFilterSlot E_MemberFilterSlot;
|
||||
struct E_MemberFilterSlot
|
||||
{
|
||||
E_MemberFilterNode *first;
|
||||
E_MemberFilterNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_MemberCacheNode E_MemberCacheNode;
|
||||
struct E_MemberCacheNode
|
||||
{
|
||||
@@ -196,6 +257,8 @@ struct E_MemberCacheNode
|
||||
E_MemberArray members;
|
||||
U64 member_hash_slots_count;
|
||||
E_MemberHashSlot *member_hash_slots;
|
||||
U64 member_filter_slots_count;
|
||||
E_MemberFilterSlot *member_filter_slots;
|
||||
};
|
||||
|
||||
typedef struct E_MemberCacheSlot E_MemberCacheSlot;
|
||||
@@ -241,6 +304,10 @@ struct E_TypeState
|
||||
// rjf: member cache table
|
||||
U64 member_cache_slots_count;
|
||||
E_MemberCacheSlot *member_cache_slots;
|
||||
|
||||
// rjf: unpacked type cache
|
||||
U64 type_cache_slots_count;
|
||||
E_TypeCacheSlot *type_cache_slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -292,15 +359,15 @@ internal E_TypeKey e_type_key_cons_(E_ConsTypeParams *params);
|
||||
#define e_type_key_cons(...) e_type_key_cons_(&(E_ConsTypeParams){.kind = E_TypeKind_Null, __VA_ARGS__})
|
||||
|
||||
//- rjf: constructed type construction helpers
|
||||
internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count);
|
||||
internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, E_TypeFlags flags);
|
||||
internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count, E_TypeFlags flags);
|
||||
internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags);
|
||||
internal E_TypeKey e_type_key_cons_base(Type *type);
|
||||
|
||||
//- rjf: basic type key functions
|
||||
internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r);
|
||||
|
||||
//- rjf: key -> info extraction
|
||||
internal U64 e_hash_from_type_key(E_TypeKey key);
|
||||
internal U64 e_hash_from_type(E_Type *type);
|
||||
internal E_TypeKind e_type_kind_from_key(E_TypeKey key);
|
||||
internal U64 e_type_byte_size_from_key(E_TypeKey key);
|
||||
internal E_Type *e_type_from_key(Arena *arena, E_TypeKey key);
|
||||
@@ -322,11 +389,16 @@ internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key);
|
||||
//- rjf: type key data structures
|
||||
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
|
||||
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
|
||||
internal E_String2TypeKeyMap e_string2typekey_map_make(Arena *arena, U64 slots_count);
|
||||
internal void e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key);
|
||||
internal E_TypeKey e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Lookups
|
||||
|
||||
internal E_Type *e_type_from_key__cached(E_TypeKey key);
|
||||
internal E_MemberCacheNode *e_member_cache_node_from_type_key(E_TypeKey key);
|
||||
internal E_MemberArray e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter);
|
||||
internal E_MemberArray e_type_data_members_from_key__cached(E_TypeKey key);
|
||||
internal E_Member e_type_member_from_key_name__cached(E_TypeKey key, String8 name);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ str8_lit_comp("CharLiteral"),
|
||||
str8_lit_comp("Symbol"),
|
||||
};
|
||||
|
||||
String8 e_expr_kind_strings[48] =
|
||||
String8 e_expr_kind_strings[51] =
|
||||
{
|
||||
str8_lit_comp("Nil"),
|
||||
str8_lit_comp("Ref"),
|
||||
@@ -49,6 +49,7 @@ str8_lit_comp("BitOr"),
|
||||
str8_lit_comp("LogAnd"),
|
||||
str8_lit_comp("LogOr"),
|
||||
str8_lit_comp("Ternary"),
|
||||
str8_lit_comp("Call"),
|
||||
str8_lit_comp("LeafBytecode"),
|
||||
str8_lit_comp("LeafMember"),
|
||||
str8_lit_comp("LeafStringLiteral"),
|
||||
@@ -58,12 +59,14 @@ str8_lit_comp("LeafF64"),
|
||||
str8_lit_comp("LeafF32"),
|
||||
str8_lit_comp("LeafIdent"),
|
||||
str8_lit_comp("LeafOffset"),
|
||||
str8_lit_comp("LeafValue"),
|
||||
str8_lit_comp("LeafFilePath"),
|
||||
str8_lit_comp("TypeIdent"),
|
||||
str8_lit_comp("Ptr"),
|
||||
str8_lit_comp("Array"),
|
||||
str8_lit_comp("Func"),
|
||||
str8_lit_comp("Define"),
|
||||
str8_lit_comp("Tag"),
|
||||
};
|
||||
|
||||
String8 e_interpretation_code_display_strings[11] =
|
||||
@@ -81,7 +84,7 @@ str8_lit_comp("Insufficient evaluation machine stack space."),
|
||||
str8_lit_comp("Malformed bytecode."),
|
||||
};
|
||||
|
||||
E_OpInfo e_expr_kind_op_info_table[48] =
|
||||
E_OpInfo e_expr_kind_op_info_table[51] =
|
||||
{
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
@@ -116,6 +119,8 @@ E_OpInfo e_expr_kind_op_info_table[48] =
|
||||
{ E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp("") },
|
||||
{ E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp(":") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp("("), str8_lit_comp(","), str8_lit_comp(")") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
@@ -131,6 +136,7 @@ E_OpInfo e_expr_kind_op_info_table[48] =
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
|
||||
{ E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp("") },
|
||||
{ E_OpKind_Null, 0, str8_lit_comp("=>"), str8_lit_comp(","), str8_lit_comp("") },
|
||||
};
|
||||
|
||||
U8 e_kind_basic_byte_size_table[56] =
|
||||
@@ -250,7 +256,7 @@ str8_lit_comp("class"),
|
||||
str8_lit_comp("enum"),
|
||||
str8_lit_comp("bitfield"),
|
||||
str8_lit_comp("variadic"),
|
||||
str8_lit_comp("collection"),
|
||||
str8_lit_comp("set"),
|
||||
};
|
||||
|
||||
C_LINKAGE_END
|
||||
|
||||
@@ -74,7 +74,7 @@ E_TypeKind_IncompleteClass,
|
||||
E_TypeKind_IncompleteEnum,
|
||||
E_TypeKind_Bitfield,
|
||||
E_TypeKind_Variadic,
|
||||
E_TypeKind_Collection,
|
||||
E_TypeKind_Set,
|
||||
E_TypeKind_COUNT,
|
||||
E_TypeKind_FirstBasic = E_TypeKind_Void,
|
||||
E_TypeKind_LastBasic = E_TypeKind_ComplexF128,
|
||||
@@ -124,6 +124,7 @@ E_ExprKind_BitOr,
|
||||
E_ExprKind_LogAnd,
|
||||
E_ExprKind_LogOr,
|
||||
E_ExprKind_Ternary,
|
||||
E_ExprKind_Call,
|
||||
E_ExprKind_LeafBytecode,
|
||||
E_ExprKind_LeafMember,
|
||||
E_ExprKind_LeafStringLiteral,
|
||||
@@ -133,12 +134,14 @@ E_ExprKind_LeafF64,
|
||||
E_ExprKind_LeafF32,
|
||||
E_ExprKind_LeafIdent,
|
||||
E_ExprKind_LeafOffset,
|
||||
E_ExprKind_LeafValue,
|
||||
E_ExprKind_LeafFilePath,
|
||||
E_ExprKind_TypeIdent,
|
||||
E_ExprKind_Ptr,
|
||||
E_ExprKind_Array,
|
||||
E_ExprKind_Func,
|
||||
E_ExprKind_Define,
|
||||
E_ExprKind_Tag,
|
||||
E_ExprKind_COUNT,
|
||||
} E_ExprKindEnum;
|
||||
|
||||
@@ -160,9 +163,9 @@ E_InterpretationCode_COUNT,
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 e_token_kind_strings[6];
|
||||
extern String8 e_expr_kind_strings[48];
|
||||
extern String8 e_expr_kind_strings[51];
|
||||
extern String8 e_interpretation_code_display_strings[11];
|
||||
extern E_OpInfo e_expr_kind_op_info_table[48];
|
||||
extern E_OpInfo e_expr_kind_op_info_table[51];
|
||||
extern U8 e_kind_basic_byte_size_table[56];
|
||||
extern String8 e_kind_basic_string_table[56];
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
@table(coverage_check name name_lower string ih ex xr xe display_name docs schema description)
|
||||
EV_ViewRuleTable:
|
||||
{
|
||||
{x Default default "default" - - - x "Default" - "" "" }
|
||||
{x Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
|
||||
{x List list "list" - - - x "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
|
||||
{x Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." }
|
||||
@@ -106,22 +105,3 @@ EV_ViewRuleTable:
|
||||
{x Hex hex "hex" x - - - "Display In Hexadecimal" x "" "Specifies that all numeric values should be shown in base 16 (hexadecimal)." }
|
||||
{x NoAddress no_addr "no_addr" x - - - "Omit Addresses" x "" "Specifies that addresses should be omitted from visualizations, if possible." }
|
||||
}
|
||||
|
||||
@enum EV_ViewRuleKind:
|
||||
{
|
||||
@expand(EV_ViewRuleTable a) `$(a.name)`,
|
||||
COUNT,
|
||||
}
|
||||
|
||||
@gen
|
||||
{
|
||||
@expand(EV_ViewRuleTable a) `$(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`;
|
||||
@expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
|
||||
@expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
|
||||
}
|
||||
|
||||
@data(EV_ViewRuleInfo) @c_file ev_builtin_view_rule_info_table:
|
||||
{
|
||||
@expand(EV_ViewRuleTable a)
|
||||
```{str8_lit_comp("$(a.string)"), (EV_ViewRuleInfoFlag_Inherited*$(a.ih == "x"))|(EV_ViewRuleInfoFlag_Expandable*$(a.ex == "x")), $(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.xr != "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil)"), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) }```;
|
||||
}
|
||||
|
||||
@@ -1,557 +0,0 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Tree Info Extraction Helpers
|
||||
|
||||
internal U64
|
||||
ev_base_offset_from_eval(E_Eval eval)
|
||||
{
|
||||
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(eval.type_key)))
|
||||
{
|
||||
eval = e_value_eval_from_eval(eval);
|
||||
}
|
||||
return eval.value.u64;
|
||||
}
|
||||
|
||||
internal E_Value
|
||||
ev_value_from_params(MD_Node *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 expr = md_string_from_children(scratch.arena, params);
|
||||
E_Eval eval = e_eval_from_string(scratch.arena, expr);
|
||||
E_Eval value_eval = e_value_eval_from_eval(eval);
|
||||
scratch_end(scratch);
|
||||
return value_eval.value;
|
||||
}
|
||||
|
||||
internal E_TypeKey
|
||||
ev_type_key_from_params(MD_Node *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 expr = md_string_from_children(scratch.arena, params);
|
||||
E_TokenArray tokens = e_token_array_from_text(scratch.arena, expr);
|
||||
E_Parse parse = e_parse_type_from_text_tokens(scratch.arena, expr, &tokens);
|
||||
E_TypeKey type_key = e_type_from_expr(parse.expr);
|
||||
scratch_end(scratch);
|
||||
return type_key;
|
||||
}
|
||||
|
||||
internal E_Value
|
||||
ev_value_from_params_key(MD_Node *params, String8 key)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
MD_Node *key_node = md_child_from_string(params, key, 0);
|
||||
String8 expr = md_string_from_children(scratch.arena, key_node);
|
||||
E_Eval eval = e_eval_from_string(scratch.arena, expr);
|
||||
E_Eval value_eval = e_value_eval_from_eval(eval);
|
||||
scratch_end(scratch);
|
||||
return value_eval.value;
|
||||
}
|
||||
|
||||
internal Rng1U64
|
||||
ev_range_from_eval_params(E_Eval eval, MD_Node *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 size = ev_value_from_params_key(params, str8_lit("size")).u64;
|
||||
E_TypeKey type_key = e_type_unwrap(eval.type_key);
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(eval.type_key));
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
|
||||
if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
|
||||
direct_type_kind == E_TypeKind_Union ||
|
||||
direct_type_kind == E_TypeKind_Class ||
|
||||
direct_type_kind == E_TypeKind_Array))
|
||||
{
|
||||
size = e_type_byte_size_from_key(e_type_direct_from_key(e_type_unwrap(eval.type_key)));
|
||||
}
|
||||
if(size == 0 && eval.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct ||
|
||||
type_kind == E_TypeKind_Union ||
|
||||
type_kind == E_TypeKind_Class ||
|
||||
type_kind == E_TypeKind_Array))
|
||||
{
|
||||
size = e_type_byte_size_from_key(e_type_unwrap(eval.type_key));
|
||||
}
|
||||
if(size == 0)
|
||||
{
|
||||
size = 16384;
|
||||
}
|
||||
Rng1U64 result = {0};
|
||||
result.min = ev_base_offset_from_eval(eval);
|
||||
result.max = result.min + size;
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Arch
|
||||
ev_arch_from_eval_params(E_Eval eval, MD_Node *params)
|
||||
{
|
||||
Arch arch = Arch_Null;
|
||||
MD_Node *arch_node = md_child_from_string(params, str8_lit("arch"), 0);
|
||||
String8 arch_kind_string = arch_node->first->string;
|
||||
if(str8_match(arch_kind_string, str8_lit("x64"), StringMatchFlag_CaseInsensitive))
|
||||
{
|
||||
arch = Arch_x64;
|
||||
}
|
||||
return arch;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: default
|
||||
|
||||
typedef struct EV_DefaultExpandAccel EV_DefaultExpandAccel;
|
||||
struct EV_DefaultExpandAccel
|
||||
{
|
||||
E_MemberArray members;
|
||||
E_EnumValArray enum_vals;
|
||||
U64 array_count;
|
||||
B32 array_need_extra_deref;
|
||||
B32 is_ptr2ptr;
|
||||
};
|
||||
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(default)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
U64 total_row_count = 0;
|
||||
EV_DefaultExpandAccel *accel = push_array(arena, EV_DefaultExpandAccel, 1);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: unpack expression type info
|
||||
//
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
|
||||
E_TypeKey type_key = e_type_unwrap(irtree.type_key);
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(type_key));
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: structs/unions/classes -> expansions generate rows for all members
|
||||
//
|
||||
if((type_kind == E_TypeKind_Struct ||
|
||||
type_kind == E_TypeKind_Union ||
|
||||
type_kind == E_TypeKind_Class) ||
|
||||
(e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
|
||||
direct_type_kind == E_TypeKind_Union ||
|
||||
direct_type_kind == E_TypeKind_Class)))
|
||||
{
|
||||
E_TypeKey struct_type_key = e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key;
|
||||
accel->members = e_type_data_members_from_key__cached(struct_type_key);
|
||||
total_row_count = accel->members.count;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: enums -> expansions generate rows for all members
|
||||
//
|
||||
else if(type_kind == E_TypeKind_Enum ||
|
||||
(e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Enum))
|
||||
{
|
||||
E_Type *type = e_type_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key);
|
||||
accel->enum_vals.v = type->enum_vals;
|
||||
accel->enum_vals.count = type->count;
|
||||
total_row_count = accel->enum_vals.count;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: arrays -> expansions generate rows for all elements
|
||||
//
|
||||
else if(type_kind == E_TypeKind_Array ||
|
||||
(e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Array))
|
||||
{
|
||||
B32 need_extra_deref = e_type_kind_is_pointer_or_ref(type_kind);
|
||||
E_Expr *array_expr = need_extra_deref ? e_expr_ref_deref(arena, expr) : expr;
|
||||
E_Type *type = e_type_from_key(arena, need_extra_deref ? direct_type_key : type_key);
|
||||
total_row_count = type->count;
|
||||
accel->array_count = type->count;
|
||||
accel->array_need_extra_deref = need_extra_deref;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: pointer-to-pointer -> expansions generate dereference
|
||||
//
|
||||
else if(e_type_kind_is_pointer_or_ref(type_kind) && e_type_kind_is_pointer_or_ref(direct_type_kind))
|
||||
{
|
||||
total_row_count = 1;
|
||||
accel->is_ptr2ptr = 1;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: package result
|
||||
//
|
||||
EV_ExpandInfo result = {0};
|
||||
{
|
||||
result.user_data = accel;
|
||||
result.row_count = total_row_count;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(default)
|
||||
{
|
||||
EV_DefaultExpandAccel *accel = (EV_DefaultExpandAccel *)user_data;
|
||||
EV_ExpandRangeInfo result = {0};
|
||||
U64 needed_row_count = dim_1u64(idx_range);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: fill with members
|
||||
//
|
||||
if(accel->members.count != 0)
|
||||
{
|
||||
E_MemberArray *members = &accel->members;
|
||||
result.row_exprs_count = Min(needed_row_count, members->count);
|
||||
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
|
||||
result.row_strings = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
|
||||
for EachIndex(row_expr_idx, result.row_exprs_count)
|
||||
{
|
||||
E_Member *member = &members->v[idx_range.min + row_expr_idx];
|
||||
result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, member->name);
|
||||
result.row_members[row_expr_idx] = member;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: fill with enum vals
|
||||
//
|
||||
else if(accel->enum_vals.count != 0)
|
||||
{
|
||||
E_EnumValArray *enumvals = &accel->enum_vals;
|
||||
result.row_exprs_count = Min(needed_row_count, enumvals->count);
|
||||
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
|
||||
result.row_strings = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
|
||||
for EachIndex(row_expr_idx, result.row_exprs_count)
|
||||
{
|
||||
E_EnumVal *enumval = &enumvals->v[idx_range.min + row_expr_idx];
|
||||
result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, enumval->name);
|
||||
result.row_members[row_expr_idx] = &e_member_nil;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: fill with array indices
|
||||
//
|
||||
else if(accel->array_count != 0)
|
||||
{
|
||||
E_Expr *array_expr = accel->array_need_extra_deref ? e_expr_ref_deref(arena, expr) : expr;
|
||||
result.row_exprs_count = Min(needed_row_count, accel->array_count);
|
||||
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
|
||||
result.row_strings = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
|
||||
for EachIndex(row_expr_idx, result.row_exprs_count)
|
||||
{
|
||||
result.row_exprs[row_expr_idx] = e_expr_ref_array_index(arena, array_expr, idx_range.min + row_expr_idx);
|
||||
result.row_members[row_expr_idx] = &e_member_nil;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: fill with ptr-to-ptr deref
|
||||
//
|
||||
else if(accel->is_ptr2ptr)
|
||||
{
|
||||
result.row_exprs_count = 1;
|
||||
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
|
||||
result.row_strings = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
|
||||
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
|
||||
result.row_exprs[0] = e_expr_ref_deref(arena, expr);
|
||||
result.row_members[0] = &e_member_nil;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "array"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
|
||||
E_TypeKey type_key = irtree.type_key;
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
if(e_type_kind_is_pointer_or_ref(type_kind))
|
||||
{
|
||||
E_Value count = ev_value_from_params(params);
|
||||
E_TypeKey element_type_key = e_type_ptee_from_key(type_key);
|
||||
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count.u64);
|
||||
E_TypeKey ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
|
||||
expr = e_expr_ref_cast(arena, ptr_type_key, expr);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "list"
|
||||
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(list)
|
||||
{
|
||||
EV_ExpandInfo info = {0};
|
||||
return info;
|
||||
}
|
||||
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(list)
|
||||
{
|
||||
EV_ExpandRangeInfo info = {0};
|
||||
return info;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "slice"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
|
||||
E_TypeKind type_kind = e_type_kind_from_key(irtree.type_key);
|
||||
if(type_kind == E_TypeKind_Struct || type_kind == E_TypeKind_Class)
|
||||
{
|
||||
// rjf: unpack members
|
||||
E_MemberArray members = e_type_data_members_from_key__cached(irtree.type_key);
|
||||
|
||||
// rjf: choose base pointer & count members
|
||||
E_Member *base_ptr_member = 0;
|
||||
E_Member *count_member = 0;
|
||||
for(U64 idx = 0; idx < members.count; idx += 1)
|
||||
{
|
||||
E_Member *member = &members.v[idx];
|
||||
E_TypeKey member_type = e_type_unwrap(member->type_key);
|
||||
E_TypeKind member_type_kind = e_type_kind_from_key(member_type);
|
||||
if(count_member == 0 && e_type_kind_is_integer(member_type_kind))
|
||||
{
|
||||
count_member = member;
|
||||
}
|
||||
if(base_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind))
|
||||
{
|
||||
base_ptr_member = &members.v[idx];
|
||||
}
|
||||
if(count_member != 0 && base_ptr_member != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: evaluate count member, determine count
|
||||
U64 count = 0;
|
||||
if(count_member != 0)
|
||||
{
|
||||
E_Expr *count_member_expr = e_expr_ref_member_access(scratch.arena, expr, count_member->name);
|
||||
E_Eval count_member_eval = e_eval_from_expr(scratch.arena, count_member_expr);
|
||||
E_Eval count_member_value_eval = e_value_eval_from_eval(count_member_eval);
|
||||
count = count_member_value_eval.value.u64;
|
||||
}
|
||||
|
||||
// rjf: generate new struct slice type
|
||||
E_TypeKey slice_type_key = zero_struct;
|
||||
if(base_ptr_member != 0 && count_member != 0)
|
||||
{
|
||||
String8 struct_name = e_type_string_from_key(scratch.arena, irtree.type_key);
|
||||
E_TypeKey element_type_key = e_type_ptee_from_key(base_ptr_member->type_key);
|
||||
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count);
|
||||
E_TypeKey sized_base_ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
|
||||
E_MemberList slice_type_members = {0};
|
||||
e_member_list_push(scratch.arena, &slice_type_members, count_member);
|
||||
e_member_list_push(scratch.arena, &slice_type_members, &(E_Member){.kind = E_MemberKind_DataField, .type_key = sized_base_ptr_type_key, .name = base_ptr_member->name, .pretty_name = base_ptr_member->pretty_name, .off = base_ptr_member->off});
|
||||
E_MemberArray slice_type_members_array = e_member_array_from_list(scratch.arena, &slice_type_members);
|
||||
slice_type_key = e_type_key_cons(.arch = e_type_state->ctx->primary_module->arch,
|
||||
.kind = E_TypeKind_Struct,
|
||||
.name = struct_name,
|
||||
.members = slice_type_members_array.v,
|
||||
.count = slice_type_members_array.count);
|
||||
}
|
||||
|
||||
// rjf: generate new expression tree - addr of struct, cast-to-ptr, deref
|
||||
if(base_ptr_member != 0 && count_member != 0)
|
||||
{
|
||||
expr = e_expr_ref_addr(arena, expr);
|
||||
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, slice_type_key, 0), expr);
|
||||
expr = e_expr_ref_deref(arena, expr);
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "bswap"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap)
|
||||
{
|
||||
expr = e_expr_ref_bswap(arena, expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "cast"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast)
|
||||
{
|
||||
E_TypeKey type_key = ev_type_key_from_params(params);
|
||||
expr = e_expr_ref_cast(arena, type_key, expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "wrap"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(wrap)
|
||||
{
|
||||
String8 wrap_string = md_string_from_children(arena, params);
|
||||
E_Expr *wrap_expr = e_parse_expr_from_text(arena, wrap_string);
|
||||
E_Expr *new_root_expr = wrap_expr;
|
||||
if(wrap_expr != &e_expr_nil)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
typedef struct Task Task;
|
||||
struct Task
|
||||
{
|
||||
Task *next;
|
||||
E_Expr *parent;
|
||||
E_Expr *expr;
|
||||
};
|
||||
Task start_task = {0, &e_expr_nil, wrap_expr};
|
||||
Task *first_task = &start_task;
|
||||
Task *last_task = first_task;
|
||||
for(Task *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
if(t->expr->kind == E_ExprKind_LeafIdent && str8_match(t->expr->string, str8_lit("$expr"), 0))
|
||||
{
|
||||
E_Expr *original_expr_ref = e_expr_ref(arena, expr);
|
||||
if(t->parent != &e_expr_nil)
|
||||
{
|
||||
e_expr_insert_child(t->parent, t->expr, original_expr_ref);
|
||||
e_expr_remove_child(t->parent, t->expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_root_expr = original_expr_ref;
|
||||
}
|
||||
}
|
||||
else for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next)
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
task->parent = t->expr;
|
||||
task->expr = child;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return new_root_expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "only"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(only)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
|
||||
E_TypeKey type_key = irtree.type_key;
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
E_TypeKey direct_type_key = e_type_direct_from_key(type_key);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
|
||||
B32 is_ptr = e_type_kind_is_pointer_or_ref(type_kind);
|
||||
E_TypeKey struct_type_key = is_ptr ? direct_type_key : type_key;
|
||||
E_TypeKind struct_type_kind = is_ptr ? direct_type_kind : type_kind;
|
||||
if(struct_type_kind == E_TypeKind_Struct ||
|
||||
struct_type_kind == E_TypeKind_Union ||
|
||||
struct_type_kind == E_TypeKind_Class)
|
||||
{
|
||||
E_MemberArray current_members = e_type_data_members_from_key__cached(struct_type_key);
|
||||
E_MemberList new_members = {0};
|
||||
for MD_EachNode(node, params->first)
|
||||
{
|
||||
for EachIndex(idx, current_members.count)
|
||||
{
|
||||
if(str8_match(node->string, current_members.v[idx].name, 0))
|
||||
{
|
||||
e_member_list_push(scratch.arena, &new_members, ¤t_members.v[idx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
E_MemberArray new_members_array = e_member_array_from_list(scratch.arena, &new_members);
|
||||
E_TypeKey new_type = {0};
|
||||
if(new_members_array.count == 1 && new_members_array.v[0].off == 0)
|
||||
{
|
||||
new_type = new_members_array.v[0].type_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
String8 struct_name = e_type_string_from_key(scratch.arena, struct_type_key);
|
||||
new_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = struct_name, .members = new_members_array.v, .count = new_members_array.count);
|
||||
}
|
||||
if(!is_ptr)
|
||||
{
|
||||
expr = e_expr_ref_addr(arena, expr);
|
||||
}
|
||||
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, new_type, 0), expr);
|
||||
if(!is_ptr)
|
||||
{
|
||||
expr = e_expr_ref_deref(arena, expr);
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: "omit"
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(omit)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
|
||||
E_TypeKey type_key = irtree.type_key;
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
E_TypeKey direct_type_key = e_type_direct_from_key(type_key);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
|
||||
B32 is_ptr = e_type_kind_is_pointer_or_ref(type_kind);
|
||||
E_TypeKey struct_type_key = is_ptr ? direct_type_key : type_key;
|
||||
E_TypeKind struct_type_kind = is_ptr ? direct_type_kind : type_kind;
|
||||
if(struct_type_kind == E_TypeKind_Struct ||
|
||||
struct_type_kind == E_TypeKind_Union ||
|
||||
struct_type_kind == E_TypeKind_Class)
|
||||
{
|
||||
E_MemberArray current_members = e_type_data_members_from_key__cached(struct_type_key);
|
||||
E_MemberList new_members = {0};
|
||||
for EachIndex(idx, current_members.count)
|
||||
{
|
||||
B32 include = 1;
|
||||
for MD_EachNode(node, params->first)
|
||||
{
|
||||
if(str8_match(node->string, current_members.v[idx].name, 0))
|
||||
{
|
||||
include = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(include)
|
||||
{
|
||||
e_member_list_push(scratch.arena, &new_members, ¤t_members.v[idx]);
|
||||
}
|
||||
}
|
||||
E_MemberArray new_members_array = e_member_array_from_list(scratch.arena, &new_members);
|
||||
E_TypeKey new_type = {0};
|
||||
String8 struct_name = e_type_string_from_key(scratch.arena, struct_type_key);
|
||||
new_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = struct_name, .members = new_members_array.v, .count = new_members_array.count);
|
||||
if(!is_ptr)
|
||||
{
|
||||
expr = e_expr_ref_addr(arena, expr);
|
||||
}
|
||||
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, new_type, 0), expr);
|
||||
if(!is_ptr)
|
||||
{
|
||||
expr = e_expr_ref_deref(arena, expr);
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return expr;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
|
||||
#define EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Tree Info Extraction Helpers
|
||||
|
||||
internal U64 ev_base_offset_from_eval(E_Eval eval);
|
||||
internal E_Value ev_value_from_params(MD_Node *params);
|
||||
internal E_TypeKey ev_type_key_from_params(MD_Node *params);
|
||||
internal E_Value ev_value_from_params_key(MD_Node *params, String8 key);
|
||||
internal Rng1U64 ev_range_from_eval_params(E_Eval eval, MD_Node *params);
|
||||
internal Arch ev_arch_from_eval_params(E_Eval eval, MD_Node *params);
|
||||
|
||||
#endif // EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -75,31 +75,7 @@ struct EV_View
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Instance Types
|
||||
|
||||
typedef struct EV_ViewRule EV_ViewRule;
|
||||
struct EV_ViewRule
|
||||
{
|
||||
MD_Node *root;
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleNode EV_ViewRuleNode;
|
||||
struct EV_ViewRuleNode
|
||||
{
|
||||
EV_ViewRuleNode *next;
|
||||
EV_ViewRule v;
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleList EV_ViewRuleList;
|
||||
struct EV_ViewRuleList
|
||||
{
|
||||
EV_ViewRuleNode *first;
|
||||
EV_ViewRuleNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Info Types
|
||||
//~ rjf: Expansion Rule Types
|
||||
|
||||
typedef struct EV_ExpandInfo EV_ExpandInfo;
|
||||
struct EV_ExpandInfo
|
||||
@@ -111,82 +87,46 @@ struct EV_ExpandInfo
|
||||
B32 rows_default_expanded;
|
||||
};
|
||||
|
||||
typedef struct EV_ExpandRangeInfo EV_ExpandRangeInfo;
|
||||
struct EV_ExpandRangeInfo
|
||||
{
|
||||
U64 row_exprs_count;
|
||||
String8 *row_strings;
|
||||
String8 *row_view_rules;
|
||||
E_Expr **row_exprs;
|
||||
E_Member **row_members;
|
||||
};
|
||||
#define EV_EXPAND_RULE_INFO_FUNCTION_SIG(name) EV_ExpandInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr, E_Expr *tag)
|
||||
#define EV_EXPAND_RULE_INFO_FUNCTION_NAME(name) ev_expand_rule_info__##name
|
||||
#define EV_EXPAND_RULE_INFO_FUNCTION_DEF(name) internal EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_EXPAND_RULE_INFO_FUNCTION_NAME(name))
|
||||
typedef EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_ExpandRuleInfoHookFunctionType);
|
||||
|
||||
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(name) E_Expr *name(Arena *arena, E_Expr *expr, MD_Node *params)
|
||||
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name) ev_view_rule_expr_resolution__##name
|
||||
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name))
|
||||
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(name) EV_ExpandInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr, MD_Node *params)
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(name) ev_view_rule_expr_expand_info__##name
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(name))
|
||||
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(name) EV_ExpandRangeInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr, MD_Node *params, Rng1U64 idx_range, void *user_data)
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(name) ev_view_rule_expr_expand_range_info__##name
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(name))
|
||||
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(U64 num, void *user_data)
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name) ev_view_rule_expr_expand_id_from_num_##name
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name))
|
||||
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(U64 id, void *user_data)
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name) ev_view_rule_expr_expand_num_from_id_##name
|
||||
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name))
|
||||
|
||||
typedef EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(EV_ViewRuleExprResolutionHookFunctionType);
|
||||
typedef EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(EV_ViewRuleExprExpandInfoHookFunctionType);
|
||||
typedef EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(EV_ViewRuleExprExpandRangeInfoHookFunctionType);
|
||||
typedef EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(EV_ViewRuleExprExpandIDFromNumHookFunctionType);
|
||||
typedef EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(EV_ViewRuleExprExpandNumFromIDHookFunctionType);
|
||||
|
||||
typedef U32 EV_ViewRuleInfoFlags; // NOTE(rjf): see @view_rule_info
|
||||
enum
|
||||
{
|
||||
EV_ViewRuleInfoFlag_Inherited = (1<<0),
|
||||
EV_ViewRuleInfoFlag_Expandable = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleInfo EV_ViewRuleInfo;
|
||||
struct EV_ViewRuleInfo
|
||||
typedef struct EV_ExpandRule EV_ExpandRule;
|
||||
struct EV_ExpandRule
|
||||
{
|
||||
String8 string;
|
||||
EV_ViewRuleInfoFlags flags;
|
||||
EV_ViewRuleExprResolutionHookFunctionType *expr_resolution;
|
||||
EV_ViewRuleExprExpandInfoHookFunctionType *expr_expand_info;
|
||||
EV_ViewRuleExprExpandRangeInfoHookFunctionType *expr_expand_range_info;
|
||||
EV_ViewRuleExprExpandIDFromNumHookFunctionType *expr_expand_id_from_num;
|
||||
EV_ViewRuleExprExpandIDFromNumHookFunctionType *expr_expand_num_from_id;
|
||||
EV_ExpandRuleInfoHookFunctionType *info;
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleInfoNode EV_ViewRuleInfoNode;
|
||||
struct EV_ViewRuleInfoNode
|
||||
typedef struct EV_ExpandRuleNode EV_ExpandRuleNode;
|
||||
struct EV_ExpandRuleNode
|
||||
{
|
||||
EV_ViewRuleInfoNode *next;
|
||||
EV_ViewRuleInfo v;
|
||||
EV_ExpandRuleNode *next;
|
||||
EV_ExpandRule v;
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleInfoSlot EV_ViewRuleInfoSlot;
|
||||
struct EV_ViewRuleInfoSlot
|
||||
typedef struct EV_ExpandRuleSlot EV_ExpandRuleSlot;
|
||||
struct EV_ExpandRuleSlot
|
||||
{
|
||||
EV_ViewRuleInfoNode *first;
|
||||
EV_ViewRuleInfoNode *last;
|
||||
EV_ExpandRuleNode *first;
|
||||
EV_ExpandRuleNode *last;
|
||||
};
|
||||
|
||||
typedef struct EV_ViewRuleInfoTable EV_ViewRuleInfoTable;
|
||||
struct EV_ViewRuleInfoTable
|
||||
typedef struct EV_ExpandRuleTable EV_ExpandRuleTable;
|
||||
struct EV_ExpandRuleTable
|
||||
{
|
||||
EV_ViewRuleInfoSlot *slots;
|
||||
EV_ExpandRuleSlot *slots;
|
||||
U64 slots_count;
|
||||
};
|
||||
|
||||
typedef struct EV_ExpandRuleTagPair EV_ExpandRuleTagPair;
|
||||
struct EV_ExpandRuleTagPair
|
||||
{
|
||||
EV_ExpandRule *rule;
|
||||
E_Expr *tag;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Blocks
|
||||
|
||||
@@ -209,10 +149,12 @@ struct EV_Block
|
||||
// rjf: expression / visualization info
|
||||
String8 string;
|
||||
E_Expr *expr;
|
||||
EV_ViewRuleList *view_rules;
|
||||
EV_ViewRuleInfo *expand_view_rule_info;
|
||||
MD_Node *expand_view_rule_params;
|
||||
void *expand_view_rule_info_user_data;
|
||||
E_Expr *lookup_tag;
|
||||
E_Expr *expand_tag;
|
||||
E_LookupRule *lookup_rule;
|
||||
EV_ExpandRule *expand_rule;
|
||||
void *lookup_rule_user_data;
|
||||
void *expand_rule_user_data;
|
||||
|
||||
// rjf: expansion info
|
||||
U64 row_count;
|
||||
@@ -256,29 +198,27 @@ struct EV_BlockRangeList
|
||||
typedef struct EV_Row EV_Row;
|
||||
struct EV_Row
|
||||
{
|
||||
EV_Row *next;
|
||||
|
||||
// rjf: block hierarchy info
|
||||
EV_Block *block;
|
||||
EV_Key key;
|
||||
|
||||
// rjf: row size/scroll info
|
||||
U64 visual_size;
|
||||
U64 visual_size_skipped;
|
||||
U64 visual_size_chopped;
|
||||
|
||||
// rjf: expression / visualization info
|
||||
String8 string;
|
||||
E_Expr *expr;
|
||||
E_Member *member;
|
||||
EV_ViewRuleList *view_rules;
|
||||
};
|
||||
|
||||
typedef struct EV_WindowedRowNode EV_WindowedRowNode;
|
||||
struct EV_WindowedRowNode
|
||||
{
|
||||
EV_WindowedRowNode *next;
|
||||
U64 visual_size_skipped;
|
||||
U64 visual_size_chopped;
|
||||
EV_Row row;
|
||||
};
|
||||
|
||||
typedef struct EV_WindowedRowList EV_WindowedRowList;
|
||||
struct EV_WindowedRowList
|
||||
{
|
||||
EV_Row *first;
|
||||
EV_Row *last;
|
||||
EV_WindowedRowNode *first;
|
||||
EV_WindowedRowNode *last;
|
||||
U64 count;
|
||||
U64 count_before_visual;
|
||||
U64 count_before_semantic;
|
||||
@@ -329,29 +269,19 @@ enum
|
||||
////////////////////////////////
|
||||
//~ rjf: Nil/Identity View Rule Hooks
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(identity);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(nil);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(nil);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(nil);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only EV_ViewRuleInfo ev_nil_view_rule_info =
|
||||
global read_only EV_ExpandRule ev_nil_expand_rule =
|
||||
{
|
||||
{0},
|
||||
0,
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity),
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil),
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil),
|
||||
EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity),
|
||||
EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity),
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil),
|
||||
};
|
||||
thread_static EV_ViewRuleInfoTable *ev_view_rule_info_table = 0;
|
||||
global read_only EV_ViewRuleList ev_nil_view_rule_list = {0};
|
||||
thread_static EV_ExpandRuleTable *ev_view_rule_info_table = 0;
|
||||
thread_static EV_AutoViewRuleTable *ev_auto_view_rule_table = 0;
|
||||
global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, &e_expr_nil, &ev_nil_view_rule_list, &ev_nil_view_rule_info};
|
||||
global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_lookup_rule__nil, &ev_nil_expand_rule};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Key Functions
|
||||
@@ -387,39 +317,27 @@ internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Info Table Building / Selection / Lookups
|
||||
|
||||
internal void ev_view_rule_info_table_push(Arena *arena, EV_ViewRuleInfoTable *table, EV_ViewRuleInfo *info);
|
||||
internal void ev_view_rule_info_table_push_builtins(Arena *arena, EV_ViewRuleInfoTable *table);
|
||||
internal void ev_select_view_rule_info_table(EV_ViewRuleInfoTable *table);
|
||||
internal EV_ViewRuleInfo *ev_view_rule_info_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Automatic Type -> View Rule Table Building / Selection / Lookups
|
||||
|
||||
internal void ev_auto_view_rule_table_push_new(Arena *arena, EV_AutoViewRuleTable *table, E_TypeKey type_key, String8 view_rule, B32 is_required);
|
||||
internal void ev_select_auto_view_rule_table(EV_AutoViewRuleTable *table);
|
||||
internal EV_ViewRuleList *ev_auto_view_rules_from_type_key(Arena *arena, E_TypeKey type_key, B32 gather_required, B32 gather_optional);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: View Rule Instance List Building
|
||||
|
||||
internal void ev_view_rule_list_push_tree(Arena *arena, EV_ViewRuleList *list, MD_Node *root);
|
||||
internal void ev_view_rule_list_push_string(Arena *arena, EV_ViewRuleList *list, String8 string);
|
||||
internal EV_ViewRuleList *ev_view_rule_list_from_string(Arena *arena, String8 string);
|
||||
internal EV_ViewRuleList *ev_view_rule_list_from_expr_fastpaths(Arena *arena, String8 string);
|
||||
internal EV_ViewRuleList *ev_view_rule_list_from_inheritance(Arena *arena, EV_ViewRuleList *src);
|
||||
internal EV_ViewRuleList *ev_view_rule_list_copy(Arena *arena, EV_ViewRuleList *src);
|
||||
internal void ev_view_rule_list_concat_in_place(EV_ViewRuleList *dst, EV_ViewRuleList **src);
|
||||
internal void ev_expand_rule_table_push(Arena *arena, EV_ExpandRuleTable *table, EV_ExpandRule *info);
|
||||
#define ev_expand_rule_table_push_new(arena, table, ...) ev_expand_rule_table_push((arena), (table), &(EV_ExpandRule){__VA_ARGS__})
|
||||
internal void ev_select_expand_rule_table(EV_ExpandRuleTable *table);
|
||||
internal EV_ExpandRule *ev_expand_rule_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Resolution (Dynamic Overrides, View Rule Application)
|
||||
|
||||
internal E_Expr *ev_resolved_from_expr(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_rules);
|
||||
#if 0 // TODO(rjf): @cfg (dynamic type resolution)
|
||||
internal E_Expr *ev_resolved_from_expr(Arena *arena, E_Expr *expr);
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Upgrading Expressions w/ Tags From All Sources
|
||||
|
||||
internal void ev_keyed_expr_push_tags(Arena *arena, EV_View *view, EV_Block *block, EV_Key key, E_Expr *expr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Block Building
|
||||
|
||||
internal EV_BlockTree ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules);
|
||||
internal EV_BlockTree ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules);
|
||||
internal EV_BlockTree ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChain exprs);
|
||||
internal U64 ev_depth_from_block(EV_Block *block);
|
||||
|
||||
////////////////////////////////
|
||||
@@ -429,11 +347,15 @@ internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockT
|
||||
internal EV_BlockRange ev_block_range_from_num(EV_BlockRangeList *block_ranges, U64 num);
|
||||
internal EV_Key ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num);
|
||||
internal U64 ev_num_from_key(EV_BlockRangeList *block_ranges, EV_Key key);
|
||||
internal U64 ev_vnum_from_num(EV_BlockRangeList *block_ranges, U64 num);
|
||||
internal U64 ev_num_from_vnum(EV_BlockRangeList *block_ranges, U64 vidx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Row Building
|
||||
|
||||
internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 visible_range);
|
||||
internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 vnum_range);
|
||||
internal EV_Row *ev_row_from_num(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, U64 num);
|
||||
internal EV_WindowedRowList ev_rows_from_num_range(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 num_range);
|
||||
internal String8 ev_expr_string_from_row(Arena *arena, EV_Row *row, EV_StringFlags flags);
|
||||
internal B32 ev_row_is_expandable(EV_Row *row);
|
||||
internal B32 ev_row_is_editable(EV_Row *row);
|
||||
@@ -448,4 +370,9 @@ internal String8 ev_string_from_hresult_code(U32 code);
|
||||
internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringFlags flags, U32 radix, U32 min_digits, E_Eval eval);
|
||||
internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression & IR-Tree => Expand Rule
|
||||
|
||||
internal EV_ExpandRuleTagPair ev_expand_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree);
|
||||
|
||||
#endif // EVAL_VISUALIZATION_CORE_H
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "eval_visualization_core.c"
|
||||
#include "eval_visualization_builtin_view_rules.c"
|
||||
|
||||
@@ -5,6 +5,5 @@
|
||||
#define EVAL_VISUALIZATION_INC_H
|
||||
|
||||
#include "eval_visualization_core.h"
|
||||
#include "eval_visualization_builtin_view_rules.h"
|
||||
|
||||
#endif // EVAL_VISUALIZATION_INC_H
|
||||
|
||||
@@ -3,24 +3,3 @@
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
EV_ViewRuleInfo ev_builtin_view_rule_info_table[14] =
|
||||
{
|
||||
{str8_lit_comp("default"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(default) , EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(default) , EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("array"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(array) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("list"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(list) , EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(list) , EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("slice"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(slice) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("bswap"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(bswap) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("cast"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(cast) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("wrap"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(wrap) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("only"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(only) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("omit"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(omit) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("bin"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("oct"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("dec"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("hex"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
{str8_lit_comp("no_addr"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
|
||||
};
|
||||
|
||||
C_LINKAGE_END
|
||||
|
||||
|
||||
@@ -6,34 +6,4 @@
|
||||
#ifndef EVAL_VISUALIZATION_META_H
|
||||
#define EVAL_VISUALIZATION_META_H
|
||||
|
||||
typedef enum EV_ViewRuleKind
|
||||
{
|
||||
EV_ViewRuleKind_Default,
|
||||
EV_ViewRuleKind_Array,
|
||||
EV_ViewRuleKind_List,
|
||||
EV_ViewRuleKind_Slice,
|
||||
EV_ViewRuleKind_ByteSwap,
|
||||
EV_ViewRuleKind_Cast,
|
||||
EV_ViewRuleKind_Wrap,
|
||||
EV_ViewRuleKind_Only,
|
||||
EV_ViewRuleKind_Omit,
|
||||
EV_ViewRuleKind_Bin,
|
||||
EV_ViewRuleKind_Oct,
|
||||
EV_ViewRuleKind_Dec,
|
||||
EV_ViewRuleKind_Hex,
|
||||
EV_ViewRuleKind_NoAddress,
|
||||
EV_ViewRuleKind_COUNT,
|
||||
} EV_ViewRuleKind;
|
||||
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(wrap);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(only);
|
||||
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(omit);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(default);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(list);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(default);
|
||||
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(list);
|
||||
#endif // EVAL_VISUALIZATION_META_H
|
||||
|
||||
@@ -189,11 +189,11 @@ fs_key_from_path_range(String8 path, Rng1U64 range)
|
||||
return key;
|
||||
}
|
||||
|
||||
internal U64
|
||||
fs_timestamp_from_path(String8 path)
|
||||
internal FileProperties
|
||||
fs_properties_from_path(String8 path)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 result = 0;
|
||||
FileProperties result = {0};
|
||||
path = path_normalized_from_string(scratch.arena, path);
|
||||
U64 path_hash = fs_little_hash_from_string(path);
|
||||
U64 slot_idx = path_hash%fs_shared->slots_count;
|
||||
@@ -206,33 +206,7 @@ fs_timestamp_from_path(String8 path)
|
||||
{
|
||||
if(str8_match(path, n->path, 0))
|
||||
{
|
||||
result = n->timestamp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
fs_size_from_path(String8 path)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 result = 0;
|
||||
path = path_normalized_from_string(scratch.arena, path);
|
||||
U64 path_hash = fs_little_hash_from_string(path);
|
||||
U64 slot_idx = path_hash%fs_shared->slots_count;
|
||||
U64 stripe_idx = slot_idx%fs_shared->stripes_count;
|
||||
FS_Slot *slot = &fs_shared->slots[slot_idx];
|
||||
FS_Stripe *stripe = &fs_shared->stripes[stripe_idx];
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
for(FS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(path, n->path, 0))
|
||||
{
|
||||
result = n->size;
|
||||
result = n->props;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -314,8 +288,9 @@ ASYNC_WORK_DEF(fs_stream_work)
|
||||
ProfBegin("load \"%.*s\"", str8_varg(path));
|
||||
FileProperties pre_props = os_properties_from_file_path(path);
|
||||
U64 range_size = dim_1u64(range);
|
||||
U64 read_size = Min(pre_props.size, range_size);
|
||||
U64 read_size = Min(pre_props.size - range.min, range_size);
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, path);
|
||||
B32 file_handle_is_valid = !os_handle_match(os_handle_zero(), file);
|
||||
U64 data_arena_size = read_size+ARENA_HEADER_SIZE;
|
||||
data_arena_size += KB(4)-1;
|
||||
data_arena_size -= data_arena_size%KB(4);
|
||||
@@ -328,8 +303,12 @@ ASYNC_WORK_DEF(fs_stream_work)
|
||||
os_file_close(file);
|
||||
FileProperties post_props = os_properties_from_file_path(path);
|
||||
|
||||
//- rjf: abort if modification timestamps differ - we did not successfully read the file
|
||||
if(pre_props.modified != post_props.modified)
|
||||
//- rjf: abort if modification timestamps or sizes differ - we did not successfully read the file
|
||||
B32 read_good = (pre_props.modified == post_props.modified &&
|
||||
pre_props.size == post_props.size &&
|
||||
read_size == data.size &&
|
||||
(file_handle_is_valid || pre_props.flags & FilePropertyFlag_IsFolder));
|
||||
if(!read_good)
|
||||
{
|
||||
ProfScope("abort")
|
||||
{
|
||||
@@ -360,29 +339,13 @@ ASYNC_WORK_DEF(fs_stream_work)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node != 0)
|
||||
if(node != 0 && read_good)
|
||||
{
|
||||
if(node->timestamp != 0)
|
||||
if(node->props.modified != 0)
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&fs_shared->change_gen);
|
||||
}
|
||||
if(post_props.modified == pre_props.modified)
|
||||
{
|
||||
node->timestamp = post_props.modified;
|
||||
node->size = post_props.size;
|
||||
}
|
||||
U64 range_hash = fs_little_hash_from_string(str8_struct(&range));
|
||||
U64 range_slot_idx = range_hash%node->slots_count;
|
||||
FS_RangeSlot *range_slot = &node->slots[range_slot_idx];
|
||||
FS_RangeNode *range_node = 0;
|
||||
for(FS_RangeNode *n = range_slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(MemoryMatchStruct(&n->range, &range))
|
||||
{
|
||||
range_node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node->props = post_props;
|
||||
}
|
||||
}
|
||||
os_condition_variable_broadcast(path_stripe->cv);
|
||||
@@ -413,7 +376,7 @@ fs_detector_thread__entry_point(void *p)
|
||||
for(FS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
FileProperties props = os_properties_from_file_path(n->path);
|
||||
if(props.modified != n->timestamp)
|
||||
if(props.modified != n->props.modified)
|
||||
{
|
||||
for(U64 range_slot_idx = 0; range_slot_idx < n->slots_count; range_slot_idx += 1)
|
||||
{
|
||||
|
||||
@@ -31,8 +31,7 @@ struct FS_Node
|
||||
|
||||
// rjf: file metadata
|
||||
String8 path;
|
||||
U64 timestamp;
|
||||
U64 size;
|
||||
FileProperties props;
|
||||
|
||||
// rjf: sub-table of per-requested-file-range info
|
||||
U64 slots_count;
|
||||
@@ -108,8 +107,7 @@ internal U64 fs_change_gen(void);
|
||||
internal U128 fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us);
|
||||
internal U128 fs_key_from_path_range(String8 path, Rng1U64 range);
|
||||
|
||||
internal U64 fs_timestamp_from_path(String8 path);
|
||||
internal U64 fs_size_from_path(String8 path);
|
||||
internal FileProperties fs_properties_from_path(String8 path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Streaming Work
|
||||
|
||||
@@ -555,8 +555,8 @@ fnt_hash2style_from_tag_size_flags(FNT_Tag tag, F32 size, FNT_RasterFlags flags)
|
||||
hash2style_node = push_array(f_state->raster_arena, FNT_Hash2StyleRasterCacheNode, 1);
|
||||
DLLPushBack_NP(slot->first, slot->last, hash2style_node, hash_next, hash_prev);
|
||||
hash2style_node->style_hash = style_hash;
|
||||
hash2style_node->ascent = metrics.ascent;
|
||||
hash2style_node->descent= metrics.descent;
|
||||
hash2style_node->ascent = metrics.ascent;
|
||||
hash2style_node->descent = metrics.descent;
|
||||
hash2style_node->utf8_class1_direct_map = push_array_no_zero(f_state->raster_arena, F_RasterCacheInfo, 256);
|
||||
hash2style_node->hash2info_slots_count = 1024;
|
||||
hash2style_node->hash2info_slots = push_array(f_state->raster_arena, FNT_Hash2InfoRasterCacheSlot, hash2style_node->hash2info_slots_count);
|
||||
|
||||
@@ -191,6 +191,7 @@ fp_init(void)
|
||||
//- rjf: make sharp-hinted rendering params
|
||||
{
|
||||
FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params);
|
||||
gamma = 1.f;
|
||||
FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params);
|
||||
if(fp_dwrite_state->dwrite2_is_supported)
|
||||
{
|
||||
@@ -219,6 +220,7 @@ fp_init(void)
|
||||
//- rjf: make sharp-unhinted rendering params
|
||||
{
|
||||
FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params);
|
||||
gamma = 1.f;
|
||||
FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params);
|
||||
if(fp_dwrite_state->dwrite2_is_supported)
|
||||
{
|
||||
@@ -247,6 +249,7 @@ fp_init(void)
|
||||
//- rjf: make smooth-hinted rendering params
|
||||
{
|
||||
FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params);
|
||||
gamma = 1.f;
|
||||
FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params);
|
||||
if(fp_dwrite_state->dwrite2_is_supported)
|
||||
{
|
||||
@@ -432,7 +435,7 @@ fp_raster(Arena *arena, FP_Handle font_handle, F32 size, FP_RasterFlags flags, S
|
||||
F32 right_side_bearing = 0;
|
||||
if(font.face != 0)
|
||||
{
|
||||
atlas_dim.y = (S16)ceil_f32((96.f/72.f) * size * (font_metrics.ascent + font_metrics.descent) / design_units_per_em) + 1;
|
||||
atlas_dim.y = (S16)round_f32((96.f/72.f) * size * (font_metrics.ascent + font_metrics.descent + font_metrics.lineGap) / design_units_per_em) + 1;
|
||||
for(U64 idx = 0; idx < glyphs_count; idx += 1)
|
||||
{
|
||||
DWRITE_GLYPH_METRICS *glyph_metrics = glyphs_metrics + idx;
|
||||
@@ -476,11 +479,14 @@ fp_raster(Arena *arena, FP_Handle font_handle, F32 size, FP_RasterFlags flags, S
|
||||
}
|
||||
|
||||
//- rjf: draw glyph run
|
||||
Vec2F32 draw_p = {0, (F32)atlas_dim.y};
|
||||
Vec2F32 draw_p = {0, (F32)atlas_dim.y - 1};
|
||||
if(font.face != 0)
|
||||
{
|
||||
F32 descent = round_f32((96.f/72.f)*size * font_metrics.descent / design_units_per_em);
|
||||
F32 line_gap = round_f32((96.f/72.f)*size * font_metrics.lineGap / design_units_per_em);
|
||||
draw_p.y -= descent;
|
||||
draw_p.y -= line_gap;
|
||||
draw_p.y += 1;
|
||||
}
|
||||
DWRITE_GLYPH_RUN glyph_run = {0};
|
||||
if(font.face != 0)
|
||||
|
||||
+67
-10
@@ -108,7 +108,10 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
node = push_array(stripe->arena, HS_Node, 1);
|
||||
}
|
||||
node->hash = hash;
|
||||
node->arena = *data_arena;
|
||||
if(data_arena != 0)
|
||||
{
|
||||
node->arena = *data_arena;
|
||||
}
|
||||
node->data = data;
|
||||
node->scope_ref_count = 0;
|
||||
node->key_ref_count = 1;
|
||||
@@ -117,9 +120,15 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
else
|
||||
{
|
||||
existing_node->key_ref_count += 1;
|
||||
arena_release(*data_arena);
|
||||
if(data_arena != 0)
|
||||
{
|
||||
arena_release(*data_arena);
|
||||
}
|
||||
}
|
||||
if(data_arena != 0)
|
||||
{
|
||||
*data_arena = 0;
|
||||
}
|
||||
*data_arena = 0;
|
||||
}
|
||||
|
||||
//- rjf: commit this hash to key cache
|
||||
@@ -143,17 +152,17 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
|
||||
}
|
||||
if(key_node)
|
||||
{
|
||||
if(key_node->hash_history_gen >= ArrayCount(key_node->hash_history))
|
||||
if(key_node->hash_history_gen >= HS_KEY_HASH_HISTORY_STRONG_REF_COUNT)
|
||||
{
|
||||
key_expired_hash = key_node->hash_history[key_node->hash_history_gen%ArrayCount(key_node->hash_history)];
|
||||
key_expired_hash = key_node->hash_history[(key_node->hash_history_gen-HS_KEY_HASH_HISTORY_STRONG_REF_COUNT)%ArrayCount(key_node->hash_history)];
|
||||
}
|
||||
key_node->hash_history[key_node->hash_history_gen%ArrayCount(key_node->hash_history)] = hash;
|
||||
key_node->hash_history_gen += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: if this key's history cache was full, dec key ref count of oldest hash
|
||||
ProfScope("if this key's history cache was full, dec key ref count of oldest hash")
|
||||
//- rjf: decrement key ref count of expired hash
|
||||
ProfScope("decrement key ref count of expired hash")
|
||||
if(!u128_match(key_expired_hash, u128_zero()))
|
||||
{
|
||||
U64 old_hash_slot_idx = key_expired_hash.u64[1]%hs_shared->slots_count;
|
||||
@@ -241,6 +250,49 @@ hs_scope_touch_node__stripe_r_guarded(HS_Scope *scope, HS_Node *node)
|
||||
SLLStackPush(scope->top_touch, touch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Downstream Accesses
|
||||
|
||||
internal void
|
||||
hs_hash_downstream_inc(U128 hash)
|
||||
{
|
||||
U64 slot_idx = hash.u64[1]%hs_shared->slots_count;
|
||||
U64 stripe_idx = slot_idx%hs_shared->stripes_count;
|
||||
HS_Slot *slot = &hs_shared->slots[slot_idx];
|
||||
HS_Stripe *stripe = &hs_shared->stripes[stripe_idx];
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
for(HS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(u128_match(hash, n->hash))
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&n->downstream_ref_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
hs_hash_downstream_dec(U128 hash)
|
||||
{
|
||||
U64 slot_idx = hash.u64[1]%hs_shared->slots_count;
|
||||
U64 stripe_idx = slot_idx%hs_shared->stripes_count;
|
||||
HS_Slot *slot = &hs_shared->slots[slot_idx];
|
||||
HS_Stripe *stripe = &hs_shared->stripes[stripe_idx];
|
||||
OS_MutexScopeR(stripe->rw_mutex)
|
||||
{
|
||||
for(HS_Node *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
if(u128_match(hash, n->hash))
|
||||
{
|
||||
ins_atomic_u64_dec_eval(&n->downstream_ref_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Lookup
|
||||
|
||||
@@ -312,7 +364,8 @@ hs_evictor_thread__entry_point(void *p)
|
||||
{
|
||||
U64 key_ref_count = ins_atomic_u64_eval(&n->key_ref_count);
|
||||
U64 scope_ref_count = ins_atomic_u64_eval(&n->scope_ref_count);
|
||||
if(key_ref_count == 0 && scope_ref_count == 0)
|
||||
U64 downstream_ref_count = ins_atomic_u64_eval(&n->downstream_ref_count);
|
||||
if(key_ref_count == 0 && scope_ref_count == 0 && downstream_ref_count == 0)
|
||||
{
|
||||
slot_has_work = 1;
|
||||
break;
|
||||
@@ -326,11 +379,15 @@ hs_evictor_thread__entry_point(void *p)
|
||||
next = n->next;
|
||||
U64 key_ref_count = ins_atomic_u64_eval(&n->key_ref_count);
|
||||
U64 scope_ref_count = ins_atomic_u64_eval(&n->scope_ref_count);
|
||||
if(key_ref_count == 0 && scope_ref_count == 0)
|
||||
U64 downstream_ref_count = ins_atomic_u64_eval(&n->downstream_ref_count);
|
||||
if(key_ref_count == 0 && scope_ref_count == 0 && downstream_ref_count == 0)
|
||||
{
|
||||
DLLRemove(slot->first, slot->last, n);
|
||||
SLLStackPush(hs_shared->stripes_free_nodes[stripe_idx], n);
|
||||
arena_release(n->arena);
|
||||
if(n->arena != 0)
|
||||
{
|
||||
arena_release(n->arena);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
//~ rjf: Cache Types
|
||||
|
||||
#define HS_KEY_HASH_HISTORY_COUNT 64
|
||||
#define HS_KEY_HASH_HISTORY_STRONG_REF_COUNT 2
|
||||
|
||||
typedef struct HS_KeyNode HS_KeyNode;
|
||||
struct HS_KeyNode
|
||||
@@ -35,6 +36,7 @@ struct HS_Node
|
||||
String8 data;
|
||||
U64 scope_ref_count;
|
||||
U64 key_ref_count;
|
||||
U64 downstream_ref_count;
|
||||
};
|
||||
|
||||
typedef struct HS_Slot HS_Slot;
|
||||
@@ -138,6 +140,12 @@ internal HS_Scope *hs_scope_open(void);
|
||||
internal void hs_scope_close(HS_Scope *scope);
|
||||
internal void hs_scope_touch_node__stripe_r_guarded(HS_Scope *scope, HS_Node *node);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Downstream Accesses
|
||||
|
||||
internal void hs_hash_downstream_inc(U128 hash);
|
||||
internal void hs_hash_downstream_dec(U128 hash);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Lookups
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef int64_t RDI_S64;
|
||||
////////////////////////////////////////////////////////////////
|
||||
//~ Format Constants
|
||||
|
||||
// \"raddbg\0\0\"
|
||||
// "raddbg\0\0"
|
||||
#define RDI_MAGIC_CONSTANT 0x0000676264646172
|
||||
#define RDI_ENCODING_VERSION 11
|
||||
|
||||
|
||||
+9
-3
@@ -968,7 +968,10 @@ if(work_top == 0) {work_top = &broken_work;}\
|
||||
String8 tag_name = md_content_string_from_token_flags_str8(token[1].flags, tag_name_raw);
|
||||
MD_Node *node = md_push_node(arena, MD_NodeKind_Tag, md_node_flags_from_token_flags(token[1].flags), tag_name, tag_name_raw, token[0].range.min);
|
||||
DLLPushBack_NPZ(&md_nil_node, work_top->first_gathered_tag, work_top->last_gathered_tag, node, next, prev);
|
||||
if(token+2 < tokens_opl && token[2].flags & MD_TokenFlag_Reserved && str8_match(str8_substr(text, token[2].range), str8_lit("("), 0))
|
||||
if(token+2 < tokens_opl && token[2].flags & MD_TokenFlag_Reserved &&
|
||||
(str8_match(str8_substr(text, token[2].range), str8_lit("("), 0) ||
|
||||
str8_match(str8_substr(text, token[2].range), str8_lit("["), 0) ||
|
||||
str8_match(str8_substr(text, token[2].range), str8_lit("{"), 0)))
|
||||
{
|
||||
token += 3;
|
||||
MD_ParseWorkPush(MD_ParseWorkKind_Main, node);
|
||||
@@ -1052,10 +1055,13 @@ if(work_top == 0) {work_top = &broken_work;}\
|
||||
goto end_consume;
|
||||
}
|
||||
|
||||
//- rjf: [main_implicit] newline -> pop
|
||||
//- rjf: [main_implicit] newline -> pop *all* current implicit work tasks
|
||||
if(work_top->kind == MD_ParseWorkKind_MainImplicit && token->flags & MD_TokenFlag_Newline)
|
||||
{
|
||||
MD_ParseWorkPop();
|
||||
for(;work_top->kind == MD_ParseWorkKind_MainImplicit;)
|
||||
{
|
||||
MD_ParseWorkPop();
|
||||
}
|
||||
token += 1;
|
||||
goto end_consume;
|
||||
}
|
||||
|
||||
+17
-9
@@ -686,8 +686,8 @@ mg_string_from_row_desc_idx(MD_Node *row_parent, MG_ColumnDescArray descs, U64 i
|
||||
cell_idx -= 1;
|
||||
}
|
||||
}
|
||||
MD_Node *node = md_child_from_index(row_parent, cell_idx);
|
||||
result = node->string;
|
||||
MD_Node *node = md_child_from_index(row_parent, cell_idx);
|
||||
result = node->string;
|
||||
}break;
|
||||
|
||||
case MG_ColumnKind_CheckForTag:
|
||||
@@ -828,8 +828,8 @@ mg_eval_table_expand_expr__string(Arena *arena, MG_StrExpr *expr, MG_TableExpand
|
||||
}break;
|
||||
|
||||
case MG_StrExprOp_Null:
|
||||
{
|
||||
str8_list_push(arena, out, expr->node->string);
|
||||
{
|
||||
str8_list_push(arena, out, expr->node->string);
|
||||
}break;
|
||||
|
||||
case MG_StrExprOp_Dot:
|
||||
@@ -900,7 +900,14 @@ mg_eval_table_expand_expr__string(Arena *arena, MG_StrExpr *expr, MG_TableExpand
|
||||
}
|
||||
|
||||
// rjf: push lookup string
|
||||
{
|
||||
{
|
||||
B32 is_multiline = (str8_find_needle(lookup_string, 0, str8_lit("\n"), 0) < lookup_string.size);
|
||||
if(is_multiline)
|
||||
{
|
||||
lookup_string = indented_from_string(mg_arena, lookup_string);
|
||||
lookup_string = escaped_from_raw_str8(mg_arena, lookup_string);
|
||||
lookup_string = escaped_from_raw_str8(mg_arena, lookup_string);
|
||||
}
|
||||
str8_list_push(arena, out, lookup_string);
|
||||
}
|
||||
}break;
|
||||
@@ -1010,9 +1017,10 @@ mg_loop_table_column_expansion(Arena *arena, String8 strexpr, MG_TableExpandInfo
|
||||
char_idx += 1;
|
||||
}
|
||||
}
|
||||
String8 expansion_str = str8_list_join(arena, &expansion_strs, 0);
|
||||
String8 expansion_str = str8_list_join(arena, &expansion_strs, 0);
|
||||
if(expansion_str.size != 0)
|
||||
{
|
||||
{
|
||||
expansion_str = raw_from_escaped_str8(mg_arena, expansion_str);
|
||||
str8_list_push(arena, out, expansion_str);
|
||||
}
|
||||
}
|
||||
@@ -1028,7 +1036,7 @@ mg_string_list_from_table_gen(Arena *arena, MG_Map grid_name_map, MG_Map grid_co
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
if(md_node_is_nil(gen->first) && gen->string.size != 0)
|
||||
{
|
||||
str8_list_push(arena, &result, gen->string);
|
||||
str8_list_push(arena, &result, raw_from_escaped_str8(arena, gen->string));
|
||||
str8_list_push(arena, &result, str8_lit("\n"));
|
||||
}
|
||||
else for MD_EachNode(strexpr_node, gen->first)
|
||||
@@ -1080,7 +1088,7 @@ mg_string_list_from_table_gen(Arena *arena, MG_Map grid_name_map, MG_Map grid_co
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_push(arena, &result, strexpr_node->string);
|
||||
str8_list_push(arena, &result, raw_from_escaped_str8(arena, strexpr_node->string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,16 @@ arena_alloc_(ArenaParams *params)
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->cmt_size = params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
#if ARENA_FREE_LIST
|
||||
arena->free_size = 0;
|
||||
arena->free_last = 0;
|
||||
#endif
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
@@ -85,30 +89,67 @@ arena_push(Arena *arena, U64 size, U64 align)
|
||||
// rjf: chain, if needed
|
||||
if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
if(size + ARENA_HEADER_SIZE > res_size)
|
||||
Arena *new_block = 0;
|
||||
|
||||
#if ARENA_FREE_LIST
|
||||
Arena *prev_block;
|
||||
for(new_block = arena->free_last, prev_block = 0; new_block != 0; prev_block = new_block, new_block = new_block->prev)
|
||||
{
|
||||
res_size = size + ARENA_HEADER_SIZE;
|
||||
cmt_size = size + ARENA_HEADER_SIZE;
|
||||
if(new_block->res >= AlignPow2(size, align))
|
||||
{
|
||||
if(prev_block)
|
||||
{
|
||||
prev_block->prev = new_block->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
arena->free_last = new_block->prev;
|
||||
}
|
||||
arena->free_size -= new_block->res_size;
|
||||
AsanUnpoisonMemoryRegion((U8*)new_block + ARENA_HEADER_SIZE, new_block->res_size - ARENA_HEADER_SIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Arena *new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags);
|
||||
#endif
|
||||
|
||||
if(new_block == 0)
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
if(size + ARENA_HEADER_SIZE > res_size)
|
||||
{
|
||||
res_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
|
||||
cmt_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
|
||||
}
|
||||
new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags);
|
||||
}
|
||||
|
||||
new_block->base_pos = current->base_pos + current->res;
|
||||
SLLStackPush_N(arena->current, new_block, prev);
|
||||
|
||||
current = new_block;
|
||||
pos_pre = AlignPow2(current->pos, align);
|
||||
pos_pst = pos_pre + size;
|
||||
}
|
||||
|
||||
// rjf: commit new pages, if needed
|
||||
if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
|
||||
if(current->cmt < pos_pst)
|
||||
{
|
||||
U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
|
||||
U64 cmt_pst_aligned = pos_pst + current->cmt_size-1;
|
||||
cmt_pst_aligned -= cmt_pst_aligned%current->cmt_size;
|
||||
U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
|
||||
U64 cmt_size = cmt_pst_clamped - current->cmt;
|
||||
os_commit((U8 *)current + current->cmt, cmt_size);
|
||||
U8 *cmt_ptr = (U8 *)current + current->cmt;
|
||||
if(current->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
os_commit_large(cmt_ptr, cmt_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_commit(cmt_ptr, cmt_size);
|
||||
}
|
||||
current->cmt = cmt_pst_clamped;
|
||||
}
|
||||
|
||||
@@ -146,11 +187,23 @@ arena_pop_to(Arena *arena, U64 pos)
|
||||
{
|
||||
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
|
||||
Arena *current = arena->current;
|
||||
|
||||
#if ARENA_FREE_LIST
|
||||
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||
{
|
||||
prev = current->prev;
|
||||
current->pos = ARENA_HEADER_SIZE;
|
||||
arena->free_size += current->res_size;
|
||||
SLLStackPush_N(arena->free_last, current, prev);
|
||||
AsanPoisonMemoryRegion((U8*)current + ARENA_HEADER_SIZE, current->res_size - ARENA_HEADER_SIZE);
|
||||
}
|
||||
#else
|
||||
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||
{
|
||||
prev = current->prev;
|
||||
os_release(current, current->res);
|
||||
}
|
||||
#endif
|
||||
arena->current = current;
|
||||
U64 new_pos = big_pos - current->base_pos;
|
||||
AssertAlways(new_pos <= current->pos);
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Constants
|
||||
|
||||
#define ARENA_HEADER_SIZE 64
|
||||
#define ARENA_HEADER_SIZE 128
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Types
|
||||
|
||||
typedef U32 ArenaFlags;
|
||||
typedef U64 ArenaFlags;
|
||||
enum
|
||||
{
|
||||
ArenaFlag_NoChain = (1<<0),
|
||||
@@ -34,12 +34,16 @@ struct Arena
|
||||
Arena *prev; // previous arena in chain
|
||||
Arena *current; // current arena in chain
|
||||
ArenaFlags flags;
|
||||
U32 cmt_size;
|
||||
U64 cmt_size;
|
||||
U64 res_size;
|
||||
U64 base_pos;
|
||||
U64 pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
#if ARENA_FREE_LIST
|
||||
U64 free_size;
|
||||
Arena *free_last;
|
||||
#endif
|
||||
};
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
|
||||
@@ -50,12 +54,19 @@ struct Temp
|
||||
U64 pos;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Global Defaults
|
||||
|
||||
global U64 arena_default_reserve_size = MB(64);
|
||||
global U64 arena_default_commit_size = KB(64);
|
||||
global ArenaFlags arena_default_flags = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
internal Arena *arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__})
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, __VA_ARGS__})
|
||||
internal void arena_release(Arena *arena);
|
||||
|
||||
//- rjf: arena push/pop/pos core functions
|
||||
|
||||
@@ -98,9 +98,10 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
|
||||
next = node->next;
|
||||
String8 option_name = node->string;
|
||||
|
||||
// NOTE(rjf): Look at -- or - at the start of an argument to determine if it's
|
||||
// a flag option. All arguments after a single "--" (with no trailing string
|
||||
// on the command line will be considered as input files.
|
||||
// NOTE(rjf): Look at --, -, or / (only on Windows) at the start of an
|
||||
// argument to determine if it's a flag option. All arguments after a
|
||||
// single "--" (with no trailing string on the command line will be
|
||||
// considered as input files.
|
||||
B32 is_option = 1;
|
||||
if(after_passthrough_option == 0)
|
||||
{
|
||||
@@ -117,6 +118,11 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
|
||||
{
|
||||
option_name = str8_skip(option_name, 1);
|
||||
}
|
||||
else if(operating_system_from_context() == OperatingSystem_Windows &&
|
||||
str8_match(str8_prefix(node->string, 1), str8_lit("/"), 0))
|
||||
{
|
||||
option_name = str8_skip(option_name, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_option = 0;
|
||||
@@ -184,6 +190,18 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fill argc/argv
|
||||
parsed.argc = command_line.node_count;
|
||||
parsed.argv = push_array(arena, char *, parsed.argc);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(String8Node *n = command_line.first; n != 0; n = n->next)
|
||||
{
|
||||
parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ struct CmdLine
|
||||
String8List inputs;
|
||||
U64 option_table_size;
|
||||
CmdLineOpt **option_table;
|
||||
U64 argc;
|
||||
char **argv;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -155,11 +155,11 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_MINOR)
|
||||
# define BUILD_VERSION_MINOR 0
|
||||
# define BUILD_VERSION_MINOR 9
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 0
|
||||
# define BUILD_VERSION_PATCH 14
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
@@ -183,7 +183,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_ISSUES_LINK_STRING_LITERAL)
|
||||
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGames/raddebugger/issues"
|
||||
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGamesExt/raddebugger/issues"
|
||||
#endif
|
||||
|
||||
#define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND
|
||||
|
||||
@@ -143,12 +143,6 @@ bswap_u64(U64 x)
|
||||
|
||||
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
|
||||
|
||||
internal U64
|
||||
count_bits_set16(U16 val)
|
||||
{
|
||||
return __popcnt16(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set32(U32 val)
|
||||
{
|
||||
@@ -195,46 +189,40 @@ clz64(U64 mask)
|
||||
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
|
||||
internal U64
|
||||
count_bits_set16(U16 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
return __builtin_popcount(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set64(U64 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
return __builtin_popcountll(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctz32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
return __builtin_ctz(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
return __builtin_clz(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctz64(U64 val)
|
||||
{
|
||||
return __builtin_ctzll(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz64(U64 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
return __builtin_clzll(val);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -399,23 +387,23 @@ txt_rng_contains(TxtRng r, TxtPt pt)
|
||||
//~ rjf: Toolchain/Environment Enum Functions
|
||||
|
||||
internal U64
|
||||
bit_size_from_arch(Architecture arch)
|
||||
bit_size_from_arch(Arch arch)
|
||||
{
|
||||
// TODO(rjf): metacode
|
||||
U64 arch_bitsize = 0;
|
||||
switch(arch)
|
||||
{
|
||||
case Architecture_x64: arch_bitsize = 64; break;
|
||||
case Architecture_x86: arch_bitsize = 32; break;
|
||||
case Architecture_arm64: arch_bitsize = 64; break;
|
||||
case Architecture_arm32: arch_bitsize = 32; break;
|
||||
case Arch_x64: arch_bitsize = 64; break;
|
||||
case Arch_x86: arch_bitsize = 32; break;
|
||||
case Arch_arm64: arch_bitsize = 64; break;
|
||||
case Arch_arm32: arch_bitsize = 32; break;
|
||||
default: break;
|
||||
}
|
||||
return arch_bitsize;
|
||||
}
|
||||
|
||||
internal U64
|
||||
max_instruction_size_from_arch(Architecture arch)
|
||||
max_instruction_size_from_arch(Arch arch)
|
||||
{
|
||||
// TODO(rjf): make this real
|
||||
return 64;
|
||||
@@ -434,17 +422,17 @@ operating_system_from_context(void){
|
||||
return os;
|
||||
}
|
||||
|
||||
internal Architecture
|
||||
architecture_from_context(void){
|
||||
Architecture arch = Architecture_Null;
|
||||
internal Arch
|
||||
arch_from_context(void){
|
||||
Arch arch = Arch_Null;
|
||||
#if ARCH_X64
|
||||
arch = Architecture_x64;
|
||||
arch = Arch_x64;
|
||||
#elif ARCH_X86
|
||||
arch = Architecture_x86;
|
||||
arch = Arch_x86;
|
||||
#elif ARCH_ARM64
|
||||
arch = Architecture_arm64;
|
||||
arch = Arch_arm64;
|
||||
#elif ARCH_ARM32
|
||||
arch = Architecture_arm32;
|
||||
arch = Arch_arm32;
|
||||
#endif
|
||||
return arch;
|
||||
}
|
||||
@@ -526,6 +514,60 @@ date_time_from_micro_seconds(U64 time){
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal DateTime
|
||||
date_time_from_unix_time(U64 unix_time)
|
||||
{
|
||||
DateTime date = {0};
|
||||
date.year = 1970;
|
||||
date.day = 1 + (unix_time / 86400);
|
||||
date.sec = (U32)unix_time % 60;
|
||||
date.min = (U32)(unix_time / 60) % 60;
|
||||
date.hour = (U32)(unix_time / 3600) % 24;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
for(date.month = 0; date.month < 12; ++date.month)
|
||||
{
|
||||
U64 c = 0;
|
||||
switch(date.month)
|
||||
{
|
||||
case Month_Jan: c = 31; break;
|
||||
case Month_Feb:
|
||||
{
|
||||
if((date.year % 4 == 0) && ((date.year % 100) != 0 || (date.year % 400) == 0))
|
||||
{
|
||||
c = 29;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 28;
|
||||
}
|
||||
} break;
|
||||
case Month_Mar: c = 31; break;
|
||||
case Month_Apr: c = 30; break;
|
||||
case Month_May: c = 31; break;
|
||||
case Month_Jun: c = 30; break;
|
||||
case Month_Jul: c = 31; break;
|
||||
case Month_Aug: c = 31; break;
|
||||
case Month_Sep: c = 30; break;
|
||||
case Month_Oct: c = 31; break;
|
||||
case Month_Nov: c = 30; break;
|
||||
case Month_Dec: c = 31; break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
if(date.day <= c)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
date.day -= c;
|
||||
}
|
||||
++date.year;
|
||||
}
|
||||
exit:;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
||||
|
||||
|
||||
@@ -40,6 +40,12 @@
|
||||
# define thread_static __thread
|
||||
#endif
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# define force_inline __forceinline
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
# define force_inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Linkage Keyword Macros
|
||||
|
||||
@@ -118,8 +124,10 @@
|
||||
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
|
||||
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
||||
|
||||
#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1)
|
||||
#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1)
|
||||
#define EachIndex(it, count) (U64 it = 0; it < (count); it += 1)
|
||||
#define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1)
|
||||
#define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1))
|
||||
#define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory Operation Macros
|
||||
@@ -170,33 +178,49 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Atomic Operations
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include <windows.h>
|
||||
# include <tmmintrin.h>
|
||||
# include <wmmintrin.h>
|
||||
#if COMPILER_MSVC
|
||||
# include <intrin.h>
|
||||
# if ARCH_X64
|
||||
# define ins_atomic_u64_eval(x) InterlockedAdd64((volatile __int64 *)(x), 0)
|
||||
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
||||
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
|
||||
# define ins_atomic_u64_eval(x) *((volatile U64 *)(x))
|
||||
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
||||
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
|
||||
# define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c))
|
||||
# define ins_atomic_u32_eval(x,c) InterlockedAdd((volatile LONG *)(x), 0)
|
||||
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
||||
# define ins_atomic_u32_eval(x) *((volatile U32 *)(x))
|
||||
# define ins_atomic_u32_inc_eval(x) InterlockedIncrement((volatile LONG *)x)
|
||||
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
|
||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
|
||||
# define ins_atomic_u32_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c)
|
||||
# else
|
||||
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||
# endif
|
||||
#elif OS_LINUX
|
||||
# if ARCH_X64
|
||||
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
|
||||
# else
|
||||
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||
# error Atomic intrinsics not defined for this compiler / architecture combination.
|
||||
# endif
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
# define ins_atomic_u64_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
# define ins_atomic_u64_inc_eval(x) (__atomic_fetch_add((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) + 1)
|
||||
# define ins_atomic_u64_dec_eval(x) (__atomic_fetch_sub((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) - 1)
|
||||
# define ins_atomic_u64_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST)
|
||||
# define ins_atomic_u64_add_eval(x,c) (__atomic_fetch_add((volatile U64 *)(x), c, __ATOMIC_SEQ_CST) + (c))
|
||||
# define ins_atomic_u64_eval_cond_assign(x,k,c) ({ U64 _new = (c); __atomic_compare_exchange_n((volatile U64 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
|
||||
# define ins_atomic_u32_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
# define ins_atomic_u32_inc_eval(x) (__atomic_fetch_add((volatile U32 *)(x), 1, __ATOMIC_SEQ_CST) + 1)
|
||||
# define ins_atomic_u32_add_eval(x,c) (__atomic_fetch_add((volatile U32 *)(x), c, __ATOMIC_SEQ_CST) + (c))
|
||||
# define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST)
|
||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((volatile U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
|
||||
#else
|
||||
# error Atomic intrinsics not defined for this operating system.
|
||||
# error Atomic intrinsics not defined for this compiler / architecture.
|
||||
#endif
|
||||
|
||||
#if ARCH_64BIT
|
||||
# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u64_eval_cond_assign((volatile U64 *)(x), (U64)(k), (U64)(c))
|
||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile U64 *)(x), (U64)(c))
|
||||
# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u64_eval((volatile U64 *)x)
|
||||
#elif ARCH_32BIT
|
||||
# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u32_eval_cond_assign((volatile U32 *)(x), (U32)(k), (U32)(c))
|
||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u32_eval_assign((volatile U32 *)(x), (U32)(c))
|
||||
# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u32_eval((volatile U32 *)x)
|
||||
#else
|
||||
# error Atomic intrinsics for pointers not defined for this architecture.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
@@ -430,16 +454,25 @@ typedef enum OperatingSystem
|
||||
}
|
||||
OperatingSystem;
|
||||
|
||||
typedef enum Architecture
|
||||
typedef enum ImageType
|
||||
{
|
||||
Architecture_Null,
|
||||
Architecture_x64,
|
||||
Architecture_x86,
|
||||
Architecture_arm64,
|
||||
Architecture_arm32,
|
||||
Architecture_COUNT,
|
||||
Image_Null,
|
||||
Image_CoffPe,
|
||||
Image_Elf32,
|
||||
Image_Elf64,
|
||||
Image_Macho
|
||||
} ImageType;
|
||||
|
||||
typedef enum Arch
|
||||
{
|
||||
Arch_Null,
|
||||
Arch_x64,
|
||||
Arch_x86,
|
||||
Arch_arm64,
|
||||
Arch_arm32,
|
||||
Arch_COUNT,
|
||||
}
|
||||
Architecture;
|
||||
Arch;
|
||||
|
||||
typedef enum Compiler
|
||||
{
|
||||
@@ -468,6 +501,51 @@ struct TxtRng
|
||||
TxtPt max;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Globally Unique Ids
|
||||
|
||||
typedef union Guid Guid;
|
||||
union Guid
|
||||
{
|
||||
struct
|
||||
{
|
||||
U32 data1;
|
||||
U16 data2;
|
||||
U16 data3;
|
||||
U8 data4[8];
|
||||
};
|
||||
U8 v[16];
|
||||
};
|
||||
StaticAssert(sizeof(Guid) == 16, g_guid_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Arrays
|
||||
|
||||
typedef struct U16Array U16Array;
|
||||
struct U16Array
|
||||
{
|
||||
U64 count;
|
||||
U16 *v;
|
||||
};
|
||||
typedef struct U32Array U32Array;
|
||||
struct U32Array
|
||||
{
|
||||
U64 count;
|
||||
U32 *v;
|
||||
};
|
||||
typedef struct U64Array U64Array;
|
||||
struct U64Array
|
||||
{
|
||||
U64 count;
|
||||
U64 *v;
|
||||
};
|
||||
typedef struct U128Array U128Array;
|
||||
struct U128Array
|
||||
{
|
||||
U64 count;
|
||||
U128 *v;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Constants
|
||||
|
||||
@@ -734,7 +812,16 @@ internal U16 bswap_u16(U16 x);
|
||||
internal U32 bswap_u32(U32 x);
|
||||
internal U64 bswap_u64(U64 x);
|
||||
|
||||
internal U64 count_bits_set16(U16 val);
|
||||
#if ARCH_LITTLE_ENDIAN
|
||||
# define from_be_u16(x) bswap_u16(x)
|
||||
# define from_be_u32(x) bswap_u32(x)
|
||||
# define from_be_u64(x) bswap_u64(x)
|
||||
#else
|
||||
# define from_be_u16(x) (x)
|
||||
# define from_be_u32(x) (x)
|
||||
# define from_be_u64(x) (x)
|
||||
#endif
|
||||
|
||||
internal U64 count_bits_set32(U32 val);
|
||||
internal U64 count_bits_set64(U64 val);
|
||||
|
||||
@@ -770,19 +857,20 @@ internal B32 txt_rng_contains(TxtRng r, TxtPt pt);
|
||||
////////////////////////////////
|
||||
//~ rjf: Toolchain/Environment Enum Functions
|
||||
|
||||
internal U64 bit_size_from_arch(Architecture arch);
|
||||
internal U64 max_instruction_size_from_arch(Architecture arch);
|
||||
internal U64 bit_size_from_arch(Arch arch);
|
||||
internal U64 max_instruction_size_from_arch(Arch arch);
|
||||
|
||||
internal OperatingSystem operating_system_from_context(void);
|
||||
internal Architecture architecture_from_context(void);
|
||||
internal Arch arch_from_context(void);
|
||||
internal Compiler compiler_from_context(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Functions
|
||||
|
||||
internal DenseTime dense_time_from_date_time(DateTime date_time);
|
||||
internal DateTime date_time_from_dense_time(DenseTime time);
|
||||
internal DateTime date_time_from_micro_seconds(U64 time);
|
||||
internal DateTime date_time_from_dense_time(DenseTime time);
|
||||
internal DateTime date_time_from_micro_seconds(U64 time);
|
||||
internal DateTime date_time_from_unix_time(U64 unix_time);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
||||
|
||||
@@ -1,26 +1,43 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
global U64 global_update_tick_idx = 0;
|
||||
|
||||
internal void
|
||||
main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count)
|
||||
main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
ThreadNameF("[main thread]");
|
||||
|
||||
//- rjf: set up telemetry
|
||||
#if PROFILE_TELEMETRY
|
||||
local_persist U8 tm_data[MB(64)];
|
||||
local_persist char tm_data[MB(64)];
|
||||
tmLoadLibrary(TM_RELEASE);
|
||||
tmSetMaxThreadCount(256);
|
||||
tmInitialize(sizeof(tm_data), (char *)tm_data);
|
||||
tmInitialize(sizeof(tm_data), tm_data);
|
||||
#endif
|
||||
ThreadNameF("[main thread]");
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, (int)arguments_count, arguments);
|
||||
|
||||
//- rjf: parse command line
|
||||
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments);
|
||||
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
|
||||
|
||||
//- rjf: begin captures
|
||||
B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture"));
|
||||
if(capture)
|
||||
{
|
||||
ProfBeginCapture(arguments[0]);
|
||||
}
|
||||
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
|
||||
ts_init();
|
||||
|
||||
#if PROFILE_TELEMETRY
|
||||
tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE);
|
||||
#endif
|
||||
|
||||
//- rjf: initialize all included layers
|
||||
#if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL)
|
||||
async_init(&cmdline);
|
||||
#endif
|
||||
#if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL)
|
||||
p2r_init();
|
||||
#endif
|
||||
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
|
||||
hs_init();
|
||||
@@ -37,19 +54,16 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum
|
||||
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
|
||||
dasm_init();
|
||||
#endif
|
||||
#if defined(DI_H) && !defined(DI_INIT_MANUAL)
|
||||
#if defined(DBGI_H) && !defined(DI_INIT_MANUAL)
|
||||
di_init();
|
||||
#endif
|
||||
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
|
||||
fzy_init();
|
||||
#endif
|
||||
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
|
||||
dmn_init();
|
||||
#endif
|
||||
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
|
||||
ctrl_init();
|
||||
#endif
|
||||
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL)
|
||||
#if defined(OS_GFX_H) && !defined(OS_GFX_INIT_MANUAL)
|
||||
os_gfx_init();
|
||||
#endif
|
||||
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
|
||||
@@ -64,21 +78,25 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum
|
||||
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
|
||||
geo_init();
|
||||
#endif
|
||||
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL)
|
||||
f_init();
|
||||
#if defined(FONT_CACHE_H) && !defined(FNT_INIT_MANUAL)
|
||||
fnt_init();
|
||||
#endif
|
||||
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL)
|
||||
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
|
||||
df_core_init(&cmdline, hist);
|
||||
#if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL)
|
||||
d_init();
|
||||
#endif
|
||||
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL)
|
||||
df_gfx_init(update_and_render, df_state_delta_history());
|
||||
#if defined(RADDBG_CORE_H) && !defined(RD_INIT_MANUAL)
|
||||
rd_init(&cmdline);
|
||||
#endif
|
||||
|
||||
//- rjf: call into entry point
|
||||
entry_point(&cmdline);
|
||||
|
||||
//- rjf: end captures
|
||||
if(capture)
|
||||
{
|
||||
ProfEndCapture();
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@@ -90,3 +108,23 @@ supplement_thread_base_entry_point(void (*entry_point)(void *params), void *para
|
||||
entry_point(params);
|
||||
tctx_release();
|
||||
}
|
||||
|
||||
internal U64
|
||||
update_tick_idx(void)
|
||||
{
|
||||
U64 result = ins_atomic_u64_eval(&global_update_tick_idx);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
update(void)
|
||||
{
|
||||
ProfTick(0);
|
||||
ins_atomic_u64_inc_eval(&global_update_tick_idx);
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
B32 result = frame();
|
||||
#else
|
||||
B32 result = 0;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#ifndef BASE_ENTRY_POINT_H
|
||||
#define BASE_ENTRY_POINT_H
|
||||
|
||||
internal void main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count);
|
||||
internal void main_thread_base_entry_point(int argc, char **argv);
|
||||
internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params);
|
||||
internal U64 update_tick_idx(void);
|
||||
internal B32 update(void);
|
||||
|
||||
#endif // BASE_ENTRY_POINT_H
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Base Includes
|
||||
|
||||
#undef RADDBG_LAYER_COLOR
|
||||
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f
|
||||
#undef MARKUP_LAYER_COLOR
|
||||
#define MARKUP_LAYER_COLOR 0.20f, 0.60f, 0.80f
|
||||
|
||||
#include "metagen_base_core.c"
|
||||
#include "metagen_base_profile.c"
|
||||
@@ -15,5 +15,6 @@
|
||||
#include "metagen_base_thread_context.c"
|
||||
#include "metagen_base_command_line.c"
|
||||
#include "metagen_base_markup.c"
|
||||
#include "metagen_base_meta.c"
|
||||
#include "metagen_base_log.c"
|
||||
#include "metagen_base_entry_point.c"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "metagen_base_thread_context.h"
|
||||
#include "metagen_base_command_line.h"
|
||||
#include "metagen_base_markup.h"
|
||||
#include "metagen_base_meta.h"
|
||||
#include "metagen_base_log.h"
|
||||
#include "metagen_base_entry_point.h"
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ log_scope_end(Arena *arena)
|
||||
SLLStackPop(log_active->top_scope);
|
||||
if(arena != 0)
|
||||
{
|
||||
for(EachEnumVal(LogMsgKind, kind))
|
||||
for EachEnumVal(LogMsgKind, kind)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0);
|
||||
|
||||
@@ -394,7 +394,7 @@ internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.m
|
||||
internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal U32 dim_1u32(Rng1U32 r) {U32 c = r.max-r.min; return c;}
|
||||
internal U32 dim_1u32(Rng1U32 r) {U32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;}
|
||||
internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
@@ -404,7 +404,7 @@ internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.m
|
||||
internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal S32 dim_1s32(Rng1S32 r) {S32 c = r.max-r.min; return c;}
|
||||
internal S32 dim_1s32(Rng1S32 r) {S32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;}
|
||||
internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
@@ -414,7 +414,7 @@ internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.m
|
||||
internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;}
|
||||
internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal U64 dim_1u64(Rng1U64 r) {U64 c = r.max-r.min; return c;}
|
||||
internal U64 dim_1u64(Rng1U64 r) {U64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;}
|
||||
internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
@@ -424,7 +424,7 @@ internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.m
|
||||
internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;}
|
||||
internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal S64 dim_1s64(Rng1S64 r) {S64 c = r.max-r.min; return c;}
|
||||
internal S64 dim_1s64(Rng1S64 r) {S64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;}
|
||||
internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
@@ -434,7 +434,7 @@ internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.m
|
||||
internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal F32 dim_1f32(Rng1F32 r) {F32 c = r.max-r.min; return c;}
|
||||
internal F32 dim_1f32(Rng1F32 r) {F32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;}
|
||||
internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
@@ -444,7 +444,7 @@ internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s1
|
||||
internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;}
|
||||
internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;}
|
||||
internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(r.max.x-r.min.x), (S16)(r.max.y-r.min.y)}; return dim;}
|
||||
internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0)), (S16)(((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0))}; return dim;}
|
||||
internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
@@ -454,7 +454,7 @@ internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s3
|
||||
internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;}
|
||||
internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;}
|
||||
internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
@@ -464,7 +464,7 @@ internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s6
|
||||
internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;}
|
||||
internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;}
|
||||
internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
@@ -474,7 +474,7 @@ internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f3
|
||||
internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;}
|
||||
internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;}
|
||||
internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
@@ -591,6 +591,49 @@ u32_from_rgba(Vec4F32 rgba)
|
||||
////////////////////////////////
|
||||
//~ rjf: List Type Functions
|
||||
|
||||
internal void
|
||||
rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng)
|
||||
{
|
||||
Rng1U64Node *n = push_array(arena, Rng1U64Node, 1);
|
||||
MemoryCopyStruct(&n->v, &rng);
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
list->count += 1;
|
||||
}
|
||||
|
||||
internal void
|
||||
rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat)
|
||||
{
|
||||
if(to_concat->first)
|
||||
{
|
||||
if(list->first)
|
||||
{
|
||||
list->last->next = to_concat->first;
|
||||
list->last = to_concat->last;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->first = to_concat->first;
|
||||
list->last = to_concat->last;
|
||||
}
|
||||
MemoryZeroStruct(to_concat);
|
||||
}
|
||||
}
|
||||
|
||||
internal Rng1U64Array
|
||||
rng1u64_array_from_list(Arena *arena, Rng1U64List *list)
|
||||
{
|
||||
Rng1U64Array arr = {0};
|
||||
arr.count = list->count;
|
||||
arr.v = push_array_no_zero(arena, Rng1U64, arr.count);
|
||||
U64 idx = 0;
|
||||
for(Rng1U64Node *n = list->first; n != 0; n = n->next)
|
||||
{
|
||||
arr.v[idx] = n->v;
|
||||
idx += 1;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
internal void
|
||||
rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng)
|
||||
{
|
||||
|
||||
@@ -329,6 +329,28 @@ union Rng2S64
|
||||
////////////////////////////////
|
||||
//~ rjf: List Types
|
||||
|
||||
typedef struct Rng1U64Node Rng1U64Node;
|
||||
struct Rng1U64Node
|
||||
{
|
||||
Rng1U64Node *next;
|
||||
Rng1U64 v;
|
||||
};
|
||||
|
||||
typedef struct Rng1U64List Rng1U64List;
|
||||
struct Rng1U64List
|
||||
{
|
||||
U64 count;
|
||||
Rng1U64Node *first;
|
||||
Rng1U64Node *last;
|
||||
};
|
||||
|
||||
typedef struct Rng1U64Array Rng1U64Array;
|
||||
struct Rng1U64Array
|
||||
{
|
||||
Rng1U64 *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct Rng1S64Node Rng1S64Node;
|
||||
struct Rng1S64Node
|
||||
{
|
||||
@@ -643,6 +665,10 @@ internal U32 u32_from_rgba(Vec4F32 rgba);
|
||||
////////////////////////////////
|
||||
//~ rjf: List Type Functions
|
||||
|
||||
internal void rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng);
|
||||
internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat);
|
||||
internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list);
|
||||
|
||||
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
|
||||
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
|
||||
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info Lookups
|
||||
|
||||
internal Member *
|
||||
member_from_name(Type *type, String8 name)
|
||||
{
|
||||
Member *member = &member_nil;
|
||||
if(type->members != 0 && name.size != 0)
|
||||
{
|
||||
for(U64 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
if(str8_match(type->members[idx].name, name, 0))
|
||||
{
|
||||
member = &type->members[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info * Instance Operations
|
||||
|
||||
internal void
|
||||
typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
typedef struct RebaseTypeTask RebaseTypeTask;
|
||||
struct RebaseTypeTask
|
||||
{
|
||||
RebaseTypeTask *next;
|
||||
Type *type;
|
||||
U8 *ptr;
|
||||
};
|
||||
RebaseTypeTask start_task = {0, type, data.str};
|
||||
RebaseTypeTask *first_task = &start_task;
|
||||
RebaseTypeTask *last_task = first_task;
|
||||
for(RebaseTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
switch(t->type->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case TypeKind_Ptr:
|
||||
if(!(t->type->flags & TypeFlag_IsExternal))
|
||||
{
|
||||
*(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr));
|
||||
}break;
|
||||
case TypeKind_Array:
|
||||
{
|
||||
for(U64 idx = 0; idx < t->type->count; idx += 1)
|
||||
{
|
||||
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->ptr = t->ptr + t->type->direct->size * idx;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}break;
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
for(U64 idx = 0; idx < t->type->count; idx += 1)
|
||||
{
|
||||
Member *member = &t->type->members[idx];
|
||||
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
|
||||
task->type = member->type;
|
||||
task->ptr = t->ptr + member->value;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal String8
|
||||
serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List strings = {0};
|
||||
str8_serial_begin(scratch.arena, &strings);
|
||||
{
|
||||
typedef struct SerializeTypeTask SerializeTypeTask;
|
||||
struct SerializeTypeTask
|
||||
{
|
||||
SerializeTypeTask *next;
|
||||
Type *type;
|
||||
U64 count;
|
||||
U8 *src;
|
||||
Type *containing_type;
|
||||
U8 *containing_ptr;
|
||||
B32 is_post_header;
|
||||
};
|
||||
SerializeTypeTask start_task = {0, type, 1, data.str};
|
||||
SerializeTypeTask *first_task = &start_task;
|
||||
SerializeTypeTask *last_task = first_task;
|
||||
for(SerializeTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
switch(t->type->kind)
|
||||
{
|
||||
//- rjf: leaf -> just copy the data directly
|
||||
default:
|
||||
if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf)
|
||||
{
|
||||
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
|
||||
}break;
|
||||
|
||||
//- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise just write as plain data
|
||||
case TypeKind_Ptr:
|
||||
{
|
||||
// rjf: unpack info about this pointer
|
||||
TypeSerializePtrRefInfo *ptr_ref_info = 0;
|
||||
for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1)
|
||||
{
|
||||
if(params->ptr_ref_infos[idx].type == t->type->direct)
|
||||
{
|
||||
ptr_ref_info = ¶ms->ptr_ref_infos[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: indexification -> subtract base, divide direct size, write index
|
||||
if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0)
|
||||
{
|
||||
U64 ptr_value = 0;
|
||||
MemoryCopy(&ptr_value, t->src, sizeof(ptr_value));
|
||||
U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size);
|
||||
str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value);
|
||||
}
|
||||
|
||||
// rjf: offsetification -> subtract base, write offsets
|
||||
else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0)
|
||||
{
|
||||
U64 ptr_value = 0;
|
||||
MemoryCopy(&ptr_value, t->src, sizeof(ptr_value));
|
||||
U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base);
|
||||
str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value);
|
||||
}
|
||||
|
||||
// rjf: size-by-member (pre-header): still potentially dependent on other members which
|
||||
// delimit our size, so push a new post-header task for pointer.
|
||||
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
|
||||
{
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type;
|
||||
task->count = t->count;
|
||||
task->src = t->src;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
task->is_post_header = 1;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
|
||||
// rjf: size-by-member (post-header): all flat parts of containing struct have been
|
||||
// iterated, so now we can read the size, & descend to new task to read pointer
|
||||
// destination contents
|
||||
else if(t->type->count_delimiter_name.size != 0 && t->is_post_header)
|
||||
{
|
||||
// rjf: determine count of this pointer
|
||||
U64 count = 0;
|
||||
{
|
||||
Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name);
|
||||
MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size);
|
||||
}
|
||||
|
||||
// rjf: push task
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = count;
|
||||
task->src = *(void **)t->src;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
|
||||
// rjf: catch-all: write pointer value
|
||||
else
|
||||
{
|
||||
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: arrays -> descend to underlying type, + count
|
||||
case TypeKind_Array:
|
||||
{
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->type->count;
|
||||
task->src = t->src;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}break;
|
||||
|
||||
//- rjf: struct -> descend to members
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
U64 off = 0;
|
||||
for(U64 idx = 0; idx < t->count; idx += 1)
|
||||
{
|
||||
for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1)
|
||||
{
|
||||
if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->members[member_idx].type;
|
||||
task->count = 1;
|
||||
task->src = t->src + idx*t->type->size + t->type->members[member_idx].value;
|
||||
task->containing_type = t->type;
|
||||
task->containing_ptr = t->src;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: enum -> descend to basic type interpretation
|
||||
case TypeKind_Enum:
|
||||
{
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->count;
|
||||
task->src = t->src;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
String8 result = str8_serial_end(arena, &strings);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
|
||||
{
|
||||
String8 result = {0};
|
||||
result.size = type->size;
|
||||
result.str = push_array(arena, U8, result.size);
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
typedef struct DeserializeTypeTask DeserializeTypeTask;
|
||||
struct DeserializeTypeTask
|
||||
{
|
||||
DeserializeTypeTask *next;
|
||||
Type *type;
|
||||
U64 count;
|
||||
U8 *dst;
|
||||
Type *containing_type;
|
||||
U8 *containing_ptr;
|
||||
B32 is_post_header;
|
||||
};
|
||||
U64 read_off = 0;
|
||||
DeserializeTypeTask start_task = {0, type, 1, result.str};
|
||||
DeserializeTypeTask *first_task = &start_task;
|
||||
DeserializeTypeTask *last_task = first_task;
|
||||
for(DeserializeTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
U8 *t_src = data.str + read_off;
|
||||
switch(t->type->kind)
|
||||
{
|
||||
//- rjf: leaf -> copy the data directly
|
||||
default:
|
||||
if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf)
|
||||
{
|
||||
MemoryCopy(t->dst, t_src, t->type->size*t->count);
|
||||
read_off += t->type->size*t->count;
|
||||
}break;
|
||||
|
||||
//- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip
|
||||
case TypeKind_Ptr:
|
||||
{
|
||||
// rjf: unpack info about this pointer
|
||||
TypeSerializePtrRefInfo *ptr_ref_info = 0;
|
||||
for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1)
|
||||
{
|
||||
if(params->ptr_ref_infos[idx].type == t->type->direct)
|
||||
{
|
||||
ptr_ref_info = ¶ms->ptr_ref_infos[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: indexification -> add base, multiply direct size
|
||||
if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0)
|
||||
{
|
||||
U64 ptr_value = 0;
|
||||
MemoryCopy(&ptr_value, t_src, sizeof(ptr_value));
|
||||
U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size;
|
||||
MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value));
|
||||
read_off += sizeof(ptr_value);
|
||||
}
|
||||
|
||||
// rjf: offsetification -> subtract base, write offsets
|
||||
else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0)
|
||||
{
|
||||
U64 ptr_value = 0;
|
||||
MemoryCopy(&ptr_value, t_src, sizeof(ptr_value));
|
||||
U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base;
|
||||
MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value));
|
||||
read_off += sizeof(ptr_value);
|
||||
}
|
||||
|
||||
// rjf: size-by-member (pre-header): still potentially dependent on other members which
|
||||
// delimit our size, so push a new post-header task for pointer.
|
||||
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
|
||||
{
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type;
|
||||
task->count = t->count;
|
||||
task->dst = t->dst;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
task->is_post_header = 1;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
|
||||
// rjf: size-by-member (post-header): all flat parts of containing struct have been
|
||||
// iterated, so now we can read the size, & descend to new task to read pointer
|
||||
// destination contents
|
||||
else if(t->type->count_delimiter_name.size != 0 && t->is_post_header)
|
||||
{
|
||||
// rjf: determine count of this pointer
|
||||
U64 count = 0;
|
||||
{
|
||||
Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name);
|
||||
MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size);
|
||||
}
|
||||
|
||||
// rjf: allocate buffer for pointer destination; write address into pointer value slot
|
||||
U64 ptr_dest_buffer_size = (count+1)*t->type->direct->size;
|
||||
U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size);
|
||||
MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer));
|
||||
|
||||
// rjf: push task
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = count;
|
||||
task->dst = ptr_dest_buffer;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
|
||||
// rjf: catch-all: read pointer value
|
||||
else
|
||||
{
|
||||
MemoryCopy(t->dst, t_src, t->type->size*t->count);
|
||||
read_off += t->type->size*t->count;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: arrays -> descend to underlying type, + count
|
||||
case TypeKind_Array:
|
||||
{
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->type->count;
|
||||
task->dst = t->dst;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}break;
|
||||
|
||||
//- rjf: struct -> descend to members
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
for(U64 idx = 0; idx < t->count; idx += 1)
|
||||
{
|
||||
for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1)
|
||||
{
|
||||
if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->members[member_idx].type;
|
||||
task->count = 1;
|
||||
task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value;
|
||||
task->containing_type = t->type;
|
||||
task->containing_ptr = t->dst;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: enum -> descend to basic type interpretation
|
||||
case TypeKind_Enum:
|
||||
{
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->count;
|
||||
task->dst = t->dst;
|
||||
task->containing_type = t->containing_type;
|
||||
task->containing_ptr = t->containing_ptr;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
if(params->advance_out != 0)
|
||||
{
|
||||
params->advance_out[0] = read_off;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 data_srlz = serialized_from_typed_data(scratch.arena, type, data, params);
|
||||
String8 data_copy = deserialized_from_typed_data(arena, type, data_srlz, params);
|
||||
scratch_end(scratch);
|
||||
return data_copy;
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_META_H
|
||||
#define BASE_META_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Meta Markup Features
|
||||
|
||||
#define EmbedFile(name, path)
|
||||
#define TweakB32(name, default) (TWEAK_##name)
|
||||
#define TweakF32(name, default, min, max) (TWEAK_##name)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tweak Info Tables
|
||||
|
||||
typedef struct TweakB32Info TweakB32Info;
|
||||
struct TweakB32Info
|
||||
{
|
||||
String8 name;
|
||||
B32 default_value;
|
||||
B32 *value_ptr;
|
||||
};
|
||||
|
||||
typedef struct TweakF32Info TweakF32Info;
|
||||
struct TweakF32Info
|
||||
{
|
||||
String8 name;
|
||||
F32 default_value;
|
||||
Rng1F32 value_range;
|
||||
F32 *value_ptr;
|
||||
};
|
||||
|
||||
typedef struct TweakB32InfoTable TweakB32InfoTable;
|
||||
struct TweakB32InfoTable
|
||||
{
|
||||
TweakB32Info *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct TweakF32InfoTable TweakF32InfoTable;
|
||||
struct TweakF32InfoTable
|
||||
{
|
||||
TweakF32Info *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct EmbedInfo EmbedInfo;
|
||||
struct EmbedInfo
|
||||
{
|
||||
String8 name;
|
||||
String8 *data;
|
||||
U128 *hash;
|
||||
};
|
||||
|
||||
typedef struct EmbedInfoTable EmbedInfoTable;
|
||||
struct EmbedInfoTable
|
||||
{
|
||||
EmbedInfo *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info Types
|
||||
|
||||
typedef enum TypeKind
|
||||
{
|
||||
TypeKind_Null,
|
||||
|
||||
// rjf: leaves
|
||||
TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void,
|
||||
TypeKind_U8,
|
||||
TypeKind_U16,
|
||||
TypeKind_U32,
|
||||
TypeKind_U64,
|
||||
TypeKind_S8,
|
||||
TypeKind_S16,
|
||||
TypeKind_S32,
|
||||
TypeKind_S64,
|
||||
TypeKind_B8,
|
||||
TypeKind_B16,
|
||||
TypeKind_B32,
|
||||
TypeKind_B64,
|
||||
TypeKind_F32,
|
||||
TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64,
|
||||
|
||||
// rjf: operators
|
||||
TypeKind_Ptr,
|
||||
TypeKind_Array,
|
||||
|
||||
// rjf: user-defined-types
|
||||
TypeKind_Struct,
|
||||
TypeKind_Union,
|
||||
TypeKind_Enum,
|
||||
|
||||
TypeKind_COUNT
|
||||
}
|
||||
TypeKind;
|
||||
|
||||
typedef U32 TypeFlags;
|
||||
enum
|
||||
{
|
||||
TypeFlag_IsExternal = (1<<0),
|
||||
TypeFlag_IsPlainText = (1<<1),
|
||||
TypeFlag_IsCodeText = (1<<2),
|
||||
TypeFlag_IsPathText = (1<<3),
|
||||
};
|
||||
|
||||
typedef U32 MemberFlags;
|
||||
enum
|
||||
{
|
||||
MemberFlag_DoNotSerialize = (1<<0),
|
||||
};
|
||||
|
||||
typedef struct Type Type;
|
||||
typedef struct Member Member;
|
||||
struct Member
|
||||
{
|
||||
String8 name;
|
||||
String8 pretty_name;
|
||||
Type *type;
|
||||
U64 value;
|
||||
MemberFlags flags;
|
||||
};
|
||||
|
||||
typedef struct Type Type;
|
||||
struct Type
|
||||
{
|
||||
TypeKind kind;
|
||||
TypeFlags flags;
|
||||
U64 size;
|
||||
Type *direct;
|
||||
String8 name;
|
||||
String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N]
|
||||
U64 count;
|
||||
Member *members;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Serialization Parameters
|
||||
|
||||
typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo;
|
||||
struct TypeSerializePtrRefInfo
|
||||
{
|
||||
Type *type; // pointers to this
|
||||
void *indexify_base; // can be indexified using this
|
||||
void *offsetify_base; // can be offsetified using this
|
||||
void *nil_ptr; // is terminal if matching 0 or this
|
||||
};
|
||||
|
||||
typedef struct TypeSerializeParams TypeSerializeParams;
|
||||
struct TypeSerializeParams
|
||||
{
|
||||
U64 *advance_out;
|
||||
TypeSerializePtrRefInfo *ptr_ref_infos;
|
||||
U64 ptr_ref_infos_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Name -> Type Info
|
||||
|
||||
#define type(T) (&T##__type)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info Table Initializer Helpers
|
||||
|
||||
#define member_lit_comp(S, ti, m, ...) {str8_lit_comp(#m), {0}, (ti), OffsetOf(S, m), __VA_ARGS__}
|
||||
#define struct_members(S) read_only global Member S##__members[] =
|
||||
#define struct_type(S, ...) read_only global Type S##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#S), {0}, ArrayCount(S##__members), S##__members, __VA_ARGS__}
|
||||
#define named_struct_type(name, S, ...) read_only global Type name##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#name), {0}, ArrayCount(name##__members), name##__members, __VA_ARGS__}
|
||||
#define ptr_type(name, ti, ...) read_only global Type name = {TypeKind_Ptr, 0, sizeof(void *), (ti), __VA_ARGS__}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil};
|
||||
read_only global Member member_nil = {{0}, {0}, &type_nil};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Built-In Types
|
||||
|
||||
//- rjf: leaves
|
||||
read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")};
|
||||
read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")};
|
||||
read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")};
|
||||
read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")};
|
||||
read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")};
|
||||
read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")};
|
||||
read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")};
|
||||
read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")};
|
||||
read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")};
|
||||
read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")};
|
||||
read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")};
|
||||
read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")};
|
||||
read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")};
|
||||
read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")};
|
||||
read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")};
|
||||
read_only global Type *type_kind_type_table[] =
|
||||
{
|
||||
&type_nil,
|
||||
type(void),
|
||||
type(U8),
|
||||
type(U16),
|
||||
type(U32),
|
||||
type(U64),
|
||||
type(S8),
|
||||
type(S16),
|
||||
type(S32),
|
||||
type(S64),
|
||||
type(B8),
|
||||
type(B16),
|
||||
type(B32),
|
||||
type(B64),
|
||||
type(F32),
|
||||
type(F64),
|
||||
&type_nil,
|
||||
&type_nil,
|
||||
&type_nil,
|
||||
&type_nil,
|
||||
&type_nil,
|
||||
};
|
||||
|
||||
//- rjf: Rng1U64
|
||||
struct_members(Rng1U64)
|
||||
{
|
||||
member_lit_comp(Rng1U64, type(U64), min),
|
||||
member_lit_comp(Rng1U64, type(U64), max),
|
||||
};
|
||||
struct_type(Rng1U64);
|
||||
|
||||
//- rjf: String8
|
||||
ptr_type(String8__str_ptr_type, type(U8), str8_lit_comp("size"));
|
||||
struct_members(String8)
|
||||
{
|
||||
member_lit_comp(String8, &String8__str_ptr_type, str),
|
||||
member_lit_comp(String8, type(U64), size),
|
||||
};
|
||||
struct_type(String8);
|
||||
|
||||
//- rjf: String8Node
|
||||
extern Type String8Node__type;
|
||||
Type String8Node__ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &String8Node__type};
|
||||
Member String8Node__members[] =
|
||||
{
|
||||
{str8_lit_comp("next"), {0}, &String8Node__ptr_type, OffsetOf(String8Node, next)},
|
||||
{str8_lit_comp("string"), {0}, type(String8), OffsetOf(String8Node, string)},
|
||||
};
|
||||
Type String8Node__type =
|
||||
{
|
||||
TypeKind_Struct,
|
||||
0,
|
||||
sizeof(String8Node),
|
||||
&type_nil,
|
||||
str8_lit_comp("String8Node"),
|
||||
{0},
|
||||
ArrayCount(String8Node__members),
|
||||
String8Node__members,
|
||||
};
|
||||
|
||||
//- rjf: String8List
|
||||
Member String8List__members[] =
|
||||
{
|
||||
{str8_lit_comp("first"), {0}, &String8Node__ptr_type, OffsetOf(String8List, first)},
|
||||
{str8_lit_comp("last"), {0}, &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize},
|
||||
{str8_lit_comp("node_count"), {0}, type(U64), OffsetOf(String8List, node_count)},
|
||||
{str8_lit_comp("total_size"), {0}, type(U64), OffsetOf(String8List, total_size)},
|
||||
};
|
||||
Type String8List__type =
|
||||
{
|
||||
TypeKind_Struct,
|
||||
0,
|
||||
sizeof(String8List),
|
||||
&type_nil,
|
||||
str8_lit_comp("String8List"),
|
||||
{0},
|
||||
ArrayCount(String8List__members),
|
||||
String8List__members,
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info Lookups
|
||||
|
||||
internal Member *member_from_name(Type *type, String8 name);
|
||||
#define EachMember(T, it) (Member *it = (type(T))->members; it != 0 && it < (type(T))->members + (type(T))->count; it += 1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info * Instance Operations
|
||||
|
||||
internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr);
|
||||
internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
#define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base))
|
||||
#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__})
|
||||
#define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
|
||||
#define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
|
||||
|
||||
#endif // BASE_META_H
|
||||
@@ -43,26 +43,48 @@
|
||||
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
|
||||
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
|
||||
# define ProfColor(color) tmZoneColorSticky(color)
|
||||
# define ProfBeginV(...) \
|
||||
if (TM_API_PTR) { \
|
||||
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
|
||||
Temp scratch = scratch_begin(0,0); \
|
||||
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
|
||||
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
|
||||
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
|
||||
TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \
|
||||
scratch_end(scratch); \
|
||||
}
|
||||
# define ProfNoteV(...) \
|
||||
if (TM_API_PTR) { \
|
||||
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
|
||||
Temp scratch = scratch_begin(0,0); \
|
||||
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
|
||||
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
|
||||
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
|
||||
TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \
|
||||
scratch_end(scratch); \
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Zeroify Undefined Defines
|
||||
|
||||
#if !defined(ProfBegin)
|
||||
# define ProfBegin(...) (0)
|
||||
# define ProfBeginDynamic(...) (0)
|
||||
# define ProfEnd(...) (0)
|
||||
# define ProfTick(...) (0)
|
||||
# define ProfIsCapturing(...) (0)
|
||||
# define ProfBeginCapture(...) (0)
|
||||
# define ProfEndCapture(...) (0)
|
||||
# define ProfThreadName(...) (0)
|
||||
# define ProfMsg(...) (0)
|
||||
# define ProfBeginLockWait(...) (0)
|
||||
# define ProfEndLockWait(...) (0)
|
||||
# define ProfLockTake(...) (0)
|
||||
# define ProfLockDrop(...) (0)
|
||||
# define ProfColor(...) (0)
|
||||
# define ProfBegin(...) (0)
|
||||
# define ProfBeginDynamic(...) (0)
|
||||
# define ProfEnd(...) (0)
|
||||
# define ProfTick(...) (0)
|
||||
# define ProfIsCapturing(...) (0)
|
||||
# define ProfBeginCapture(...) (0)
|
||||
# define ProfEndCapture(...) (0)
|
||||
# define ProfThreadName(...) (0)
|
||||
# define ProfMsg(...) (0)
|
||||
# define ProfBeginLockWait(...) (0)
|
||||
# define ProfEndLockWait(...) (0)
|
||||
# define ProfLockTake(...) (0)
|
||||
# define ProfLockDrop(...) (0)
|
||||
# define ProfColor(...) (0)
|
||||
# define ProfBeginV(...) (0)
|
||||
# define ProfNoteV(...) (0)
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -215,12 +215,42 @@ str32_cstring(U32 *c){
|
||||
internal String8
|
||||
str8_cstring_capped(void *cstr, void *cap)
|
||||
{
|
||||
char *ptr = (char*)cstr;
|
||||
char *opl = (char*)cap;
|
||||
char *ptr = (char *)cstr;
|
||||
char *opl = (char *)cap;
|
||||
for (;ptr < opl && *ptr != 0; ptr += 1);
|
||||
U64 size = (U64)(ptr - (char *)cstr);
|
||||
String8 result = {(U8*)cstr, size};
|
||||
return(result);
|
||||
String8 result = str8((U8*)cstr, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String16
|
||||
str16_cstring_capped(void *cstr, void *cap)
|
||||
{
|
||||
U16 *ptr = (U16 *)cstr;
|
||||
U16 *opl = (U16 *)cap;
|
||||
for (;ptr < opl && *ptr != 0; ptr += 1);
|
||||
U64 size = (U64)(ptr - (U16 *)cstr);
|
||||
String16 result = str16(cstr, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_cstring_capped_reverse(void *raw_start, void *raw_cap)
|
||||
{
|
||||
U8 *start = raw_start;
|
||||
U8 *ptr = raw_cap;
|
||||
for(; ptr > start; )
|
||||
{
|
||||
ptr -= 1;
|
||||
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
U64 size = (U64)(ptr - start);
|
||||
String8 result = str8(start, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -263,31 +293,41 @@ backslashed_from_str8(Arena *arena, String8 string)
|
||||
//~ rjf: String Matching
|
||||
|
||||
internal B32
|
||||
str8_match(String8 a, String8 b, StringMatchFlags flags){
|
||||
str8_match(String8 a, String8 b, StringMatchFlags flags)
|
||||
{
|
||||
B32 result = 0;
|
||||
if (a.size == b.size || (flags & StringMatchFlag_RightSideSloppy)){
|
||||
B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive);
|
||||
if(a.size == b.size && flags == 0)
|
||||
{
|
||||
result = MemoryMatch(a.str, b.str, b.size);
|
||||
}
|
||||
else if(a.size == b.size || (flags & StringMatchFlag_RightSideSloppy))
|
||||
{
|
||||
B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive);
|
||||
B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive);
|
||||
U64 size = Min(a.size, b.size);
|
||||
U64 size = Min(a.size, b.size);
|
||||
result = 1;
|
||||
for (U64 i = 0; i < size; i += 1){
|
||||
for(U64 i = 0; i < size; i += 1)
|
||||
{
|
||||
U8 at = a.str[i];
|
||||
U8 bt = b.str[i];
|
||||
if (case_insensitive){
|
||||
if(case_insensitive)
|
||||
{
|
||||
at = char_to_upper(at);
|
||||
bt = char_to_upper(bt);
|
||||
}
|
||||
if (slash_insensitive){
|
||||
if(slash_insensitive)
|
||||
{
|
||||
at = char_to_correct_slash(at);
|
||||
bt = char_to_correct_slash(bt);
|
||||
}
|
||||
if (at != bt){
|
||||
if(at != bt)
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
@@ -322,6 +362,22 @@ str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags)
|
||||
{
|
||||
U64 result = 0;
|
||||
for(S64 i = string.size - start_pos - needle.size; i >= 0; --i)
|
||||
{
|
||||
String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size));
|
||||
if(str8_match(haystack, needle, flags))
|
||||
{
|
||||
result = (U64)i + needle.size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
str8_ends_with(String8 string, String8 end, StringMatchFlags flags){
|
||||
String8 postfix = str8_postfix(string, end.size);
|
||||
@@ -500,6 +556,22 @@ s64_from_str8(String8 string, U32 radix){
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal U32
|
||||
u32_from_str8(String8 string, U32 radix)
|
||||
{
|
||||
U64 x64 = u64_from_str8(string, radix);
|
||||
U32 x32 = safe_cast_u32(x64);
|
||||
return x32;
|
||||
}
|
||||
|
||||
internal S32
|
||||
s32_from_str8(String8 string, U32 radix)
|
||||
{
|
||||
S64 x64 = s64_from_str8(string, radix);
|
||||
S32 x32 = safe_cast_s32(x64);
|
||||
return x32;
|
||||
}
|
||||
|
||||
internal B32
|
||||
try_u64_from_str8_c_rules(String8 string, U64 *x){
|
||||
B32 is_integer = 0;
|
||||
@@ -544,21 +616,121 @@ try_s64_from_str8_c_rules(String8 string, S64 *x){
|
||||
//- rjf: integer -> string
|
||||
|
||||
internal String8
|
||||
str8_from_memory_size(Arena *arena, U64 z){
|
||||
String8 result = {0};
|
||||
if (z < KB(1)){
|
||||
result = push_str8f(arena, "%llu b", z);
|
||||
str8_from_memory_size(Arena *arena, U64 size)
|
||||
{
|
||||
String8 result;
|
||||
|
||||
if(size < KB(1))
|
||||
{
|
||||
result = push_str8f(arena, "%llu Bytes", size);
|
||||
}
|
||||
else if (z < MB(1)){
|
||||
result = push_str8f(arena, "%llu.%02llu Kb", z/KB(1), ((100*z)/KB(1))%100);
|
||||
else if(size < MB(1))
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100);
|
||||
}
|
||||
else if (z < GB(1)){
|
||||
result = push_str8f(arena, "%llu.%02llu Mb", z/MB(1), ((100*z)/MB(1))%100);
|
||||
else if(size < GB(1))
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100);
|
||||
}
|
||||
else{
|
||||
result = push_str8f(arena, "%llu.%02llu Gb", z/GB(1), ((100*z)/GB(1))%100);
|
||||
else if(size < TB(1))
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100);
|
||||
}
|
||||
return(result);
|
||||
else
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_count(Arena *arena, U64 count)
|
||||
{
|
||||
String8 result;
|
||||
|
||||
if(count < 1 * 1000)
|
||||
{
|
||||
result = push_str8f(arena, "%llu", count);
|
||||
}
|
||||
else if(count < 1000000)
|
||||
{
|
||||
U64 frac = ((count * 100) / 1000) % 100;
|
||||
if(frac > 0)
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = push_str8f(arena, "%lluK", count / 1000);
|
||||
}
|
||||
}
|
||||
else if(count < 1000000000)
|
||||
{
|
||||
U64 frac = ((count * 100) / 1000000) % 100;
|
||||
if(frac > 0)
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = push_str8f(arena, "%lluM", count / 1000000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 frac = ((count * 100) * 1000000000) % 100;
|
||||
if(frac > 0)
|
||||
{
|
||||
result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = push_str8f(arena, "%lluB", count / 1000000000, frac);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_bits_u32(Arena *arena, U32 x)
|
||||
{
|
||||
U8 c0 = 'a' + ((x >> 28) & 0xf);
|
||||
U8 c1 = 'a' + ((x >> 24) & 0xf);
|
||||
U8 c2 = 'a' + ((x >> 20) & 0xf);
|
||||
U8 c3 = 'a' + ((x >> 16) & 0xf);
|
||||
U8 c4 = 'a' + ((x >> 12) & 0xf);
|
||||
U8 c5 = 'a' + ((x >> 8) & 0xf);
|
||||
U8 c6 = 'a' + ((x >> 4) & 0xf);
|
||||
U8 c7 = 'a' + ((x >> 0) & 0xf);
|
||||
String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_bits_u64(Arena *arena, U64 x)
|
||||
{
|
||||
U8 c0 = 'a' + ((x >> 60) & 0xf);
|
||||
U8 c1 = 'a' + ((x >> 56) & 0xf);
|
||||
U8 c2 = 'a' + ((x >> 52) & 0xf);
|
||||
U8 c3 = 'a' + ((x >> 48) & 0xf);
|
||||
U8 c4 = 'a' + ((x >> 44) & 0xf);
|
||||
U8 c5 = 'a' + ((x >> 40) & 0xf);
|
||||
U8 c6 = 'a' + ((x >> 36) & 0xf);
|
||||
U8 c7 = 'a' + ((x >> 32) & 0xf);
|
||||
U8 c8 = 'a' + ((x >> 28) & 0xf);
|
||||
U8 c9 = 'a' + ((x >> 24) & 0xf);
|
||||
U8 ca = 'a' + ((x >> 20) & 0xf);
|
||||
U8 cb = 'a' + ((x >> 16) & 0xf);
|
||||
U8 cc = 'a' + ((x >> 12) & 0xf);
|
||||
U8 cd = 'a' + ((x >> 8) & 0xf);
|
||||
U8 ce = 'a' + ((x >> 4) & 0xf);
|
||||
U8 cf = 'a' + ((x >> 0) & 0xf);
|
||||
String8 result = push_str8f(arena,
|
||||
"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
@@ -685,27 +857,28 @@ f64_from_str8(String8 string)
|
||||
{
|
||||
// rjf: find starting pos of numeric string, as well as sign
|
||||
F64 sign = +1.0;
|
||||
//U64 first_numeric = 0;
|
||||
if(string.str[0] == '-')
|
||||
{
|
||||
//first_numeric = 1;
|
||||
sign = -1.0;
|
||||
}
|
||||
else if(string.str[0] == '+')
|
||||
{
|
||||
//first_numeric = 1;
|
||||
sign = 1.0;
|
||||
}
|
||||
|
||||
// rjf: gather numerics
|
||||
U64 num_valid_chars = 0;
|
||||
char buffer[64];
|
||||
B32 exp = 0;
|
||||
for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1)
|
||||
{
|
||||
if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.')
|
||||
if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.' || string.str[idx] == 'e' ||
|
||||
(exp && (string.str[idx] == '+' || string.str[idx] == '-')))
|
||||
{
|
||||
buffer[num_valid_chars] = string.str[idx];
|
||||
num_valid_chars += 1;
|
||||
exp = 0;
|
||||
exp = (string.str[idx] == 'e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,7 +1311,9 @@ str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){
|
||||
internal String8
|
||||
str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){
|
||||
StringJoin params = {0};
|
||||
switch (style){
|
||||
switch(style)
|
||||
{
|
||||
case PathStyle_Null:{}break;
|
||||
case PathStyle_Relative:
|
||||
case PathStyle_WindowsAbsolute:
|
||||
{
|
||||
@@ -1151,9 +1326,8 @@ str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){
|
||||
params.sep = str8_lit("/");
|
||||
}break;
|
||||
}
|
||||
|
||||
String8 result = str8_list_join(arena, path, ¶ms);
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8TxtPtPair
|
||||
@@ -1346,70 +1520,127 @@ utf8_from_utf32_single(U8 *buffer, U32 character){
|
||||
//~ rjf: Unicode String Conversions
|
||||
|
||||
internal String8
|
||||
str8_from_16(Arena *arena, String16 in){
|
||||
U64 cap = in.size*3;
|
||||
U8 *str = push_array_no_zero(arena, U8, cap + 1);
|
||||
U16 *ptr = in.str;
|
||||
U16 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for (;ptr < opl; ptr += consume.inc){
|
||||
consume = utf16_decode(ptr, opl - ptr);
|
||||
size += utf8_encode(str + size, consume.codepoint);
|
||||
str8_from_16(Arena *arena, String16 in)
|
||||
{
|
||||
String8 result = str8_zero();
|
||||
if(in.size)
|
||||
{
|
||||
U64 cap = in.size*3;
|
||||
U8 *str = push_array_no_zero(arena, U8, cap + 1);
|
||||
U16 *ptr = in.str;
|
||||
U16 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for(;ptr < opl; ptr += consume.inc)
|
||||
{
|
||||
consume = utf16_decode(ptr, opl - ptr);
|
||||
size += utf8_encode(str + size, consume.codepoint);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size));
|
||||
result = str8(str, size);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size));
|
||||
return(str8(str, size));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String16
|
||||
str16_from_8(Arena *arena, String8 in){
|
||||
U64 cap = in.size*2;
|
||||
U16 *str = push_array_no_zero(arena, U16, cap + 1);
|
||||
U8 *ptr = in.str;
|
||||
U8 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for (;ptr < opl; ptr += consume.inc){
|
||||
consume = utf8_decode(ptr, opl - ptr);
|
||||
size += utf16_encode(str + size, consume.codepoint);
|
||||
str16_from_8(Arena *arena, String8 in)
|
||||
{
|
||||
String16 result = str16_zero();
|
||||
if(in.size)
|
||||
{
|
||||
U64 cap = in.size*2;
|
||||
U16 *str = push_array_no_zero(arena, U16, cap + 1);
|
||||
U8 *ptr = in.str;
|
||||
U8 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for(;ptr < opl; ptr += consume.inc)
|
||||
{
|
||||
consume = utf8_decode(ptr, opl - ptr);
|
||||
size += utf16_encode(str + size, consume.codepoint);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size)*2);
|
||||
result = str16(str, size);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size)*2);
|
||||
return(str16(str, size));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
str8_from_32(Arena *arena, String32 in){
|
||||
U64 cap = in.size*4;
|
||||
U8 *str = push_array_no_zero(arena, U8, cap + 1);
|
||||
U32 *ptr = in.str;
|
||||
U32 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
for (;ptr < opl; ptr += 1){
|
||||
size += utf8_encode(str + size, *ptr);
|
||||
str8_from_32(Arena *arena, String32 in)
|
||||
{
|
||||
String8 result = str8_zero();
|
||||
if(in.size)
|
||||
{
|
||||
U64 cap = in.size*4;
|
||||
U8 *str = push_array_no_zero(arena, U8, cap + 1);
|
||||
U32 *ptr = in.str;
|
||||
U32 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
for(;ptr < opl; ptr += 1)
|
||||
{
|
||||
size += utf8_encode(str + size, *ptr);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size));
|
||||
result = str8(str, size);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size));
|
||||
return(str8(str, size));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String32
|
||||
str32_from_8(Arena *arena, String8 in){
|
||||
U64 cap = in.size;
|
||||
U32 *str = push_array_no_zero(arena, U32, cap + 1);
|
||||
U8 *ptr = in.str;
|
||||
U8 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for (;ptr < opl; ptr += consume.inc){
|
||||
consume = utf8_decode(ptr, opl - ptr);
|
||||
str[size] = consume.codepoint;
|
||||
size += 1;
|
||||
str32_from_8(Arena *arena, String8 in)
|
||||
{
|
||||
String32 result = str32_zero();
|
||||
if(in.size)
|
||||
{
|
||||
U64 cap = in.size;
|
||||
U32 *str = push_array_no_zero(arena, U32, cap + 1);
|
||||
U8 *ptr = in.str;
|
||||
U8 *opl = ptr + in.size;
|
||||
U64 size = 0;
|
||||
UnicodeDecode consume;
|
||||
for(;ptr < opl; ptr += consume.inc)
|
||||
{
|
||||
consume = utf8_decode(ptr, opl - ptr);
|
||||
str[size] = consume.codepoint;
|
||||
size += 1;
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size)*4);
|
||||
result = str32(str, size);
|
||||
}
|
||||
str[size] = 0;
|
||||
arena_pop(arena, (cap - size)*4);
|
||||
return(str32(str, size));
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ String -> Enum Conversions
|
||||
|
||||
read_only global struct
|
||||
{
|
||||
String8 string;
|
||||
OperatingSystem os;
|
||||
} g_os_enum_map[] =
|
||||
{
|
||||
{ str8_lit_comp(""), OperatingSystem_Null },
|
||||
{ str8_lit_comp("Windows"), OperatingSystem_Windows, },
|
||||
{ str8_lit_comp("Linux"), OperatingSystem_Linux, },
|
||||
{ str8_lit_comp("Mac"), OperatingSystem_Mac, },
|
||||
};
|
||||
StaticAssert(ArrayCount(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check);
|
||||
|
||||
internal OperatingSystem
|
||||
operating_system_from_string(String8 string)
|
||||
{
|
||||
for(U64 i = 0; i < ArrayCount(g_os_enum_map); ++i)
|
||||
{
|
||||
if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive))
|
||||
{
|
||||
return g_os_enum_map[i].os;
|
||||
}
|
||||
}
|
||||
return OperatingSystem_Null;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -1444,22 +1675,18 @@ string_from_side(Side side){
|
||||
}
|
||||
|
||||
internal String8
|
||||
string_from_operating_system(OperatingSystem os){
|
||||
local_persist String8 strings[] = {
|
||||
str8_lit_comp("Null"),
|
||||
str8_lit_comp("Windows"),
|
||||
str8_lit_comp("Linux"),
|
||||
str8_lit_comp("Mac"),
|
||||
};
|
||||
String8 result = str8_lit("error");
|
||||
if (os < OperatingSystem_COUNT){
|
||||
result = strings[os];
|
||||
string_from_operating_system(OperatingSystem os)
|
||||
{
|
||||
String8 result = g_os_enum_map[OperatingSystem_Null].string;
|
||||
if(os < ArrayCount(g_os_enum_map))
|
||||
{
|
||||
result = g_os_enum_map[os].string;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
string_from_architecture(Architecture arch){
|
||||
string_from_arch(Arch arch){
|
||||
local_persist String8 strings[] = {
|
||||
str8_lit_comp("Null"),
|
||||
str8_lit_comp("x64"),
|
||||
@@ -1468,7 +1695,7 @@ string_from_architecture(Architecture arch){
|
||||
str8_lit_comp("arm32"),
|
||||
};
|
||||
String8 result = str8_lit("error");
|
||||
if (arch < Architecture_COUNT){
|
||||
if (arch < Arch_COUNT){
|
||||
result = strings[arch];
|
||||
}
|
||||
return(result);
|
||||
@@ -1565,6 +1792,78 @@ string_from_elapsed_time(Arena *arena, DateTime dt){
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Globally UNique Ids
|
||||
|
||||
internal String8
|
||||
string_from_guid(Arena *arena, Guid guid)
|
||||
{
|
||||
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
guid.data1,
|
||||
guid.data2,
|
||||
guid.data3,
|
||||
guid.data4[0],
|
||||
guid.data4[1],
|
||||
guid.data4[2],
|
||||
guid.data4[3],
|
||||
guid.data4[4],
|
||||
guid.data4[5],
|
||||
guid.data4[6],
|
||||
guid.data4[7]);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
try_guid_from_string(String8 string, Guid *guid_out)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
B32 is_parsed = 0;
|
||||
String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties);
|
||||
if(list.node_count == 5)
|
||||
{
|
||||
String8 data1_str = list.first->string;
|
||||
String8 data2_str = list.first->next->string;
|
||||
String8 data3_str = list.first->next->next->string;
|
||||
String8 data4_hi_str = list.first->next->next->next->string;
|
||||
String8 data4_lo_str = list.first->next->next->next->next->string;
|
||||
if(str8_is_integer(data1_str, 16) &&
|
||||
str8_is_integer(data2_str, 16) &&
|
||||
str8_is_integer(data3_str, 16) &&
|
||||
str8_is_integer(data4_hi_str, 16) &&
|
||||
str8_is_integer(data4_lo_str, 16))
|
||||
{
|
||||
U64 data1 = u64_from_str8(data1_str, 16);
|
||||
U64 data2 = u64_from_str8(data2_str, 16);
|
||||
U64 data3 = u64_from_str8(data3_str, 16);
|
||||
U64 data4_hi = u64_from_str8(data4_hi_str, 16);
|
||||
U64 data4_lo = u64_from_str8(data4_lo_str, 16);
|
||||
if(data1 <= max_U32 &&
|
||||
data2 <= max_U16 &&
|
||||
data3 <= max_U16 &&
|
||||
data4_hi <= max_U16 &&
|
||||
data4_lo <= 0xffffffffffff)
|
||||
{
|
||||
guid_out->data1 = (U32)data1;
|
||||
guid_out->data2 = (U16)data2;
|
||||
guid_out->data3 = (U16)data3;
|
||||
U64 data4 = (data4_hi << 48) | data4_lo;
|
||||
MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4));
|
||||
is_parsed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return is_parsed;
|
||||
}
|
||||
|
||||
internal Guid
|
||||
guid_from_string(String8 string)
|
||||
{
|
||||
Guid guid = {0};
|
||||
try_guid_from_string(string, &guid);
|
||||
return guid;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Text Indentation
|
||||
|
||||
@@ -1593,6 +1892,10 @@ indented_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth*2, indentation_bytes, line);
|
||||
}
|
||||
if(line.size == 0 && indented_strings.node_count != 0 && off < string.size)
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &indented_strings, "\n");
|
||||
}
|
||||
line_begin_off = off+1;
|
||||
depth = next_depth;
|
||||
}break;
|
||||
@@ -1603,6 +1906,100 @@ indented_from_string(Arena *arena, String8 string)
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Escaping
|
||||
|
||||
internal String8
|
||||
escaped_from_raw_str8(Arena *arena, String8 string)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List parts = {0};
|
||||
U64 start_split_idx = 0;
|
||||
for(U64 idx = 0; idx <= string.size; idx += 1)
|
||||
{
|
||||
U8 byte = (idx < string.size) ? string.str[idx] : 0;
|
||||
B32 split = 1;
|
||||
String8 separator_replace = {0};
|
||||
switch(byte)
|
||||
{
|
||||
default:{split = 0;}break;
|
||||
case 0: {}break;
|
||||
case '\a': {separator_replace = str8_lit("\\a");}break;
|
||||
case '\b': {separator_replace = str8_lit("\\b");}break;
|
||||
case '\f': {separator_replace = str8_lit("\\f");}break;
|
||||
case '\n': {separator_replace = str8_lit("\\n");}break;
|
||||
case '\r': {separator_replace = str8_lit("\\r");}break;
|
||||
case '\t': {separator_replace = str8_lit("\\t");}break;
|
||||
case '\v': {separator_replace = str8_lit("\\v");}break;
|
||||
case '\\': {separator_replace = str8_lit("\\\\");}break;
|
||||
case '"': {separator_replace = str8_lit("\\\"");}break;
|
||||
case '?': {separator_replace = str8_lit("\\?");}break;
|
||||
}
|
||||
if(split)
|
||||
{
|
||||
String8 substr = str8_substr(string, r1u64(start_split_idx, idx));
|
||||
start_split_idx = idx+1;
|
||||
str8_list_push(scratch.arena, &parts, substr);
|
||||
if(separator_replace.size != 0)
|
||||
{
|
||||
str8_list_push(scratch.arena, &parts, separator_replace);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringJoin join = {0};
|
||||
String8 result = str8_list_join(arena, &parts, &join);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
raw_from_escaped_str8(Arena *arena, String8 string)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List strs = {0};
|
||||
U64 start = 0;
|
||||
for(U64 idx = 0; idx <= string.size; idx += 1)
|
||||
{
|
||||
if(idx == string.size || string.str[idx] == '\\' || string.str[idx] == '\r')
|
||||
{
|
||||
String8 str = str8_substr(string, r1u64(start, idx));
|
||||
if(str.size != 0)
|
||||
{
|
||||
str8_list_push(scratch.arena, &strs, str);
|
||||
}
|
||||
start = idx+1;
|
||||
}
|
||||
if(idx < string.size && string.str[idx] == '\\')
|
||||
{
|
||||
U8 next_char = string.str[idx+1];
|
||||
U8 replace_byte = 0;
|
||||
switch(next_char)
|
||||
{
|
||||
default:{}break;
|
||||
case 'a': replace_byte = 0x07; break;
|
||||
case 'b': replace_byte = 0x08; break;
|
||||
case 'e': replace_byte = 0x1b; break;
|
||||
case 'f': replace_byte = 0x0c; break;
|
||||
case 'n': replace_byte = 0x0a; break;
|
||||
case 'r': replace_byte = 0x0d; break;
|
||||
case 't': replace_byte = 0x09; break;
|
||||
case 'v': replace_byte = 0x0b; break;
|
||||
case '\\':replace_byte = '\\'; break;
|
||||
case '\'':replace_byte = '\''; break;
|
||||
case '"': replace_byte = '"'; break;
|
||||
case '?': replace_byte = '?'; break;
|
||||
}
|
||||
String8 replace_string = push_str8_copy(scratch.arena, str8(&replace_byte, 1));
|
||||
str8_list_push(scratch.arena, &strs, replace_string);
|
||||
idx += 1;
|
||||
start += 1;
|
||||
}
|
||||
}
|
||||
String8 result = str8_list_join(arena, &strs, 0);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Wrapping
|
||||
|
||||
@@ -1973,3 +2370,77 @@ str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out)
|
||||
*block_out = str8_substr(string, range);
|
||||
return block_out->size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out)
|
||||
{
|
||||
U64 value = 0;
|
||||
U64 shift = 0;
|
||||
U64 cursor = off;
|
||||
for(;;)
|
||||
{
|
||||
U8 byte = 0;
|
||||
U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte);
|
||||
|
||||
if(bytes_read != sizeof(byte))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
U8 val = byte & 0x7fu;
|
||||
value |= ((U64)val) << shift;
|
||||
|
||||
cursor += bytes_read;
|
||||
shift += 7u;
|
||||
|
||||
if((byte & 0x80u) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(value_out != 0)
|
||||
{
|
||||
*value_out = value;
|
||||
}
|
||||
U64 bytes_read = cursor - off;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
internal U64
|
||||
str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out)
|
||||
{
|
||||
U64 value = 0;
|
||||
U64 shift = 0;
|
||||
U64 cursor = off;
|
||||
for(;;)
|
||||
{
|
||||
U8 byte;
|
||||
U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte);
|
||||
if(bytes_read != sizeof(byte))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
U8 val = byte & 0x7fu;
|
||||
value |= ((U64)val) << shift;
|
||||
|
||||
cursor += bytes_read;
|
||||
shift += 7u;
|
||||
|
||||
if((byte & 0x80u) == 0)
|
||||
{
|
||||
if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0)
|
||||
{
|
||||
value |= -(S64)(1ull << shift);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(value_out != 0)
|
||||
{
|
||||
*value_out = value;
|
||||
}
|
||||
U64 bytes_read = cursor - off;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ enum
|
||||
|
||||
typedef enum PathStyle
|
||||
{
|
||||
PathStyle_Null,
|
||||
PathStyle_Relative,
|
||||
PathStyle_WindowsAbsolute,
|
||||
PathStyle_UnixAbsolute,
|
||||
@@ -192,6 +193,8 @@ internal String8 str8_cstring(char *c);
|
||||
internal String16 str16_cstring(U16 *c);
|
||||
internal String32 str32_cstring(U32 *c);
|
||||
internal String8 str8_cstring_capped(void *cstr, void *cap);
|
||||
internal String16 str16_cstring_capped(void *cstr, void *cap);
|
||||
internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Stylization
|
||||
@@ -205,6 +208,7 @@ internal String8 backslashed_from_str8(Arena *arena, String8 string);
|
||||
|
||||
internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags);
|
||||
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
|
||||
internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
|
||||
internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags);
|
||||
|
||||
////////////////////////////////
|
||||
@@ -231,13 +235,19 @@ internal String8 push_str8f(Arena *arena, char *fmt, ...);
|
||||
//- rjf: string -> integer
|
||||
internal S64 sign_from_str8(String8 string, String8 *string_tail);
|
||||
internal B32 str8_is_integer(String8 string, U32 radix);
|
||||
|
||||
internal U64 u64_from_str8(String8 string, U32 radix);
|
||||
internal S64 s64_from_str8(String8 string, U32 radix);
|
||||
internal U32 u32_from_str8(String8 string, U32 radix);
|
||||
internal S32 s32_from_str8(String8 string, U32 radix);
|
||||
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
|
||||
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
|
||||
|
||||
//- rjf: integer -> string
|
||||
internal String8 str8_from_memory_size(Arena *arena, U64 z);
|
||||
internal String8 str8_from_memory_size(Arena *arena, U64 size);
|
||||
internal String8 str8_from_count(Arena *arena, U64 count);
|
||||
internal String8 str8_from_bits_u32(Arena *arena, U32 x);
|
||||
internal String8 str8_from_bits_u64(Arena *arena, U64 x);
|
||||
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
||||
internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
||||
|
||||
@@ -309,13 +319,18 @@ internal String16 str16_from_8(Arena *arena, String8 in);
|
||||
internal String8 str8_from_32(Arena *arena, String32 in);
|
||||
internal String32 str32_from_8(Arena *arena, String8 in);
|
||||
|
||||
////////////////////////////////
|
||||
//~ String -> Enum Conversions
|
||||
|
||||
internal OperatingSystem operating_system_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Types & Space Enum -> String Conversions
|
||||
|
||||
internal String8 string_from_dimension(Dimension dimension);
|
||||
internal String8 string_from_side(Side side);
|
||||
internal String8 string_from_operating_system(OperatingSystem os);
|
||||
internal String8 string_from_architecture(Architecture arch);
|
||||
internal String8 string_from_arch(Arch arch);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Types -> String
|
||||
@@ -326,11 +341,24 @@ internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Globally Unique Ids
|
||||
|
||||
internal String8 string_from_guid(Arena *arena, Guid guid);
|
||||
internal B32 try_guid_from_string(String8 string, Guid *guid_out);
|
||||
internal Guid guid_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Text Indentation
|
||||
|
||||
internal String8 indented_from_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Escaping
|
||||
|
||||
internal String8 escaped_from_raw_str8(Arena *arena, String8 string);
|
||||
internal String8 raw_from_escaped_str8(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Wrapping
|
||||
|
||||
@@ -372,10 +400,13 @@ internal void str8_serial_push_string(Arena *arena, String8List *srl, String8
|
||||
|
||||
internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity);
|
||||
internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val);
|
||||
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
|
||||
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);
|
||||
internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
|
||||
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out);
|
||||
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
|
||||
internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out);
|
||||
internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out);
|
||||
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
|
||||
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr)))
|
||||
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read_array(string, off, ptr, 1)
|
||||
|
||||
#endif // BASE_STRINGS_H
|
||||
|
||||
@@ -26,7 +26,7 @@ internal void tctx_init_and_equip(TCTX *tctx);
|
||||
internal void tctx_release(void);
|
||||
internal TCTX* tctx_get_equipped(void);
|
||||
|
||||
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
|
||||
internal Arena* tctx_get_scratch(Arena **conflicts, U64 countt);
|
||||
|
||||
internal void tctx_set_thread_name(String8 name);
|
||||
internal String8 tctx_get_thread_name(void);
|
||||
|
||||
@@ -246,8 +246,7 @@ entry_point(CmdLine *cmdline)
|
||||
}
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "%S_%S,\n", enum_member_prefix, escaped);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "%S_%S,\n", enum_member_prefix, n->string);
|
||||
}
|
||||
if(enum_base_type_name.size == 0)
|
||||
{
|
||||
@@ -278,8 +277,7 @@ entry_point(CmdLine *cmdline)
|
||||
str8_list_pushf(mg_arena, &layer->enums, "#define %S \\\n", node->string);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "X(%S)\\\n", escaped);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "X(%S)\\\n", n->string);
|
||||
}
|
||||
str8_list_push(mg_arena, &layer->enums, str8_lit("\n"));
|
||||
}
|
||||
@@ -303,8 +301,7 @@ entry_point(CmdLine *cmdline)
|
||||
str8_list_pushf(mg_arena, &layer->structs, "struct %S\n{\n", node->string);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->structs, "%S;\n", escaped);
|
||||
str8_list_pushf(mg_arena, &layer->structs, "%S;\n", n->string);
|
||||
}
|
||||
str8_list_pushf(mg_arena, &layer->structs, "};\n\n");
|
||||
}
|
||||
@@ -333,8 +330,7 @@ entry_point(CmdLine *cmdline)
|
||||
str8_list_pushf(mg_arena, &layer->c_tables, "%S %S[%I64u] =\n{\n", element_type, node->string, gen_strings.node_count);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->c_tables, "%S,\n", escaped);
|
||||
str8_list_pushf(mg_arena, &layer->c_tables, "%S,\n", n->string);
|
||||
}
|
||||
str8_list_push(mg_arena, &layer->c_tables, str8_lit("};\n\n"));
|
||||
}
|
||||
@@ -364,8 +360,7 @@ entry_point(CmdLine *cmdline)
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "default:{}break;\n");
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "%S;\n", escaped);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "%S;\n", n->string);
|
||||
}
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "}\n");
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "return result;\n");
|
||||
@@ -398,8 +393,7 @@ entry_point(CmdLine *cmdline)
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 trimmed = str8_skip_chop_whitespace(n->string);
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, trimmed);
|
||||
str8_list_push(mg_arena, out, escaped);
|
||||
str8_list_push(mg_arena, out, trimmed);
|
||||
str8_list_push(mg_arena, out, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1628,7 +1628,7 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
|
||||
}
|
||||
|
||||
//- rjf: call into "real" entry point
|
||||
main_thread_base_entry_point(entry_point, argv, (U64)argc);
|
||||
main_thread_base_entry_point(argc, argv);
|
||||
}
|
||||
|
||||
#if BUILD_CONSOLE_INTERFACE
|
||||
|
||||
@@ -443,6 +443,12 @@ os_copy_file_path(String8 dst, String8 src)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_move_file_path(String8 dst, String8 src)
|
||||
{
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_full_path_from_path(Arena *arena, String8 path)
|
||||
{
|
||||
|
||||
@@ -202,6 +202,7 @@ internal void os_abort(S32 exit_code);
|
||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||
internal void os_file_close(OS_Handle file);
|
||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||
#define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr))
|
||||
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||
@@ -209,6 +210,7 @@ internal OS_FileID os_id_from_file(OS_Handle file);
|
||||
internal B32 os_file_reserve_size(OS_Handle file, U64 size);
|
||||
internal B32 os_delete_file_at_path(String8 path);
|
||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||
internal B32 os_move_file_path(String8 dst, String8 src);
|
||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 os_file_path_exists(String8 path);
|
||||
internal B32 os_folder_path_exists(String8 path);
|
||||
|
||||
@@ -503,6 +503,17 @@ os_copy_file_path(String8 dst, String8 src)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_move_file_path(String8 dst, String8 src)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String16 dst16 = str16_from_8(scratch.arena, dst);
|
||||
String16 src16 = str16_from_8(scratch.arena, src);
|
||||
B32 result = MoveFileW((WCHAR*)src16.str, (WCHAR*)dst16.str);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_full_path_from_path(Arena *arena, String8 path)
|
||||
{
|
||||
@@ -560,6 +571,28 @@ os_properties_from_file_path(String8 path)
|
||||
os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime);
|
||||
props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
WCHAR buffer[512] = {0};
|
||||
DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer);
|
||||
U64 last_slash_pos = 0;
|
||||
for(;last_slash_pos < path.size; last_slash_pos = str8_find_needle(path, last_slash_pos+1, str8_lit("/"), StringMatchFlag_SlashInsensitive));
|
||||
String8 path_trimmed = str8_prefix(path, last_slash_pos);
|
||||
for(U64 off = 0; off < (U64)length;)
|
||||
{
|
||||
String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off);
|
||||
off += next_drive_string_16.size+1;
|
||||
String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16);
|
||||
next_drive_string = str8_chop_last_slash(next_drive_string);
|
||||
if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive))
|
||||
{
|
||||
props.flags |= FilePropertyFlag_IsFolder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
FindClose(handle);
|
||||
scratch_end(scratch);
|
||||
return props;
|
||||
|
||||
@@ -71,8 +71,10 @@ os_get_clipboard_text(Arena *arena)
|
||||
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle
|
||||
os_window_open(Vec2F32 resolution, OS_WindowFlags flags, String8 title)
|
||||
os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
||||
{
|
||||
Vec2F32 resolution = dim_2f32(rect);
|
||||
|
||||
//- rjf: allocate window
|
||||
OS_LNX_Window *w = os_lnx_gfx_state->free_window;
|
||||
if(w)
|
||||
@@ -283,6 +285,12 @@ os_dim_from_monitor(OS_Handle monitor)
|
||||
return v2f32(0, 0);
|
||||
}
|
||||
|
||||
internal F32
|
||||
os_dpi_from_monitor(OS_Handle monitor)
|
||||
{
|
||||
return 96.f;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Events (Implemented Per-OS)
|
||||
|
||||
|
||||
+4
-2
@@ -21,7 +21,8 @@ struct OS_GfxInfo
|
||||
typedef U32 OS_WindowFlags;
|
||||
enum
|
||||
{
|
||||
OS_WindowFlag_CustomBorder = (1<<0),
|
||||
OS_WindowFlag_CustomBorder = (1<<0),
|
||||
OS_WindowFlag_UseDefaultPosition = (1<<1),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -139,7 +140,7 @@ internal String8 os_get_clipboard_text(Arena *arena);
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_window_open(Vec2F32 resolution, OS_WindowFlags flags, String8 title);
|
||||
internal OS_Handle os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title);
|
||||
internal void os_window_close(OS_Handle window);
|
||||
internal void os_window_first_paint(OS_Handle window);
|
||||
internal void os_window_focus(OS_Handle window);
|
||||
@@ -168,6 +169,7 @@ internal OS_Handle os_primary_monitor(void);
|
||||
internal OS_Handle os_monitor_from_window(OS_Handle window);
|
||||
internal String8 os_name_from_monitor(Arena *arena, OS_Handle monitor);
|
||||
internal Vec2F32 os_dim_from_monitor(OS_Handle monitor);
|
||||
internal F32 os_dpi_from_monitor(OS_Handle monitor);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Events (Implemented Per-OS)
|
||||
|
||||
@@ -34,7 +34,7 @@ os_get_clipboard_text(Arena *arena)
|
||||
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle
|
||||
os_window_open(Vec2F32 resolution, OS_WindowFlags flags, String8 title)
|
||||
os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
||||
{
|
||||
OS_Handle handle = {1};
|
||||
return handle;
|
||||
@@ -181,6 +181,12 @@ os_dim_from_monitor(OS_Handle monitor)
|
||||
return v;
|
||||
}
|
||||
|
||||
internal F32
|
||||
os_dpi_from_monitor(OS_Handle monitor)
|
||||
{
|
||||
return 96.f;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Events (Implemented Per-OS)
|
||||
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
typedef BOOL w32_SetProcessDpiAwarenessContext_Type(void* value);
|
||||
typedef UINT w32_GetDpiForWindow_Type(HWND hwnd);
|
||||
typedef HRESULT w32_GetDpiForMonitor_Type(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY);
|
||||
typedef int w32_GetSystemMetricsForDpi_Type(int nIndex, UINT dpi);
|
||||
#define w32_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((void*)-4)
|
||||
global w32_GetDpiForWindow_Type *w32_GetDpiForWindow_func = 0;
|
||||
global w32_GetDpiForMonitor_Type *w32_GetDpiForMonitor_func = 0;
|
||||
global w32_GetSystemMetricsForDpi_Type *w32_GetSystemMetricsForDpi_func = 0;
|
||||
|
||||
////////////////////////////////
|
||||
@@ -713,9 +715,10 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
// of the top hit area so manually checking that.
|
||||
F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f;
|
||||
S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
|
||||
S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
// NOTE(rjf): it seems incorrect to apply this padding here...
|
||||
// S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
|
||||
B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y + padding;
|
||||
B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y; // + padding;
|
||||
B32 is_over_title_bar = pos_client.y >= 0 && pos_client.y < window->custom_border_title_thickness;
|
||||
|
||||
//- rjf: check against title bar client areas
|
||||
@@ -811,6 +814,7 @@ os_gfx_init(void)
|
||||
(w32_SetProcessDpiAwarenessContext_Type*)GetProcAddress(module, "SetProcessDpiAwarenessContext");
|
||||
w32_GetDpiForWindow_func =
|
||||
(w32_GetDpiForWindow_Type*)GetProcAddress(module, "GetDpiForWindow");
|
||||
w32_GetDpiForMonitor_func = (w32_GetDpiForMonitor_Type *)GetProcAddress(module, "GetDpiForMonitor");
|
||||
w32_GetSystemMetricsForDpi_func = (w32_GetSystemMetricsForDpi_Type *)GetProcAddress(module, "GetSystemMetricsForDpi");
|
||||
FreeLibrary(module);
|
||||
}
|
||||
@@ -1011,9 +1015,12 @@ os_get_clipboard_text(Arena *arena)
|
||||
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle
|
||||
os_window_open(Vec2F32 resolution, OS_WindowFlags flags, String8 title)
|
||||
os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
||||
{
|
||||
B32 custom_border = !!(flags & OS_WindowFlag_CustomBorder);
|
||||
B32 use_default_position = !!(flags & OS_WindowFlag_UseDefaultPosition);
|
||||
Vec2F32 pos = rect.p0;
|
||||
Vec2F32 dim = dim_2f32(rect);
|
||||
|
||||
//- rjf: make hwnd
|
||||
HWND hwnd = 0;
|
||||
@@ -1025,9 +1032,10 @@ os_window_open(Vec2F32 resolution, OS_WindowFlags flags, String8 title)
|
||||
L"graphical-window",
|
||||
(WCHAR*)title16.str,
|
||||
WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
(int)resolution.x,
|
||||
(int)resolution.y,
|
||||
use_default_position ? CW_USEDEFAULT : (S32)pos.x,
|
||||
use_default_position ? CW_USEDEFAULT : (S32)pos.y,
|
||||
(S32)dim.x,
|
||||
(S32)dim.y,
|
||||
0, 0,
|
||||
os_w32_gfx_state->hInstance,
|
||||
0);
|
||||
@@ -1385,6 +1393,21 @@ os_dim_from_monitor(OS_Handle monitor)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal F32
|
||||
os_dpi_from_monitor(OS_Handle monitor)
|
||||
{
|
||||
F32 result = 96.f;
|
||||
HMONITOR monitor_handle = (HMONITOR)monitor.u64[0];
|
||||
if(w32_GetDpiForMonitor_func != 0)
|
||||
{
|
||||
UINT dpi_x = 0;
|
||||
UINT dpi_y = 0;
|
||||
HRESULT hr = w32_GetDpiForMonitor_func(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
|
||||
result = (F32)dpi_x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Events (Implemented Per-OS)
|
||||
|
||||
|
||||
+1733
-1140
File diff suppressed because it is too large
Load Diff
+573
-713
File diff suppressed because it is too large
Load Diff
+841
-591
File diff suppressed because it is too large
Load Diff
+11243
-10491
File diff suppressed because it is too large
Load Diff
+493
-851
File diff suppressed because it is too large
Load Diff
+110
-102
@@ -1,6 +1,48 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: 0.9.16 changes
|
||||
//
|
||||
// - Auto view rules have been upgraded to support type pattern-matching. This
|
||||
// makes them usable for generic types in various languages.
|
||||
// - The `slice` view rule has been streamlined and simplified. When an
|
||||
// expression with a `slice` view rule is expanded, it will simply expand to
|
||||
// the slice's contents, which matches the behavior with static arrays.
|
||||
// - The `slice` view rule now supports `first, one-past-last` pointer pairs,
|
||||
// as well as `base_pointer, length` pairs.
|
||||
// - The syntax for view rules has changed to improve its familiarity,
|
||||
// usability, and to improve its consistency with the rest of the evaluation
|
||||
// language. It now appears like function calls, and many arguments no longer
|
||||
// need to be explicitly named. For example, instead of
|
||||
// `bitmap:{w:1024, h:1024}`, the new view rule syntax would be
|
||||
// `bitmap(1024, 1024)`. Commas can still be omitted. Named arguments are
|
||||
// still possible (and required in some cases): `disasm(size=1024, arch=x64)`
|
||||
// - The hover evaluation feature has been majorly upgraded to support all
|
||||
// features normally available in the `Watch` view. Hover evaluations now
|
||||
// explicitly show type information, and contain a view rule column, which
|
||||
// can be edited in an identical way as the `Watch` view.
|
||||
// - Added "auto tabs", which are colored differently than normal tabs. These
|
||||
// tabs are automatically opened by the debugger when snapping to source code
|
||||
// which is not already opened. They are automatically replaced and recycled
|
||||
// when the debugger needs to snap to new locations. This will greatly reduce
|
||||
// the number of unused source code tabs accumulated throughout a debugging
|
||||
// session. These tabs can still be promoted to permanent tabs, in which case
|
||||
// they'll stay around until manually closed.
|
||||
// - The `Scheduler` view has been removed, in favor of three separate views,
|
||||
// which present various versions of the same information: `Threads`,
|
||||
// `Processes`, and `Machines`. The justification for this is that the
|
||||
// common case is debugging a small number of programs, usually 1, and for
|
||||
// those purposes, the `Threads` view is sufficient if not desirable, and
|
||||
// the extra information provided by `Processes` and `Machines`, while useful
|
||||
// in other contexts, is not useful in that common case.
|
||||
// - The two separate interfaces for editing threads, breakpoints, and watch
|
||||
// pins (the right-click context menu and the dedicated tabs) have been
|
||||
// merged.
|
||||
// - Added the ability to add per-target environment strings.
|
||||
// - Fixed an annoyance where the debugger would open a console window, even
|
||||
// for graphical programs, causing a flicker.
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: feature cleanup, code dedup, code elimination pass:
|
||||
//
|
||||
@@ -25,6 +67,17 @@
|
||||
// etc., all need to be merged, and optionally contextualized/filtered.
|
||||
// right-clicking a tab should be equivalent to spawning a command lister,
|
||||
// but only with commands that are directly
|
||||
//
|
||||
// [ ] r8 bitmap view rule seems incorrect?
|
||||
// [ ] crash bug, release mode - filter globals view (try with debugging raddbg, typing `dev` in globals view)
|
||||
//
|
||||
// [ ] stepping-onto a line with a conditional breakpoint, which fails, causes a
|
||||
// single step over the first instruction of that line, even if the thread
|
||||
// would've stopped at the first instruction due to the step, were that bp not
|
||||
// there.
|
||||
//
|
||||
// [ ] if a breakpoint matches the entry point's starting address, its hit count
|
||||
// is not correctly incremented.
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: post-0.9.12 TODO notes
|
||||
@@ -603,106 +656,58 @@ entry_point(CmdLine *cmd_line)
|
||||
String8List args = cmd_line->inputs;
|
||||
if(args.node_count > 0 && args.first->string.size != 0)
|
||||
{
|
||||
//- TODO(rjf): @cfg setup initial target from command line arguments
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//- rjf: unpack command line inputs
|
||||
String8 executable_name_string = {0};
|
||||
String8 arguments_string = {0};
|
||||
String8 working_directory_string = {0};
|
||||
{
|
||||
// rjf: unpack full executable path
|
||||
if(args.first->string.size != 0)
|
||||
{
|
||||
String8 current_path = os_get_current_path(scratch.arena);
|
||||
String8 exe_name = args.first->string;
|
||||
PathStyle style = path_style_from_str8(exe_name);
|
||||
if(style == PathStyle_Relative)
|
||||
{
|
||||
exe_name = push_str8f(scratch.arena, "%S/%S", current_path, exe_name);
|
||||
exe_name = path_normalized_from_string(scratch.arena, exe_name);
|
||||
}
|
||||
executable_name_string = exe_name;
|
||||
}
|
||||
|
||||
// rjf: unpack working directory
|
||||
if(args.first->string.size != 0)
|
||||
{
|
||||
String8 path_part_of_arg = str8_chop_last_slash(args.first->string);
|
||||
if(path_part_of_arg.size != 0)
|
||||
{
|
||||
String8 path = push_str8f(scratch.arena, "%S/", path_part_of_arg);
|
||||
working_directory_string = path;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: unpack arguments
|
||||
String8List passthrough_args_list = {0};
|
||||
for(String8Node *n = args.first->next; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
|
||||
}
|
||||
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
|
||||
arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join);
|
||||
}
|
||||
|
||||
//- rjf: build config tree
|
||||
RD_Cfg *command_line_root = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("command_line"));
|
||||
RD_Cfg *target = rd_cfg_new(command_line_root, str8_lit("target"));
|
||||
RD_Cfg *exe = rd_cfg_new(target, str8_lit("executable"));
|
||||
RD_Cfg *args = rd_cfg_new(target, str8_lit("arguments"));
|
||||
RD_Cfg *wdir = rd_cfg_new(target, str8_lit("working_directory"));
|
||||
rd_cfg_new(exe, executable_name_string);
|
||||
rd_cfg_new(args, arguments_string);
|
||||
rd_cfg_new(wdir, working_directory_string);
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
RD_Entity *target = rd_entity_alloc(rd_entity_root(), RD_EntityKind_Target);
|
||||
rd_entity_equip_cfg_src(target, RD_CfgSrc_CommandLine);
|
||||
String8List passthrough_args_list = {0};
|
||||
for(String8Node *n = args.first->next; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
|
||||
}
|
||||
|
||||
// rjf: get current path
|
||||
String8 current_path = os_get_current_path(scratch.arena);
|
||||
|
||||
// rjf: equip exe
|
||||
if(args.first->string.size != 0)
|
||||
//- rjf: unpack command line inputs
|
||||
String8 executable_name_string = {0};
|
||||
String8 arguments_string = {0};
|
||||
String8 working_directory_string = {0};
|
||||
{
|
||||
String8 exe_name = args.first->string;
|
||||
RD_Entity *exe = rd_entity_alloc(target, RD_EntityKind_Executable);
|
||||
PathStyle style = path_style_from_str8(exe_name);
|
||||
if(style == PathStyle_Relative)
|
||||
// rjf: unpack full executable path
|
||||
if(args.first->string.size != 0)
|
||||
{
|
||||
exe_name = push_str8f(scratch.arena, "%S/%S", current_path, exe_name);
|
||||
exe_name = path_normalized_from_string(scratch.arena, exe_name);
|
||||
String8 current_path = os_get_current_path(scratch.arena);
|
||||
String8 exe_name = args.first->string;
|
||||
PathStyle style = path_style_from_str8(exe_name);
|
||||
if(style == PathStyle_Relative)
|
||||
{
|
||||
exe_name = push_str8f(scratch.arena, "%S/%S", current_path, exe_name);
|
||||
exe_name = path_normalized_from_string(scratch.arena, exe_name);
|
||||
}
|
||||
executable_name_string = exe_name;
|
||||
}
|
||||
rd_entity_equip_name(exe, exe_name);
|
||||
|
||||
// rjf: unpack working directory
|
||||
if(args.first->string.size != 0)
|
||||
{
|
||||
String8 path_part_of_arg = str8_chop_last_slash(args.first->string);
|
||||
if(path_part_of_arg.size != 0)
|
||||
{
|
||||
String8 path = push_str8f(scratch.arena, "%S/", path_part_of_arg);
|
||||
working_directory_string = path;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: unpack arguments
|
||||
String8List passthrough_args_list = {0};
|
||||
for(String8Node *n = args.first->next; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
|
||||
}
|
||||
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
|
||||
arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join);
|
||||
}
|
||||
|
||||
// rjf: equip working directory
|
||||
String8 path_part_of_arg = str8_chop_last_slash(args.first->string);
|
||||
if(path_part_of_arg.size != 0)
|
||||
{
|
||||
String8 path = push_str8f(scratch.arena, "%S/", path_part_of_arg);
|
||||
RD_Entity *wdir = rd_entity_alloc(target, RD_EntityKind_WorkingDirectory);
|
||||
rd_entity_equip_name(wdir, path);
|
||||
}
|
||||
//- rjf: build config tree
|
||||
RD_Cfg *command_line_root = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("command_line"));
|
||||
RD_Cfg *target = rd_cfg_new(command_line_root, str8_lit("target"));
|
||||
RD_Cfg *exe = rd_cfg_new(target, str8_lit("executable"));
|
||||
RD_Cfg *args = rd_cfg_new(target, str8_lit("arguments"));
|
||||
RD_Cfg *wdir = rd_cfg_new(target, str8_lit("working_directory"));
|
||||
rd_cfg_new(exe, executable_name_string);
|
||||
rd_cfg_new(args, arguments_string);
|
||||
rd_cfg_new(wdir, working_directory_string);
|
||||
|
||||
// rjf: equip args
|
||||
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
|
||||
String8 args_str = str8_list_join(scratch.arena, &passthrough_args_list, &join);
|
||||
if(args_str.size != 0)
|
||||
{
|
||||
RD_Entity *args_entity = rd_entity_alloc(target, RD_EntityKind_Arguments);
|
||||
rd_entity_equip_name(args_entity, args_str);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
@@ -754,29 +759,32 @@ entry_point(CmdLine *cmd_line)
|
||||
if(msg.size != 0)
|
||||
{
|
||||
log_infof("ipc_msg: \"%S\"", msg);
|
||||
RD_Window *dst_window = rd_state->first_window;
|
||||
for(RD_Window *window = dst_window; window != 0; window = window->next)
|
||||
RD_WindowState *dst_ws = rd_state->first_window_state;
|
||||
for(RD_WindowState *ws = dst_ws; ws != &rd_nil_window_state; ws = ws->order_next)
|
||||
{
|
||||
if(os_window_is_focused(window->os))
|
||||
if(os_window_is_focused(ws->os))
|
||||
{
|
||||
dst_window = window;
|
||||
dst_ws = ws;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dst_window != 0)
|
||||
if(dst_ws != &rd_nil_window_state)
|
||||
{
|
||||
dst_window->window_temporarily_focused_ipc = 1;
|
||||
dst_ws->window_temporarily_focused_ipc = 1;
|
||||
U64 first_space_pos = str8_find_needle(msg, 0, str8_lit(" "), 0);
|
||||
String8 cmd_kind_name_string = str8_prefix(msg, first_space_pos);
|
||||
String8 cmd_args_string = str8_skip_chop_whitespace(str8_skip(msg, first_space_pos));
|
||||
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_kind_name_string);
|
||||
if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope()
|
||||
{
|
||||
if(dst_window != rd_window_from_handle(rd_regs()->window))
|
||||
if(dst_ws->cfg_id != rd_regs()->window)
|
||||
{
|
||||
rd_regs()->window = rd_handle_from_window(dst_window);
|
||||
rd_regs()->panel = rd_handle_from_panel(dst_window->focused_panel);
|
||||
rd_regs()->view = dst_window->focused_panel->selected_tab_view;
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
RD_PanelTree panel_tree = rd_panel_tree_from_cfg(scratch.arena, rd_cfg_from_id(dst_ws->cfg_id));
|
||||
rd_regs()->window = dst_ws->cfg_id;
|
||||
rd_regs()->panel = panel_tree.focused->cfg->id;
|
||||
rd_regs()->view = panel_tree.focused->selected_tab->id;
|
||||
scratch_end(scratch);
|
||||
}
|
||||
rd_regs_fill_slot_from_string(cmd_kind_info->query.slot, cmd_args_string);
|
||||
rd_push_cmd(cmd_kind_name_string, rd_regs());
|
||||
|
||||
+1012
-6092
File diff suppressed because it is too large
Load Diff
+123
-71
@@ -10,8 +10,8 @@
|
||||
typedef U32 RD_CodeViewBuildFlags;
|
||||
enum
|
||||
{
|
||||
RD_CodeViewBuildFlag_Margins = (1<<0),
|
||||
RD_CodeViewBuildFlag_All = 0xffffffff,
|
||||
RD_CodeViewBuildFlag_Margins = (1<<0),
|
||||
RD_CodeViewBuildFlag_All = 0xffffffff,
|
||||
};
|
||||
|
||||
typedef struct RD_CodeViewState RD_CodeViewState;
|
||||
@@ -41,13 +41,85 @@ struct RD_CodeViewBuildResult
|
||||
////////////////////////////////
|
||||
//~ rjf: Watch View Types
|
||||
|
||||
typedef U32 RD_WatchViewFlags;
|
||||
typedef enum RD_WatchCellKind
|
||||
{
|
||||
RD_WatchCellKind_Expr, // strings to represent expression itself
|
||||
RD_WatchCellKind_Tag, // strings to represent attached tags at row-granularity
|
||||
RD_WatchCellKind_Eval, // an evaluation of the expression, with some optional modification - e.g. `$expr.some_member`, or `typeof($expr)`
|
||||
RD_WatchCellKind_ViewUI, // an arbitrary user interface, supplied by a hook
|
||||
RD_WatchCellKind_CallStackFrame, // a slot for a yellow arrow, to show call stack frame selection
|
||||
}
|
||||
RD_WatchCellKind;
|
||||
|
||||
typedef U32 RD_WatchCellFlags;
|
||||
enum
|
||||
{
|
||||
RD_WatchViewFlag_NoHeader = (1<<0),
|
||||
RD_WatchViewFlag_PrettyNameMembers = (1<<1),
|
||||
RD_WatchViewFlag_PrettyEntityRows = (1<<2),
|
||||
RD_WatchViewFlag_DisableCacheLines = (1<<3),
|
||||
RD_WatchCellFlag_Button = (1<<0),
|
||||
RD_WatchCellFlag_Background = (1<<1),
|
||||
RD_WatchCellFlag_ActivateWithSingleClick = (1<<2),
|
||||
RD_WatchCellFlag_IsNonCode = (1<<3),
|
||||
RD_WatchCellFlag_CanEdit = (1<<4),
|
||||
RD_WatchCellFlag_IsErrored = (1<<5),
|
||||
};
|
||||
|
||||
typedef struct RD_WatchCell RD_WatchCell;
|
||||
struct RD_WatchCell
|
||||
{
|
||||
RD_WatchCell *next;
|
||||
RD_WatchCellKind kind;
|
||||
U64 index;
|
||||
String8 string;
|
||||
E_Eval eval;
|
||||
DR_FStrList fstrs;
|
||||
RD_WatchCellFlags flags;
|
||||
F32 default_pct;
|
||||
F32 pct;
|
||||
F32 px;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchCellList RD_WatchCellList;
|
||||
struct RD_WatchCellList
|
||||
{
|
||||
RD_WatchCell *first;
|
||||
RD_WatchCell *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchRowInfo RD_WatchRowInfo;
|
||||
struct RD_WatchRowInfo
|
||||
{
|
||||
E_Eval eval;
|
||||
CTRL_Entity *module;
|
||||
B32 can_expand;
|
||||
B32 expr_is_editable;
|
||||
String8 group_cfg_name;
|
||||
RD_Cfg *group_cfg_parent;
|
||||
RD_Cfg *group_cfg_child;
|
||||
CTRL_Entity *group_entity;
|
||||
CTRL_Entity *callstack_thread;
|
||||
U64 callstack_unwind_index;
|
||||
U64 callstack_inline_depth;
|
||||
U64 callstack_vaddr;
|
||||
String8 cell_style_key;
|
||||
RD_WatchCellList cells;
|
||||
RD_ViewUIRule *view_ui_rule;
|
||||
E_Expr *view_ui_tag;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchRowCellInfo RD_WatchRowCellInfo;
|
||||
struct RD_WatchRowCellInfo
|
||||
{
|
||||
RD_WatchCellFlags flags;
|
||||
E_Eval eval;
|
||||
RD_Cfg *cfg;
|
||||
CTRL_Entity *entity;
|
||||
String8 cmd_name;
|
||||
String8 string;
|
||||
DR_FStrList fstrs;
|
||||
String8 error_tooltip;
|
||||
String8 inheritance_tooltip;
|
||||
RD_ViewUIRule *view_ui_rule;
|
||||
E_Expr *view_ui_tag;
|
||||
};
|
||||
|
||||
typedef enum RD_WatchViewColumnKind
|
||||
@@ -93,48 +165,19 @@ struct RD_WatchViewColumn
|
||||
B32 rangify_braces;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchViewRowCtrl RD_WatchViewRowCtrl;
|
||||
struct RD_WatchViewRowCtrl
|
||||
typedef struct RD_WatchPt RD_WatchPt;
|
||||
struct RD_WatchPt
|
||||
{
|
||||
RD_EntityKind entity_kind;
|
||||
CTRL_EntityKind ctrl_entity_kind;
|
||||
RD_CmdKind kind;
|
||||
};
|
||||
|
||||
typedef enum RD_WatchViewRowKind
|
||||
{
|
||||
RD_WatchViewRowKind_Normal,
|
||||
RD_WatchViewRowKind_Header,
|
||||
RD_WatchViewRowKind_Canvas,
|
||||
RD_WatchViewRowKind_PrettyEntityControls,
|
||||
}
|
||||
RD_WatchViewRowKind;
|
||||
|
||||
typedef struct RD_WatchViewPoint RD_WatchViewPoint;
|
||||
struct RD_WatchViewPoint
|
||||
{
|
||||
S64 x;
|
||||
EV_Key parent_key;
|
||||
EV_Key key;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchViewRowInfo RD_WatchViewRowInfo;
|
||||
struct RD_WatchViewRowInfo
|
||||
{
|
||||
RD_EntityKind collection_entity_kind;
|
||||
RD_Entity *collection_entity;
|
||||
CTRL_EntityKind collection_ctrl_entity_kind;
|
||||
CTRL_Entity *collection_ctrl_entity;
|
||||
CTRL_Entity *callstack_thread;
|
||||
U64 callstack_unwind_index;
|
||||
U64 callstack_inline_depth;
|
||||
U64 cell_id;
|
||||
};
|
||||
|
||||
typedef struct RD_WatchViewTextEditState RD_WatchViewTextEditState;
|
||||
struct RD_WatchViewTextEditState
|
||||
{
|
||||
RD_WatchViewTextEditState *pt_hash_next;
|
||||
RD_WatchViewPoint pt;
|
||||
RD_WatchPt pt;
|
||||
TxtPt cursor;
|
||||
TxtPt mark;
|
||||
U8 input_buffer[1024];
|
||||
@@ -148,18 +191,15 @@ struct RD_WatchViewState
|
||||
{
|
||||
B32 initialized;
|
||||
|
||||
// rjf: column state
|
||||
Arena *column_arena;
|
||||
RD_WatchViewColumn *first_column;
|
||||
RD_WatchViewColumn *last_column;
|
||||
RD_WatchViewColumn *free_column;
|
||||
U64 column_count;
|
||||
// rjf: filter history
|
||||
Arena *filter_arena;
|
||||
String8 last_filter;
|
||||
|
||||
// rjf; table cursor state
|
||||
RD_WatchViewPoint cursor;
|
||||
RD_WatchViewPoint mark;
|
||||
RD_WatchViewPoint next_cursor;
|
||||
RD_WatchViewPoint next_mark;
|
||||
RD_WatchPt cursor;
|
||||
RD_WatchPt mark;
|
||||
RD_WatchPt next_cursor;
|
||||
RD_WatchPt next_mark;
|
||||
|
||||
// rjf: text input state
|
||||
Arena *text_edit_arena;
|
||||
@@ -178,34 +218,46 @@ internal RD_CodeViewBuildResult rd_code_view_build(Arena *arena, RD_CodeViewStat
|
||||
////////////////////////////////
|
||||
//~ rjf: Watch View Functions
|
||||
|
||||
//- rjf: index -> column
|
||||
internal RD_WatchViewColumn *rd_watch_view_column_from_x(RD_WatchViewState *wv, S64 index);
|
||||
//- rjf: cell list building
|
||||
internal U64 rd_id_from_watch_cell(RD_WatchCell *cell);
|
||||
internal RD_WatchCell *rd_watch_cell_list_push(Arena *arena, RD_WatchCellList *list);
|
||||
internal RD_WatchCell *rd_watch_cell_list_push_new_(Arena *arena, RD_WatchCellList *list, RD_WatchCell *params);
|
||||
#define rd_watch_cell_list_push_new(arena, list, kind_, ...) rd_watch_cell_list_push_new_((arena), (list), &(RD_WatchCell){.kind = (kind_), __VA_ARGS__})
|
||||
|
||||
//- rjf: watch view points <-> table coordinates
|
||||
internal B32 rd_watch_view_point_match(RD_WatchViewPoint a, RD_WatchViewPoint b);
|
||||
internal RD_WatchViewPoint rd_watch_view_point_from_tbl(EV_BlockRangeList *block_ranges, Vec2S64 tbl);
|
||||
internal Vec2S64 rd_tbl_from_watch_view_point(EV_BlockRangeList *block_ranges, RD_WatchViewPoint pt);
|
||||
internal B32 rd_watch_pt_match(RD_WatchPt a, RD_WatchPt b);
|
||||
internal RD_WatchPt rd_watch_pt_from_tbl(EV_BlockRangeList *block_ranges, Vec2S64 tbl);
|
||||
internal Vec2S64 rd_tbl_from_watch_pt(EV_BlockRangeList *block_ranges, RD_WatchPt pt);
|
||||
|
||||
//- rjf: row -> context info
|
||||
internal RD_WatchViewRowInfo rd_watch_view_row_info_from_row(EV_Row *row);
|
||||
//- rjf: row -> info
|
||||
internal RD_WatchRowInfo rd_watch_row_info_from_row(Arena *arena, EV_Row *row);
|
||||
|
||||
//- rjf: watch view flags & row & row info -> row kind
|
||||
internal RD_WatchViewRowKind rd_watch_view_row_kind_from_flags_row_info(RD_WatchViewFlags flags, EV_Row *row, RD_WatchViewRowInfo *info);
|
||||
|
||||
//- rjf: row/column -> exprs / strings
|
||||
internal E_Expr *rd_expr_from_watch_view_row_column(Arena *arena, EV_View *ev_view, EV_Row *row, RD_WatchViewColumn *col);
|
||||
internal String8 rd_string_from_eval_viz_row_column(Arena *arena, EV_View *ev, EV_Row *row, RD_WatchViewColumn *col, EV_StringFlags string_flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size_px);
|
||||
//- rjf: row * cell -> info
|
||||
internal RD_WatchRowCellInfo rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_flags, RD_WatchRowInfo *row_info, RD_WatchCell *cell, FNT_Tag font, F32 font_size, F32 max_size_px);
|
||||
|
||||
//- rjf: table coordinates -> text edit state
|
||||
internal RD_WatchViewTextEditState *rd_watch_view_text_edit_state_from_pt(RD_WatchViewState *wv, RD_WatchViewPoint pt);
|
||||
internal RD_WatchViewTextEditState *rd_watch_view_text_edit_state_from_pt(RD_WatchViewState *wv, RD_WatchPt pt);
|
||||
|
||||
//- rjf: watch view column state mutation
|
||||
internal RD_WatchViewColumn *rd_watch_view_column_alloc_(RD_WatchViewState *wv, RD_WatchViewColumnKind kind, F32 pct, RD_WatchViewColumnParams *params);
|
||||
#define rd_watch_view_column_alloc(wv, kind, pct, ...) rd_watch_view_column_alloc_((wv), (kind), (pct), &(RD_WatchViewColumnParams){.string = str8_zero(), __VA_ARGS__})
|
||||
internal void rd_watch_view_column_release(RD_WatchViewState *wv, RD_WatchViewColumn *col);
|
||||
////////////////////////////////
|
||||
//~ rjf: View Hooks
|
||||
|
||||
//- rjf: watch view main hooks
|
||||
internal void rd_watch_view_init(RD_WatchViewState *ewv);
|
||||
internal void rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 root_expr, String8 root_view_rule, B32 modifiable, U32 default_radix, Rng2F32 rect);
|
||||
// TODO(rjf): eliminate once we are predeclaring these with metacode
|
||||
|
||||
RD_VIEW_UI_FUNCTION_DEF(null);
|
||||
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(text);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(disasm);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(bitmap);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(color_rgba);
|
||||
EV_EXPAND_RULE_INFO_FUNCTION_DEF(geo3d);
|
||||
|
||||
RD_VIEW_UI_FUNCTION_DEF(text);
|
||||
RD_VIEW_UI_FUNCTION_DEF(disasm);
|
||||
RD_VIEW_UI_FUNCTION_DEF(memory);
|
||||
RD_VIEW_UI_FUNCTION_DEF(bitmap);
|
||||
RD_VIEW_UI_FUNCTION_DEF(checkbox);
|
||||
RD_VIEW_UI_FUNCTION_DEF(color_rgba);
|
||||
RD_VIEW_UI_FUNCTION_DEF(geo3d);
|
||||
|
||||
#endif // RADDBG_VIEWS_H
|
||||
|
||||
+1205
-430
File diff suppressed because it is too large
Load Diff
+68
-17
@@ -5,21 +5,64 @@
|
||||
#define RADDBG_WIDGETS_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Line Edit Types
|
||||
//~ rjf: Cell Types
|
||||
|
||||
typedef U32 RD_LineEditFlags;
|
||||
typedef U32 RD_CellFlags;
|
||||
enum
|
||||
{
|
||||
RD_LineEditFlag_Expander = (1<<0),
|
||||
RD_LineEditFlag_ExpanderSpace = (1<<1),
|
||||
RD_LineEditFlag_ExpanderPlaceholder = (1<<2),
|
||||
RD_LineEditFlag_DisableEdit = (1<<3),
|
||||
RD_LineEditFlag_CodeContents = (1<<4),
|
||||
RD_LineEditFlag_KeyboardClickable = (1<<5),
|
||||
RD_LineEditFlag_Border = (1<<6),
|
||||
RD_LineEditFlag_NoBackground = (1<<7),
|
||||
RD_LineEditFlag_PreferDisplayString = (1<<8),
|
||||
RD_LineEditFlag_DisplayStringIsCode = (1<<9),
|
||||
//- rjf: expander
|
||||
RD_CellFlag_Expander = (1<<0),
|
||||
RD_CellFlag_ExpanderSpace = (1<<1),
|
||||
RD_CellFlag_ExpanderPlaceholder = (1<<2),
|
||||
|
||||
//- rjf: toggle switch extension
|
||||
RD_CellFlag_ToggleSwitch = (1<<3),
|
||||
|
||||
//- rjf: slider extension
|
||||
RD_CellFlag_Slider = (1<<4),
|
||||
|
||||
//- rjf: behavior
|
||||
RD_CellFlag_DisableEdit = (1<<5),
|
||||
RD_CellFlag_KeyboardClickable = (1<<6),
|
||||
RD_CellFlag_SingleClickActivate = (1<<7),
|
||||
|
||||
//- rjf: contents description
|
||||
RD_CellFlag_CodeContents = (1<<8),
|
||||
|
||||
//- rjf: appearance
|
||||
RD_CellFlag_Border = (1<<9),
|
||||
RD_CellFlag_NoBackground = (1<<10),
|
||||
RD_CellFlag_Button = (1<<11),
|
||||
RD_CellFlag_PreferDisplayString = (1<<12),
|
||||
RD_CellFlag_DisplayStringIsCode = (1<<13),
|
||||
};
|
||||
|
||||
typedef struct RD_CellParams RD_CellParams;
|
||||
struct RD_CellParams
|
||||
{
|
||||
//- rjf: catachall parameters
|
||||
RD_CellFlags flags;
|
||||
S32 depth;
|
||||
FuzzyMatchRangeList *fuzzy_matches;
|
||||
String8 pre_edit_value;
|
||||
DR_FStrList fstrs;
|
||||
|
||||
//- rjf: expander r/w info
|
||||
B32 *expanded_out;
|
||||
|
||||
//- rjf: toggle-switch r/w info
|
||||
B32 *toggled_out;
|
||||
|
||||
//- rjf: slider info r/w info
|
||||
Rng1U64 slider_value_range;
|
||||
U64 *slider_value_out;
|
||||
|
||||
//- rjf: text editing r/w info
|
||||
TxtPt *cursor;
|
||||
TxtPt *mark;
|
||||
U8 *edit_buffer;
|
||||
U64 edit_buffer_size;
|
||||
U64 *edit_string_size_out;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -43,9 +86,9 @@ struct RD_CodeSliceParams
|
||||
String8 *line_text;
|
||||
Rng1U64 *line_ranges;
|
||||
TXT_TokenArray *line_tokens;
|
||||
RD_EntityList *line_bps;
|
||||
RD_CfgList *line_bps;
|
||||
CTRL_EntityList *line_ips;
|
||||
RD_EntityList *line_pins;
|
||||
RD_CfgList *line_pins;
|
||||
U64 *line_vaddrs;
|
||||
D_LineList *line_infos;
|
||||
DI_KeyList relevant_dbgi_keys;
|
||||
@@ -77,6 +120,14 @@ struct RD_CodeSliceSignal
|
||||
#define RD_Palette(code) UI_Palette(rd_palette_from_code(code))
|
||||
#define RD_Font(slot) UI_Font(rd_font_from_slot(slot)) UI_TextRasterFlags(rd_raster_flags_from_slot((slot)))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: UI Widgets: Fancy Title Strings
|
||||
|
||||
internal DR_FStrList rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg);
|
||||
internal DR_FStrList rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras);
|
||||
internal DR_FStrList rd_title_fstrs_from_code_name(Arena *arena, String8 code_name);
|
||||
internal DR_FStrList rd_title_fstrs_from_file_path(Arena *arena, String8 file_path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: UI Widgets: Loading Overlay
|
||||
|
||||
@@ -108,13 +159,13 @@ internal B32 rd_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count
|
||||
internal UI_Signal rd_label(String8 string);
|
||||
internal UI_Signal rd_error_label(String8 string);
|
||||
internal B32 rd_help_label(String8 string);
|
||||
internal DR_FancyStringList rd_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
|
||||
internal DR_FStrList rd_fstrs_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
|
||||
internal UI_Box *rd_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: UI Widgets: Line Edit
|
||||
|
||||
internal UI_Signal rd_line_edit(RD_LineEditFlags flags, S32 depth, FuzzyMatchRangeList *matches, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, String8 string);
|
||||
internal UI_Signal rd_line_editf(RD_LineEditFlags flags, S32 depth, FuzzyMatchRangeList *matches, TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, B32 *expanded_out, String8 pre_edit_value, char *fmt, ...);
|
||||
internal UI_Signal rd_cell(RD_CellParams *params, String8 string);
|
||||
internal UI_Signal rd_cellf(RD_CellParams *params, char *fmt, ...);
|
||||
|
||||
#endif // RADDBG_WIDGETS_H
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "coff/coff_parse.h"
|
||||
#include "codeview/codeview.h"
|
||||
#include "codeview/codeview_parse.h"
|
||||
#include "codeview/codeview_enum.h"
|
||||
#include "msf/msf.h"
|
||||
#include "msf/msf_parse.h"
|
||||
#include "pdb/pdb.h"
|
||||
@@ -43,6 +44,7 @@
|
||||
#include "coff/coff_parse.c"
|
||||
#include "codeview/codeview.c"
|
||||
#include "codeview/codeview_parse.c"
|
||||
#include "codeview/codeview_enum.c"
|
||||
#include "msf/msf.c"
|
||||
#include "msf/msf_parse.c"
|
||||
#include "pdb/pdb.c"
|
||||
@@ -223,7 +225,7 @@ entry_point(CmdLine *cmdline)
|
||||
{
|
||||
convert2bake = p2r_convert(arena, user2convert);
|
||||
}
|
||||
|
||||
|
||||
//- rjf: dump breakpad text
|
||||
String8List dump = {0};
|
||||
ProfScope("dump breakpad text")
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"////////////////////////////////////////////////////////////////";
|
||||
"//~ Format Constants";
|
||||
"";
|
||||
"// \"raddbg\0\0\"";
|
||||
"// \"raddbg\\0\\0\"";
|
||||
"#define RDI_MAGIC_CONSTANT 0x0000676264646172";
|
||||
"#define RDI_ENCODING_VERSION 11";
|
||||
"";
|
||||
|
||||
@@ -787,12 +787,11 @@ ASYNC_WORK_DEF(p2r_units_convert_work)
|
||||
}
|
||||
|
||||
// rjf: build line table, fill with parsed binary annotations
|
||||
|
||||
if(inlinee_lines_parsed != 0)
|
||||
{
|
||||
// rjf: grab checksums sub-section
|
||||
CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section;
|
||||
|
||||
|
||||
// rjf: gathered lines
|
||||
typedef struct LineChunk LineChunk;
|
||||
struct LineChunk
|
||||
@@ -810,12 +809,12 @@ ASYNC_WORK_DEF(p2r_units_convert_work)
|
||||
U32 last_file_off = max_U32;
|
||||
U32 curr_file_off = max_U32;
|
||||
RDIM_LineTable* line_table = 0;
|
||||
|
||||
|
||||
CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff);
|
||||
for(;;)
|
||||
{
|
||||
CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots);
|
||||
|
||||
|
||||
if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile)
|
||||
{
|
||||
last_file_off = curr_file_off;
|
||||
@@ -829,7 +828,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work)
|
||||
if((last_file_off != max_U32 && last_file_off != curr_file_off))
|
||||
{
|
||||
String8 seq_file_name = {0};
|
||||
|
||||
|
||||
if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size)
|
||||
{
|
||||
CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + last_file_off);
|
||||
@@ -901,7 +900,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work)
|
||||
first_line_chunk = last_line_chunk = 0;
|
||||
total_line_chunk_line_count = 0;
|
||||
}
|
||||
|
||||
|
||||
if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine)
|
||||
{
|
||||
LineChunk *chunk = last_line_chunk;
|
||||
@@ -919,7 +918,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work)
|
||||
chunk->count += 1;
|
||||
total_line_chunk_line_count += 1;
|
||||
}
|
||||
|
||||
|
||||
if(step.flags == 0)
|
||||
{
|
||||
break;
|
||||
@@ -2436,14 +2435,14 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work)
|
||||
for(;;)
|
||||
{
|
||||
CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots);
|
||||
|
||||
|
||||
if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitRange)
|
||||
{
|
||||
// rjf: build new range & add to scope
|
||||
RDIM_Rng1U64 voff_range = { step.range.min, step.range.max };
|
||||
rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range);
|
||||
}
|
||||
|
||||
|
||||
if(step.flags & CV_C13InlineSiteDecoderStepFlag_ExtendLastRange)
|
||||
{
|
||||
if(scope->voff_ranges.last != 0)
|
||||
@@ -2451,7 +2450,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work)
|
||||
scope->voff_ranges.last->v.max = step.range.max;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(step.flags == 0)
|
||||
{
|
||||
break;
|
||||
@@ -2524,7 +2523,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
named_streams = pdb_named_stream_table_from_info(arena, info);
|
||||
MemoryCopyStruct(&auth_guid, &info->auth_guid);
|
||||
scratch_end(scratch);
|
||||
|
||||
|
||||
if (info->features & PDB_FeatureFlag_MINIMAL_DBG_INFO) {
|
||||
fprintf(stderr, "ERROR: PDB was linked with /DEBUG:FASTLINK (partial debug info is not supported). Please relink using /DEBUG:FULL.");
|
||||
os_abort(1);
|
||||
@@ -2888,13 +2887,13 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
if(in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 1: construct all root/stub types from TPI")
|
||||
{
|
||||
itype_type_ptrs = push_array(arena, RDIM_Type *, tpi_leaf->itype_opl);
|
||||
|
||||
|
||||
//////////////////////////
|
||||
//- build basic type
|
||||
//
|
||||
{
|
||||
RDIM_DataModel data_model = rdim_infer_data_model(OperatingSystem_Windows, top_level_info.arch);
|
||||
|
||||
|
||||
RDI_TypeKind short_type = rdim_short_type_from_data_model(data_model);
|
||||
RDI_TypeKind ushort_type = rdim_unsigned_short_type_from_data_model(data_model);
|
||||
RDI_TypeKind int_type = rdim_int_type_from_data_model(data_model);
|
||||
@@ -2904,7 +2903,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
RDI_TypeKind long_long_type = rdim_long_long_type_from_data_model(data_model);
|
||||
RDI_TypeKind ulong_long_type = rdim_unsigned_long_long_type_from_data_model(data_model);
|
||||
RDI_TypeKind ptr_type = rdim_pointer_size_t_type_from_data_model(data_model);
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
char * name;
|
||||
@@ -2959,7 +2958,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{ "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 , 1, 1, 1 }, // always UTF-32
|
||||
{ "__pointer" , ptr_type , CV_BasicType_PTR , 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
for(U64 i = 0; i < ArrayCount(table); i += 1)
|
||||
{
|
||||
U64 builtin_size;
|
||||
@@ -2971,14 +2970,14 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{
|
||||
builtin_size = rdi_size_from_basic_type_kind(table[i].kind_rdi);
|
||||
}
|
||||
|
||||
|
||||
RDIM_Type *builtin = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl);
|
||||
builtin->kind = table[i].kind_rdi;
|
||||
builtin->name = str8_cstring(table[i].name);
|
||||
builtin->byte_size = builtin_size;
|
||||
|
||||
|
||||
itype_type_ptrs[table[i].kind_cv] = builtin;
|
||||
|
||||
|
||||
if(table[i].make_pointer_near)
|
||||
{
|
||||
CV_TypeIndex near_ptr_itype = table[i].kind_cv | 0x100;
|
||||
@@ -2986,7 +2985,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
ptr_near->kind = RDI_TypeKind_Ptr;
|
||||
ptr_near->byte_size = 2;
|
||||
ptr_near->direct_type = builtin;
|
||||
|
||||
|
||||
itype_type_ptrs[near_ptr_itype] = ptr_near;
|
||||
}
|
||||
if(table[i].make_pointer_32)
|
||||
@@ -2996,7 +2995,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
ptr_32->kind = RDI_TypeKind_Ptr;
|
||||
ptr_32->byte_size = 4;
|
||||
ptr_32->direct_type = builtin;
|
||||
|
||||
|
||||
itype_type_ptrs[ptr_32_itype] = ptr_32;
|
||||
}
|
||||
if(table[i].make_pointer_64)
|
||||
@@ -3006,12 +3005,12 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
ptr_64->kind = RDI_TypeKind_Ptr;
|
||||
ptr_64->byte_size = 8;
|
||||
ptr_64->direct_type = builtin;
|
||||
|
||||
|
||||
itype_type_ptrs[ptr_64_itype] = ptr_64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: build non-basic type
|
||||
//
|
||||
@@ -3021,7 +3020,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
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);
|
||||
|
||||
|
||||
if(range->off+range->hdr.size <= tpi_leaf->data.size &&
|
||||
range->off+2+header_struct_size <= tpi_leaf->data.size &&
|
||||
range->hdr.size >= 2)
|
||||
@@ -3278,7 +3277,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{
|
||||
dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct);
|
||||
}
|
||||
|
||||
|
||||
B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) &&
|
||||
((lf->props & CV_TypeProp_HasUniqueName) != 0));
|
||||
if(do_unique_name_lookup)
|
||||
@@ -3286,7 +3285,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
U8 *unique_name_ptr = name_ptr + name.size + 1;
|
||||
dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl);
|
||||
}
|
||||
|
||||
|
||||
dst_type->name = name;
|
||||
dst_type->byte_size = safe_cast_u32(size_u64);
|
||||
}break;
|
||||
@@ -3318,7 +3317,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
dst_type->byte_size = (U32)size_u64;
|
||||
dst_type->name = name;
|
||||
}
|
||||
|
||||
|
||||
B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) &&
|
||||
((lf->props & CV_TypeProp_HasUniqueName) != 0));
|
||||
if(do_unique_name_lookup)
|
||||
@@ -3354,7 +3353,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
dst_type->byte_size = (U32)size_u64;
|
||||
dst_type->name = name;
|
||||
}
|
||||
|
||||
|
||||
B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) &&
|
||||
((lf->props & CV_TypeProp_HasUniqueName) != 0));
|
||||
if(do_unique_name_lookup)
|
||||
@@ -3389,7 +3388,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
dst_type->byte_size = direct_type ? direct_type->byte_size : 0;
|
||||
dst_type->name = name;
|
||||
}
|
||||
|
||||
|
||||
B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) &&
|
||||
((lf->props & CV_TypeProp_HasUniqueName) != 0));
|
||||
if(do_unique_name_lookup)
|
||||
@@ -3576,7 +3575,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
help_state.arena = p2r_state->arena;
|
||||
help_state.work_thread_arenas_count = p2r_state->work_thread_arenas_count;
|
||||
help_state.work_thread_arenas = p2r_state->work_thread_arenas;
|
||||
|
||||
|
||||
P2R_Bake2Serialize *result = push_array(arena, P2R_Bake2Serialize, 1);
|
||||
result->bake_results = rdim_bake(&help_state, &in->bake_params);
|
||||
return result;
|
||||
|
||||
@@ -83,6 +83,20 @@ str8_lit_comp(
|
||||
" return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float linear_from_srgb_f32(float x)\n"
|
||||
"{\n"
|
||||
" return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float4 linear_from_srgba(float4 v)\n"
|
||||
"{\n"
|
||||
" float4 result = float4(linear_from_srgb_f32(v.x),\n"
|
||||
" linear_from_srgb_f32(v.y),\n"
|
||||
" linear_from_srgb_f32(v.z),\n"
|
||||
" v.w);\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//- rjf: vertex shader\n"
|
||||
"\n"
|
||||
"Vertex2Pixel\n"
|
||||
@@ -122,7 +136,8 @@ str8_lit_comp(
|
||||
" cpu2vertex.corner_radii_px.w,\n"
|
||||
" cpu2vertex.corner_radii_px.z,\n"
|
||||
" };\n"
|
||||
" float4 src_color[] = {\n"
|
||||
" float4 src_color[] =\n"
|
||||
" {\n"
|
||||
" cpu2vertex.color01,\n"
|
||||
" cpu2vertex.color00,\n"
|
||||
" cpu2vertex.color11,\n"
|
||||
@@ -164,6 +179,7 @@ str8_lit_comp(
|
||||
" if(vertex2pixel.omit_texture < 1)\n"
|
||||
" {\n"
|
||||
" albedo_sample = mul(main_t2d.Sample(main_sampler, vertex2pixel.texcoord_pct), texture_sample_channel_map);\n"
|
||||
" albedo_sample = linear_from_srgba(albedo_sample);\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" // rjf: determine SDF sample position\n"
|
||||
|
||||
@@ -520,7 +520,7 @@ r_window_equip(OS_Handle handle)
|
||||
{
|
||||
swapchain_desc.Width = 0; // NOTE(rjf): use window width
|
||||
swapchain_desc.Height = 0; // NOTE(rjf): use window height
|
||||
swapchain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
swapchain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
swapchain_desc.Stereo = FALSE;
|
||||
swapchain_desc.SampleDesc.Count = 1;
|
||||
swapchain_desc.SampleDesc.Quality = 0;
|
||||
@@ -672,8 +672,11 @@ r_tex2d_release(R_Handle handle)
|
||||
ProfBeginFunction();
|
||||
OS_MutexScopeW(r_d3d11_state->device_rw_mutex)
|
||||
{
|
||||
R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle);
|
||||
SLLStackPush(r_d3d11_state->first_to_free_tex2d, texture);
|
||||
R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle);
|
||||
if(texture != &r_d3d11_tex2d_nil)
|
||||
{
|
||||
SLLStackPush(r_d3d11_state->first_to_free_tex2d, texture);
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
}
|
||||
@@ -705,16 +708,19 @@ r_fill_tex2d_region(R_Handle handle, Rng2S32 subrect, void *data)
|
||||
ProfBeginFunction();
|
||||
OS_MutexScopeW(r_d3d11_state->device_rw_mutex)
|
||||
{
|
||||
R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle);
|
||||
Assert(texture->kind == R_ResourceKind_Dynamic && "only dynamic texture can update region");
|
||||
U64 bytes_per_pixel = r_tex2d_format_bytes_per_pixel_table[texture->format];
|
||||
Vec2S32 dim = v2s32(subrect.x1 - subrect.x0, subrect.y1 - subrect.y0);
|
||||
D3D11_BOX dst_box =
|
||||
{
|
||||
(UINT)subrect.x0, (UINT)subrect.y0, 0,
|
||||
(UINT)subrect.x1, (UINT)subrect.y1, 1,
|
||||
};
|
||||
r_d3d11_state->device_ctx->lpVtbl->UpdateSubresource(r_d3d11_state->device_ctx, (ID3D11Resource *)texture->texture, 0, &dst_box, data, dim.x*bytes_per_pixel, 0);
|
||||
R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle);
|
||||
if(texture != &r_d3d11_tex2d_nil)
|
||||
{
|
||||
Assert(texture->kind == R_ResourceKind_Dynamic && "only dynamic texture can update region");
|
||||
U64 bytes_per_pixel = r_tex2d_format_bytes_per_pixel_table[texture->format];
|
||||
Vec2S32 dim = v2s32(subrect.x1 - subrect.x0, subrect.y1 - subrect.y0);
|
||||
D3D11_BOX dst_box =
|
||||
{
|
||||
(UINT)subrect.x0, (UINT)subrect.y0, 0,
|
||||
(UINT)subrect.x1, (UINT)subrect.y1, 1,
|
||||
};
|
||||
r_d3d11_state->device_ctx->lpVtbl->UpdateSubresource(r_d3d11_state->device_ctx, (ID3D11Resource *)texture->texture, 0, &dst_box, data, dim.x*bytes_per_pixel, 0);
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
}
|
||||
@@ -820,8 +826,10 @@ r_end_frame(void)
|
||||
tex = next)
|
||||
{
|
||||
next = tex->next;
|
||||
tex->view->lpVtbl->Release(tex->view);
|
||||
tex->texture->lpVtbl->Release(tex->texture);
|
||||
tex->view->lpVtbl->Release(tex->view);
|
||||
tex->texture->lpVtbl->Release(tex->texture);
|
||||
tex->view = 0;
|
||||
tex->texture = 0;
|
||||
tex->generation += 1;
|
||||
SLLStackPush(r_d3d11_state->first_free_tex2d, tex);
|
||||
}
|
||||
@@ -888,7 +896,7 @@ r_window_begin_frame(OS_Handle window, R_Handle window_equip)
|
||||
D3D11_TEXTURE2D_DESC color_desc = zero_struct;
|
||||
{
|
||||
wnd->framebuffer->lpVtbl->GetDesc(wnd->framebuffer, &color_desc);
|
||||
color_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
color_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
color_desc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE;
|
||||
}
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = zero_struct;
|
||||
@@ -898,7 +906,7 @@ r_window_begin_frame(OS_Handle window, R_Handle window_equip)
|
||||
}
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = zero_struct;
|
||||
{
|
||||
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srv_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MipLevels = -1;
|
||||
}
|
||||
|
||||
@@ -171,9 +171,9 @@ struct R_D3D11_State
|
||||
//~ rjf: Globals
|
||||
|
||||
global R_D3D11_State *r_d3d11_state = 0;
|
||||
global R_D3D11_Window r_d3d11_window_nil = {&r_d3d11_window_nil};
|
||||
global R_D3D11_Tex2D r_d3d11_tex2d_nil = {&r_d3d11_tex2d_nil};
|
||||
global R_D3D11_Buffer r_d3d11_buffer_nil = {&r_d3d11_buffer_nil};
|
||||
global read_only R_D3D11_Window r_d3d11_window_nil = {&r_d3d11_window_nil};
|
||||
global read_only R_D3D11_Tex2D r_d3d11_tex2d_nil = {&r_d3d11_tex2d_nil};
|
||||
global read_only R_D3D11_Buffer r_d3d11_buffer_nil = {&r_d3d11_buffer_nil};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
@@ -81,6 +81,20 @@ float rect_sdf(float2 sample_pos, float2 rect_half_size, float r)
|
||||
return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;
|
||||
}
|
||||
|
||||
float linear_from_srgb_f32(float x)
|
||||
{
|
||||
return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
float4 linear_from_srgba(float4 v)
|
||||
{
|
||||
float4 result = float4(linear_from_srgb_f32(v.x),
|
||||
linear_from_srgb_f32(v.y),
|
||||
linear_from_srgb_f32(v.z),
|
||||
v.w);
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: vertex shader
|
||||
|
||||
Vertex2Pixel
|
||||
@@ -120,7 +134,8 @@ vs_main(CPU2Vertex cpu2vertex)
|
||||
cpu2vertex.corner_radii_px.w,
|
||||
cpu2vertex.corner_radii_px.z,
|
||||
};
|
||||
float4 src_color[] = {
|
||||
float4 src_color[] =
|
||||
{
|
||||
cpu2vertex.color01,
|
||||
cpu2vertex.color00,
|
||||
cpu2vertex.color11,
|
||||
@@ -162,6 +177,7 @@ ps_main(Vertex2Pixel vertex2pixel) : SV_TARGET
|
||||
if(vertex2pixel.omit_texture < 1)
|
||||
{
|
||||
albedo_sample = mul(main_t2d.Sample(main_sampler, vertex2pixel.texcoord_pct), texture_sample_channel_map);
|
||||
albedo_sample = linear_from_srgba(albedo_sample);
|
||||
}
|
||||
|
||||
// rjf: determine SDF sample position
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user