mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 06:48:41 +00:00
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:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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`,
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
@@ -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
@@ -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),
|
||||
|
||||
+1
-5
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user