diff --git a/libs/ir/cbuild.toml b/libs/ir/cbuild.toml new file mode 100644 index 0000000..42a7cbe --- /dev/null +++ b/libs/ir/cbuild.toml @@ -0,0 +1,10 @@ +[package] +name = "ir" +version = "0.1.0" +authors = [] +description = "" + +dependencies = [{ name = "scc_core", path = "../../runtime/scc_core" }] +# dependencies = [] +# features = {} +# default_features = [] diff --git a/libs/ir/include/ir_builtin.h b/libs/ir/include/ir_builtin.h new file mode 100644 index 0000000..96c4a15 --- /dev/null +++ b/libs/ir/include/ir_builtin.h @@ -0,0 +1,9 @@ +#ifndef __SCC_IR_BUILTIN_H__ +#define __SCC_IR_BUILTIN_H__ + +#include "ir_def.h" + +extern scc_ir_type_t scc_ir_builtin_i32; +extern scc_ir_node_t scc_ir_builtin_zero; + +#endif /* __SCC_IR_BUILTIN_H__ */ diff --git a/libs/ir/include/ir_def.h b/libs/ir/include/ir_def.h new file mode 100644 index 0000000..9bda495 --- /dev/null +++ b/libs/ir/include/ir_def.h @@ -0,0 +1,178 @@ +#ifndef __SCC_IR_DEF_H__ +#define __SCC_IR_DEF_H__ + +#include + +typedef struct scc_ir_node scc_ir_node_t; +typedef SCC_VEC(scc_ir_node_t) scc_ir_node_vec_t; + +typedef enum scc_ir_type_tag { + SCC_IR_TYPE_VOID, + SCC_IR_TYPE_I32, + SCC_IR_TYPE_PTR, + SCC_IR_TYPE_ARRAY, + SCC_IR_TYPE_FUNC, +} scc_ir_type_tag_t; + +typedef struct scc_ir_type scc_ir_type_t; +typedef SCC_VEC(scc_ir_type_t) scc_ir_type_vec_t; + +struct scc_ir_type { + scc_ir_type_tag_t tag; + + union { + struct { + const scc_ir_type_t *base; + usize len; + } array; + struct { + const scc_ir_type_t *base; + } pointer; + struct { + scc_ir_type_vec_t params; + const scc_ir_type_t *ret_type; + } function; + } data; +}; + +typedef struct scc_ir_bblock { + const char *label; + scc_ir_node_vec_t instrs; + // ir_arr_t used_by; +} scc_ir_bblock_t; // basic block +typedef SCC_VEC(scc_ir_bblock_t) scc_ir_bblock_vec_t; + +typedef struct { + const char *name; + scc_ir_type_t *type; + scc_ir_node_vec_t params; + scc_ir_bblock_vec_t bblocks; +} scc_ir_func_t; +typedef SCC_VEC(scc_ir_func_t) scc_ir_func_vec_t; + +typedef enum scc_ir_node_tag { + SCC_IR_NODE_NULL, + SCC_IR_NODE_CONST_INT, + SCC_IR_NODE_ALLOC, + SCC_IR_NODE_LOAD, + SCC_IR_NODE_STORE, + SCC_IR_NODE_GET_PTR, + SCC_IR_NODE_OP, + SCC_IR_NODE_BRANCH, + SCC_IR_NODE_JUMP, + SCC_IR_NODE_CALL, + SCC_IR_NODE_RET, +} scc_ir_node_tag_t; + +typedef enum { + /// Empty op for init or nop + IR_OP_EMPTY, + /// Not equal to. + IR_OP_NEQ, + /// Equal to. + IR_OP_EQ, + /// Greater than. + IR_OP_GT, + /// Less than. + IR_OP_LT, + /// Greater than or equal to. + IR_OP_GE, + /// Less than or equal to. + IR_OP_LE, + /// Addition. + IR_OP_ADD, + /// Subtraction. + IR_OP_SUB, + /// Multiplication. + IR_OP_MUL, + /// Division. + IR_OP_DIV, + /// Modulo. + IR_OP_MOD, + /// Bitwise AND. + IR_OP_AND, + /// Bitwise OR. + IR_OP_OR, + /// Bitwise XOR. + IR_OP_XOR, + /// Bitwise NOT. + IR_OP_NOT, + /// Shift left logical. + IR_OP_SHL, + /// Shift right logical. + IR_OP_SHR, + /// Shift right arithmetic. + IR_OP_SAR, +} scc_ir_op_type_t; + +struct scc_ir_node { + const scc_ir_type_t *type; + const char *name; + scc_ir_node_vec_t used_by; + scc_ir_node_tag_t tag; + union { + union { + i8 int8; + i16 int16; + i32 int32; + i64 int64; + // TODO int128 + i8 int_any[4]; + } const_int; + union { + u8 uint8; + u16 uint16; + u32 uint32; + u64 uint64; + // TODO uint128; + u8 uint_any[4]; + } const_uint; + // aggregate; + // func_arg_ref; + // block_arg_ref; + // global_alloc; + struct { + scc_ir_node_t *target; + } load; + struct { + scc_ir_node_t *target; + scc_ir_node_t *value; + } store; + struct { + scc_ir_node_t *src_addr; + scc_ir_node_t *index; + } get_ptr; + struct { + scc_ir_node_t *src_addr; + scc_ir_node_t *index; + } get_elem_ptr; + struct { + scc_ir_op_type_t op; + scc_ir_node_t *lhs; + scc_ir_node_t *rhs; + } op; + struct { + scc_ir_node_t *cond; + scc_ir_bblock_t *true_bblock; + scc_ir_bblock_t *false_bblock; + } branch; + struct { + scc_ir_bblock_t *target_bblock; + } jump; + struct { + scc_ir_func_t *callee; + scc_ir_node_vec_t args; + } call; + struct { + scc_ir_node_t *ret_val; + } ret; + } data; +}; + +typedef struct { + scc_ir_node_vec_t global_vals; + scc_ir_func_vec_t funcs; + scc_ir_func_vec_t extern_funcs; +} ir_cprog_t; + +#endif /* __SCC_IR_DEF_H__ */ diff --git a/libs/ir/include/ir_dump.h b/libs/ir/include/ir_dump.h new file mode 100644 index 0000000..aa4c0bd --- /dev/null +++ b/libs/ir/include/ir_dump.h @@ -0,0 +1,16 @@ +#ifndef __SCC_IR_DUMP_H__ +#define __SCC_IR_DUMP_H__ + +#include "ir_def.h" + +typedef struct { + +} scc_ir_dump_ctx_t; + +void scc_ir_type_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_type_t *in); +void scc_ir_bblock_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_bblock_t *in); +void scc_ir_func_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_func_t *in); +void scc_ir_node_dump(scc_ir_dump_ctx_t *ctx, scc_ir_node_t *in); +void scc_ir_cprog_dump(scc_ir_dump_ctx_t *ctx, ir_cprog_t *in); + +#endif /* __SCC_IR_DUMP_H__ */ diff --git a/libs/ir/include/scc_ir.h b/libs/ir/include/scc_ir.h new file mode 100644 index 0000000..f543118 --- /dev/null +++ b/libs/ir/include/scc_ir.h @@ -0,0 +1,27 @@ +#ifndef __SCC_IR_H__ +#define __SCC_IR_H__ + +#include "ir_def.h" + +void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag); +void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label); +void scc_ir_func_init(scc_ir_func_t *in, const char *name); + +// node name can be null ptr +void scc_ir_node_init(scc_ir_node_t *in, const char *name, + scc_ir_node_tag_t tag); + +void scc_ir_cprog_init(ir_cprog_t *in); + +scc_ir_type_t *scc_ir_type_alloc(scc_ir_type_tag_t tag); +scc_ir_bblock_t *scc_ir_bblock_alloc(const char *label); +scc_ir_func_t *scc_ir_func_alloc(const char *name); +scc_ir_node_t *scc_ir_node_alloc(const char *name, scc_ir_node_tag_t tag); + +// scc_ir_type_t *scc_ir_type_alloc_with_ctx(scc_ir_type_tag_t tag); +// scc_ir_bblock_t *scc_ir_bblock_alloc_with_ctx(const char *label); +// scc_ir_func_t *scc_ir_func_alloc_with_ctx(const char *name); +// scc_ir_node_t *scc_ir_node_alloc_with_ctx(const char *name, +// scc_ir_node_tag_t tag); + +#endif /* __SCC_IR_H__ */ diff --git a/libs/ir/src/ir_builtin.c b/libs/ir/src/ir_builtin.c new file mode 100644 index 0000000..e822335 --- /dev/null +++ b/libs/ir/src/ir_builtin.c @@ -0,0 +1,10 @@ +#include + +scc_ir_type_t scc_ir_builtin_i32 = { + .tag = SCC_IR_TYPE_I32, +}; + +scc_ir_node_t scc_ir_builtin_zero = { + .tag = SCC_IR_NODE_CONST_INT, + .data.const_int.int_any = {0}, +}; \ No newline at end of file diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c new file mode 100644 index 0000000..9cd61c4 --- /dev/null +++ b/libs/ir/src/ir_dump.c @@ -0,0 +1,13 @@ +#include + +void scc_ir_type_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_type_t *in) { + return; +} +void scc_ir_bblock_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_bblock_t *in) { + return; +} +void scc_ir_func_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_func_t *in) { + return; +} +void scc_ir_node_dump(scc_ir_dump_ctx_t *ctx, scc_ir_node_t *in) { return; } +void scc_ir_cprog_dump(scc_ir_dump_ctx_t *ctx, ir_cprog_t *in) { return; } \ No newline at end of file diff --git a/libs/ir/src/scc_ir.c b/libs/ir/src/scc_ir.c new file mode 100644 index 0000000..a3848b2 --- /dev/null +++ b/libs/ir/src/scc_ir.c @@ -0,0 +1,128 @@ +#include + +void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag) { + Assert(in != null); + in->tag = tag; + switch (tag) { + case SCC_IR_TYPE_ARRAY: + in->data.array.base = null; + in->data.array.len = 0; + break; + case SCC_IR_TYPE_PTR: + in->data.pointer.base = null; + break; + case SCC_IR_TYPE_FUNC: + scc_vec_init(in->data.function.params); + in->data.function.ret_type = null; + break; + case SCC_IR_TYPE_VOID: + case SCC_IR_TYPE_I32: + break; + default: + UNREACHABLE(); + break; + } +} + +void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label) { + Assert(in != null); + Assert(label != null); + in->label = label; + scc_vec_init(in->instrs); +} + +void scc_ir_func_init(scc_ir_func_t *in, const char *name) { + Assert(in != null); + Assert(name != null); + in->name = name; + in->type = null; + scc_vec_init(in->bblocks); + scc_vec_init(in->params); +} + +void scc_ir_node_init(scc_ir_node_t *in, const char *name, + scc_ir_node_tag_t tag) { + Assert(in != null); + in->name = name; + in->tag = tag; + scc_vec_init(in->used_by); + in->type = null; + + switch (tag) { + case SCC_IR_NODE_NULL: + break; + case SCC_IR_NODE_CONST_INT: + // TODO + in->data.const_int.int32 = 0; + break; + case SCC_IR_NODE_ALLOC: + TODO(); + break; + case SCC_IR_NODE_LOAD: + in->data.load.target = null; + break; + case SCC_IR_NODE_STORE: + in->data.store.target = null; + in->data.store.value = null; + break; + case SCC_IR_NODE_GET_PTR: + in->data.get_ptr.src_addr = null; + in->data.get_ptr.index = null; + break; + case SCC_IR_NODE_OP: + in->data.op.op = IR_OP_EMPTY; + in->data.op.lhs = null; + in->data.op.rhs = null; + break; + case SCC_IR_NODE_BRANCH: + in->data.branch.cond = null; + in->data.branch.true_bblock = null; + in->data.branch.false_bblock = null; + break; + case SCC_IR_NODE_JUMP: + in->data.jump.target_bblock = null; + break; + case SCC_IR_NODE_CALL: + scc_vec_init(in->data.call.args); + in->data.call.callee = null; + break; + case SCC_IR_NODE_RET: + in->data.ret.ret_val = null; + break; + default: + UNREACHABLE(); + break; + } +} + +void scc_ir_cprog_init(ir_cprog_t *in) { + Assert(in != null); + scc_vec_init(in->extern_funcs); + scc_vec_init(in->funcs); + scc_vec_init(in->global_vals); +} + +scc_ir_type_t *scc_ir_type_alloc(scc_ir_type_tag_t tag) { + scc_ir_type_t *ret = scc_malloc(sizeof(scc_ir_type_t)); + Assert(ret != null); + scc_ir_type_init(ret, tag); + return ret; +} +scc_ir_bblock_t *scc_ir_bblock_alloc(const char *label) { + scc_ir_bblock_t *ret = scc_malloc(sizeof(scc_ir_bblock_t)); + Assert(ret != null); + scc_ir_bblock_init(ret, label); + return ret; +} +scc_ir_func_t *scc_ir_func_alloc(const char *name) { + scc_ir_func_t *ret = scc_malloc(sizeof(scc_ir_func_t)); + Assert(ret != null); + scc_ir_func_init(ret, name); + return ret; +} +scc_ir_node_t *scc_ir_node_alloc(const char *name, scc_ir_node_tag_t tag) { + scc_ir_node_t *ret = scc_malloc(sizeof(scc_ir_node_t)); + Assert(ret != null); + scc_ir_node_init(ret, name, tag); + return ret; +} diff --git a/libs/ir/tests/test_ir.c b/libs/ir/tests/test_ir.c new file mode 100644 index 0000000..1616237 --- /dev/null +++ b/libs/ir/tests/test_ir.c @@ -0,0 +1,10 @@ +#include + +void test_example() { + printf("Test passed!\n"); +} + +int main() { + test_example(); + return 0; +}