mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-17 01:22:24 -07:00
434 lines
14 KiB
C
434 lines
14 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: IR Tree Types
|
|
|
|
typedef struct E_IRNode E_IRNode;
|
|
struct E_IRNode
|
|
{
|
|
E_IRNode *first;
|
|
E_IRNode *last;
|
|
E_IRNode *next;
|
|
RDI_EvalOp op;
|
|
E_Space space;
|
|
String8 string;
|
|
E_Value value;
|
|
};
|
|
|
|
typedef struct E_IRTreeAndType E_IRTreeAndType;
|
|
struct E_IRTreeAndType
|
|
{
|
|
E_IRNode *root;
|
|
E_TypeKey type_key;
|
|
E_Mode mode;
|
|
E_MsgList msgs;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Member/Index Lookup Hooks
|
|
|
|
typedef struct E_LookupInfo E_LookupInfo;
|
|
struct E_LookupInfo
|
|
{
|
|
void *user_data;
|
|
U64 named_expr_count;
|
|
U64 idxed_expr_count;
|
|
};
|
|
|
|
typedef struct E_LookupAccess E_LookupAccess;
|
|
struct E_LookupAccess
|
|
{
|
|
E_IRTreeAndType irtree_and_type;
|
|
};
|
|
|
|
#define E_LOOKUP_INFO_FUNCTION_SIG(name) E_LookupInfo name(Arena *arena, E_IRTreeAndType *lhs, String8 filter)
|
|
#define E_LOOKUP_INFO_FUNCTION_NAME(name) e_lookup_info_##name
|
|
#define E_LOOKUP_INFO_FUNCTION_DEF(name) internal E_LOOKUP_INFO_FUNCTION_SIG(E_LOOKUP_INFO_FUNCTION_NAME(name))
|
|
typedef E_LOOKUP_INFO_FUNCTION_SIG(E_LookupInfoFunctionType);
|
|
E_LOOKUP_INFO_FUNCTION_DEF(default);
|
|
|
|
#define E_LOOKUP_ACCESS_FUNCTION_SIG(name) E_LookupAccess name(Arena *arena, E_ExprKind kind, E_Expr *lhs, E_Expr *rhs, void *user_data)
|
|
#define E_LOOKUP_ACCESS_FUNCTION_NAME(name) e_lookup_access_##name
|
|
#define E_LOOKUP_ACCESS_FUNCTION_DEF(name) internal E_LOOKUP_ACCESS_FUNCTION_SIG(E_LOOKUP_ACCESS_FUNCTION_NAME(name))
|
|
typedef E_LOOKUP_ACCESS_FUNCTION_SIG(E_LookupAccessFunctionType);
|
|
E_LOOKUP_ACCESS_FUNCTION_DEF(default);
|
|
|
|
#define E_LOOKUP_RANGE_FUNCTION_SIG(name) void name(Arena *arena, E_Expr *lhs, Rng1U64 idx_range, E_Expr **exprs, String8 *exprs_strings, void *user_data)
|
|
#define E_LOOKUP_RANGE_FUNCTION_NAME(name) e_lookup_range_##name
|
|
#define E_LOOKUP_RANGE_FUNCTION_DEF(name) internal E_LOOKUP_RANGE_FUNCTION_SIG(E_LOOKUP_RANGE_FUNCTION_NAME(name))
|
|
typedef E_LOOKUP_RANGE_FUNCTION_SIG(E_LookupRangeFunctionType);
|
|
E_LOOKUP_RANGE_FUNCTION_DEF(default);
|
|
|
|
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(U64 num, void *user_data)
|
|
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name) e_lookup_id_from_num_##name
|
|
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(name) internal E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name))
|
|
typedef E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LookupIDFromNumFunctionType);
|
|
E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(default);
|
|
|
|
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(U64 id, void *user_data)
|
|
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name) e_lookup_num_from_id_##name
|
|
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(name) internal E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name))
|
|
typedef E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LookupNumFromIDFunctionType);
|
|
E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(default);
|
|
|
|
typedef struct E_LookupRule E_LookupRule;
|
|
struct E_LookupRule
|
|
{
|
|
String8 name;
|
|
E_LookupInfoFunctionType *info;
|
|
E_LookupAccessFunctionType *access;
|
|
E_LookupRangeFunctionType *range;
|
|
E_LookupIDFromNumFunctionType *id_from_num;
|
|
E_LookupNumFromIDFunctionType *num_from_id;
|
|
};
|
|
|
|
typedef struct E_LookupRuleNode E_LookupRuleNode;
|
|
struct E_LookupRuleNode
|
|
{
|
|
E_LookupRuleNode *next;
|
|
E_LookupRule v;
|
|
};
|
|
|
|
typedef struct E_LookupRuleSlot E_LookupRuleSlot;
|
|
struct E_LookupRuleSlot
|
|
{
|
|
E_LookupRuleNode *first;
|
|
E_LookupRuleNode *last;
|
|
};
|
|
|
|
typedef struct E_LookupRuleMap E_LookupRuleMap;
|
|
struct E_LookupRuleMap
|
|
{
|
|
E_LookupRuleSlot *slots;
|
|
U64 slots_count;
|
|
};
|
|
|
|
typedef struct E_LookupRuleTagPair E_LookupRuleTagPair;
|
|
struct E_LookupRuleTagPair
|
|
{
|
|
E_LookupRule *rule;
|
|
E_Expr *tag;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: IR Generation Hooks
|
|
|
|
#define E_IRGEN_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr, E_Expr *tag)
|
|
#define E_IRGEN_FUNCTION_NAME(name) e_irgen_##name
|
|
#define E_IRGEN_FUNCTION_DEF(name) internal E_IRGEN_FUNCTION_SIG(E_IRGEN_FUNCTION_NAME(name))
|
|
typedef E_IRGEN_FUNCTION_SIG(E_IRGenFunctionType);
|
|
E_IRGEN_FUNCTION_DEF(default);
|
|
|
|
typedef struct E_IRGenRule E_IRGenRule;
|
|
struct E_IRGenRule
|
|
{
|
|
String8 name;
|
|
E_IRGenFunctionType *irgen;
|
|
};
|
|
|
|
typedef struct E_IRGenRuleNode E_IRGenRuleNode;
|
|
struct E_IRGenRuleNode
|
|
{
|
|
E_IRGenRuleNode *next;
|
|
E_IRGenRule v;
|
|
};
|
|
|
|
typedef struct E_IRGenRuleSlot E_IRGenRuleSlot;
|
|
struct E_IRGenRuleSlot
|
|
{
|
|
E_IRGenRuleNode *first;
|
|
E_IRGenRuleNode *last;
|
|
};
|
|
|
|
typedef struct E_IRGenRuleMap E_IRGenRuleMap;
|
|
struct E_IRGenRuleMap
|
|
{
|
|
U64 slots_count;
|
|
E_IRGenRuleSlot *slots;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Type Pattern -> Hook Key Data Structure (Auto View Rules)
|
|
|
|
typedef struct E_AutoHookNode E_AutoHookNode;
|
|
struct E_AutoHookNode
|
|
{
|
|
E_AutoHookNode *hash_next;
|
|
E_AutoHookNode *pattern_order_next;
|
|
E_TypeKey type_key;
|
|
String8List type_pattern_parts;
|
|
E_Expr *tag_expr;
|
|
};
|
|
|
|
typedef struct E_AutoHookSlot E_AutoHookSlot;
|
|
struct E_AutoHookSlot
|
|
{
|
|
E_AutoHookNode *first;
|
|
E_AutoHookNode *last;
|
|
};
|
|
|
|
typedef struct E_AutoHookMap E_AutoHookMap;
|
|
struct E_AutoHookMap
|
|
{
|
|
U64 slots_count;
|
|
E_AutoHookSlot *slots;
|
|
E_AutoHookNode *first_pattern;
|
|
E_AutoHookNode *last_pattern;
|
|
};
|
|
|
|
typedef struct E_AutoHookParams E_AutoHookParams;
|
|
struct E_AutoHookParams
|
|
{
|
|
E_TypeKey type_key;
|
|
String8 type_pattern;
|
|
String8 tag_expr_string;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Used Tag Map Data Structure
|
|
|
|
typedef struct E_UsedTagNode E_UsedTagNode;
|
|
struct E_UsedTagNode
|
|
{
|
|
E_UsedTagNode *next;
|
|
E_UsedTagNode *prev;
|
|
E_Expr *tag;
|
|
};
|
|
|
|
typedef struct E_UsedTagSlot E_UsedTagSlot;
|
|
struct E_UsedTagSlot
|
|
{
|
|
E_UsedTagNode *first;
|
|
E_UsedTagNode *last;
|
|
};
|
|
|
|
typedef struct E_UsedTagMap E_UsedTagMap;
|
|
struct E_UsedTagMap
|
|
{
|
|
U64 slots_count;
|
|
E_UsedTagSlot *slots;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Type Key -> Auto Hook Expr List Cache
|
|
|
|
typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode;
|
|
struct E_TypeAutoHookCacheNode
|
|
{
|
|
E_TypeAutoHookCacheNode *next;
|
|
E_TypeKey key;
|
|
E_ExprList exprs;
|
|
};
|
|
|
|
typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot;
|
|
struct E_TypeAutoHookCacheSlot
|
|
{
|
|
E_TypeAutoHookCacheNode *first;
|
|
E_TypeAutoHookCacheNode *last;
|
|
};
|
|
|
|
typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap;
|
|
struct E_TypeAutoHookCacheMap
|
|
{
|
|
U64 slots_count;
|
|
E_TypeAutoHookCacheSlot *slots;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: IR Context
|
|
|
|
typedef struct E_IRCtx E_IRCtx;
|
|
struct E_IRCtx
|
|
{
|
|
E_String2ExprMap *macro_map;
|
|
E_LookupRuleMap *lookup_rule_map;
|
|
E_IRGenRuleMap *irgen_rule_map;
|
|
E_AutoHookMap *auto_hook_map;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: IR State
|
|
|
|
typedef struct E_IRTreeAndTypeCacheNode E_IRTreeAndTypeCacheNode;
|
|
struct E_IRTreeAndTypeCacheNode
|
|
{
|
|
E_IRTreeAndTypeCacheNode *next;
|
|
E_Expr *expr;
|
|
E_IRTreeAndType irtree_and_type;
|
|
};
|
|
|
|
typedef struct E_IRTreeAndTypeCacheSlot E_IRTreeAndTypeCacheSlot;
|
|
struct E_IRTreeAndTypeCacheSlot
|
|
{
|
|
E_IRTreeAndTypeCacheNode *first;
|
|
E_IRTreeAndTypeCacheNode *last;
|
|
};
|
|
|
|
typedef struct E_IRState E_IRState;
|
|
struct E_IRState
|
|
{
|
|
Arena *arena;
|
|
U64 arena_eval_start_pos;
|
|
|
|
// rjf: ir context
|
|
E_IRCtx *ctx;
|
|
|
|
// rjf: caches
|
|
E_UsedTagMap *used_tag_map;
|
|
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
|
|
U64 irtree_and_type_cache_slots_count;
|
|
E_IRTreeAndTypeCacheSlot *irtree_and_type_cache_slots;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Globals
|
|
|
|
local_persist read_only E_LookupRule e_lookup_rule__nil =
|
|
{
|
|
str8_lit_comp("nil"),
|
|
E_LOOKUP_INFO_FUNCTION_NAME(default),
|
|
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
|
|
E_LOOKUP_RANGE_FUNCTION_NAME(default),
|
|
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
|
|
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
|
|
};
|
|
local_persist read_only E_LookupRule e_lookup_rule__default =
|
|
{
|
|
str8_lit_comp("default"),
|
|
E_LOOKUP_INFO_FUNCTION_NAME(default),
|
|
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
|
|
E_LOOKUP_RANGE_FUNCTION_NAME(default),
|
|
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
|
|
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
|
|
};
|
|
local_persist read_only E_IRGenRule e_irgen_rule__default =
|
|
{
|
|
str8_lit_comp("default"),
|
|
E_IRGEN_FUNCTION_NAME(default),
|
|
};
|
|
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
|
|
thread_static E_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 E_IRCtx *e_selected_ir_ctx(void);
|
|
internal void e_select_ir_ctx(E_IRCtx *ctx);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Lookups
|
|
|
|
internal E_LookupRuleMap e_lookup_rule_map_make(Arena *arena, U64 slots_count);
|
|
internal void e_lookup_rule_map_insert(Arena *arena, E_LookupRuleMap *map, E_LookupRule *rule);
|
|
#define e_lookup_rule_map_insert_new(arena, map, name_, ...) e_lookup_rule_map_insert((arena), (map), &(E_LookupRule){.name = (name_), __VA_ARGS__})
|
|
|
|
internal E_LookupRule *e_lookup_rule_from_string(String8 string);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: IR Gen Rules
|
|
|
|
internal E_IRGenRuleMap e_irgen_rule_map_make(Arena *arena, U64 slots_count);
|
|
internal void e_irgen_rule_map_insert(Arena *arena, E_IRGenRuleMap *map, E_IRGenRule *rule);
|
|
#define e_irgen_rule_map_insert_new(arena, map, name_, ...) e_irgen_rule_map_insert((arena), (map), &(E_IRGenRule){.name = (name_), __VA_ARGS__})
|
|
|
|
internal E_IRGenRule *e_irgen_rule_from_string(String8 string);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Auto Hooks
|
|
|
|
internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count);
|
|
internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params);
|
|
#define e_auto_hook_map_insert_new(arena, map, ...) e_auto_hook_map_insert_new_((arena), (map), &(E_AutoHookParams){.type_key = zero_struct, __VA_ARGS__})
|
|
internal E_ExprList e_auto_hook_tag_exprs_from_type_key(Arena *arena, E_TypeKey type_key);
|
|
internal E_ExprList e_auto_hook_tag_exprs_from_type_key__cached(E_TypeKey type_key);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: 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: top-level irtree/type extraction
|
|
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
|
|
|
|
//- rjf: irtree -> linear ops/bytecode
|
|
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_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: IRified Expression Cache
|
|
|
|
internal E_IRTreeAndType e_irtree_and_type_from_expr__cached(E_Expr *expr);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Expression & IR-Tree => Lookup Rule
|
|
|
|
internal E_LookupRuleTagPair e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree);
|
|
|
|
#endif // EVAL_IR_H
|