mie: re-implement vectors of blocks and registers using vector move callbacks

vector move callbacks allow mie_name instances to be stored in movable memory,
as the internal bst pointers can now be fixed during vector resize operations.
This commit is contained in:
2026-01-18 22:58:17 +00:00
parent 759aaf9fd8
commit 55161cd6c8
17 changed files with 122 additions and 45 deletions

View File

@@ -14,7 +14,7 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o
const struct mie_op_arg *left = &op->op_args.items[0];
const struct mie_op_arg *right = &op->op_args.items[1];
const struct mie_register *result = op->op_result.items[0];
const struct mie_register *result = &op->op_result.items[0];
const struct mie_attribute *pred_attr
= mie_attribute_map_get(&op->op_attrib, "predicate");
long long pred;

View File

@@ -27,14 +27,14 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o
b_stream_write_fmt(printer->p_stream, NULL, " @%s(", sym_name_cstr);
const struct mie_region *code = &op->op_regions.items[0];
const struct mie_block *entry = code->r_blocks.items[0];
const struct mie_block *entry = &code->r_blocks.items[0];
for (size_t i = 0; i < MIE_VECTOR_COUNT(entry->b_params); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
const struct mie_register *param = entry->b_params.items[i];
const struct mie_register *param = &entry->b_params.items[i];
mie_printer_print_register(printer, param, MIE_PRINT_F_INCLUDE_TYPE);
}

View File

@@ -12,10 +12,12 @@ struct mie_register;
struct mie_block {
struct mie_name b_name;
MIE_VECTOR_DECLARE(struct mie_register *, b_params);
MIE_VECTOR_DECLARE(struct mie_register, b_params);
MIE_VECTOR_DECLARE(struct mie_op, b_ops);
};
extern struct mie_vector_ops mie_block_vector_ops;
MIE_API struct mie_op *mie_block_add_op(struct mie_block *block);
#endif

View File

@@ -63,7 +63,7 @@ struct mie_op {
MIE_VECTOR_DECLARE(struct mie_op_successor, op_successors);
struct mie_attribute_map op_attrib;
MIE_VECTOR_DECLARE(struct mie_op_arg, op_args);
MIE_VECTOR_DECLARE(struct mie_register *, op_result);
MIE_VECTOR_DECLARE(struct mie_register, op_result);
};
MIE_API struct mie_op *mie_op_create(void);

View File

@@ -9,7 +9,7 @@ struct mie_block;
struct mie_region {
struct mie_name_map *r_names;
MIE_VECTOR_DECLARE(struct mie_block *, r_blocks);
MIE_VECTOR_DECLARE(struct mie_block, r_blocks);
};
MIE_API struct mie_block *mie_region_add_block(struct mie_region *region);

View File

@@ -2,6 +2,7 @@
#define MIE_IR_REGISTER_H_
#include <mie/name.h>
#include <mie/vector.h>
struct mie_target_register;
@@ -48,4 +49,9 @@ struct mie_register {
struct mie_op *reg_op;
};
extern struct mie_vector_ops mie_register_vector_ops;
MIE_API void mie_register_move(struct mie_register *dest, struct mie_register *src);
MIE_API void mie_register_cleanup(struct mie_register *reg);
#endif

View File

