mie: implement a full rewriter with pattern-matching and rewriting support

the new rewriter interface supports running patterns over an Op's children
matching Ops that conform to a pattern, and rewriting Ops in arbitrary ways.
This commit is contained in:
2026-01-25 15:06:43 +00:00
parent 8cdbf5389c
commit 287983fa95
11 changed files with 951 additions and 60 deletions

View File

@@ -1,60 +0,0 @@
#ifndef MIE_IR_REWRITE_H_
#define MIE_IR_REWRITE_H_
#include <mie/misc.h>
#include <mie/status.h>
#include <stddef.h>
struct mie_op;
struct mie_ctx;
struct mie_rewriter;
struct mie_register;
#define MIE_REWRITE_RESULT(result, status) \
((struct mie_rewrite_result) {.r_result = (result), .r_status = (status)})
enum mie_match_result {
MIE_NO_MATCH_FOUND = 0,
MIE_MATCH_FOUND,
};
struct mie_rewrite_result {
enum {
MIE_REWRITE_SUCCESS = 0,
MIE_REWRITE_IGNORE,
MIE_REWRITE_FAILURE,
} r_result;
enum mie_status r_status;
};
struct mie_rewrite_pattern {
struct {
const char *t_dialect_name, *t_op_name;
const struct mie_op_definition *t_op;
} p_root;
enum mie_match_result (*p_match)(const struct mie_op *);
struct mie_rewrite_result (*p_rewrite)(
struct mie_op *, struct mie_rewriter *);
};
MIE_API struct mie_rewriter *mie_rewriter_create(struct mie_ctx *ctx);
MIE_API struct mie_block *mie_rewriter_get_insertion_block(
struct mie_rewriter *rewriter);
MIE_API struct mie_op *mie_rewriter_get_insertion_point(
struct mie_rewriter *rewriter);
MIE_API struct mie_block *mie_rewriter_split_block(
struct mie_rewriter *rewriter, struct mie_block *block,
struct mie_op *before);
MIE_API struct mie_block *mie_rewriter_create_block(
struct mie_rewriter *rewriter, struct mie_block *insert_before);
MIE_API struct mie_op *mie_rewriter_put_op(
struct mie_rewriter *rewriter, const char *dialect, const char *op,
struct mie_register **args, size_t nr_args);
MIE_API enum mie_status mie_rewriter_erase_op(
struct mie_rewriter *rewriter, struct mie_op *op);
#endif

View File

@@ -246,3 +246,24 @@
} while (0)
#endif
/******************************************************************************/
/* REWRITE PATTER MACROS */
/******************************************************************************/
#define MIE_REWRITE_PATTERN_BEGIN(name) \
struct mie_pattern *name##_create(struct mie_pattern_set *set) \
{ \
struct mie_pattern *self = mie_pattern_set_add(set); \
if (!self) { \
return NULL; \
}
#define MIE_REWRITE_PATTERN_END() \
return self; \
}
#define MIE_REWRITE_PATTERN_ROOT(dialect_name, op_name) \
self->p_root.t_dialect_name = (dialect_name); \
self->p_root.t_op_name = (op_name)
#define MIE_REWRITE_PATTERN_MATCH(func) self->p_match = (func)
#define MIE_REWRITE_PATTERN_REWRITE(func) self->p_rewrite = (func)

View File

@@ -0,0 +1,20 @@
#ifndef MIE_REWRITE_CONVERT_H_
#define MIE_REWRITE_CONVERT_H_
#include <mie/ctx.h>
struct mie_pattern_set;
struct mie_convert_config;
MIE_API struct mie_convert_config *mie_convert_config_create(struct mie_ctx *ctx);
MIE_API void mie_convert_config_destroy(struct mie_convert_config *cfg);
MIE_API enum mie_status mie_convert_config_add_illegal_op(
struct mie_convert_config *cfg, const char *dialect_name,
const char *op_name);
MIE_API enum mie_status mie_convert_apply(
struct mie_op *op, struct mie_convert_config *cfg,
struct mie_pattern_set *patterns);
#endif

View File

