Files
spl/stage1/spl_ir.h
2026-08-06 19:26:30 +08:00

281 lines
9.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __SPL_IR_H__
#define __SPL_IR_H__
#include "../stage0/include/utils.h"
#include "spl_type.h"
/* clang-format off */
#define SPL_IR_FN_TABLE \
X(arith.add, V0, SPL_IR_ARITH_ADD) \
X(arith.sub, V0, SPL_IR_ARITH_SUB) \
X(arith.mul, V0, SPL_IR_ARITH_MUL) \
X(arith.div, V0, SPL_IR_ARITH_DIV) \
X(arith.rem, V0, SPL_IR_ARITH_REM) \
X(arith.neg, V0, SPL_IR_ARITH_NEG) \
X(arith.abs, V0, SPL_IR_ARITH_ABS) \
X(arith.and, V0, SPL_IR_ARITH_AND) \
X(arith.or, V0, SPL_IR_ARITH_OR) \
X(arith.xor, V0, SPL_IR_ARITH_XOR) \
X(arith.shl, V0, SPL_IR_ARITH_SHL) \
X(arith.shr, V0, SPL_IR_ARITH_SHR) \
X(arith.not, V0, SPL_IR_ARITH_NOT) \
X(cmp.eq, V0, SPL_IR_CMP_EQ) \
X(cmp.ne, V0, SPL_IR_CMP_NE) \
X(cmp.lt, V0, SPL_IR_CMP_LT) \
X(cmp.le, V0, SPL_IR_CMP_LE) \
X(cmp.gt, V0, SPL_IR_CMP_GT) \
X(cmp.ge, V0, SPL_IR_CMP_GE) \
X(cast.trunc, V0, SPL_IR_CAST_TRUNC) \
X(cast.zext, V0, SPL_IR_CAST_ZEXT) \
X(cast.sext, V0, SPL_IR_CAST_SEXT) \
X(cast.fext, V0, SPL_IR_CAST_FEXT) \
X(cast.ftrunc, V0, SPL_IR_CAST_FTRUNC) \
X(cast.bitcast, V0, SPL_IR_CAST_BITCAST) \
X(cast.ptr2int, V0, SPL_IR_CAST_PTR2INT) \
X(cast.int2ptr, V0, SPL_IR_CAST_INT2PTR) \
X(cast.bool2int, V0, SPL_IR_CAST_BOOL2INT) \
X(case.int2float, V0, SPL_IR_CASE_INT2FLOAT) \
X(case.float2int, V0, SPL_IR_CASE_FLOAT2INT) \
X(mem.alloca, V0, SPL_IR_MEM_ALLOCA) \
X(mem.global_alloc, V0, SPL_IR_MEM_GLOBAL_ALLOC) \
X(mem.load, V0, SPL_IR_MEM_LOAD) \
X(mem.store, V0, SPL_IR_MEM_STORE) \
X(mem.offset, V0, SPL_IR_MEM_OFFSET) \
X(mem.field, V0, SPL_IR_MEM_FIELD_PTR) \
X(mem.copy, V0, SPL_IR_MEM_COPY) \
X(mem.set, V0, SPL_IR_MEM_SET) \
X(mem.fence, V0, SPL_IR_MEM_FENCE) \
X(type.const, V0, SPL_IR_TYPE_CONST) \
X(type.bitsizeof, V0, SPL_IR_TYPE_BITSIZEOF) \
X(type.sizeof, V0, SPL_IR_TYPE_SIZEOF) \
X(type.alignof, V0, SPL_IR_TYPE_ALIGNOF) \
X(type.offsetof, V0, SPL_IR_TYPE_OFFSETOF) \
X(type.field_count, V0, SPL_IR_TYPE_FIELD_COUNT) \
X(agg.construct, V0, SPL_IR_AGG_CONSTRUCT) \
X(agg.extract, V0, SPL_IR_AGG_EXTRACT) \
X(agg.insert, V0, SPL_IR_AGG_INSERT) \
X(atomic.load, V0, SPL_IR_ATOMIC_LOAD) \
X(atomic.store, V0, SPL_IR_ATOMIC_STORE) \
X(atomic.rmw_add, V0, SPL_IR_ATOMIC_RMW_ADD) \
X(atomic.rmw_sub, V0, SPL_IR_ATOMIC_RMW_SUB) \
X(atomic.rmw_and, V0, SPL_IR_ATOMIC_RMW_AND) \
X(atomic.rmw_or, V0, SPL_IR_ATOMIC_RMW_OR) \
X(atomic.rmw_xor, V0, SPL_IR_ATOMIC_RMW_XOR) \
X(atomic.rmw_xchg, V0, SPL_IR_ATOMIC_RMW_XCHG) \
X(atomic.cmpxchg, V0, SPL_IR_ATOMIC_CMPXCHG) \
X(control.select, V0, SPL_IR_CONTROL_SELECT) \
X(control.br, V0, SPL_IR_CONTROL_BR) \
X(control.jmp, V0, SPL_IR_CONTROL_JMP) \
X(control.call, V0, SPL_IR_CONTROL_CALL) \
X(control.param, V0, SPL_IR_CONTROL_PARAM) \
X(control.ret, V0, SPL_IR_CONTROL_RET) \
X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \
X(control.trap, V0, SPL_IR_CONTROL_TRAP) \
X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \
X(dbg.declare, V0, SPL_IR_DBG_DECLARE)
typedef enum {
#ifdef X
#undef X
#endif
#define X(a, b, c) c,
SPL_IR_FN_TABLE
#undef X
} spl_ir_kind_t;
/* clang-format on */
typedef usize spl_ir_node_ref_t; /* 0 is error */
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
typedef usize spl_ir_func_ref_t; /* 0 is error */
typedef struct {
spl_ir_kind_t kind;
usize src_ref; /* AST 节点 ref调试行号用ast2ir 注解) */
union {
struct {
spl_type_id_t tid;
spl_ir_node_ref_t left;
spl_ir_node_ref_t right;
} arith;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t a;
spl_ir_node_ref_t b;
} cmp;
struct {
spl_type_id_t from_tid;
spl_type_id_t to_tid;
spl_ir_node_ref_t val;
} cast;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t count;
} mem_alloc;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t const_node;
} mem_global_alloc;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
} mem_load;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
spl_ir_node_ref_t val;
} mem_store;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
spl_ir_node_ref_t offset;
} mem_offset;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t agg;
usize field_idx;
} mem_field_ptr;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t dst;
spl_ir_node_ref_t src;
spl_ir_node_ref_t size;
} mem_copy;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t dst;
spl_ir_node_ref_t val;
spl_ir_node_ref_t size;
} mem_set;
struct {
spl_ir_node_ref_t ordering;
} mem_fence;
struct {
spl_type_id_t tid;
union {
usize int_lit;
double float_lit;
const char *cstr_lit;
char ch_lit;
spl_ir_func_ref_t fn;
};
} type_const;
struct {
spl_type_id_t tid;
} bitsizeof;
struct {
spl_type_id_t tid;
} ir_sizeof;
struct {
spl_type_id_t tid;
} ir_alignof;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t field_idx;
} ir_offsetof;
struct {
spl_type_id_t tid;
} field_count;
struct {
spl_type_id_t tid;
spl_ir_node_ref_vec_t fields;
} agg_construct;
struct {
spl_type_id_t tid;
spl_type_id_t field_tid;
usize field_idx;
spl_ir_node_ref_t val;
} agg_extract;
struct {
spl_type_id_t tid;
usize field_idx;
spl_ir_node_ref_t agg;
spl_ir_node_ref_t field;
} agg_insert;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t cond;
spl_ir_node_ref_t true_val;
spl_ir_node_ref_t false_val;
} control_select;
struct {
spl_ir_node_ref_t cond;
spl_ir_node_ref_t true_label;
spl_ir_node_ref_t false_label;
} control_br;
struct {
spl_ir_node_ref_t label;
} control_jmp;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t func;
spl_ir_node_ref_vec_t params;
} control_call;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t idx;
} control_param;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t val;
} control_ret;
};
} spl_ir_node_t;
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
typedef struct {
enum {
SPL_IR_ATTR_NONE,
SPL_IR_ATTR_LINK, /* 不实现 */
SPL_IR_ATTR_ABI, /* 只有 C ABI 支持 */
SPL_IR_ATTR_SYMBOL, /* 不实现 */
SPL_IR_ATTR_NAKED, /* 不实现 */
SPL_IR_ATTR_NOINLINE, /* 不实现 */
SPL_IR_ATTR_ALWAYSINLINE, /* 不实现 */
};
} spl_ir_attr_t;
typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t;
/* 调试:函数内变量(名 → 内存位置。alloca 节点或参数槽。 */
typedef struct {
const char *name; /* 指向 AST 字符串,不拥有 */
spl_ir_node_ref_t alloca; /* 非参数alloca 节点 ref */
spl_type_id_t tid;
int is_param; /* 参数则用 param_idx */
usize param_idx;
usize offset; /* fp 字节偏移LADDR imm 语义ir2vm 填) */
} spl_ir_dbg_var_t;
typedef VEC(spl_ir_dbg_var_t) spl_ir_dbg_var_vec_t;
typedef struct {
const char *name;
spl_ir_attr_t attr;
spl_type_id_t fn_tid;
spl_ir_node_vec_t nodes;
spl_ir_node_ref_vec_t labels;
spl_ir_dbg_var_vec_t dbg_vars; /* 调试变量表fp 偏移在 ir2vm 填) */
} spl_ir_func_t;
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
typedef struct {
spl_ir_func_vec_t funcs;
spl_ir_node_vec_t gdata;
} spl_ir_t;
void spl_ir_init(spl_ir_t *ir);
void spl_ir_drop(spl_ir_t *ir);
spl_ir_node_ref_t spl_ir_alloc_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir);
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id);
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty);
const char *spl_ir_kind_name(spl_ir_kind_t kind);
#endif /* __SPL_IR_H__ */