@@ -35,16 +35,26 @@ struct mie_name_map_entry {
};
};
struct mie_name_bucket {
struct mie_name_map_entry b_base;
b_queue b_names;
};
/* stores a unique name, and forms a binary tree of similar entries.
* this struct is designed to be embedded directly within a larger struct
* (rather than just as a pointer), allowing the larger struct to be part
* of a name map. Because of this, mie_name CANNOT be used in any memory that
* may be re-allocated. If a mie_name is moved after it is added to a
* mie_name_map, the internal bst pointers that make up the map will be
* invalidated, causing some very obscure memory-related errors. */
* invalidated, causing some very obscure memory-related errors.
*
* if mie_name IS stored in movable memory, care must be taken to use
* mie_name_move rather than memcpy/memmove to move the mie_name from
* one location to another. */
struct mie_name {
struct mie_name_map_entry n_base;
struct mie_name_map *n_parent;
struct mie_name_bucket *n_bucket;
char *n_str;
/* if this name was read from a file, these structs can be used to
@@ -52,11 +62,6 @@ struct mie_name {
struct mie_file_span n_start, n_end;
};
struct mie_name_bucket {
struct mie_name_map_entry b_base;
b_queue b_names;
};
struct mie_name_map {
const struct mie_name_map *m_parent;
b_btree m_entries;
@@ -73,6 +78,7 @@ extern struct mie_name *mie_name_map_put(
struct mie_name_map *map, struct mie_name *entry, const char *hint,
enum mie_name_map_flags flags);
extern void mie_name_move(struct mie_name *dst, struct mie_name *src);
extern void mie_name_destroy(struct mie_name *name);
#endif

View File

@@ -102,7 +102,7 @@ MIE_API bool mie_parser_parse_register(
struct mie_register *out);
MIE_API bool mie_parser_parse_register_list(
struct mie_parser *ctx, struct mie_name_map *names,
MIE_VECTOR_REF_PARAM(struct mie_register *, out));
MIE_VECTOR_REF_PARAM(struct mie_register, out));
MIE_API bool mie_parser_parse_region(
struct mie_parser *ctx, struct mie_region *region);

View File

@@ -5,14 +5,5 @@
struct mie_block *mie_region_add_block(struct mie_region *region)
{
struct mie_block *block = malloc(sizeof *block);
if (!block) {
return NULL;
}
memset(block, 0x0, sizeof *block);
mie_vector_push_back(region->r_blocks, &block, NULL);
return block;
return mie_vector_emplace_back(region->r_blocks, &mie_block_vector_ops);
}

37
mie/ir/register.c Normal file
View File

@@ -0,0 +1,37 @@
#include <assert.h>
#include <mie/ir/register.h>
static enum mie_status cleanup(void *p)
{
mie_register_cleanup(p);
return MIE_SUCCESS;
}
static enum mie_status move(void *dst, void *src, size_t itemsz)
{
assert(itemsz == sizeof(struct mie_register));
struct mie_register *dest_reg = dst, *src_reg = src;
mie_register_move(dest_reg, src_reg);
return MIE_SUCCESS;
}
struct mie_vector_ops mie_register_vector_ops = {
.v_destroy = cleanup,
.v_move = move,
};
void mie_register_move(struct mie_register *dest, struct mie_register *src)
{
memmove(dest, src, sizeof *dest);
if (src->reg_flags & MIE_REGISTER_F_VIRTUAL) {
mie_name_move(&dest->reg_name, &src->reg_name);
}
}
void mie_register_cleanup(struct mie_register *reg)
{
if (reg->reg_flags & MIE_REGISTER_F_VIRTUAL) {
mie_name_destroy(&reg->reg_name);
}
}

View File

@@ -163,7 +163,7 @@ static enum mie_status schedule_children_of_region(
b_queue_entry *tmp = &item->i_entry;
for (size_t i = 0; i < MIE_VECTOR_COUNT(region->r_blocks); i++) {
struct mie_block *block = region->r_blocks.items[i];
struct mie_block *block = &region->r_blocks.items[i];
struct walk_schedule_item *child
= block_schedule_item_create(block);

View File

@@ -88,6 +88,7 @@ static b_status put_name_in_bucket(
}
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
name->n_bucket = bucket;
return B_SUCCESS;
}
@@ -125,6 +126,8 @@ static b_status put_name(struct mie_name_map *map, struct mie_name *name)
b_queue_push_back(&bucket->b_names, &existing_name->n_base.e_entry);
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
existing_name->n_bucket = name->n_bucket = bucket;
put_entry(&map->m_entries, &bucket->b_base);
return B_SUCCESS;
@@ -279,6 +282,26 @@ struct mie_name *mie_name_map_put(
return NULL;
}
void mie_name_move(struct mie_name *dst, struct mie_name *src)
{
if (!src->n_parent) {
memmove(dst, src, sizeof *src);
return;
}
memmove(dst, src, sizeof *src);
if (src->n_bucket) {
b_queue_move(
&src->n_bucket->b_names, &dst->n_base.e_entry,
&src->n_base.e_entry);
} else {
b_btree_move(
&src->n_parent->m_entries, &dst->n_base.e_node,
&src->n_base.e_node);
}
}
void mie_name_destroy(struct mie_name *name)
{
struct mie_name_map *parent = name->n_parent;

View File

@@ -717,7 +717,7 @@ bool mie_parser_parse_register(
bool mie_parser_parse_register_list(
struct mie_parser *ctx, struct mie_name_map *names,
MIE_VECTOR_REF_PARAM(struct mie_register *, out))
MIE_VECTOR_REF_PARAM(struct mie_register, out))
{
bool ok = false;
struct mie_register *reg = NULL;
@@ -728,12 +728,7 @@ bool mie_parser_parse_register_list(
return false;
}
reg = calloc(1, sizeof *reg);
if (!reg) {
return false;
}
mie_vector_ref_push_back(out, &reg, NULL);
reg = mie_vector_ref_emplace_back(out, &mie_register_vector_ops);
if (!mie_parser_parse_register(ctx, names, reg)) {
return false;
@@ -754,11 +749,7 @@ bool mie_parser_parse_register_list(
return false;
}
reg = calloc(1, sizeof *reg);
if (!reg) {
return false;
}
mie_vector_ref_push_back(out, &reg, NULL);
reg = mie_vector_ref_emplace_back(out, &mie_register_vector_ops);
if (!mie_parser_parse_register(ctx, names, reg)) {
return false;
@@ -898,8 +889,8 @@ static bool parse_block_parameters(
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(block_params); i++) {
struct mie_register *param_reg = calloc(1, sizeof *param_reg);
mie_vector_push_back(block->b_params, &param_reg, NULL);
struct mie_register *param_reg = mie_vector_emplace_back(
block->b_params, &mie_register_vector_ops);
param_reg->reg_flags = block_params.items[i].arg_unresolved.reg_flags
| MIE_REGISTER_F_BLOCK_PARAM;
@@ -1162,7 +1153,7 @@ static bool parse_generic_op(
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(func_type->func_out); i++) {
dest->op_result.items[i]->reg_type = func_type->func_out.items[i];
dest->op_result.items[i].reg_type = func_type->func_out.items[i];
}
return true;

View File

@@ -1,8 +1,29 @@
#include <assert.h>
#include <mie/ir/block.h>
#include <mie/ir/op.h>
#include <mie/ir/register.h>
#include <mie/print/printer.h>
static enum mie_status cleanup(void *p)
{
return MIE_SUCCESS;
}
static enum mie_status move(void *dst, void *src, size_t itemsz)
{
assert(itemsz == sizeof(struct mie_block));
struct mie_block *dest_block = dst, *src_block = src;
memmove(dest_block, src_block, sizeof *src_block);
mie_name_move(&dest_block->b_name, &src_block->b_name);
return MIE_SUCCESS;
}
struct mie_vector_ops mie_block_vector_ops = {
.v_destroy = cleanup,
.v_move = move,
};
static void print_block_header_params(
struct mie_printer *printer, const struct mie_block *block)
{
@@ -17,11 +38,11 @@ static void print_block_header_params(
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_register(printer, block->b_params.items[i], 0);
mie_printer_print_register(printer, &block->b_params.items[i], 0);
b_stream_write_string(printer->p_stream, ": ", NULL);
mie_printer_print_type(printer, block->b_params.items[i]->reg_type);
mie_printer_print_type(printer, block->b_params.items[i].reg_type);
}
b_stream_write_char(printer->p_stream, ')');

View File

@@ -179,7 +179,7 @@ static void print_type_signature(
b_stream_write_string(printer->p_stream, ", ", NULL);
}
type = op->op_result.items[i]->reg_type;
type = op->op_result.items[i].reg_type;
mie_printer_print_type(printer, type);
}
@@ -225,7 +225,7 @@ void mie_printer_print_op(struct mie_printer *printer, const struct mie_op *op)
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_register(printer, op->op_result.items[i], 0);
mie_printer_print_register(printer, &op->op_result.items[i], 0);
}
if (MIE_VECTOR_COUNT(op->op_result) > 0) {

View File

@@ -15,7 +15,7 @@ void mie_printer_print_region(
block_flags = MIE_PRINT_F_EXCLUDE_BLOCK_HEADER;
}
const struct mie_block *block = region->r_blocks.items[i];
const struct mie_block *block = &region->r_blocks.items[i];
mie_printer_print_block(printer, block, block_flags);
}

View File

@@ -209,7 +209,7 @@ void *__mie_vector_emplace_back(
void *p = 0;
vector_wrap(&v, vector, item_size, count, max);
p = vector_emplace_back(&v, NULL);
p = vector_emplace_back(&v, ops);
vector_unwrap(&v, vector, item_size, count, max);
return p;