@@ -0,0 +1,16 @@
#ifndef MIE_REWRITE_GREEDY_H_
#define MIE_REWRITE_GREEDY_H_
#include <mie/ctx.h>
struct mie_pattern_set;
struct mie_greedy_config;
MIE_API struct mie_greedy_config *mie_greedy_config_create(struct mie_ctx *ctx);
MIE_API void mie_greedy_config_destroy(struct mie_greedy_config *cfg);
MIE_API enum mie_status mie_greedy_apply(
struct mie_op *op, struct mie_greedy_config *cfg,
struct mie_pattern_set *patterns);
#endif

View File

@@ -0,0 +1,54 @@
#ifndef MIE_REWRITE_PATTERN_H_
#define MIE_REWRITE_PATTERN_H_
#include <mie/vector.h>
#define MIE_REWRITE_RESULT(result, status) \
((struct mie_rewrite_result) {.r_result = (result), .r_status = (status)})
struct mie_op;
struct mie_rewriter;
enum mie_match_result {
MIE_NO_MATCH_FOUND = 0,
MIE_MATCH_FOUND,
};
struct mie_rewrite_result {
enum {
MIE_REWRITE_SUCCESS = 0,
MIE_REWRITE_IGNORE,
MIE_REWRITE_FAILURE,
} r_result;
enum mie_status r_status;
};
struct mie_pattern {
struct {
const char *t_dialect_name, *t_op_name;
const struct mie_op_definition *t_op;
} p_root;
enum mie_match_result (*p_match)(const struct mie_op *);
struct mie_rewrite_result (*p_rewrite)(
struct mie_op *, struct mie_rewriter *);
};
struct mie_pattern_set {
MIE_VECTOR_DECLARE(struct mie_pattern, s_patterns);
};
MIE_API void mie_pattern_set_init(struct mie_pattern_set *set);
MIE_API void mie_pattern_set_cleanup(struct mie_pattern_set *set);
MIE_API struct mie_pattern *mie_pattern_set_add(struct mie_pattern_set *set);
MIE_API struct mie_pattern *mie_pattern_set_match(
struct mie_pattern_set *set, const struct mie_op *op);
MIE_API enum mie_match_result mie_pattern_match(
const struct mie_pattern *pattern, const struct mie_op *op);
MIE_API struct mie_rewrite_result mie_pattern_rewrite(
const struct mie_pattern *pattern, struct mie_op *op,
struct mie_rewriter *rewriter);
#endif

View File

