Files
raddebugger/src/eval/eval_ir.h
T

252 lines
7.8 KiB
C

// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_IR_H
#define EVAL_IR_H
////////////////////////////////
//~ rjf: Bytecode Operation Types
enum
{
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
E_IRExtKind_SetSpace,
E_IRExtKind_COUNT
};
typedef struct E_Op E_Op;
struct E_Op
{
E_Op *next;
RDI_EvalOp opcode;
E_Value value;
String8 string;
};
typedef struct E_OpList E_OpList;
struct E_OpList
{
E_Op *first;
E_Op *last;
U64 op_count;
U64 encoded_size;
};
////////////////////////////////
//~ rjf: Used Tag Map Data Structure
typedef struct E_UsedExprNode E_UsedExprNode;
struct E_UsedExprNode
{
E_UsedExprNode *next;
E_UsedExprNode *prev;
E_Expr *expr;
};
typedef struct E_UsedExprSlot E_UsedExprSlot;
struct E_UsedExprSlot
{
E_UsedExprNode *first;
E_UsedExprNode *last;
};
typedef struct E_UsedExprMap E_UsedExprMap;
struct E_UsedExprMap
{
U64 slots_count;
E_UsedExprSlot *slots;
};
////////////////////////////////
//~ rjf: Type Key -> Auto Hook Expr List Cache
typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode;
struct E_TypeAutoHookCacheNode
{
E_TypeAutoHookCacheNode *next;
E_TypeKey key;
E_ExprList exprs;
};
typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot;
struct E_TypeAutoHookCacheSlot
{
E_TypeAutoHookCacheNode *first;
E_TypeAutoHookCacheNode *last;
};
typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap;
struct E_TypeAutoHookCacheMap
{
U64 slots_count;
E_TypeAutoHookCacheSlot *slots;
};
////////////////////////////////
//~ rjf: Evaluated String ID Map
typedef struct E_StringIDNode E_StringIDNode;
struct E_StringIDNode
{
E_StringIDNode *hash_next;
E_StringIDNode *id_next;
U64 id;
String8 string;
};
typedef struct E_StringIDSlot E_StringIDSlot;
struct E_StringIDSlot
{
E_StringIDNode *first;
E_StringIDNode *last;
};
typedef struct E_StringIDMap E_StringIDMap;
struct E_StringIDMap
{
U64 id_slots_count;
E_StringIDSlot *id_slots;
U64 hash_slots_count;
E_StringIDSlot *hash_slots;
};
////////////////////////////////
//~ rjf: IR Context
typedef struct E_IRCtx E_IRCtx;
struct E_IRCtx
{
// rjf: instruction pointer info
U64 thread_ip_vaddr;
U64 thread_ip_voff;
E_Space thread_reg_space;
// rjf: modules
E_Module *modules;
U64 modules_count;
E_Module *primary_module;
// rjf: identifier-resolution maps
E_String2NumMap *regs_map;
E_String2NumMap *reg_alias_map;
E_String2NumMap *locals_map; // (within `primary_module`)
E_String2NumMap *member_map; // (within `primary_module`)
E_String2ExprMap *macro_map;
// rjf: hook maps
E_AutoHookMap *auto_hook_map;
};
////////////////////////////////
//~ rjf: IR State
typedef struct E_IRState E_IRState;
struct E_IRState
{
Arena *arena;
U64 arena_eval_start_pos;
// rjf: ir context
E_IRCtx *ctx;
// rjf: unpacked ctx
RDI_Procedure *thread_ip_procedure;
// rjf: overridden irtree
E_IRTreeAndType *overridden_irtree;
B32 disallow_autohooks;
B32 disallow_chained_fastpaths;
// rjf: caches
E_UsedExprMap *used_expr_map;
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
U64 string_id_gen;
E_StringIDMap *string_id_map;
};
////////////////////////////////
//~ rjf: Globals
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
thread_static E_IRState *e_ir_state = 0;
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind);
internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal void e_select_ir_ctx(E_IRCtx *ctx);
////////////////////////////////
//~ rjf: Auto Hooks
internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count);
internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params);
#define e_auto_hook_map_insert_new(arena, map, ...) e_auto_hook_map_insert_new_((arena), (map), &(E_AutoHookParams){.type_key = zero_struct, __VA_ARGS__})
internal E_ExprList e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key);
internal E_ExprList e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key);
////////////////////////////////
//~ rjf: Evaluated String IDs
internal U64 e_id_from_string(String8 string);
internal String8 e_string_from_id(U64 id);
////////////////////////////////
//~ rjf: IR-ization Functions
//- rjf: op list functions
internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, E_Value value);
internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x);
internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x);
internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode);
internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space);
internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string);
internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push);
//- rjf: ir tree core building helpers
internal E_IRNode *e_push_irnode(Arena *arena, RDI_EvalOp op);
internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
//- rjf: ir subtree building helpers
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
internal E_IRNode *e_irtree_leaf_u128(Arena *arena, U128 u128);
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
internal E_IRNode *e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c);
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
//- rjf: expression poison checking
internal B32 e_expr_is_poisoned(E_Expr *expr);
internal void e_expr_poison(E_Expr *expr);
internal void e_expr_unpoison(E_Expr *expr);
//- rjf: top-level irtree/type extraction
E_TYPE_ACCESS_FUNCTION_DEF(default);
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
//- rjf: irtree -> linear ops/bytecode
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out);
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
//- rjf: leaf-bytecode expression extensions
internal E_Expr *e_expr_irext_member_access(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, String8 member_name);
internal E_Expr *e_expr_irext_array_index(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, U64 index);
internal E_Expr *e_expr_irext_deref(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree);
internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_TypeKey type_key);
#endif // EVAL_IR_H