398 lines
17 KiB
C
398 lines
17 KiB
C
#ifndef __SPL_IR_H__
|
|
#define __SPL_IR_H__
|
|
|
|
#include "../stage0/include/utils.h"
|
|
#include "spl_dbg.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(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(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) \
|
|
|
|
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;
|
|
spl_dbg_node_t dbg;
|
|
union {
|
|
spl_type_id_t tid;
|
|
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_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, /* 不实现 */
|
|
} kind;
|
|
} spl_ir_attr_t;
|
|
typedef VEC(spl_ir_attr_t) spl_ir_attr_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_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);
|
|
|
|
typedef struct {
|
|
spl_ir_t ir;
|
|
spl_ir_func_ref_t current_fn;
|
|
spl_ir_node_ref_t current_node;
|
|
spl_ir_node_ref_vec_t reloc_label;
|
|
spl_dbg_node_t dbg;
|
|
} spl_ir_builder_t;
|
|
|
|
/* clang-format off */
|
|
#define SPL_IR_BIN_ARITH_TABLE \
|
|
X(arith_add, SPL_IR_ARITH_ADD) \
|
|
X(arith_sub, SPL_IR_ARITH_SUB) \
|
|
X(arith_mul, SPL_IR_ARITH_MUL) \
|
|
X(arith_div, SPL_IR_ARITH_DIV) \
|
|
X(arith_rem, SPL_IR_ARITH_REM) \
|
|
X(arith_and, SPL_IR_ARITH_AND) \
|
|
X(arith_or, SPL_IR_ARITH_OR) \
|
|
X(arith_xor, SPL_IR_ARITH_XOR) \
|
|
X(arith_shl, SPL_IR_ARITH_SHL) \
|
|
X(arith_shr, SPL_IR_ARITH_SHR)
|
|
#define SPL_IR_UN_ARITH_TABLE \
|
|
X(arith_neg, SPL_IR_ARITH_NEG) \
|
|
X(arith_abs, SPL_IR_ARITH_ABS) \
|
|
X(arith_not, SPL_IR_ARITH_NOT)
|
|
#define SPL_IR_CMP_TABLE \
|
|
X(cmp_eq, SPL_IR_CMP_EQ) \
|
|
X(cmp_ne, SPL_IR_CMP_NE) \
|
|
X(cmp_lt, SPL_IR_CMP_LT) \
|
|
X(cmp_le, SPL_IR_CMP_LE) \
|
|
X(cmp_gt, SPL_IR_CMP_GT) \
|
|
X(cmp_ge, SPL_IR_CMP_GE)
|
|
#define SPL_IR_CAST_TABLE \
|
|
X(cast_trunc, SPL_IR_CAST_TRUNC) \
|
|
X(cast_zext, SPL_IR_CAST_ZEXT) \
|
|
X(cast_sext, SPL_IR_CAST_SEXT) \
|
|
X(cast_fext, SPL_IR_CAST_FEXT) \
|
|
X(cast_ftrunc, SPL_IR_CAST_FTRUNC) \
|
|
X(cast_bitcast, SPL_IR_CAST_BITCAST) \
|
|
X(cast_ptr2int, SPL_IR_CAST_PTR2INT) \
|
|
X(cast_int2ptr, SPL_IR_CAST_INT2PTR) \
|
|
X(cast_bool2int, SPL_IR_CAST_BOOL2INT) \
|
|
X(case_int2float, SPL_IR_CASE_INT2FLOAT) \
|
|
X(case_float2int, SPL_IR_CASE_FLOAT2INT)
|
|
/* clang-format on */
|
|
void spl_ir_builder_init(spl_ir_builder_t *b);
|
|
void spl_ir_builder_drop(spl_ir_builder_t *b);
|
|
|
|
spl_ir_func_ref_t spl_ir_builder_fn_new(spl_ir_builder_t *b, const char *name,
|
|
spl_type_id_t fn_tid);
|
|
spl_ir_func_ref_t spl_ir_builder_cur_fn(const spl_ir_builder_t *b);
|
|
void spl_ir_builder_set_dbg(spl_ir_builder_t *b, spl_dbg_node_t dbg);
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_block_new(spl_ir_builder_t *b);
|
|
|
|
#define X(name, kind) \
|
|
spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t tid, \
|
|
spl_ir_node_ref_t left, spl_ir_node_ref_t right);
|
|
SPL_IR_BIN_ARITH_TABLE
|
|
#undef X
|
|
|
|
#define X(name, kind) \
|
|
spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t tid, \
|
|
spl_ir_node_ref_t val);
|
|
SPL_IR_UN_ARITH_TABLE
|
|
#undef X
|
|
|
|
#define X(name, kind) \
|
|
spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t tid, \
|
|
spl_ir_node_ref_t a, spl_ir_node_ref_t b);
|
|
SPL_IR_CMP_TABLE
|
|
#undef X
|
|
|
|
#define X(name, kind) \
|
|
spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t from_tid, \
|
|
spl_type_id_t to_tid, spl_ir_node_ref_t val);
|
|
SPL_IR_CAST_TABLE
|
|
#undef X
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_mem_alloca(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t count);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_global_alloc(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t const_node);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_load(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t ptr);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_store(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t ptr, spl_ir_node_ref_t val);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_offset(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t ptr, spl_ir_node_ref_t offset);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_field(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t agg, usize field_idx);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_copy(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t dst, spl_ir_node_ref_t src,
|
|
spl_ir_node_ref_t size);
|
|
spl_ir_node_ref_t spl_ir_builder_mem_set(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t dst, spl_ir_node_ref_t val,
|
|
spl_ir_node_ref_t size);
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val);
|
|
spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
double val);
|
|
spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
const char *val);
|
|
spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val);
|
|
spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_func_ref_t val);
|
|
spl_ir_node_ref_t spl_ir_builder_type_bitsizeof(spl_ir_builder_t *b, spl_type_id_t tid);
|
|
spl_ir_node_ref_t spl_ir_builder_type_sizeof(spl_ir_builder_t *b, spl_type_id_t tid);
|
|
spl_ir_node_ref_t spl_ir_builder_type_alignof(spl_ir_builder_t *b, spl_type_id_t tid);
|
|
spl_ir_node_ref_t spl_ir_builder_type_offsetof(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t field_idx);
|
|
spl_ir_node_ref_t spl_ir_builder_type_field_count(spl_ir_builder_t *b, spl_type_id_t tid);
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_agg_construct(spl_ir_builder_t *b, spl_type_id_t tid);
|
|
void spl_ir_builder_agg_construct_field(spl_ir_builder_t *b, spl_ir_node_ref_t node,
|
|
spl_ir_node_ref_t field);
|
|
spl_ir_node_ref_t spl_ir_builder_agg_extract(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_type_id_t field_tid, usize field_idx,
|
|
spl_ir_node_ref_t val);
|
|
spl_ir_node_ref_t spl_ir_builder_agg_insert(spl_ir_builder_t *b, spl_type_id_t tid, usize field_idx,
|
|
spl_ir_node_ref_t agg, spl_ir_node_ref_t field);
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_control_select(spl_ir_builder_t *b, 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);
|
|
spl_ir_node_ref_t spl_ir_builder_control_br(spl_ir_builder_t *b, spl_ir_node_ref_t cond,
|
|
spl_ir_node_ref_t true_label,
|
|
spl_ir_node_ref_t false_label);
|
|
spl_ir_node_ref_t spl_ir_builder_control_jmp(spl_ir_builder_t *b, spl_ir_node_ref_t label);
|
|
spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t func);
|
|
void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t node,
|
|
spl_ir_node_ref_t arg);
|
|
spl_ir_node_ref_t spl_ir_builder_control_param(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t idx);
|
|
spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t tid,
|
|
spl_ir_node_ref_t val);
|
|
spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b);
|
|
spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b);
|
|
|
|
spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b);
|
|
|
|
#endif /* __SPL_IR_H__ */
|