@@ -0,0 +1,108 @@
#ifndef MIE_IR_REWRITE_H_
#define MIE_IR_REWRITE_H_
#include <mie/ir/emit.h>
#include <mie/misc.h>
#include <mie/status.h>
#include <mie/vector.h>
#include <stddef.h>
struct mie_op;
struct mie_ctx;
struct mie_region;
struct mie_register;
struct mie_op_successor;
struct mie_rewriter {
struct mie_emitter r_base;
struct mie_ctx *r_ctx;
/* anything ops added to the IR are inserted in this block. */
struct mie_block *r_insert_block;
/* anything ops added to the IR are inserted after this op.
* if this is null, the insertion point is the end of r_insert_block. */
struct mie_op *r_insert_point;
};
MIE_API void mie_rewriter_init(struct mie_rewriter *rw, struct mie_ctx *ctx);
MIE_API void mie_rewriter_cleanup(struct mie_rewriter *rw);
MIE_API struct mie_ctx *mie_rewriter_get_ctx(const struct mie_rewriter *rw);
MIE_API struct mie_block *mie_rewriter_get_insertion_block(struct mie_rewriter *rw);
MIE_API struct mie_op *mie_rewriter_get_insertion_point(struct mie_rewriter *rw);
MIE_API struct mie_block *mie_rewriter_set_insertion_block(
struct mie_rewriter *rw, struct mie_block *block);
MIE_API struct mie_op *mie_rewriter_set_insertion_point(
struct mie_rewriter *rw, struct mie_op *insert_point);
MIE_API struct mie_block *mie_rewriter_split_block(
struct mie_rewriter *rw, struct mie_block *block, struct mie_op *before,
const char *name);
MIE_API struct mie_block *mie_rewriter_create_block(
struct mie_rewriter *rw, struct mie_block *insert_before, const char *name);
MIE_API enum mie_status mie_rewriter_move_block_to_start(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to);
MIE_API enum mie_status mie_rewriter_move_block_to_end(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to);
MIE_API enum mie_status mie_rewriter_move_block_before(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to, struct mie_block *before);
MIE_API enum mie_status mie_rewriter_move_block_after(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to, struct mie_block *after);
MIE_API enum mie_status mie_rewriter_rename_block(
struct mie_rewriter *rw, struct mie_block *block, const char *name);
MIE_API enum mie_status mie_rewriter_move_blocks_to_start(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to);
MIE_API enum mie_status mie_rewriter_move_blocks_to_end(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to);
MIE_API enum mie_status mie_rewriter_move_blocks_before(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to,
struct mie_block *before);
MIE_API enum mie_status mie_rewriter_move_blocks_after(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to,
struct mie_block *after);
MIE_API enum mie_status mie_rewriter_move_region_to_start(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to);
MIE_API enum mie_status mie_rewriter_move_region_to_end(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to);
MIE_API enum mie_status mie_rewriter_move_region_before(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to, struct mie_region *before);
MIE_API enum mie_status mie_rewriter_move_region_after(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to, struct mie_region *after);
MIE_API struct mie_op *mie_rewriter_put_op(
struct mie_rewriter *rw, const char *dialect, const char *op,
struct mie_register **args, size_t nr_args);
MIE_API struct mie_op *mie_rewriter_replace_op(
struct mie_rewriter *rw, struct mie_op *op, const char *dialect_name,
const char *op_name);
MIE_API struct mie_op_successor *mie_rewriter_add_op_successor(
struct mie_rewriter *rw, struct mie_op *op, struct mie_block *dest,
struct mie_register **args, size_t nr_args);
MIE_API enum mie_status mie_rewriter_erase_op(
struct mie_rewriter *rw, struct mie_op *op);
MIE_API enum mie_status mie_rewriter_move_op_args_to_successor(
struct mie_rewriter *rw, struct mie_op *op, struct mie_op_successor *s);
MIE_API enum mie_status mie_rewriter_replace_register(
struct mie_rewriter *rw, struct mie_register *old,
struct mie_register *new);
MIE_API enum mie_status mie_rewriter_rename_register(
struct mie_rewriter *rw, struct mie_register *reg, const char *name);
MIE_API enum mie_status mie_rewriter_put_name(
struct mie_rewriter *rw, struct mie_name *name, const char *hint);
#endif

View File

88
mie/rewrite/convert.c Normal file
View File

@@ -0,0 +1,88 @@
#include <mie/ctx.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/walk.h>
#include <mie/rewrite/convert.h>
#include <mie/rewrite/pattern.h>
#include <mie/rewrite/rewriter.h>
#include <mie/vector.h>
#include <stdlib.h>
struct mie_convert_config {
struct mie_ctx *cfg_ctx;
MIE_VECTOR_DECLARE(const struct mie_op_definition *, cfg_illegal_ops);
};
struct mie_convert_config *mie_convert_config_create(struct mie_ctx *ctx)
{
struct mie_convert_config *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->cfg_ctx = ctx;
return out;
}
void mie_convert_config_destroy(struct mie_convert_config *cfg)
{
mie_vector_destroy(cfg->cfg_illegal_ops, NULL);
free(cfg);
}
enum mie_status mie_convert_config_add_illegal_op(
struct mie_convert_config *cfg, const char *dialect_name, const char *op_name)
{
const struct mie_op_definition *op
= mie_ctx_get_op_definition(cfg->cfg_ctx, dialect_name, op_name);
if (!op) {
return MIE_ERR_NO_ENTRY;
}
const struct mie_op_definition **slot
= mie_vector_emplace_back(cfg->cfg_illegal_ops, NULL);
if (!slot) {
return MIE_ERR_NO_MEMORY;
}
*slot = op;
return MIE_SUCCESS;
}
enum mie_status mie_convert_apply(
struct mie_op *root, struct mie_convert_config *cfg,
struct mie_pattern_set *patterns)
{
enum mie_status status = MIE_SUCCESS;
enum mie_walker_flags walk_flags = MIE_WALKER_F_INCLUDE_OPS
| MIE_WALKER_F_POSTORDER
| MIE_WALKER_F_FORWARD;
struct mie_walker walker;
mie_walker_begin(&walker, root, walk_flags);
struct mie_rewriter rw;
mie_rewriter_init(&rw, cfg->cfg_ctx);
do {
const struct mie_walk_item *item = mie_walker_get(&walker);
struct mie_op *op = item->i_op;
struct mie_pattern *pattern = mie_pattern_set_match(patterns, op);
if (!pattern) {
continue;
}
struct mie_rewrite_result result
= mie_pattern_rewrite(pattern, op, &rw);
if (result.r_result == MIE_REWRITE_FAILURE) {
status = result.r_status;
break;
}
} while (mie_walker_step(&walker) == MIE_SUCCESS);
mie_walker_end(&walker);
return status;
}

