#include #include #include #include #include #include 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 struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx) { return mie_ctx_get_type(ctx, MIE_TYPE_LABEL); } static void cleanup(struct mie_value *value) { struct mie_block *block = MIE_BLOCK(value); b_queue_iterator it; b_queue_iterator_begin(&block->b_phi, &it); while (b_queue_iterator_is_valid(&it)) { struct mie_value *v = b_unbox(struct mie_value, it.entry, v_entry); b_queue_iterator_erase(&it); mie_value_destroy(v); } b_queue_iterator_begin(&block->b_instr, &it); while (b_queue_iterator_is_valid(&it)) { struct mie_value *v = b_unbox(struct mie_value, it.entry, v_entry); b_queue_iterator_erase(&it); mie_value_destroy(v); } if (block->b_terminator) { mie_value_destroy(MIE_VALUE(block->b_terminator)); } } const struct mie_value_type block_value_type = { .t_id = MIE_VALUE_BLOCK, .t_get_type = get_type, .t_cleanup = cleanup, };