#include #include #include #include #include #include #include #include #include #include #include #include #include #include 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_int_cache_entry, i_node, i_type.t_width, put_cached_int_type) B_BTREE_DEFINE_SIMPLE_GET( 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) { struct mie_ctx *out = malloc(sizeof *out); if (!out) { return NULL; } memset(out, 0x0, sizeof *out); 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; } void mie_ctx_destroy(struct mie_ctx *ctx) { ctx->ctx_true = NULL; ctx->ctx_false = NULL; b_btree_iterator it = {}; b_btree_iterator_begin(&ctx->ctx_int_cache, &it); while (b_btree_iterator_is_valid(&it)) { struct ctx_int_cache_entry *entry = b_unbox(struct ctx_int_cache_entry, it.node, i_node); b_btree_iterator_erase(&it); 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); } const size_t nr_types = sizeof ctx->ctx_types / sizeof ctx->ctx_types[0]; for (size_t i = 0; i < nr_types; i++) { mie_value_destroy(MIE_VALUE(ctx->ctx_types[i])); ctx->ctx_types[i] = NULL; } 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, unsigned int nr_bits) { 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); } 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(value, 0x0, sizeof *value); 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; 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) { struct mie_builder *out = malloc(sizeof *out); if (!out) { return NULL; } memset(out, 0x0, sizeof *out); out->b_ctx = ctx; out->b_module = mod; return out; } void mie_builder_destroy(struct mie_builder *builder) { free(builder); } void mie_builder_put_record( struct mie_builder *builder, struct mie_const *val, const char *name) { if (!builder->b_module) { return; } b_queue_iterator it = {}; b_queue_foreach (&it, &builder->b_module->m_records) { struct mie_value *rec = b_unbox(struct mie_value, it.entry, v_entry); if (!strcmp(rec->v_name.n_str, name)) { return; } } struct mie_record *rec = mie_record_create(val); rec->r_base.v_name.n_str = b_strdup(name); b_queue_push_back(&builder->b_module->m_records, &rec->r_base.v_entry); } void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data) { if (!builder->b_module) { return; } b_queue_iterator it = {}; b_queue_foreach (&it, &builder->b_module->m_data) { struct mie_value *cur = b_unbox(struct mie_value, it.entry, v_entry); if (!strcmp(cur->v_name.n_str, data->d_base.v_name.n_str)) { return; } } b_queue_push_back(&builder->b_module->m_data, &data->d_base.v_entry); } void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type) { if (!builder->b_module) { return; } b_queue_iterator it = {}; b_queue_foreach (&it, &builder->b_module->m_types) { struct mie_value *cur = b_unbox(struct mie_value, it.entry, v_entry); if (!strcmp(cur->v_name.n_str, type->t_base.v_name.n_str)) { return; } } b_queue_push_back(&builder->b_module->m_data, &type->t_base.v_entry); } void mie_builder_set_insert_point( struct mie_builder *builder, struct mie_block *block) { builder->b_current_block = block; } 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 = val; 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) { 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( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_mul( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_div( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_load( struct mie_builder *builder, struct mie_type *type, struct mie_value *src, const char *name) { 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) { 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) { 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( struct mie_builder *builder, struct mie_value *cond, struct mie_switch_branch *branches, size_t nr_branches, struct mie_block *default_block) { return NULL; } struct mie_value *mie_builder_br(struct mie_builder *builder, struct mie_block *dest) { 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( struct mie_builder *builder, struct mie_value *cond, struct mie_block *if_true, struct mie_block *if_false) { return NULL; } struct mie_value *mie_builder_msg( struct mie_builder *builder, struct mie_value *ret_type, struct mie_value *dest, struct mie_value *src, const char *name) { return NULL; } struct mie_value *mie_builder_cmp_eq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_cmp_lt( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_cmp_gt( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_cmp_leq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_cmp_geq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name) { return NULL; } struct mie_value *mie_builder_getelementptr( struct mie_builder *builder, struct mie_type *container_type, struct mie_value *container, struct mie_value *index, const char *name) { return NULL; } struct mie_value *mie_builder_setelementptr( struct mie_builder *builder, struct mie_type *container_type, struct mie_value *container, struct mie_value *index) { return NULL; } struct mie_phi *mie_builder_phi( struct mie_builder *builder, struct mie_type *type, unsigned int nr_edges, const char *name) { return NULL; }