30
mie/rewrite/pattern-set.c Normal file
View File

@@ -0,0 +1,30 @@
#include <mie/rewrite/pattern.h>
#include <mie/vector.h>
#include <string.h>
void mie_pattern_set_init(struct mie_pattern_set *set)
{
memset(set, 0x0, sizeof *set);
}
void mie_pattern_set_cleanup(struct mie_pattern_set *set)
{
mie_vector_destroy(set->s_patterns, NULL);
}
struct mie_pattern *mie_pattern_set_add(struct mie_pattern_set *set)
{
return mie_vector_emplace_back(set->s_patterns, NULL);
}
struct mie_pattern *mie_pattern_set_match(
struct mie_pattern_set *set, const struct mie_op *op)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(set->s_patterns); i++) {
if (mie_pattern_match(&set->s_patterns.items[i], op)) {
return &set->s_patterns.items[i];
}
}
return NULL;
}

23
mie/rewrite/pattern.c Normal file
View File

@@ -0,0 +1,23 @@
#include <mie/rewrite/pattern.h>
enum mie_match_result mie_pattern_match(
const struct mie_pattern *pattern, const struct mie_op *op)
{
if (!pattern->p_match) {
return MIE_NO_MATCH_FOUND;
}
return pattern->p_match(op);
}
struct mie_rewrite_result mie_pattern_rewrite(
const struct mie_pattern *pattern, struct mie_op *op,
struct mie_rewriter *rewriter)
{
if (!pattern->p_rewrite) {
return MIE_REWRITE_RESULT(
MIE_REWRITE_FAILURE, MIE_ERR_NOT_SUPPORTED);
}
return pattern->p_rewrite(op, rewriter);
}

591
mie/rewrite/rewriter.c Normal file
View File

