#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } struct mie_func *mie_builder_get_current_func(struct mie_builder *builder) { struct mie_block *block = builder->b_current_block; if (!block) { return NULL; } return block->b_parent; } struct mie_record *mie_builder_put_record( struct mie_builder *builder, struct mie_const *val, const char *name) { if (!builder->b_module) { return NULL; } 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)) { /* TODO what to do about `val` here? */ return MIE_RECORD(rec); } } 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); return rec; } struct mie_record *mie_builder_get_record( struct mie_builder *builder, const char *name) { if (!builder->b_module) { return NULL; } 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 MIE_RECORD(rec); } } return NULL; } #if 0 void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data) { if (!builder->b_module) { return; } const char *data_name = data->d_base.v_name.n_str; struct mie_data *v = mie_module_get_data(builder->b_module, data_name); if (v) { return; } mie_module_put_data(builder->b_module, data); } #endif #if 0 void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type) { if (!builder->b_module) { return; } const char *type_name = type->t_base.v_name.n_str; struct mie_data *v = mie_module_get_data(builder->b_module, type_name); if (v) { return; } mie_module_put_data(builder->b_module, MIE_VALUE); } #endif void mie_builder_set_insert_point( struct mie_builder *builder, struct mie_block *block) { builder->b_current_block = block; } struct mie_value *mie_builder_get_data_ptr( struct mie_builder *builder, const char *data_ident) { if (!builder->b_module) { return NULL; } struct mie_data *data = mie_module_get_data(builder->b_module, data_ident); if (!data) { struct mie_type *id = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_ID); data = mie_data_create_extern_global(id, data_ident); if (!data) { return NULL; } mie_module_put_data(builder->b_module, data, data_ident); } return MIE_VALUE(data); } struct mie_value *mie_builder_get_string_ptr( struct mie_builder *builder, const char *s) { if (!builder->b_module) { return NULL; } struct mie_data *data = mie_module_get_string_ptr(builder->b_module, s); if (!data) { struct mie_type *str = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_STR); struct mie_value *value = mie_ctx_get_string(builder->b_ctx, s); data = mie_data_create_const((struct mie_const *)value); if (!data) { return NULL; } mie_module_put_data(builder->b_module, data, ".str"); } return MIE_VALUE(data); } 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) { if (!builder->b_current_block) { return NULL; } if (builder->b_current_block->b_terminator) { return NULL; } struct mie_binary_op *sub = malloc(sizeof *sub); if (!sub) { return NULL; } memset(sub, 0x0, sizeof *sub); mie_instr_init(&sub->op_base, MIE_INSTR_SUB); sub->op_left = left; sub->op_right = right; sub->op_type = mie_value_get_type(left); if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) { free(sub); return NULL; } mie_func_generate_value_name( builder->b_current_block->b_parent, MIE_VALUE(sub), name); return MIE_VALUE(sub); } struct mie_value *mie_builder_mul( 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 *mul = malloc(sizeof *mul); if (!mul) { return NULL; } memset(mul, 0x0, sizeof *mul); mie_instr_init(&mul->op_base, MIE_INSTR_MUL); mul->op_left = left; mul->op_right = right; mul->op_type = mie_value_get_type(left); if (!mie_block_add_instr(builder->b_current_block, &mul->op_base)) { free(mul); return NULL; } mie_func_generate_value_name( builder->b_current_block->b_parent, MIE_VALUE(mul), name); return MIE_VALUE(mul); } struct mie_value *mie_builder_div( 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 *div = malloc(sizeof *div); if (!div) { return NULL; } memset(div, 0x0, sizeof *div); mie_instr_init(&div->op_base, MIE_INSTR_DIV); div->op_left = left; div->op_right = right; div->op_type = mie_value_get_type(left); if (!mie_block_add_instr(builder->b_current_block, &div->op_base)) { free(div); return NULL; } mie_func_generate_value_name( builder->b_current_block->b_parent, MIE_VALUE(div), name); return MIE_VALUE(div); } 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_type *ret_type, struct mie_value *recipient, struct mie_value *selector, struct mie_value **args, size_t nr_args, enum mie_builder_flags flags, const char *name) { if (!builder->b_current_block) { return NULL; } if (builder->b_current_block->b_terminator) { return NULL; } if ((flags & MIE_BUILDER_IGNORE_RESULT) && name) { return NULL; } struct mie_msg *msg = malloc(sizeof *msg); if (!msg) { return NULL; } memset(msg, 0x0, sizeof *msg); mie_instr_init(&msg->msg_base, MIE_INSTR_MSG); msg->msg_ret_type = ret_type; msg->msg_recipient = recipient; msg->msg_selector = selector; msg->msg_nr_args = nr_args; msg->msg_args = calloc(nr_args, sizeof(struct mie_value *)); memcpy(msg->msg_args, args, nr_args * sizeof(struct mie_value *)); if (!mie_block_add_instr(builder->b_current_block, &msg->msg_base)) { free(msg); return NULL; } if (!(flags & MIE_BUILDER_IGNORE_RESULT)) { mie_func_generate_value_name( builder->b_current_block->b_parent, MIE_VALUE(msg), name); } return MIE_VALUE(msg); } 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; }