2025-04-13 18:34:02 +01:00
|
|
|
#include <mie/block.h>
|
|
|
|
|
#include <mie/func.h>
|
|
|
|
|
#include <mie/instr.h>
|
|
|
|
|
#include <mie/type.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 19:25:23 +01:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
const struct mie_value_type block_value_type = {
|
|
|
|
|
.t_id = MIE_VALUE_BLOCK,
|
|
|
|
|
.t_get_type = get_type,
|
2025-04-13 19:25:23 +01:00
|
|
|
.t_cleanup = cleanup,
|
2025-04-13 18:34:02 +01:00
|
|
|
};
|