@@ -0,0 +1,591 @@
#include <mie/ctx.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/rewrite/rewriter.h>
#include <string.h>
void mie_rewriter_init(struct mie_rewriter *rw, struct mie_ctx *ctx)
{
memset(rw, 0x0, sizeof *rw);
rw->r_ctx = ctx;
rw->r_base.e_get_ctx = (mie_emit_get_ctx)mie_rewriter_get_ctx;
rw->r_base.e_put_op = (mie_emit_put_op)mie_rewriter_put_op;
rw->r_base.e_put_name = (mie_emit_put_name)mie_rewriter_put_name;
rw->r_base.e_put_block = NULL;
}
void mie_rewriter_cleanup(struct mie_rewriter *rw)
{
/* TODO */
}
struct mie_ctx *mie_rewriter_get_ctx(const struct mie_rewriter *rw)
{
return rw->r_ctx;
}
struct mie_block *mie_rewriter_get_insertion_block(struct mie_rewriter *rw)
{
return rw->r_insert_block;
}
struct mie_op *mie_rewriter_get_insertion_point(struct mie_rewriter *rw)
{
return rw->r_insert_point;
}
struct mie_block *mie_rewriter_set_insertion_block(
struct mie_rewriter *rw, struct mie_block *block)
{
rw->r_insert_block = block;
return block;
}
struct mie_op *mie_rewriter_set_insertion_point(
struct mie_rewriter *rw, struct mie_op *insert_point)
{
if (!insert_point && rw->r_insert_point) {
insert_point = mie_block_get_last_op(rw->r_insert_block);
}
rw->r_insert_point = insert_point;
return rw->r_insert_point;
}
static struct mie_name_map *get_name_map_for_region(struct mie_region *region)
{
while (region) {
if (region->r_names) {
return region->r_names;
}
struct mie_op *op = region->r_parent;
if (!op) {
break;
}
struct mie_block *block = op->op_container;
if (!block) {
break;
}
region = block->b_parent;
}
return NULL;
}
struct mie_block *mie_rewriter_split_block(
struct mie_rewriter *rw, struct mie_block *block, struct mie_op *before,
const char *name)
{
if (before->op_container != block) {
return NULL;
}
struct mie_region *region = block->b_parent;
struct mie_name_map *names = get_name_map_for_region(region);
struct mie_block *new_block = mie_region_add_block_after(region, block);
mie_name_map_put(names, &new_block->b_name, name, 0);
b_queue_entry *cur = &before->op_entry;
while (cur) {
struct mie_op *cur_op = b_unbox(struct mie_op, cur, op_entry);
b_queue_entry *next = b_queue_next(cur);
b_queue_delete(&block->b_ops, cur);
b_queue_push_back(&new_block->b_ops, cur);
cur_op->op_container = new_block;
cur = next;
}
return new_block;
}
struct mie_block *mie_rewriter_create_block(
struct mie_rewriter *rw, struct mie_block *insert_before, const char *name)
{
return NULL;
}
enum mie_status mie_rewriter_move_block_to_start(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to)
{
if (block->b_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->r_blocks, &block->b_entry);
b_queue_push_front(&to->r_blocks, &block->b_entry);
block->b_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_block_to_end(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to)
{
if (block->b_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->r_blocks, &block->b_entry);
b_queue_push_back(&to->r_blocks, &block->b_entry);
block->b_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_block_before(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to, struct mie_block *before)
{
if (block->b_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
if (before->b_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->r_blocks, &block->b_entry);
b_queue_insert_before(&to->r_blocks, &block->b_entry, &before->b_entry);
block->b_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_block_after(
struct mie_rewriter *rw, struct mie_block *block,
struct mie_region *from, struct mie_region *to, struct mie_block *after)
{
if (block->b_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
if (after->b_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->r_blocks, &block->b_entry);
b_queue_insert_after(&to->r_blocks, &block->b_entry, &after->b_entry);
block->b_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_rename_block(
struct mie_rewriter *rw, struct mie_block *block, const char *name)
{
struct mie_region *region = block->b_parent;
struct mie_name_map *names = get_name_map_for_region(region);
mie_name_destroy(&block->b_name);
struct mie_name *result = mie_name_map_put(names, &block->b_name, name, 0);
return result ? MIE_SUCCESS : MIE_ERR_NO_MEMORY;
}
enum mie_status mie_rewriter_move_blocks_to_start(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to)
{
b_queue_entry *cur = b_queue_first(&from->r_blocks);
b_queue_entry *insert_point = NULL;
while (cur) {
b_queue_entry *next = b_queue_next(cur);
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
b_queue_delete(&from->r_blocks, cur);
if (insert_point) {
b_queue_insert_after(&to->r_blocks, cur, insert_point);
} else {
b_queue_push_front(&to->r_blocks, cur);
}
block->b_parent = to;
insert_point = cur;
cur = next;
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_blocks_to_end(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to)
{
b_queue_entry *cur = b_queue_first(&from->r_blocks);
while (cur) {
b_queue_entry *next = b_queue_next(cur);
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
b_queue_delete(&from->r_blocks, cur);
b_queue_push_back(&to->r_blocks, cur);
block->b_parent = to;
cur = next;
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_blocks_before(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to,
struct mie_block *before)
{
if (before->b_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_entry *cur = b_queue_last(&from->r_blocks);
while (cur) {
b_queue_entry *next = b_queue_prev(cur);
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
b_queue_delete(&from->r_blocks, cur);
b_queue_insert_before(&to->r_blocks, cur, &before->b_entry);
block->b_parent = to;
cur = next;
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_blocks_after(
struct mie_rewriter *rw, struct mie_region *from, struct mie_region *to,
struct mie_block *after)
{
if (after->b_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_entry *cur = b_queue_first(&from->r_blocks);
b_queue_entry *insert_point = &after->b_entry;
while (cur) {
b_queue_entry *next = b_queue_next(cur);
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
b_queue_delete(&from->r_blocks, cur);
b_queue_insert_after(&to->r_blocks, cur, insert_point);
block->b_parent = to;
insert_point = cur;
cur = next;
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_region_to_start(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to)
{
if (region->r_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->op_regions, &region->r_entry);
b_queue_push_front(&to->op_regions, &region->r_entry);
region->r_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_region_to_end(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to)
{
if (region->r_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->op_regions, &region->r_entry);
b_queue_push_back(&to->op_regions, &region->r_entry);
region->r_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_region_before(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to, struct mie_region *before)
{
if (region->r_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
if (before->r_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->op_regions, &region->r_entry);
b_queue_insert_before(&to->op_regions, &region->r_entry, &before->r_entry);
region->r_parent = to;
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_region_after(
struct mie_rewriter *rw, struct mie_region *region, struct mie_op *from,
struct mie_op *to, struct mie_region *after)
{
if (region->r_parent != from) {
return MIE_ERR_INVALID_ARGUMENT;
}
if (after->r_parent != to) {
return MIE_ERR_INVALID_ARGUMENT;
}
b_queue_delete(&from->op_regions, &region->r_entry);
b_queue_insert_after(&to->op_regions, &region->r_entry, &after->r_entry);
region->r_parent = to;
return MIE_SUCCESS;
}
struct mie_op *mie_rewriter_put_op(
struct mie_rewriter *rw, const char *dialect_name, const char *op_name,
struct mie_register **args, size_t nr_args)
{
if (!rw->r_insert_block) {
return NULL;
}
const struct mie_op_definition *op_def
= mie_ctx_get_op_definition(rw->r_ctx, dialect_name, op_name);
if (!op_def) {
return NULL;
}
struct mie_op *op
= mie_block_add_op_after(rw->r_insert_block, rw->r_insert_point);
if (!op) {
return NULL;
}
op->op_flags = MIE_OP_F_OP_RESOLVED;
op->op_info = op_def;
op->op_dialect = op_def->op_parent;
for (size_t i = 0; i < nr_args; i++) {
struct mie_op_arg *arg = mie_op_add_arg(op);
arg->arg_flags = MIE_OP_F_ARG_RESOLVED;
arg->arg_value.u_reg = args[i];
arg->arg_value.u_user = op;
b_queue_push_back(&args[i]->reg_use, &arg->arg_value.u_entry);
}
return op;
}
struct mie_op *mie_rewriter_replace_op(
struct mie_rewriter *rw, struct mie_op *op, const char *dialect_name,
const char *op_name)
{
const struct mie_op_definition *op_def
= mie_ctx_get_op_definition(rw->r_ctx, dialect_name, op_name);
if (!op_def) {
return NULL;
}
op->op_info = op_def;
op->op_dialect = op_def->op_parent;
return op;
}
struct mie_op_successor *mie_rewriter_add_op_successor(
struct mie_rewriter *rw, struct mie_op *op, struct mie_block *dest,
struct mie_register **args, size_t nr_args)
{
return mie_op_add_successor(op, dest, args, nr_args);
}
enum mie_status mie_rewriter_erase_op(struct mie_rewriter *rw, struct mie_op *op)
{
struct mie_block *parent = op->op_container;
if (!parent) {
return MIE_ERR_BAD_STATE;
}
b_queue_delete(&parent->b_ops, &op->op_entry);
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
struct mie_op_successor *s = &op->op_successors.items[i];
for (size_t k = 0; k < MIE_VECTOR_COUNT(s->s_args); k++) {
struct mie_op_arg *arg = &s->s_args.items[k];
if (!(arg->arg_flags & MIE_OP_F_ARG_RESOLVED)) {
continue;
}
b_queue_delete(
&arg->arg_value.u_reg->reg_use,
&arg->arg_value.u_entry);
}
}
for (size_t k = 0; k < MIE_VECTOR_COUNT(op->op_args); k++) {
struct mie_op_arg *arg = &op->op_args.items[k];
if (!(arg->arg_flags & MIE_OP_F_ARG_RESOLVED)) {
continue;
}
b_queue_delete(
&arg->arg_value.u_reg->reg_use, &arg->arg_value.u_entry);
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
struct mie_register *reg = &op->op_result.items[i];
b_queue_entry *cur = b_queue_first(&reg->reg_use);
while (cur) {
b_queue_entry *next = b_queue_next(cur);
struct mie_register_use *use
= b_unbox(struct mie_register_use, cur, u_entry);
b_queue_delete(&reg->reg_use, &use->u_entry);
use->u_reg = NULL;
cur = next;
}
}
mie_attribute_map_cleanup(&op->op_attrib);
free(op);
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_move_op_args_to_successor(
struct mie_rewriter *rw, struct mie_op *op, struct mie_op_successor *s)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
struct mie_op_arg *src = &op->op_args.items[i];
struct mie_op_arg *dest = mie_vector_emplace_back(s->s_args, NULL);
struct mie_register *reg = NULL;
if (src->arg_flags & MIE_OP_F_ARG_RESOLVED) {
reg = src->arg_value.u_reg;
b_queue_delete(&reg->reg_use, &src->arg_value.u_entry);
}
memcpy(dest, src, sizeof *src);
if (reg) {
memset(&dest->arg_value.u_entry, 0x0,
sizeof dest->arg_value.u_entry);
b_queue_push_back(&reg->reg_use, &dest->arg_value.u_entry);
}
}
mie_vector_destroy(op->op_args, NULL);
return MIE_SUCCESS;
}
static enum mie_status replace_register_usage(
struct mie_op *op, struct mie_register *old, struct mie_register *new)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
struct mie_op_arg *arg = &op->op_args.items[i];
if (!(arg->arg_flags & MIE_OP_F_ARG_RESOLVED)) {
continue;
}
if (arg->arg_value.u_reg != old) {
continue;
}
b_queue_delete(&old->reg_use, &arg->arg_value.u_entry);
arg->arg_value.u_reg = new;
b_queue_push_back(&new->reg_use, &arg->arg_value.u_entry);
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
struct mie_op_successor *s = &op->op_successors.items[i];
for (size_t k = 0; k < MIE_VECTOR_COUNT(s->s_args); k++) {
struct mie_op_arg *arg = &s->s_args.items[i];
if (!(arg->arg_flags & MIE_OP_F_ARG_RESOLVED)) {
continue;
}
if (arg->arg_value.u_reg != old) {
continue;
}
b_queue_delete(&old->reg_use, &arg->arg_value.u_entry);
arg->arg_value.u_reg = new;
b_queue_push_back(&new->reg_use, &arg->arg_value.u_entry);
}
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_replace_register(
struct mie_rewriter *rw, struct mie_register *old, struct mie_register *new)
{
b_queue_entry *cur = b_queue_first(&old->reg_use);
while (cur) {
struct mie_register_use *use
= b_unbox(struct mie_register_use, cur, u_entry);
struct mie_op *op = use->u_user;
if (use->u_reg == old) {
replace_register_usage(op, old, new);
}
cur = b_queue_next(cur);
}
return MIE_SUCCESS;
}
enum mie_status mie_rewriter_rename_register(
struct mie_rewriter *rw, struct mie_register *reg, const char *name)
{
if (!reg->reg_block) {
return MIE_ERR_INVALID_ARGUMENT;
}
struct mie_region *region = reg->reg_block->b_parent;
struct mie_name_map *names = get_name_map_for_region(region);
mie_name_destroy(&reg->reg_name);
struct mie_name *result = mie_name_map_put(names, &reg->reg_name, name, 0);
return result ? MIE_SUCCESS : MIE_ERR_NO_MEMORY;
}
enum mie_status mie_rewriter_put_name(
struct mie_rewriter *rw, struct mie_name *name, const char *hint)
{
if (!rw->r_insert_block) {
return MIE_ERR_BAD_STATE;
}
struct mie_region *region = rw->r_insert_block->b_parent;
struct mie_name_map *names = get_name_map_for_region(region);
mie_name_destroy(name);
struct mie_name *result = mie_name_map_put(names, name, hint, 0);
return result ? MIE_SUCCESS : MIE_ERR_NO_MEMORY;
}