checkpoint on revised eval system; first pass on interpretation; eliminating all callbacks / eval involvement in contexts/spaces/identifier-resolution/etc.

This commit is contained in:
Ryan Fleury
2026-06-12 13:50:28 -07:00
parent ac0c7d9441
commit 2b20760386
12 changed files with 1173 additions and 54 deletions
-7
View File
@@ -1050,13 +1050,6 @@ struct E_CacheNode
E_CacheBundle bundle; E_CacheBundle bundle;
}; };
typedef struct E_CacheLookup E_CacheLookup;
struct E_CacheLookup
{
E_CacheNode *node;
U64 hash;
};
typedef struct E_CacheSlot E_CacheSlot; typedef struct E_CacheSlot E_CacheSlot;
struct E_CacheSlot struct E_CacheSlot
{ {
-32
View File
@@ -360,18 +360,6 @@ e_interpret(String8 bytecode)
} }
}break; }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: case RDI_EvalOp_FrameOff:
{ {
if(e_interpret_ctx->frame_base != 0) 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 // do nothing - the pop is handled by the control bits
}break; }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: case RDI_EvalOp_ValueRead:
{ {
U64 bytes_to_read = imm.u64; U64 bytes_to_read = imm.u64;
+617
View File
@@ -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;
}
+371
View File
@@ -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
+87
View File
@@ -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`,
}
+5
View File
@@ -0,0 +1,5 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
+87
View File
@@ -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
+1 -3
View File
@@ -58,7 +58,7 @@ sizeof(RDI_NameMapNode),
sizeof(RDI_U8), 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),
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(2, 0, 0),
RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 1, 1),
RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1),
RDI_EVAL_CTRLBITS(0, 1, 1),
RDI_EVAL_CTRLBITS(8, 0, 1), RDI_EVAL_CTRLBITS(8, 0, 1),
RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(4, 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(2, 1, 1),
RDI_EVAL_CTRLBITS(1, 0, 1), RDI_EVAL_CTRLBITS(1, 0, 1),
RDI_EVAL_CTRLBITS(0, 1, 0), RDI_EVAL_CTRLBITS(0, 1, 0),
RDI_EVAL_CTRLBITS(1, 0, 0),
RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1),
RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 1, 1),
RDI_EVAL_CTRLBITS(4, 0, 0), RDI_EVAL_CTRLBITS(4, 0, 0),
+1 -5
View File
@@ -423,7 +423,6 @@ RDI_EvalOp_Cond = 2,
RDI_EvalOp_Skip = 3, RDI_EvalOp_Skip = 3,
RDI_EvalOp_MemRead = 4, RDI_EvalOp_MemRead = 4,
RDI_EvalOp_RegRead = 5, RDI_EvalOp_RegRead = 5,
RDI_EvalOp_RegReadDyn = 6,
RDI_EvalOp_FrameOff = 7, RDI_EvalOp_FrameOff = 7,
RDI_EvalOp_ModuleOff = 8, RDI_EvalOp_ModuleOff = 8,
RDI_EvalOp_TLSOff = 9, RDI_EvalOp_TLSOff = 9,
@@ -462,7 +461,6 @@ RDI_EvalOp_TruncSigned = 41,
RDI_EvalOp_Convert = 42, RDI_EvalOp_Convert = 42,
RDI_EvalOp_Pick = 43, RDI_EvalOp_Pick = 43,
RDI_EvalOp_Pop = 44, RDI_EvalOp_Pop = 44,
RDI_EvalOp_Insert = 45,
RDI_EvalOp_ValueRead = 46, RDI_EvalOp_ValueRead = 46,
RDI_EvalOp_ByteSwap = 47, RDI_EvalOp_ByteSwap = 47,
RDI_EvalOp_CallSiteValue = 48, RDI_EvalOp_CallSiteValue = 48,
@@ -939,7 +937,6 @@ X(Cond)\
X(Skip)\ X(Skip)\
X(MemRead)\ X(MemRead)\
X(RegRead)\ X(RegRead)\
X(RegReadDyn)\
X(FrameOff)\ X(FrameOff)\
X(ModuleOff)\ X(ModuleOff)\
X(TLSOff)\ X(TLSOff)\
@@ -978,7 +975,6 @@ X(TruncSigned)\
X(Convert)\ X(Convert)\
X(Pick)\ X(Pick)\
X(Pop)\ X(Pop)\
X(Insert)\
X(ValueRead)\ X(ValueRead)\
X(ByteSwap)\ X(ByteSwap)\
X(CallSiteValue)\ 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); 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_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 #endif // RDI_H
+2
View File
@@ -415,6 +415,7 @@
#include "stap/stap_parse.h" #include "stap/stap_parse.h"
#include "demon/demon_inc.h" #include "demon/demon_inc.h"
#include "eval/eval_inc.h" #include "eval/eval_inc.h"
#include "eval2/eval2.h"
#include "dbg_engine/dbg_engine_inc.h" #include "dbg_engine/dbg_engine_inc.h"
#include "eval_visualization/eval_visualization_inc.h" #include "eval_visualization/eval_visualization_inc.h"
#include "font_provider/font_provider_inc.h" #include "font_provider/font_provider_inc.h"
@@ -474,6 +475,7 @@
#include "stap/stap_parse.c" #include "stap/stap_parse.c"
#include "demon/demon_inc.c" #include "demon/demon_inc.c"
#include "eval/eval_inc.c" #include "eval/eval_inc.c"
#include "eval2/eval2.c"
#include "dbg_engine/dbg_engine_inc.c" #include "dbg_engine/dbg_engine_inc.c"
#include "eval_visualization/eval_visualization_inc.c" #include "eval_visualization/eval_visualization_inc.c"
#include "font_provider/font_provider_inc.c" #include "font_provider/font_provider_inc.c"
+2 -2
View File
@@ -1202,7 +1202,7 @@ RDI_EvalOpTable:
{Skip 3 2 0 0} {Skip 3 2 0 0}
{MemRead 4 1 1 1} {MemRead 4 1 1 1}
{RegRead 5 4 0 1} {RegRead 5 4 0 1}
{RegReadDyn 6 0 1 1} // NOTE(rjf): 6 is free
{FrameOff 7 8 0 1} {FrameOff 7 8 0 1}
{ModuleOff 8 4 0 1} {ModuleOff 8 4 0 1}
{TLSOff 9 4 0 1} {TLSOff 9 4 0 1}
@@ -1241,7 +1241,7 @@ RDI_EvalOpTable:
{Convert 42 2 1 1} {Convert 42 2 1 1}
{Pick 43 1 0 1} {Pick 43 1 0 1}
{Pop 44 0 1 0} {Pop 44 0 1 0}
{Insert 45 1 0 0} // NOTE(rjf): 45 is free
{ValueRead 46 1 2 1} {ValueRead 46 1 2 1}
{ByteSwap 47 1 1 1} {ByteSwap 47 1 1 1}
{CallSiteValue 48 4 0 0} {CallSiteValue 48 4 0 0}
-5
View File
@@ -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); 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); imm_fmt = push_str8f(scratch.arena, "%S+%I64u, Size: %u", reg_str, byte_off, byte_size);
} break; } break;
case RDI_EvalOp_RegReadDyn: break;
case RDI_EvalOp_FrameOff: { case RDI_EvalOp_FrameOff: {
imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str);
} break; } break;
@@ -426,10 +425,6 @@ rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc)
imm_fmt = push_str8f(scratch.arena, "%u", pick); imm_fmt = push_str8f(scratch.arena, "%u", pick);
} break; } break;
case RDI_EvalOp_Pop: 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: { case RDI_EvalOp_ValueRead: {
U8 bytes_to_read = *(U8 *)imm.str; U8 bytes_to_read = *(U8 *)imm.str;
imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read);