From 2b20760386e4d9255ac86fcf10a35244deff2e10 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 12 Jun 2026 13:49:37 -0700 Subject: [PATCH] checkpoint on revised eval system; first pass on interpretation; eliminating all callbacks / eval involvement in contexts/spaces/identifier-resolution/etc. --- src/eval/eval_core.h | 7 - src/eval/eval_interpret.c | 32 -- src/eval2/eval2.c | 617 +++++++++++++++++++++++++++++++ src/eval2/eval2.h | 371 +++++++++++++++++++ src/eval2/eval2.mdesk | 87 +++++ src/eval2/generated/eval2.meta.c | 5 + src/eval2/generated/eval2.meta.h | 87 +++++ src/lib_rdi/rdi.c | 4 +- src/lib_rdi/rdi.h | 6 +- src/raddbg/raddbg_main.c | 2 + src/rdi/rdi.mdesk | 4 +- src/rdi/rdi_local.c | 5 - 12 files changed, 1173 insertions(+), 54 deletions(-) create mode 100644 src/eval2/eval2.c create mode 100644 src/eval2/eval2.h create mode 100644 src/eval2/eval2.mdesk create mode 100644 src/eval2/generated/eval2.meta.c create mode 100644 src/eval2/generated/eval2.meta.h diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index 770a2dfc..ddddebe1 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -1050,13 +1050,6 @@ struct E_CacheNode E_CacheBundle bundle; }; -typedef struct E_CacheLookup E_CacheLookup; -struct E_CacheLookup -{ - E_CacheNode *node; - U64 hash; -}; - typedef struct E_CacheSlot E_CacheSlot; struct E_CacheSlot { diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index 4d09aeec..e314ac10 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -360,18 +360,6 @@ e_interpret(String8 bytecode) } }break; - case RDI_EvalOp_RegReadDyn: - { - U64 off = svals[0].u64; - U64 size = bit_size_from_arch(e_interpret_ctx->reg_arch)/8; - B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, 0, r1u64(off, off+size)); - if(!good_read) - { - result.code = E_InterpretationCode_BadRegRead; - goto done; - } - }break; - case RDI_EvalOp_FrameOff: { if(e_interpret_ctx->frame_base != 0) @@ -949,26 +937,6 @@ e_interpret(String8 bytecode) // do nothing - the pop is handled by the control bits }break; - case RDI_EvalOp_Insert: - { - if(stack_count > imm.u64) - { - if(imm.u64 > 0) - { - E_Value tval = stack[stack_count - 1]; - E_Value *dst = stack + stack_count - 1 - imm.u64; - E_Value *shift = dst + 1; - MemoryCopy(shift, dst, imm.u64*sizeof(E_Value)); - *dst = tval; - } - } - else - { - result.code = E_InterpretationCode_BadOp; - goto done; - } - }break; - case RDI_EvalOp_ValueRead: { U64 bytes_to_read = imm.u64; diff --git a/src/eval2/eval2.c b/src/eval2/eval2.c new file mode 100644 index 00000000..15756f59 --- /dev/null +++ b/src/eval2/eval2.c @@ -0,0 +1,617 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Generated Code + +#include "eval2/generated/eval2.meta.c" + +//////////////////////////////// +//~ rjf: Space -> Memory Map Helpers + +internal void +e2_space_map_push(Arena *arena, E2_SpaceMap *map, E2_SpaceID space_id, Rng1U64 addr_range, void *data) +{ + if(map->slots_count == 0) + { + map->slots_count = 8; + map->slots = push_array(arena, E2_SpaceMapNode *, map->slots_count); + } + U64 hash = u64_hash_from_str8(str8_struct(&space_id)); + U64 slot_idx = hash%map->slots_count; + E2_SpaceMapNode *node = 0; + for(E2_SpaceMapNode *n = map->slots[slot_idx]; n != 0; n = n->next) + { + if(n->space_id == space_id) + { + node = n; + break; + } + } + if(node == 0) + { + node = push_array(arena, E2_SpaceMapNode, 1); + SLLStackPush(map->slots[slot_idx], node); + } + memory_map_push(arena, &node->memory_map, addr_range, data); +} + +internal U64 +e2_space_map_read(E2_SpaceMap *map, E2_SpaceID space_id, Rng1U64 addr_range, void *out) +{ + U64 result = 0; + { + U64 hash = u64_hash_from_str8(str8_struct(&space_id)); + U64 slot_idx = hash%map->slots_count; + E2_SpaceMapNode *node = 0; + for(E2_SpaceMapNode *n = map->slots[slot_idx]; n != 0; n = n->next) + { + if(n->space_id == space_id) + { + node = n; + break; + } + } + if(node != 0) + { + result = memory_map_read(&node->memory_map, addr_range, out); + } + } + return result; +} + +//////////////////////////////// +//~ rjf: Name -> Expr Map Helpers + +internal void +e2_expr_map_push(Arena *arena, E2_ExprMap *map, String8 name, E2_Expr *expr) +{ + if(map->slots_count == 0) + { + map->slots_count = 8; + map->slots = push_array(arena, E2_ExprMapNode *, map->slots_count); + } + U64 hash = u64_hash_from_str8(name); + U64 slot_idx = hash%map->slots_count; + E2_ExprMapNode *node = 0; + for(E2_ExprMapNode *n = map->slots[slot_idx]; n != 0; n = n->next) + { + if(str8_match(n->name, name, 0)) + { + node = n; + break; + } + } + if(node == 0) + { + node = push_array(arena, E2_ExprMapNode, 1); + node->name = str8_copy(arena, name); + node->expr = expr; + SLLStackPush(map->slots[slot_idx], node); + } +} + +internal E2_Expr * +e2_expr_from_name(E2_ExprMap *map, String8 name) +{ + E2_Expr *expr = &e2_expr_nil; + U64 hash = u64_hash_from_str8(name); + U64 slot_idx = hash%map->slots_count; + E2_ExprMapNode *node = 0; + for(E2_ExprMapNode *n = map->slots[slot_idx]; n != 0; n = n->next) + { + if(str8_match(n->name, name, 0)) + { + node = n; + break; + } + } + if(node != 0) + { + expr = node->expr; + } + return expr; +} + +//////////////////////////////// +//~ rjf: String -> Expression + +internal E2_Parse +e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_SpaceMap *space_map, E2_ExprMap *expr_map, String8 string) +{ + +} + +//////////////////////////////// +//~ rjf: Expression -> Bytecode + +internal String8 +e2_bytecode_from_expr(Arena *arena, E2_Expr *expr) +{ + +} + +//////////////////////////////// +//~ rjf: Bytecode -> Result + +internal E2_Interp +e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_map, String8 bytecode) +{ + E2_Interp interp = {E2_Status_Error}; + { + U64 off = state->bytecode_off; + U64 off_opl = bytecode.size; + B32 done = 0; + B32 good = 1; + for(;off < off_opl && !done && good;) + { + Temp scratch = scratch_begin(&arena, 1); + U64 start_off = off; + + //- rjf: read next opcode + RDI_EvalOp op = 0; + off += str8_deserial_read_struct(bytecode, off, &op); + + //- rjf: opcode -> ctrl bits + U16 ctrlbits = 0; + switch(op) + { + default: + if(op < RDI_EvalOp_COUNT) + { + ctrlbits = rdi_eval_op_ctrlbits_table[op]; + }break; + case E2_EvalOp_SetCtxID:{ctrlbits = RDI_EVAL_CTRLBITS(8, 0, 0);}break; + } + + //- rjf: ctrlbits -> push/pop/decode count + U64 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + U64 push_count = RDI_PUSHN_FROM_CTRLBITS(ctrlbits); + U64 pop_count = RDI_POPN_FROM_CTRLBITS(ctrlbits); + + //- rjf: do extra decode + String8 decode_data = str8_substr(bytecode, r1u64(off, off+decode_size)); + E2_Val decode_val = {0}; + MemoryCopy(&decode_val, decode_data.str, Min(sizeof(decode_val), decode_data.size)); + RDI_EvalTypeGroup type_group = (RDI_EvalTypeGroup)decode_val.u512.u8[0]; + U64 op_arithmetic_size = (U64)decode_val.u512.u8[1]; + off += decode_size; + + //- rjf: prepare popped stack values & to-push stack values + E2_Val *popped_vals = push_array(scratch.arena, E2_Val, pop_count); + E2_Val *push_vals = push_array(scratch.arena, E2_Val, push_count); + { + E2_InterpStackValNode *node = state->top_val; + for(U64 pop_idx = 0; node != 0 && pop_idx < pop_count; pop_idx += 1, node = node->next) + { + popped_vals[pop_idx] = node->val; + } + } + + //- rjf: do opcode + E2_CtxFlags ctx_flags = 0; + U64 ctx_base_addr = 0; + switch(op) + { + default:{}break; + + case E2_EvalOp_SetCtxID: + { + interp.status = E2_Status_NewCtxID; + interp.ctx_id = decode_val.u64; + }break; + + case RDI_EvalOp_Stop: + { + done = 1; + }break; + case RDI_EvalOp_Noop:{}break; + case RDI_EvalOp_Cond: + if(popped_vals[0].u64 != 0) + { + off += decode_val.u64; + }break; + case RDI_EvalOp_Skip: + { + off += decode_val.u64; + }break; + case RDI_EvalOp_MemRead: + { + U64 addr = popped_vals[0].u64; + U64 size = decode_val.u64; + Rng1U64 space_addr_range = r1u64(addr, addr+size); + void *read_dst = &push_vals[0]; + if(size > sizeof(push_vals[0].u512)) + { + read_dst = push_array(arena, U8, size); + } + U64 read_size = e2_space_map_read(space_map, state->selected_ctx.space_id, space_addr_range, read_dst); + arena_pop(arena, size - read_size); + push_vals[0].string = str8(read_dst, read_size); + if(read_size != size) + { + good = 0; + interp.status = E2_Status_MissedSpaceRead; + interp.missed_read_space_addr_range = space_addr_range; + } + }break; + case RDI_EvalOp_RegRead: + { + U8 rdi_reg_code = (decode_val.u64&0x0000FF)>>0; + U8 byte_size = (decode_val.u64&0x00FF00)>>8; + U8 byte_off = (decode_val.u64&0xFF0000)>>16; + Arch arch = state->selected_ctx.arch; + ARCH_Info *arch_info = arch_info_from_arch(arch); + ARCH_RegCode base_reg_code = arch_reg_code_from_rdi(arch, rdi_reg_code); + if(0 <= base_reg_code && base_reg_code < arch_info->reg_code_count) + { + Rng1U16 reg_rng = arch_info->reg_code_rng_table[base_reg_code]; + U64 off = (U64)reg_rng.min + byte_off; + U64 size = (U64)byte_size; + Rng1U64 space_addr_range = r1u64(off, off+size); + U64 read_size = e2_space_map_read(space_map, state->selected_ctx.reg_space_id, space_addr_range, &push_vals[0]); + if(read_size != size) + { + good = 0; + interp.status = E2_Status_MissedSpaceRead; + interp.missed_read_space_addr_range = space_addr_range; + } + } + else + { + good = 0; + interp.status = E2_Status_BadRegCode; + } + }break; + case RDI_EvalOp_FrameOff: {ctx_flags = E2_CtxFlag_HasFrameBase; ctx_base_addr = state->selected_ctx.frame_base_addr;}goto optional_base_off; + case RDI_EvalOp_ModuleOff: {ctx_flags = E2_CtxFlag_HasModuleBase; ctx_base_addr = state->selected_ctx.module_base_addr;}goto optional_base_off; + case RDI_EvalOp_TLSOff: {ctx_flags = E2_CtxFlag_HasTLSBase; ctx_base_addr = state->selected_ctx.tls_base_addr;}goto optional_base_off; + case RDI_EvalOp_PushCfa: {ctx_flags = E2_CtxFlag_HasCFA; ctx_base_addr = state->selected_ctx.cfa_addr;}goto optional_base_off; + optional_base_off:; + { + if(state->selected_ctx.flags & ctx_flags) + { + push_vals[0].u64 = ctx_base_addr + decode_val.u64; + } + else + { + good = 0; + interp.status = E2_Status_MissingCtxFlag; + interp.missing_ctx_flags |= ctx_flags; + } + }break; + + case RDI_EvalOp_ConstU8: + case RDI_EvalOp_ConstU16: + case RDI_EvalOp_ConstU32: + case RDI_EvalOp_ConstU64: + case RDI_EvalOp_ConstU128: + { + push_vals[0] = decode_val; + }break; + + case RDI_EvalOp_ConstString: + { + U64 string_size = decode_val.u64; + String8 string = str8_substr(bytecode, r1u64(off, off+string_size)); + off += string_size; + push_vals[0].string = string; + }break; + + case RDI_EvalOp_Abs: + { + if(0){} +#define CaseA(target_type_group, target_type) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{push_vals[0].target_type = (popped_vals[0].target_type < 0 ? -popped_vals[0].target_type : +popped_vals[0].target_type);}while(0) +#define CaseB(target_type_group, size, target_type) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{push_vals[0].target_type = (popped_vals[0].target_type < 0 ? -popped_vals[0].target_type : +popped_vals[0].target_type);}while(0) + CaseA(F32, f32); + CaseA(F64, f64); + CaseB(S, 8, s8); + CaseB(S, 16, s16); + CaseB(S, 32, s32); + CaseB(S, 64, s64); + else { MemoryCopyStruct(&push_vals[0], &popped_vals[0]); } +#undef CaseA +#undef CaseB + }break; + + case RDI_EvalOp_Neg: + { + if(0){} +#define CaseA(target_type_group, target_type) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{push_vals[0].target_type = (-popped_vals[0].target_type);}while(0) +#define CaseB(target_type_group, size, target_type) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{push_vals[0].target_type = (-popped_vals[0].target_type);}while(0) + CaseA(F32, f32); + CaseA(F64, f64); + CaseB(S, 8, s8); + CaseB(S, 16, s16); + CaseB(S, 32, s32); + CaseB(S, 64, s64); + else { MemoryCopyStruct(&push_vals[0], &popped_vals[0]); } +#undef CaseA +#undef CaseB + }break; + +#define BinOp(target_type_group, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type;}while(0) +#define SizedBinOp(target_type_group, size, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type;}while(0) +#define BinOpDiv(target_type_group, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0) +#define SizedBinOpDiv(target_type_group, size, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0) +#define BinOpDivFn(target_type_group, dst_type, src_type, fn) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = fn(popped_vals[1].src_type, popped_vals[0].src_type); } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0) +#define ArithTypeCasesInt(symbol)\ +SizedBinOp(S, 8, s8, s8, symbol);\ +SizedBinOp(S, 16, s16, s16, symbol);\ +SizedBinOp(S, 32, s32, s32, symbol);\ +SizedBinOp(S, 64, s64, s64, symbol);\ +SizedBinOp(U, 8, u8, u8, symbol);\ +SizedBinOp(U, 16, u16, u16, symbol);\ +SizedBinOp(U, 32, u32, u32, symbol);\ +SizedBinOp(U, 64, u64, u64, symbol); +#define ArithTypeCasesIntDiv(symbol)\ +SizedBinOpDiv(S, 8, s8, s8, symbol);\ +SizedBinOpDiv(S, 16, s16, s16, symbol);\ +SizedBinOpDiv(S, 32, s32, s32, symbol);\ +SizedBinOpDiv(S, 64, s64, s64, symbol);\ +SizedBinOpDiv(U, 8, u8, u8, symbol);\ +SizedBinOpDiv(U, 16, u16, u16, symbol);\ +SizedBinOpDiv(U, 32, u32, u32, symbol);\ +SizedBinOpDiv(U, 64, u64, u64, symbol); +#define LogTypeCases(symbol)\ +BinOp(F32, u64, f32, symbol);\ +BinOp(F64, u64, f64, symbol);\ +ArithTypeCasesInt(symbol) +#define ArithTypeCases(symbol)\ +BinOp(F32, f32, f32, symbol);\ +BinOp(F64, f64, f64, symbol);\ +ArithTypeCasesInt(symbol) +#define ArithTypeCasesDiv(symbol)\ +BinOpDiv(F32, f32, f32, symbol);\ +BinOpDiv(F64, f64, f64, symbol);\ +ArithTypeCasesIntDiv(symbol) +#define ArithTypeCasesIntAllU64(symbol)\ +BinOp(S, u64, u64, symbol);\ +BinOp(U, u64, u64, symbol); +#define Case(name, ...) case RDI_EvalOp_##name:{if(0){} __VA_ARGS__ else {interp.status = E2_Status_BadOpTypes; good = 0;}}break + Case(Add, ArithTypeCases(+)); + Case(Sub, ArithTypeCases(-)); + Case(Mul, ArithTypeCases(*)); + Case(Div, ArithTypeCasesDiv(/)); + Case(Mod, ArithTypeCasesIntDiv(%) BinOpDivFn(F32, f32, f32, mod_f32); BinOpDivFn(F64, f64, f64, mod_f64);); + Case(LShift, ArithTypeCasesInt(<<)); + Case(RShift, ArithTypeCasesInt(>>)); + Case(BitAnd, ArithTypeCasesIntAllU64(&)); + Case(BitOr, ArithTypeCasesIntAllU64(|)); + Case(BitXor, ArithTypeCasesIntAllU64(^)); + Case(LogAnd, ArithTypeCasesIntAllU64(&&)); + Case(LogOr, ArithTypeCasesIntAllU64(||)); + Case(LsEq, LogTypeCases(<=)); + Case(GrEq, LogTypeCases(>=)); + Case(Less, LogTypeCases(<)); + Case(Grtr, LogTypeCases(>)); +#undef Case +#undef BinOp +#undef SizedBinOp +#undef BinOpDiv +#undef SizedBinOpDiv +#undef BinOpDivFn +#undef ArithTypeCasesInt +#undef ArithTypeCasesIntDiv +#undef ArithTypeCases +#undef ArithTypeCasesDiv +#undef ArithTypeCasesIntAllU64 + + case RDI_EvalOp_EqEq: + case RDI_EvalOp_NtEq: + { + if(popped_vals[0].string.size != 0 && popped_vals[1].string.size != 0) + { + push_vals[0].u64 = str8_match(popped_vals[0].string, popped_vals[1].string, 0); + } + else + { + push_vals[0].u64 = MemoryMatchStruct(&popped_vals[0].u512, &popped_vals[1].u512); + } + if(op == RDI_EvalOp_NtEq) + { + push_vals[0].u64 = !push_vals[0].u64; + } + }break; + + case RDI_EvalOp_Trunc: + { + if(0 < decode_val.u64) + { + U64 mask = 0; + if(decode_val.u64 < 64) + { + mask = max_U64 >> (64 - decode_val.u64); + } + push_vals[0].u64 = popped_vals[0].u64&mask; + } + }break; + + case RDI_EvalOp_TruncSigned: + { + if(0 < decode_val.u64) + { + U64 mask = 0; + if(decode_val.u64 < 64) + { + mask = max_U64 >> (64 - decode_val.u64); + } + U64 high = 0; + if(popped_vals[0].u64 & (1 << (decode_val.u64 - 1))) + { + high = ~mask; + } + push_vals[0].u64 = high|(popped_vals[0].u64&mask); + } + }break; + + case RDI_EvalOp_Convert: + { + U32 in = decode_val.u64&0xFF; + U32 out = (decode_val.u64 >> 8)&0xFF; + if(in != 0) + { + switch(in + out*RDI_EvalTypeGroup_COUNT) + { + default:{good = 0; interp.status = E2_Status_BadOpTypes;}break; +#define Case(dst_tg, dst_slot, dst_type, src_tg, src_slot) case RDI_EvalTypeGroup_##src_tg + RDI_EvalTypeGroup_##dst_tg*RDI_EvalTypeGroup_COUNT:{push_vals[0].dst_slot = (dst_type)popped_vals[0].src_slot;}break + Case(U, u64, U64, F32, f32); + Case(U, u64, U64, F64, f64); + Case(S, s64, S64, F32, f32); + Case(S, s64, S64, F64, f64); + Case(F32, f32, F32, S, s64); + Case(F64, f64, F64, S, s64); + Case(F32, f32, F32, U, u64); + Case(F64, f64, F64, U, u64); + Case(F32, f32, F32, F64, f64); + Case(F64, f64, F64, F32, f32); +#undef Case + } + } + }break; + + case RDI_EvalOp_Pick: + { + U64 target_idx = decode_val.u64; + U64 idx = 0; + B32 found = 0; + for(E2_InterpStackValNode *n = state->top_val; n != 0; n = n->next, idx += 1) + { + if(idx == target_idx) + { + found = 1; + push_vals[0] = n->val; + break; + } + } + if(!found) + { + good = 0; + interp.status = E2_Status_InsufficientStackSpace; + } + }break; + + case RDI_EvalOp_Swap: + { + push_vals[0] = popped_vals[1]; + push_vals[1] = popped_vals[0]; + }break; + + case RDI_EvalOp_Pop:{NoOp;}break; + + case RDI_EvalOp_ValueRead: + { + U64 bytes_to_read = decode_val.u64; + U64 offset = popped_vals[0].u64; + if(offset + bytes_to_read <= popped_vals[1].string.size) + { + MemoryCopy(&push_vals[0].u512, popped_vals[1].string.str + offset, bytes_to_read); + } + else + { + good = 0; + interp.status = E2_Status_BadOffset; + } + }break; + + case RDI_EvalOp_ByteSwap: + { + U64 byte_size = decode_val.u64; + switch(byte_size) + { + default: + { + good = 0; + interp.status = E2_Status_UnsupportedOp; + }break; + case 2:{push_vals[0].u16 = bswap_u16(popped_vals[0].u16);}break; + case 4:{push_vals[0].u32 = bswap_u32(popped_vals[0].u32);}break; + case 8:{push_vals[0].u64 = bswap_u64(popped_vals[0].u64);}break; + } + }break; + + case RDI_EvalOp_CallSiteValue: + { + // DW_OP_entry_value: requires evaluating the embedded sub-bytecode + // in this frame's entry-time register state (i.e. caller's state + // at the call instruction). that state is not currently plumbed + // into the eval context. interpreting in the current ctx gives + // wrong values for spilled args, so report BadOp instead. + // skip past the embedded sub-bytecode in the outer stream so the + // bytes are not interpreted as outer ops on resume. + good = 0; + interp.status = E2_Status_UnsupportedOp; + }break; + + case RDI_EvalOp_PartialValue: + { + // DW_OP_piece marker: top-of-stack is a piece of a composite value. + // we do not assemble composites; for single-piece expressions the + // value already on the stack is the result. for multi-piece, only + // the first piece is returned (stack[0] is the final result). + good = 0; + interp.status = E2_Status_UnsupportedOp; + }break; + + case RDI_EvalOp_PartialValueBit: + { + // DW_OP_bit_piece marker. same caveat as PartialValue. + good = 0; + interp.status = E2_Status_UnsupportedOp; + }break; + } + + //- rjf: if opcode successful -> do stack pops + if(good) for EachIndex(pop_idx, pop_count) + { + E2_InterpStackValNode *popped = state->top_val; + if(popped != 0) + { + SLLStackPop(state->top_val); + SLLStackPush(state->free_val, popped); + } + else + { + break; + } + } + + //- rjf: if opcode successful -> do stack pushes + if(good) for EachIndex(push_idx, push_count) + { + E2_InterpStackValNode *node = state->free_val; + if(node != 0) + { + SLLStackPop(state->free_val); + } + else + { + node = push_array(arena, E2_InterpStackValNode, 1); + } + node->val = push_vals[push_idx]; + SLLStackPush(state->top_val, node); + } + + //- rjf: if opcode successful -> commit new bytecode offset + if(good) + { + state->bytecode_off = off; + } + + scratch_end(scratch); + if(off == start_off) + { + break; + } + } + if(off == off_opl && good) + { + interp.status = E2_Status_Good; + if(state->top_val != 0) + { + interp.val = state->top_val->val; + } + } + } + return interp; +} diff --git a/src/eval2/eval2.h b/src/eval2/eval2.h new file mode 100644 index 00000000..56c3f4da --- /dev/null +++ b/src/eval2/eval2.h @@ -0,0 +1,371 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef EVAL2_H +#define EVAL2_H + +//////////////////////////////// +//~ rjf: Generated Code + +#include "eval2/generated/eval2.meta.h" + +//////////////////////////////// +//~ rjf: Extended Opcodes + +enum +{ + E2_EvalOp_SetCtxID = RDI_EvalOp_COUNT, +}; + +//////////////////////////////// +//~ rjf: Compilation Statuses + +typedef enum E2_Status +{ + E2_Status_Good, + + //- rjf: need caller-provided info + E2_Status_MissedSpaceRead, + E2_Status_MissedIdentifierResolution, + E2_Status_Access, + E2_Status_NewCtxID, + + //- rjf: unrecoverable errors + E2_Status_BadRegCode, + E2_Status_MissingCtxFlag, + E2_Status_DivideByZero, + E2_Status_InsufficientStackSpace, + E2_Status_BadOpTypes, + E2_Status_UnsupportedOp, + E2_Status_BadOffset, + E2_Status_Error, +} +E2_Status; + +//////////////////////////////// +//~ rjf: Type Keys + +typedef enum E2_TypeKeyKind +{ + E2_TypeKeyKind_Null, + E2_TypeKeyKind_Basic, + E2_TypeKeyKind_Ext, + E2_TypeKeyKind_Cons, + E2_TypeKeyKind_Reg, +} +E2_TypeKeyKind; + +typedef struct E2_TypeKey E2_TypeKey; +struct E2_TypeKey +{ + E2_TypeKeyKind kind; + U32 u32[3]; + // [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias) + // [1] -> Type Index In Debug Info (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons) + // [2] -> Debug Info Number (Ext) +}; + +typedef struct E2_TypeKeyNode E2_TypeKeyNode; +struct E2_TypeKeyNode +{ + E2_TypeKeyNode *next; + E2_TypeKey v; +}; + +typedef struct E2_TypeKeyList E2_TypeKeyList; +struct E2_TypeKeyList +{ + E2_TypeKeyNode *first; + E2_TypeKeyNode *last; + U64 count; +}; + +//////////////////////////////// +//~ rjf: Unpacked Type Info + +typedef enum E2_MemberKind +{ + E2_MemberKind_Null, + E2_MemberKind_DataField, + E2_MemberKind_StaticData, + E2_MemberKind_Method, + E2_MemberKind_StaticMethod, + E2_MemberKind_VirtualMethod, + E2_MemberKind_VTablePtr, + E2_MemberKind_Base, + E2_MemberKind_VirtualBase, + E2_MemberKind_NestedType, + E2_MemberKind_Padding, + E2_MemberKind_COUNT +} +E2_MemberKind; + +typedef U32 E2_TypeFlags; +enum +{ + E2_TypeFlag_Const = (1<<0), + E2_TypeFlag_Volatile = (1<<1), + E2_TypeFlag_Restrict = (1<<2), +}; + +typedef struct E2_EnumVal E2_EnumVal; +struct E2_EnumVal +{ + String8 name; + U64 val; +}; + +typedef struct E2_Member E2_Member; +struct E2_Member +{ + E2_MemberKind kind; + E2_TypeKey type_key; + String8 name; + U64 off; + E2_TypeKeyList inheritees; +}; + +typedef struct E2_Type E2_Type; +struct E2_Type +{ + E2_TypeKind kind; + E2_TypeFlags flags; + String8 name; + U64 byte_size; + U64 count; + U64 depth; + U32 off; + Arch arch; + E2_TypeKey direct_type_key; + E2_TypeKey owner_type_key; + E2_TypeKey *param_type_keys; + E2_Member *members; + E2_EnumVal *enum_vals; + struct E2_Expr **args; +}; + +//////////////////////////////// +//~ rjf: Evaluation Values + +typedef enum E2_Mode +{ + E2_Mode_Type, // no value content - just type content + E2_Mode_Address, // value is an address into a space + E2_Mode_Value, // value is just a value, does not refer elsewhere + E2_Mode_COUNT +} +E2_Mode; + +typedef struct E2_Val E2_Val; +struct E2_Val +{ + union + { + U512 u512; + U256 u256; + U128 u128; + U64 u64; + U32 u32; + U16 u16; + U8 u8; + S64 s64; + S32 s32; + S16 s16; + S8 s8; + F64 f64; + F32 f32; + }; + String8 string; +}; + +//////////////////////////////// +//~ rjf: Evaluation "Asset" Parameters (Debug Info / Modules) + +typedef U64 E2_SpaceID; + +typedef struct E2_DbgInfo E2_DbgInfo; +struct E2_DbgInfo +{ + DI_Key dbgi_key; + RDI_Parsed *rdi; + String8 name; +}; + +typedef struct E2_Module E2_Module; +struct E2_Module +{ + E2_SpaceID space_id; + Rng1U64 addr_range; + E2_DbgInfo *dbg_info; + Arch arch; + String8 name; +}; + +typedef struct E2_Assets E2_Assets; +struct E2_Assets +{ + E2_Module *modules; + U64 modules_count; + E2_DbgInfo *dbg_infos; + U64 dbg_infos_count; +}; + +//////////////////////////////// +//~ rjf: Evaluation Contexts + +typedef U64 E2_CtxID; + +typedef U32 E2_CtxFlags; +enum +{ + E2_CtxFlag_HasFrameBase = (1<<0), + E2_CtxFlag_HasCFA = (1<<1), + E2_CtxFlag_HasModuleBase = (1<<2), + E2_CtxFlag_HasTLSBase = (1<<3), +}; + +typedef struct E2_Ctx E2_Ctx; +struct E2_Ctx +{ + // rjf: base info + E2_CtxID id; + E2_SpaceID space_id; + E2_SpaceID reg_space_id; + Arch arch; + U64 addr; + + // rjf: optional extensions + E2_CtxFlags flags; + U64 frame_base_addr; + U64 cfa_addr; + U64 module_base_addr; + U64 tls_base_addr; +}; + +//////////////////////////////// +//~ rjf: Expression Tree Building + +typedef struct E2_Expr E2_Expr; +struct E2_Expr +{ + E2_Expr *first; + E2_Expr *last; + E2_Expr *next; + String8 string; + RDI_EvalOp op; + E2_TypeKey type_key; + E2_Mode mode; + E2_Val val; +}; + +typedef struct E2_ExprMapNode E2_ExprMapNode; +struct E2_ExprMapNode +{ + E2_ExprMapNode *next; + String8 name; + E2_Expr *expr; +}; + +typedef struct E2_ExprMap E2_ExprMap; +struct E2_ExprMap +{ + E2_ExprMapNode **slots; + U64 slots_count; +}; + +typedef struct E2_ParseState E2_ParseState; +struct E2_ParseState +{ + U64 string_off; +}; + +typedef struct E2_Parse E2_Parse; +struct E2_Parse +{ + E2_Status status; + E2_SpaceID space_id; + Rng1U64 missed_read_space_addr_range; + E2_CtxID ctx_id; + E2_CtxFlags missing_ctx_flags; + E2_Expr *expr; + E2_Expr *access_expr; +}; + +//////////////////////////////// +//~ rjf: Interpretation + +typedef struct E2_SpaceMapNode E2_SpaceMapNode; +struct E2_SpaceMapNode +{ + E2_SpaceMapNode *next; + E2_SpaceID space_id; + MemoryMap memory_map; +}; + +typedef struct E2_SpaceMap E2_SpaceMap; +struct E2_SpaceMap +{ + E2_SpaceMapNode **slots; + U64 slots_count; +}; + +typedef struct E2_InterpStackValNode E2_InterpStackValNode; +struct E2_InterpStackValNode +{ + E2_InterpStackValNode *next; + E2_Val val; +}; + +typedef struct E2_InterpState E2_InterpState; +struct E2_InterpState +{ + U64 bytecode_off; + E2_Ctx selected_ctx; + E2_InterpStackValNode *top_val; + E2_InterpStackValNode *free_val; +}; + +typedef struct E2_Interp E2_Interp; +struct E2_Interp +{ + E2_Status status; + E2_SpaceID space_id; + Rng1U64 missed_read_space_addr_range; + E2_CtxID ctx_id; + E2_CtxFlags missing_ctx_flags; + E2_Val val; +}; + +//////////////////////////////// +//~ rjf: Globals + +read_only global E2_Expr e2_expr_nil = {&e2_expr_nil, &e2_expr_nil, &e2_expr_nil}; + +//////////////////////////////// +//~ rjf: Space -> Memory Map Helpers + +internal void e2_space_map_push(Arena *arena, E2_SpaceMap *map, E2_SpaceID space_id, Rng1U64 addr_range, void *data); +internal U64 e2_space_map_read(E2_SpaceMap *map, E2_SpaceID space_id, Rng1U64 addr_range, void *out); + +//////////////////////////////// +//~ rjf: Name -> Expr Map Helpers + +internal void e2_expr_map_push(Arena *arena, E2_ExprMap *map, String8 name, E2_Expr *expr); +internal E2_Expr *e2_expr_from_name(E2_ExprMap *map, String8 name); + +//////////////////////////////// +//~ rjf: String -> Expression + +internal E2_Parse e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_SpaceMap *space_map, E2_ExprMap *expr_map, String8 string); + +//////////////////////////////// +//~ rjf: Expression -> Bytecode + +internal String8 e2_bytecode_from_expr(Arena *arena, E2_Expr *expr); + +//////////////////////////////// +//~ rjf: Bytecode -> Result + +internal E2_Interp e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_map, String8 bytecode); + +#endif // EVAL2_H diff --git a/src/eval2/eval2.mdesk b/src/eval2/eval2.mdesk new file mode 100644 index 00000000..5dbaf832 --- /dev/null +++ b/src/eval2/eval2.mdesk @@ -0,0 +1,87 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +@table(name basic_string basic_byte_size) +// NOTE(rjf): basic_byte_size == 0xFF? => address sized +E2_TypeKindTable: +{ + {Null "" 0 } + {Void "void" 0 } + {Handle "HANDLE" 0xFF } + {HResult "HRESULT" 4 } + {Char8 "char8" 1 } + {Char16 "char16" 2 } + {Char32 "char32" 4 } + {UChar8 "uchar8" 1 } + {UChar16 "uchar16" 2 } + {UChar32 "uchar32" 4 } + {U8 "uint8" 1 } + {U16 "uint16" 2 } + {U32 "uint32" 4 } + {U64 "uint64" 8 } + {U128 "uint128" 16 } + {U256 "uint256" 32 } + {U512 "uint512" 64 } + {S8 "int8" 1 } + {S16 "int16" 2 } + {S32 "int32" 4 } + {S64 "int64" 8 } + {S128 "int128" 16 } + {S256 "int256" 32 } + {S512 "int512" 64 } + {Bool "bool" 1 } + {F16 "float16" 2 } + {F32 "float32" 4 } + {F32PP "float32PP" 4 } + {F48 "float48" 6 } + {F64 "float64" 8 } + {F80 "float80" 10 } + {F128 "float128" 16 } + {ComplexF32 "complex_float32" 8 } + {ComplexF64 "complex_float64" 16 } + {ComplexF80 "complex_float80" 20 } + {ComplexF128 "complex_float128" 32 } + {Modifier "modifier" 0 } + {Ptr "ptr" 0 } + {LRef "lref" 0 } + {RRef "rref" 0 } + {Array "array" 0 } + {Function "function" 0 } + {Method "method" 0 } + {MemberPtr "member_ptr" 0 } + {Struct "struct" 0 } + {Class "class" 0 } + {Union "union" 0 } + {Enum "enum" 0 } + {Alias "typedef" 0 } + {IncompleteStruct "struct" 0 } + {IncompleteUnion "union" 0 } + {IncompleteClass "class" 0 } + {IncompleteEnum "enum" 0 } + {Bitfield "bitfield" 0 } + {Variadic "variadic" 0 } + {Set "set" 0 } + {Lens "lens" 0 } + {LensSpec "lens_spec" 0 } + {MetaExpr "meta_expr" 0 } + {MetaDisplayName "meta_display_name" 0 } + {MetaDescription "meta_description" 0 } +} + +@enum E2_TypeKind: +{ + @expand(E2_TypeKindTable a) `$(a.name)`, + COUNT, + `FirstBasic = E2_TypeKind_Void`, + `LastBasic = E2_TypeKind_ComplexF128`, + `FirstInteger = E2_TypeKind_Char8`, + `LastInteger = E2_TypeKind_S512`, + `FirstSigned1 = E2_TypeKind_Char8`, + `LastSigned1 = E2_TypeKind_Char32`, + `FirstSigned2 = E2_TypeKind_S8`, + `LastSigned2 = E2_TypeKind_S512`, + `FirstIncomplete = E2_TypeKind_IncompleteStruct`, + `LastIncomplete = E2_TypeKind_IncompleteEnum`, + `FirstMeta = E2_TypeKind_MetaExpr`, + `LastMeta = E2_TypeKind_MetaDescription`, +} diff --git a/src/eval2/generated/eval2.meta.c b/src/eval2/generated/eval2.meta.c new file mode 100644 index 00000000..0378fad9 --- /dev/null +++ b/src/eval2/generated/eval2.meta.c @@ -0,0 +1,5 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + diff --git a/src/eval2/generated/eval2.meta.h b/src/eval2/generated/eval2.meta.h new file mode 100644 index 00000000..2ba002dd --- /dev/null +++ b/src/eval2/generated/eval2.meta.h @@ -0,0 +1,87 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +#ifndef EVAL2_META_H +#define EVAL2_META_H + +typedef enum E2_TypeKind +{ +E2_TypeKind_Null, +E2_TypeKind_Void, +E2_TypeKind_Handle, +E2_TypeKind_HResult, +E2_TypeKind_Char8, +E2_TypeKind_Char16, +E2_TypeKind_Char32, +E2_TypeKind_UChar8, +E2_TypeKind_UChar16, +E2_TypeKind_UChar32, +E2_TypeKind_U8, +E2_TypeKind_U16, +E2_TypeKind_U32, +E2_TypeKind_U64, +E2_TypeKind_U128, +E2_TypeKind_U256, +E2_TypeKind_U512, +E2_TypeKind_S8, +E2_TypeKind_S16, +E2_TypeKind_S32, +E2_TypeKind_S64, +E2_TypeKind_S128, +E2_TypeKind_S256, +E2_TypeKind_S512, +E2_TypeKind_Bool, +E2_TypeKind_F16, +E2_TypeKind_F32, +E2_TypeKind_F32PP, +E2_TypeKind_F48, +E2_TypeKind_F64, +E2_TypeKind_F80, +E2_TypeKind_F128, +E2_TypeKind_ComplexF32, +E2_TypeKind_ComplexF64, +E2_TypeKind_ComplexF80, +E2_TypeKind_ComplexF128, +E2_TypeKind_Modifier, +E2_TypeKind_Ptr, +E2_TypeKind_LRef, +E2_TypeKind_RRef, +E2_TypeKind_Array, +E2_TypeKind_Function, +E2_TypeKind_Method, +E2_TypeKind_MemberPtr, +E2_TypeKind_Struct, +E2_TypeKind_Class, +E2_TypeKind_Union, +E2_TypeKind_Enum, +E2_TypeKind_Alias, +E2_TypeKind_IncompleteStruct, +E2_TypeKind_IncompleteUnion, +E2_TypeKind_IncompleteClass, +E2_TypeKind_IncompleteEnum, +E2_TypeKind_Bitfield, +E2_TypeKind_Variadic, +E2_TypeKind_Set, +E2_TypeKind_Lens, +E2_TypeKind_LensSpec, +E2_TypeKind_MetaExpr, +E2_TypeKind_MetaDisplayName, +E2_TypeKind_MetaDescription, +E2_TypeKind_COUNT, +E2_TypeKind_FirstBasic = E2_TypeKind_Void, +E2_TypeKind_LastBasic = E2_TypeKind_ComplexF128, +E2_TypeKind_FirstInteger = E2_TypeKind_Char8, +E2_TypeKind_LastInteger = E2_TypeKind_S512, +E2_TypeKind_FirstSigned1 = E2_TypeKind_Char8, +E2_TypeKind_LastSigned1 = E2_TypeKind_Char32, +E2_TypeKind_FirstSigned2 = E2_TypeKind_S8, +E2_TypeKind_LastSigned2 = E2_TypeKind_S512, +E2_TypeKind_FirstIncomplete = E2_TypeKind_IncompleteStruct, +E2_TypeKind_LastIncomplete = E2_TypeKind_IncompleteEnum, +E2_TypeKind_FirstMeta = E2_TypeKind_MetaExpr, +E2_TypeKind_LastMeta = E2_TypeKind_MetaDescription, +} E2_TypeKind; + +#endif // EVAL2_META_H diff --git a/src/lib_rdi/rdi.c b/src/lib_rdi/rdi.c index c87679b5..16fb2684 100644 --- a/src/lib_rdi/rdi.c +++ b/src/lib_rdi/rdi.c @@ -58,7 +58,7 @@ sizeof(RDI_NameMapNode), sizeof(RDI_U8), }; -RDI_U16 rdi_eval_op_ctrlbits_table[54] = +RDI_U16 rdi_eval_op_ctrlbits_table[52] = { RDI_EVAL_CTRLBITS(0, 0, 0), RDI_EVAL_CTRLBITS(0, 0, 0), @@ -66,7 +66,6 @@ RDI_EVAL_CTRLBITS(2, 1, 0), RDI_EVAL_CTRLBITS(2, 0, 0), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(4, 0, 1), -RDI_EVAL_CTRLBITS(0, 1, 1), RDI_EVAL_CTRLBITS(8, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1), @@ -105,7 +104,6 @@ RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(2, 1, 1), RDI_EVAL_CTRLBITS(1, 0, 1), RDI_EVAL_CTRLBITS(0, 1, 0), -RDI_EVAL_CTRLBITS(1, 0, 0), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(4, 0, 0), diff --git a/src/lib_rdi/rdi.h b/src/lib_rdi/rdi.h index a1b93520..221c40d6 100644 --- a/src/lib_rdi/rdi.h +++ b/src/lib_rdi/rdi.h @@ -423,7 +423,6 @@ RDI_EvalOp_Cond = 2, RDI_EvalOp_Skip = 3, RDI_EvalOp_MemRead = 4, RDI_EvalOp_RegRead = 5, -RDI_EvalOp_RegReadDyn = 6, RDI_EvalOp_FrameOff = 7, RDI_EvalOp_ModuleOff = 8, RDI_EvalOp_TLSOff = 9, @@ -462,7 +461,6 @@ RDI_EvalOp_TruncSigned = 41, RDI_EvalOp_Convert = 42, RDI_EvalOp_Pick = 43, RDI_EvalOp_Pop = 44, -RDI_EvalOp_Insert = 45, RDI_EvalOp_ValueRead = 46, RDI_EvalOp_ByteSwap = 47, RDI_EvalOp_CallSiteValue = 48, @@ -939,7 +937,6 @@ X(Cond)\ X(Skip)\ X(MemRead)\ X(RegRead)\ -X(RegReadDyn)\ X(FrameOff)\ X(ModuleOff)\ X(TLSOff)\ @@ -978,7 +975,6 @@ X(TruncSigned)\ X(Convert)\ X(Pick)\ X(Pop)\ -X(Insert)\ X(ValueRead)\ X(ByteSwap)\ X(CallSiteValue)\ @@ -1480,6 +1476,6 @@ RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTyp RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); extern RDI_U16 rdi_section_element_size_table[44]; -extern RDI_U16 rdi_eval_op_ctrlbits_table[54]; +extern RDI_U16 rdi_eval_op_ctrlbits_table[52]; #endif // RDI_H diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index ee618f74..a854ef14 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -415,6 +415,7 @@ #include "stap/stap_parse.h" #include "demon/demon_inc.h" #include "eval/eval_inc.h" +#include "eval2/eval2.h" #include "dbg_engine/dbg_engine_inc.h" #include "eval_visualization/eval_visualization_inc.h" #include "font_provider/font_provider_inc.h" @@ -474,6 +475,7 @@ #include "stap/stap_parse.c" #include "demon/demon_inc.c" #include "eval/eval_inc.c" +#include "eval2/eval2.c" #include "dbg_engine/dbg_engine_inc.c" #include "eval_visualization/eval_visualization_inc.c" #include "font_provider/font_provider_inc.c" diff --git a/src/rdi/rdi.mdesk b/src/rdi/rdi.mdesk index a06ac207..ea802c86 100644 --- a/src/rdi/rdi.mdesk +++ b/src/rdi/rdi.mdesk @@ -1202,7 +1202,7 @@ RDI_EvalOpTable: {Skip 3 2 0 0} {MemRead 4 1 1 1} {RegRead 5 4 0 1} - {RegReadDyn 6 0 1 1} + // NOTE(rjf): 6 is free {FrameOff 7 8 0 1} {ModuleOff 8 4 0 1} {TLSOff 9 4 0 1} @@ -1241,7 +1241,7 @@ RDI_EvalOpTable: {Convert 42 2 1 1} {Pick 43 1 0 1} {Pop 44 0 1 0} - {Insert 45 1 0 0} + // NOTE(rjf): 45 is free {ValueRead 46 1 2 1} {ByteSwap 47 1 1 1} {CallSiteValue 48 4 0 0} diff --git a/src/rdi/rdi_local.c b/src/rdi/rdi_local.c index 247cd8bc..6e2fc0f6 100644 --- a/src/rdi/rdi_local.c +++ b/src/rdi/rdi_local.c @@ -351,7 +351,6 @@ rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); imm_fmt = push_str8f(scratch.arena, "%S+%I64u, Size: %u", reg_str, byte_off, byte_size); } break; - case RDI_EvalOp_RegReadDyn: break; case RDI_EvalOp_FrameOff: { imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); } break; @@ -426,10 +425,6 @@ rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) imm_fmt = push_str8f(scratch.arena, "%u", pick); } break; case RDI_EvalOp_Pop: break; - case RDI_EvalOp_Insert: { - U8 insert = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", insert); - } break; case RDI_EvalOp_ValueRead: { U8 bytes_to_read = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read);