diff --git a/mie/arg.c b/mie/arg.c new file mode 100644 index 0000000..628b6d8 --- /dev/null +++ b/mie/arg.c @@ -0,0 +1,12 @@ +#include + +static struct mie_type *get_type(struct mie_value *v) +{ + struct mie_arg *arg = MIE_ARG(v); + return arg->arg_type; +} + +const struct mie_value_type arg_value_type = { + .t_id = MIE_VALUE_ARG, + .t_get_type = get_type, +}; diff --git a/mie/block.c b/mie/block.c new file mode 100644 index 0000000..3667306 --- /dev/null +++ b/mie/block.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +static struct mie_type label_type = {}; + +struct mie_block *mie_block_create(struct mie_func *parent, const char *name) +{ + struct mie_block *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + mie_value_init(&out->b_base, MIE_VALUE_BLOCK); + + struct mie_value *block = MIE_VALUE(out); + + if (parent) { + block = mie_func_generate_value_name(parent, block, name); + if (!block) { + free(out); + return NULL; + } + + b_queue_push_back(&parent->f_blocks, &block->v_entry); + out->b_parent = parent; + } + + return out; +} + +bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr) +{ + switch (instr->i_type) { + case MIE_INSTR_PHI: + if (!b_queue_empty(&block->b_instr) || block->b_terminator) { + return false; + } + + b_queue_push_back(&block->b_phi, &instr->i_base.v_entry); + return true; + case MIE_INSTR_RET: + case MIE_INSTR_BR: + case MIE_INSTR_SWITCH: + if (block->b_terminator) { + return false; + } + + block->b_terminator = instr; + return true; + default: + if (block->b_terminator) { + return false; + } + + b_queue_push_back(&block->b_instr, &instr->i_base.v_entry); + return true; + } +} + +static void init_label_type(struct mie_type *out) +{ + mie_value_init(&out->t_base, MIE_VALUE_TYPE); + out->t_id = MIE_TYPE_LABEL; + out->t_width = sizeof(uintptr_t) * 8; +} + +static struct mie_type *get_type(struct mie_value *v) +{ + if (!label_type.t_id) { + init_label_type(&label_type); + } + + return &label_type; +} + +const struct mie_value_type block_value_type = { + .t_id = MIE_VALUE_BLOCK, + .t_get_type = get_type, +}; diff --git a/mie/builder.c b/mie/builder.c index b56dd1f..9ce241d 100644 --- a/mie/builder.c +++ b/mie/builder.c @@ -1,21 +1,41 @@ #include +#include +#include +#include #include #include +#include #include +#include +#include #include #include #include #include -struct ctx_cached_int { - struct mie_int i_val; +struct ctx_int_cache_entry { b_btree_node i_node; + struct mie_type i_type; + b_btree i_values; +}; + +struct ctx_int_value_cache_entry { + b_btree_node i_node; + struct mie_const i_value; }; B_BTREE_DEFINE_SIMPLE_INSERT( - struct ctx_cached_int, i_node, i_val.i_value, put_cached_int) + struct ctx_int_cache_entry, i_node, i_type.t_width, put_cached_int_type) B_BTREE_DEFINE_SIMPLE_GET( - struct ctx_cached_int, long long, i_node, i_val.i_value, get_cached_int) + struct ctx_int_cache_entry, unsigned int, i_node, i_type.t_width, + get_cached_int_type) + +B_BTREE_DEFINE_SIMPLE_INSERT( + struct ctx_int_value_cache_entry, i_node, i_value.c_v.v_int, + put_cached_int_value) +B_BTREE_DEFINE_SIMPLE_GET( + struct ctx_int_value_cache_entry, int64_t, i_node, i_value.c_v.v_int, + get_cached_int_value) struct mie_ctx *mie_ctx_create(void) { @@ -27,8 +47,8 @@ struct mie_ctx *mie_ctx_create(void) memset(out, 0x0, sizeof *out); - out->ctx_true = mie_int_create(1, 1); - out->ctx_false = mie_int_create(0, 1); + out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1)); + out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1)); return out; } @@ -36,52 +56,131 @@ struct mie_ctx *mie_ctx_create(void) void mie_ctx_destroy(struct mie_ctx *ctx) { if (ctx->ctx_true) { - mie_value_release(MIE_VALUE(ctx->ctx_true)); + mie_value_destroy(MIE_VALUE(ctx->ctx_true)); ctx->ctx_true = NULL; } if (ctx->ctx_false) { - mie_value_release(MIE_VALUE(ctx->ctx_false)); + mie_value_destroy(MIE_VALUE(ctx->ctx_false)); ctx->ctx_false = NULL; } b_btree_iterator it = {}; - b_btree_iterator_begin(&ctx->ctx_ints, &it); + b_btree_iterator_begin(&ctx->ctx_int_cache, &it); while (b_btree_iterator_is_valid(&it)) { - b_btree_node *node = it.node; + struct ctx_int_cache_entry *entry + = b_unbox(struct ctx_int_cache_entry, it.node, i_node); b_btree_iterator_erase(&it); - struct ctx_cached_int *entry - = b_unbox(struct ctx_cached_int, node, i_node); + b_btree_iterator it2 = {}; + b_btree_iterator_begin(&entry->i_values, &it2); + while (b_btree_iterator_is_valid(&it2)) { + struct ctx_int_value_cache_entry *value = b_unbox( + struct ctx_int_value_cache_entry, it2.node, i_node); + b_btree_iterator_erase(&it2); + free(value); + } + free(entry); } free(ctx); } +struct mie_type *mie_ctx_get_type(struct mie_ctx *ctx, enum mie_type_id type_id) +{ + if (type_id == MIE_TYPE_INT) { + return NULL; + } + + if (ctx->ctx_types[type_id]) { + return ctx->ctx_types[type_id]; + } + + struct mie_type *type = malloc(sizeof *type); + if (!type) { + return NULL; + } + + memset(type, 0x0, sizeof *type); + + mie_value_init(&type->t_base, MIE_VALUE_TYPE); + type->t_id = type_id; + + ctx->ctx_types[type_id] = type; + return type; +} + +struct mie_type *mie_ctx_get_int_type(struct mie_ctx *ctx, unsigned int nr_bits) +{ + struct ctx_int_cache_entry *entry + = get_cached_int_type(&ctx->ctx_int_cache, nr_bits); + + if (entry) { + return &entry->i_type; + } + + entry = malloc(sizeof *entry); + if (!entry) { + return NULL; + } + + memset(entry, 0x0, sizeof *entry); + + mie_value_init(&entry->i_type.t_base, MIE_VALUE_TYPE); + entry->i_type.t_id = MIE_TYPE_INT; + entry->i_type.t_width = nr_bits; + + put_cached_int_type(&ctx->ctx_int_cache, entry); + return &entry->i_type; +} + struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val) { return MIE_VALUE(val ? ctx->ctx_true : ctx->ctx_false); } -struct mie_value *mie_ctx_get_int(struct mie_ctx *ctx, long long val) +struct mie_value *mie_ctx_get_int( + struct mie_ctx *ctx, long long val, unsigned int nr_bits) { - struct ctx_cached_int *cache_entry = get_cached_int(&ctx->ctx_ints, val); - if (cache_entry) { - return MIE_VALUE(&cache_entry->i_val); + struct ctx_int_cache_entry *entry + = get_cached_int_type(&ctx->ctx_int_cache, nr_bits); + + if (!entry) { + entry = malloc(sizeof *entry); + if (!entry) { + return NULL; + } + + memset(entry, 0x0, sizeof *entry); + + mie_value_init(&entry->i_type.t_base, MIE_VALUE_TYPE); + entry->i_type.t_id = MIE_TYPE_INT; + entry->i_type.t_width = nr_bits; + + put_cached_int_type(&ctx->ctx_int_cache, entry); } - cache_entry = malloc(sizeof *cache_entry); - if (!cache_entry) { + struct ctx_int_value_cache_entry *value + = get_cached_int_value(&entry->i_values, val); + if (value) { + return MIE_VALUE(&value->i_value); + } + + value = malloc(sizeof *value); + if (!value) { return NULL; } - memset(cache_entry, 0x0, sizeof *cache_entry); + memset(value, 0x0, sizeof *value); - mie_int_init(&cache_entry->i_val, val, 32); - cache_entry->i_val.i_base.c_base.v_flags |= MIE_VALUE_F_STATIC; + mie_value_init(&value->i_value.c_base, MIE_VALUE_CONST); + value->i_value.c_type = &entry->i_type; + value->i_value.c_v.v_int = val; - return MIE_VALUE(&cache_entry->i_val); + put_cached_int_value(&entry->i_values, value); + + return MIE_VALUE(&value->i_value); } struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_module *mod) @@ -171,22 +270,64 @@ void mie_builder_set_insert_point( struct mie_value *mie_builder_ret(struct mie_builder *builder, struct mie_value *val) { + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + struct mie_ret *ret = malloc(sizeof *ret); if (!ret) { return NULL; } mie_instr_init(&ret->r_base, MIE_INSTR_RET); - ret->r_val = mie_value_retain(val); + ret->r_val = val; - return NULL; + if (!mie_block_add_instr(builder->b_current_block, &ret->r_base)) { + free(ret); + return NULL; + } + + return MIE_VALUE(ret); } struct mie_value *mie_builder_add( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_binary_op *add = malloc(sizeof *add); + if (!add) { + return NULL; + } + + memset(add, 0x0, sizeof *add); + + mie_instr_init(&add->op_base, MIE_INSTR_ADD); + + add->op_left = left; + add->op_right = right; + add->op_type = mie_value_get_type(left); + + if (!mie_block_add_instr(builder->b_current_block, &add->op_base)) { + free(add); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(add), name); + + return MIE_VALUE(add); } struct mie_value *mie_builder_sub( @@ -211,22 +352,93 @@ struct mie_value *mie_builder_div( } struct mie_value *mie_builder_load( - struct mie_builder *builder, struct mie_value *type, + struct mie_builder *builder, struct mie_type *type, struct mie_value *src, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_load *load = malloc(sizeof *load); + if (!load) { + return NULL; + } + + mie_instr_init(&load->l_base, MIE_INSTR_LOAD); + load->l_src = src; + load->l_type = type; + + if (!mie_block_add_instr(builder->b_current_block, &load->l_base)) { + free(load); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(load), name); + + return MIE_VALUE(load); } struct mie_value *mie_builder_store( struct mie_builder *builder, struct mie_value *val, struct mie_value *dest) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_store *store = malloc(sizeof *store); + if (!store) { + return NULL; + } + + mie_instr_init(&store->s_base, MIE_INSTR_STORE); + store->s_val = val; + store->s_dest = dest; + + if (!mie_block_add_instr(builder->b_current_block, &store->s_base)) { + free(store); + return NULL; + } + + return MIE_VALUE(store); } struct mie_value *mie_builder_alloca( struct mie_builder *builder, struct mie_type *type, const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_alloca *alloca = malloc(sizeof *alloca); + if (!alloca) { + return NULL; + } + + mie_instr_init(&alloca->a_base, MIE_INSTR_ALLOCA); + alloca->a_type = type; + + if (!mie_block_add_instr(builder->b_current_block, &alloca->a_base)) { + free(alloca); + return NULL; + } + + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(alloca), name); + + return MIE_VALUE(alloca); } struct mie_value *mie_builder_switch( @@ -239,7 +451,31 @@ struct mie_value *mie_builder_switch( struct mie_value *mie_builder_br(struct mie_builder *builder, struct mie_block *dest) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + struct mie_branch *br = malloc(sizeof *br); + if (!br) { + return NULL; + } + + memset(br, 0x0, sizeof *br); + + mie_instr_init(&br->b_base, MIE_INSTR_BR); + + br->b_dest = dest; + + if (!mie_block_add_instr(builder->b_current_block, &br->b_base)) { + free(br); + return NULL; + } + + return MIE_VALUE(br); } struct mie_value *mie_builder_br_if( diff --git a/mie/const.c b/mie/const.c index b4b3409..c4a50ab 100644 --- a/mie/const.c +++ b/mie/const.c @@ -2,25 +2,13 @@ #include #include -void mie_int_init(struct mie_int *out, long long val, unsigned int nr_bits) +static struct mie_type *get_type(struct mie_value *v) { - memset(out, 0x0, sizeof *out); - - mie_value_init(&out->i_base.c_base, MIE_VALUE_CONST); - - out->i_base.c_type = MIE_CONST_INT; - out->i_value = val; - out->i_width = nr_bits; + struct mie_const *c = MIE_CONST(v); + return c->c_type; } -struct mie_int *mie_int_create(long long val, unsigned int nr_bits) -{ - struct mie_int *out = malloc(sizeof *out); - - if (!out) { - return NULL; - } - - mie_int_init(out, val, nr_bits); - return out; -} +const struct mie_value_type const_value_type = { + .t_id = MIE_VALUE_CONST, + .t_get_type = get_type, +}; diff --git a/mie/func.c b/mie/func.c new file mode 100644 index 0000000..a49a873 --- /dev/null +++ b/mie/func.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include + +struct mie_func *mie_func_create( + const char *name, enum mie_func_type type, struct mie_type *ret_type, + struct mie_arg **args, unsigned int nr_args) +{ + struct mie_func *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + mie_value_init(&out->f_base, MIE_VALUE_FUNC); + + out->f_base.v_name.n_str = b_strdup(name); + out->f_base.v_name.n_base.e_hash = b_hash_string(name); + + out->f_type = type; + out->f_ret = ret_type; + out->f_names = mie_name_map_create(); + + for (size_t i = 0; i < nr_args; i++) { + if (args[i]) { + struct mie_value *arg_value = MIE_VALUE(args[i]); + b_queue_push_back(&out->f_args, &arg_value->v_entry); + } + } + + return out; +} + +struct mie_block *mie_func_create_block(struct mie_func *func, const char *name) +{ + struct mie_block *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + mie_value_init(&out->b_base, MIE_VALUE_BLOCK); + + struct mie_value *block = MIE_VALUE(out); + + block = mie_func_generate_value_name(func, block, name); + if (!block) { + free(out); + return NULL; + } + + out->b_parent = func; + + return out; +} + +void mie_func_insert_block( + struct mie_func *func, struct mie_block *block, struct mie_block *after) +{ + if (after) { + b_queue_insert_after( + &func->f_blocks, &block->b_base.v_entry, + &after->b_base.v_entry); + } else { + b_queue_push_back(&func->f_blocks, &block->b_base.v_entry); + } +} + +struct mie_value *mie_func_generate_value_name( + struct mie_func *func, struct mie_value *val, const char *hint) +{ + struct mie_name *name + = mie_name_map_put(func->f_names, &val->v_name, hint); + return b_unbox(struct mie_value, name, v_name); +} + +static struct mie_type *get_type(struct mie_value *v) +{ + struct mie_func *f = MIE_FUNC(v); + return f->f_ret; +} + +const struct mie_value_type func_value_type = { + .t_id = MIE_VALUE_FUNC, + .t_get_type = get_type, +}; diff --git a/mie/include/mie/arg.h b/mie/include/mie/arg.h new file mode 100644 index 0000000..803484f --- /dev/null +++ b/mie/include/mie/arg.h @@ -0,0 +1,13 @@ +#ifndef MIE_ARG_H_ +#define MIE_ARG_H_ + +#include + +#define MIE_ARG(p) ((struct mie_arg *)(p)) + +struct mie_arg { + struct mie_value arg_base; + struct mie_type *arg_type; +}; + +#endif diff --git a/mie/include/mie/block.h b/mie/include/mie/block.h index 0d6c69d..0db719a 100644 --- a/mie/include/mie/block.h +++ b/mie/include/mie/block.h @@ -1,10 +1,13 @@ #ifndef MIE_BLOCK_H_ #define MIE_BLOCK_H_ +#define MIE_BLOCK(p) ((struct mie_block *)(p)) + #include struct mie_block { struct mie_value b_base; + struct mie_func *b_parent; /* the phi instruction(s). these must appear at the start of the block * and are separated to make traversing the CFG easier */ b_queue b_phi; @@ -15,4 +18,8 @@ struct mie_block { struct mie_instr *b_terminator; }; +MIE_API struct mie_block *mie_block_create( + struct mie_func *parent, const char *name); +MIE_API bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr); + #endif diff --git a/mie/include/mie/branch.h b/mie/include/mie/branch.h index ced504d..32927f3 100644 --- a/mie/include/mie/branch.h +++ b/mie/include/mie/branch.h @@ -6,7 +6,7 @@ struct mie_branch { struct mie_instr b_base; - struct mie_label *b_dest; + struct mie_block *b_dest; }; struct mie_branch_if { diff --git a/mie/include/mie/builder.h b/mie/include/mie/builder.h index 5d62c9b..ad257c5 100644 --- a/mie/include/mie/builder.h +++ b/mie/include/mie/builder.h @@ -4,6 +4,7 @@ #include #include #include +#include #include struct b_dict; @@ -15,22 +16,28 @@ struct mie_type; struct mie_phi; struct mie_ctx { - struct mie_int *ctx_true, *ctx_false; - b_btree ctx_ints; + struct mie_const *ctx_true, *ctx_false; + struct mie_type *ctx_types[__MIE_TYPE_COUNT]; + b_btree ctx_int_cache; }; struct mie_builder { struct mie_ctx *b_ctx; struct mie_module *b_module; - struct mie_instr *b_prev_instr; struct mie_block *b_current_block; + struct mie_instr *b_prev_instr; }; extern struct mie_ctx *mie_ctx_create(void); extern void mie_ctx_destroy(struct mie_ctx *ctx); +extern struct mie_type *mie_ctx_get_type( + struct mie_ctx *ctx, enum mie_type_id type_id); +extern struct mie_type *mie_ctx_get_int_type( + struct mie_ctx *ctx, unsigned int nr_bits); extern struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val); -extern struct mie_value *mie_ctx_get_int(struct mie_ctx *ctx, long long val); +extern struct mie_value *mie_ctx_get_int( + struct mie_ctx *ctx, long long val, unsigned int nr_bits); extern struct mie_builder *mie_builder_create( struct mie_ctx *ctx, struct mie_module *mod); @@ -58,7 +65,7 @@ extern struct mie_value *mie_builder_div( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name); extern struct mie_value *mie_builder_load( - struct mie_builder *builder, struct mie_value *type, + struct mie_builder *builder, struct mie_type *type, struct mie_value *src, const char *name); extern struct mie_value *mie_builder_store( struct mie_builder *builder, struct mie_value *val, struct mie_value *dest); diff --git a/mie/include/mie/const.h b/mie/include/mie/const.h index b17c202..1b98d0e 100644 --- a/mie/include/mie/const.h +++ b/mie/include/mie/const.h @@ -3,54 +3,18 @@ #include -enum mie_const_type { - MIE_CONST_NONE = 0, - MIE_CONST_INT, - MIE_CONST_FLOAT, - MIE_CONST_STRING, - MIE_CONST_ATOM, - MIE_CONST_LABEL, - MIE_CONST_ARRAY, -}; +#define MIE_CONST(p) ((struct mie_const *)(p)) struct mie_const { struct mie_value c_base; - enum mie_const_type c_type; -}; + struct mie_type *c_type; -struct mie_int { - struct mie_const i_base; - unsigned short i_width; - long long i_value; + union { + int64_t v_int; + double v_float; + char *v_str; + char *v_atom; + } c_v; }; -struct mie_float { - struct mie_const f_base; - double f_value; -}; - -struct mie_str { - struct mie_const s_base; - char *s_value; -}; - -struct mie_atom { - struct mie_const s_base; - char *s_value; -}; - -struct mie_label { - struct mie_const l_base; - char *l_value; -}; - -struct mie_array { - struct mie_const a_base; - unsigned int a_nr_values; - struct mie_value **a_values; -}; - -extern void mie_int_init(struct mie_int *out, long long val, unsigned int nr_bits); -extern struct mie_int *mie_int_create(long long val, unsigned int nr_bits); - #endif diff --git a/mie/include/mie/func.h b/mie/include/mie/func.h index 59e2d28..cebe9c1 100644 --- a/mie/include/mie/func.h +++ b/mie/include/mie/func.h @@ -1,10 +1,14 @@ #ifndef MIE_FUNC_H_ #define MIE_FUNC_H_ +#define MIE_FUNC(p) ((struct mie_func *)(p)) + #include +struct mie_name_map; struct mie_type; struct mie_arg; +struct mie_block; struct b_dict; enum mie_func_type { @@ -17,11 +21,11 @@ enum mie_func_type { struct mie_func { struct mie_value f_base; - struct b_dict *f_named_values; enum mie_func_type f_type; - struct mie_type *f_ret; + struct mie_name_map *f_names; + b_queue f_args; b_queue f_blocks; }; @@ -29,7 +33,11 @@ struct mie_func { extern struct mie_func *mie_func_create( const char *name, enum mie_func_type type, struct mie_type *ret_type, struct mie_arg **args, unsigned int nr_args); -extern char *mie_func_generate_value_name( - struct mie_func *func, const char *name_hint); +extern struct mie_block *mie_func_create_block( + struct mie_func *func, const char *name); +extern void mie_func_insert_block( + struct mie_func *func, struct mie_block *block, struct mie_block *after); +extern struct mie_value *mie_func_generate_value_name( + struct mie_func *func, struct mie_value *val, const char *hint); #endif diff --git a/mie/include/mie/instr.h b/mie/include/mie/instr.h index fcb58ed..937eb45 100644 --- a/mie/include/mie/instr.h +++ b/mie/include/mie/instr.h @@ -3,6 +3,8 @@ #include +#define MIE_INSTR(p) ((struct mie_instr *)(p)) + enum mie_instr_type { MIE_INSTR_NONE = 0, MIE_INSTR_RET, diff --git a/mie/include/mie/module.h b/mie/include/mie/module.h index 6b7f23e..041e3b8 100644 --- a/mie/include/mie/module.h +++ b/mie/include/mie/module.h @@ -1,9 +1,13 @@ #ifndef MIE_MODULE_H_ #define MIE_MODULE_H_ +#define MIE_MODULE(p) ((struct mie_module *)(p)) + #include #include +struct mie_func; + struct mie_module { struct mie_value m_base; b_queue m_records; @@ -12,4 +16,7 @@ struct mie_module { b_queue m_func; }; +extern struct mie_module *mie_module_create(void); +extern void mie_module_add_function(struct mie_module *mod, struct mie_func *func); + #endif diff --git a/mie/include/mie/record.h b/mie/include/mie/record.h index aecdcdb..5dde197 100644 --- a/mie/include/mie/record.h +++ b/mie/include/mie/record.h @@ -1,6 +1,8 @@ #ifndef MIE_RECORD_H_ #define MIE_RECORD_H_ +#define MIE_RECORD(p) ((struct mie_record *)(p)) + #include #include diff --git a/mie/include/mie/type.h b/mie/include/mie/type.h index 346530f..e41291b 100644 --- a/mie/include/mie/type.h +++ b/mie/include/mie/type.h @@ -1,15 +1,21 @@ #ifndef MIE_TYPE_H_ #define MIE_TYPE_H_ +#define MIE_TYPE(p) ((struct mie_type *)(p)) + #include enum mie_type_id { MIE_TYPE_VOID = 0x00u, MIE_TYPE_INT = 0x01u, - MIE_TYPE_ID = 0x02u, - MIE_TYPE_STR = 0x03u, - MIE_TYPE_SYM = 0x04u, - MIE_TYPE_CLASS = 0x05u, + MIE_TYPE_PTR = 0x02u, + MIE_TYPE_ID = 0x03u, + MIE_TYPE_STR = 0x04u, + MIE_TYPE_ATOM = 0x05u, + MIE_TYPE_CLASS = 0x06u, + MIE_TYPE_ARRAY = 0x08u, + MIE_TYPE_LABEL = 0x09u, + __MIE_TYPE_COUNT, }; struct mie_type { diff --git a/mie/include/mie/value.h b/mie/include/mie/value.h index 7f62296..0edf8d0 100644 --- a/mie/include/mie/value.h +++ b/mie/include/mie/value.h @@ -7,14 +7,18 @@ #define MIE_VALUE(p) ((struct mie_value *)(p)) -enum mie_value_type { +struct mie_value; + +enum mie_value_type_id { MIE_VALUE_NONE = 0, - MIE_VALUE_CONST, + MIE_VALUE_MODULE, + MIE_VALUE_TYPE, + MIE_VALUE_RECORD, + MIE_VALUE_FUNC, MIE_VALUE_ARG, MIE_VALUE_BLOCK, MIE_VALUE_INSTR, - MIE_VALUE_OP, - MIE_VALUE_RECORD, + MIE_VALUE_CONST, }; enum mie_value_flags { @@ -22,16 +26,31 @@ enum mie_value_flags { MIE_VALUE_F_STATIC = 0x01u, }; +struct mie_value_type { + enum mie_value_type_id t_id; + struct mie_type *(*t_get_type)(struct mie_value *); +}; + struct mie_value { - unsigned int v_ref; struct mie_name v_name; - enum mie_value_type v_type; + const struct mie_value_type *v_type; enum mie_value_flags v_flags; b_queue_entry v_entry; }; -MIE_API void mie_value_init(struct mie_value *val, enum mie_value_type type); -MIE_API struct mie_value *mie_value_retain(struct mie_value *val); -MIE_API void mie_value_release(struct mie_value *val); +MIE_API void mie_value_init(struct mie_value *val, enum mie_value_type_id type); +MIE_API void mie_value_destroy(struct mie_value *val); + +MIE_API struct mie_type *mie_value_get_type(struct mie_value *val); + +static inline bool mie_value_is( + const struct mie_value *val, enum mie_value_type_id type_id) +{ + if (!val->v_type) { + return false; + } + + return val->v_type->t_id == type_id; +} #endif diff --git a/mie/instr.c b/mie/instr.c index 78b160f..8bfd49e 100644 --- a/mie/instr.c +++ b/mie/instr.c @@ -1,4 +1,8 @@ #include +#include +#include + +static struct mie_type ptr_type = {}; void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type) { @@ -6,3 +10,46 @@ void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type) mie_value_init(&instr->i_base, MIE_VALUE_INSTR); instr->i_type = type; } + +static void init_ptr_type(struct mie_type *out) +{ + mie_value_init(&out->t_base, MIE_VALUE_TYPE); + out->t_id = MIE_TYPE_PTR; + out->t_width = sizeof(uintptr_t) * 8; +} + +static struct mie_type *get_type(struct mie_value *v) +{ + struct mie_instr *instr = MIE_INSTR(v); + + if (!ptr_type.t_id) { + init_ptr_type(&ptr_type); + } + + switch (instr->i_type) { + case MIE_INSTR_RET: { + struct mie_ret *ret = (struct mie_ret *)instr; + return mie_value_get_type(ret->r_val); + } + case MIE_INSTR_ADD: + case MIE_INSTR_SUB: + case MIE_INSTR_MUL: + case MIE_INSTR_DIV: { + struct mie_binary_op *op = (struct mie_binary_op *)instr; + return op->op_type; + } + case MIE_INSTR_LOAD: { + struct mie_load *load = (struct mie_load *)instr; + return load->l_type; + } + case MIE_INSTR_ALLOCA: + return &ptr_type; + default: + return NULL; + } +} + +const struct mie_value_type instr_value_type = { + .t_id = MIE_VALUE_INSTR, + .t_get_type = get_type, +}; diff --git a/mie/module.c b/mie/module.c new file mode 100644 index 0000000..dd5498e --- /dev/null +++ b/mie/module.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +struct mie_module *mie_module_create(void) +{ + struct mie_module *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + mie_value_init(&out->m_base, MIE_VALUE_MODULE); + + return out; +} + +void mie_module_add_function(struct mie_module *mod, struct mie_func *func) +{ + b_queue_push_back(&mod->m_func, &func->f_base.v_entry); +} + +const struct mie_value_type module_value_type = { + .t_id = MIE_VALUE_MODULE, +}; diff --git a/mie/record.c b/mie/record.c index efeff2f..be4d19b 100644 --- a/mie/record.c +++ b/mie/record.c @@ -13,7 +13,17 @@ struct mie_record *mie_record_create(const struct mie_const *val) mie_value_init(&out->r_base, MIE_VALUE_RECORD); out->r_value = val; - mie_value_retain(MIE_VALUE(out->r_value)); return out; } + +static struct mie_type *get_type(struct mie_value *v) +{ + struct mie_record *r = MIE_RECORD(v); + return r->r_value->c_type; +} + +const struct mie_value_type record_value_type = { + .t_id = MIE_VALUE_RECORD, + .t_get_type = get_type, +}; diff --git a/mie/type.c b/mie/type.c new file mode 100644 index 0000000..f1724bb --- /dev/null +++ b/mie/type.c @@ -0,0 +1,11 @@ +#include + +static struct mie_type *get_type(struct mie_value *v) +{ + return MIE_TYPE(v); +} + +const struct mie_value_type type_value_type = { + .t_id = MIE_VALUE_TYPE, + .t_get_type = get_type, +}; diff --git a/mie/value.c b/mie/value.c index 5367626..0ff1a28 100644 --- a/mie/value.c +++ b/mie/value.c @@ -1,25 +1,45 @@ +#include #include -void mie_value_init(struct mie_value *val, enum mie_value_type type) +extern const struct mie_value_type module_value_type; +extern const struct mie_value_type type_value_type; +extern const struct mie_value_type record_value_type; +extern const struct mie_value_type func_value_type; +extern const struct mie_value_type arg_value_type; +extern const struct mie_value_type block_value_type; +extern const struct mie_value_type instr_value_type; +extern const struct mie_value_type const_value_type; + +static const struct mie_value_type *value_types[] = { + [MIE_VALUE_NONE] = NULL, + [MIE_VALUE_MODULE] = &module_value_type, + [MIE_VALUE_TYPE] = &type_value_type, + [MIE_VALUE_RECORD] = &record_value_type, + [MIE_VALUE_FUNC] = &func_value_type, + [MIE_VALUE_ARG] = &arg_value_type, + [MIE_VALUE_BLOCK] = &block_value_type, + [MIE_VALUE_INSTR] = &instr_value_type, + [MIE_VALUE_CONST] = &const_value_type, +}; +static const size_t nr_value_types = sizeof value_types / sizeof value_types[0]; + +void mie_value_init(struct mie_value *val, enum mie_value_type_id type) { memset(val, 0x0, sizeof *val); - val->v_ref = 1; - val->v_type = type; + val->v_type = value_types[type]; } -struct mie_value *mie_value_retain(struct mie_value *val) +void mie_value_destroy(struct mie_value *val) { - val->v_ref++; - return val; -} - -void mie_value_release(struct mie_value *val) -{ - if (val->v_ref > 1) { - val->v_ref--; - return; - } - /* TODO cleanup value */ } + +struct mie_type *mie_value_get_type(struct mie_value *val) +{ + if (val->v_type->t_get_type) { + return val->v_type->t_get_type(val); + } + + return NULL; +}