Compare commits

32 Commits

Author SHA1 Message Date
00152cac56 mie: convert-scf-to-cf: implement if match/rewrite using new interface 2026-01-25 15:08:19 +00:00
287983fa95 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.
2026-01-25 15:06:43 +00:00
8cdbf5389c mie: pass: manager: update mie_walker usage 2026-01-25 15:05:44 +00:00
00c7c3d5ea mie: parse: update parse_region_list to use new Op->Region linking mechanism 2026-01-25 15:05:18 +00:00
9e546ee32f mie: name: fix crash when destroying a zeroed mie_name 2026-01-25 15:04:37 +00:00
00ba3a3d87 mie: print: implement exception-printing of resolved, but null, op args
this is to make it easier to spot mistakes made when modifying IR.
2026-01-25 15:02:48 +00:00
d44bc8c5c0 mie: ir: op: fix crash when checking if an unresolved op is isolated 2026-01-25 15:02:17 +00:00
a22e95d88d mie: ir: op: add functions to check what an Op is, and add successors with args 2026-01-25 15:01:41 +00:00
0a791fdfb2 mie: dialect: update Op emitter functions to use mie_emitter 2026-01-25 15:00:37 +00:00
fe511011ec mie: ir: walk: implement non-recursive traversal
struct mie_walker is now a public struct that can (and should) be stack
allocated. this means that non-recursive traversal of an Op's children
uses no dynamically allocated memory.
2026-01-25 14:58:51 +00:00
e8534f8d70 mie: ir: Op->Region, Region->Block, and Block->Op lists are now b_queues rather than mie_vectors
this change has two key benefits:
 1. we no longer need to allocate large contigious buffers for Regions with lots
    of Blocks, or Blocks with lots of Ops.
 2. this simplifies re-arranging, inserting, and moving parts of the IR structure.
2026-01-25 14:56:47 +00:00
bf8c966c03 mie: ir: builder: add mie_emitter support 2026-01-25 14:53:24 +00:00
7d30e8f3ff mie: ir: add an emitter interface for emitting IR constructs
mie_emitter can be inherited from by any structure that supports
emitting IR constructs like Ops and Blocks. Dialect Op emitter
functions can wrap mie_emitter to simplify emitting specific Ops,
and these functions can then be used with any struct that inherits
from mie_emitter.
2026-01-25 14:51:36 +00:00
e9d2c0fbc7 mie: scf: implement lots of print and emit functions 2026-01-23 23:33:16 +00:00
a710ef0b24 mie: func: implement lots of print and emit functions 2026-01-23 23:22:57 +00:00
0277931ca1 mie: builtin: implement lots of print and emit functions 2026-01-23 23:22:47 +00:00
ac7860b6bd mie: ir: rewrite: add pattern and rewriter interface 2026-01-23 23:21:42 +00:00
29984307aa mie: pass: support filtering passes to any op of a given dialect 2026-01-23 23:21:16 +00:00
ac96248d7e mie: ir: builder: support adding names to non-isolated op regions 2026-01-23 23:19:29 +00:00
593eda2797 mie: trait: table: fix get_unique() unboxing the wrong pointer 2026-01-23 23:17:39 +00:00
d0ac8a9fed mie: ir: walk: re-implement walker with a stack rather than a queue 2026-01-23 22:50:05 +00:00
89ebbcc462 mie: parse: replace all op-creation with mie_block_add_op calls 2026-01-23 22:42:39 +00:00
554a1e7342 mie: ir: op: keep a pointer to the block that contains the op 2026-01-23 22:42:05 +00:00
6d1e308ff1 mie: ir: op: only create a name map if the op is isolated-from-above 2026-01-23 22:41:03 +00:00
58bd336eb8 mie: dialect: add emitter functions for various ops 2026-01-21 14:42:22 +00:00
008966e046 mie: ir: add ir builder interface 2026-01-21 14:40:22 +00:00
83343a5eea mie: ir: block: add function to create block parameters 2026-01-21 14:39:56 +00:00
76166167c9 mie: builtin: improve int attribute print callback 2026-01-21 14:39:12 +00:00
f6f6131f52 mie: builtin: add function to create mie_type_attr instances 2026-01-21 14:38:01 +00:00
33f9ccd871 mie: ir: register: implement moving and cleanup of mie_register_use 2026-01-21 14:36:24 +00:00
0c4ebe7f39 mie: ctx: add function to create ops 2026-01-21 14:17:43 +00:00
72de4ce845 mie: ir: op: add function to add op arguments 2026-01-21 14:15:02 +00:00
54 changed files with 3083 additions and 397 deletions

View File

@@ -70,6 +70,27 @@ struct mie_ctx *mie_ctx_create(void)
return out;
}
struct mie_op *mie_ctx_create_op(
const struct mie_ctx *ctx, const char *dialect, const char *op)
{
const struct mie_op_definition *def
= mie_ctx_get_op_definition(ctx, dialect, op);
if (!def) {
return NULL;
}
struct mie_op *out = mie_op_create();
if (!out) {
return NULL;
}
out->op_flags |= MIE_OP_F_OP_RESOLVED;
out->op_info = def;
out->op_dialect = def->op_parent;
return out;
}
bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op)
{
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {

View File

@@ -1,8 +1,12 @@
#include <mie/ctx.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/macros.h>
#include <mie/print/printer.h>
#include <mie/type/type.h>
static enum mie_status print(struct mie_printer *printer, const struct mie_op *op)
{
@@ -28,6 +32,22 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_register *mie_arith_addi_put(
struct mie_emitter *e, struct mie_register *left,
struct mie_register *right, const char *name)
{
struct mie_register *args[] = {left, right};
const size_t nr_args = sizeof args / sizeof args[0];
struct mie_op *op = mie_emitter_put_op(e, "arith", "addi", args, nr_args);
const struct mie_type *ty = left->reg_type;
struct mie_register *result = mie_op_add_result(op, ty);
mie_emitter_put_name(e, &result->reg_name, name);
return result;
}
MIE_OP_DEFINITION_BEGIN(mie_arith_addi, "addi")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -1,6 +1,7 @@
#include <mie/attribute/attribute.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/macros.h>
@@ -40,6 +41,40 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_register *mie_arith_constant_i_put(
struct mie_emitter *e, long long value, const char *name)
{
struct mie_op *op = mie_emitter_put_op(e, "arith", "constant", NULL, 0);
const struct mie_type *ty
= mie_ctx_get_int_type(mie_emitter_get_ctx(e), 32);
struct mie_register *result = mie_op_add_result(op, ty);
mie_emitter_put_name(e, &result->reg_name, name);
struct mie_attribute *val
= mie_ctx_get_int(mie_emitter_get_ctx(e), value, 32);
mie_attribute_map_put(&op->op_attrib, "value", val, MIE_ATTRMAP_F_REPLACE);
return result;
}
struct mie_register *mie_arith_constant_f_put(
struct mie_emitter *e, long long value, const char *name)
{
struct mie_op *op = mie_emitter_put_op(e, "arith", "constant", NULL, 0);
const struct mie_type *ty
= mie_ctx_get_int_type(mie_emitter_get_ctx(e), 32);
struct mie_register *result = mie_op_add_result(op, ty);
mie_emitter_put_name(e, &result->reg_name, name);
struct mie_attribute *val
= mie_ctx_get_float(mie_emitter_get_ctx(e), value, 32);
mie_attribute_map_put(&op->op_attrib, "value", val, MIE_ATTRMAP_F_REPLACE);
return result;
}
MIE_OP_DEFINITION_BEGIN(mie_arith_constant, "constant")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -21,16 +21,25 @@ static enum mie_status print(
b_stream_write_string(out->p_stream, "#builtin.int<", NULL);
}
if (int_ty->i_width < 64 || !abbrev) {
if (int_ty->i_width <= 64) {
b_stream_write_fmt(
out->p_stream, NULL, "%zu : i%zu",
int_val->i_val.v_small, int_ty->i_width);
} else if (int_ty->i_width == 64 && abbrev) {
b_stream_write_fmt(
out->p_stream, NULL, "%zu", int_val->i_val.v_small);
out->p_stream, NULL, "%zu", int_val->i_val.v_small,
int_ty->i_width);
} else {
b_stream_write_fmt(
out->p_stream, NULL, "INF : i%zu", int_ty->i_width);
b_stream_write_fmt(out->p_stream, NULL, "INF", int_ty->i_width);
}
if (int_ty->i_width != 64 || !abbrev) {
b_stream_write_string(out->p_stream, " : ", NULL);
if (abbrev) {
b_stream_write_fmt(
out->p_stream, NULL, "i%zu", int_ty->i_width);
} else {
b_stream_write_fmt(
out->p_stream, NULL, "!builtin.int<%zu>",
int_ty->i_width);
}
}
if (!abbrev) {

View File

@@ -7,6 +7,23 @@
#include <mie/parse/parser.h>
#include <mie/print/printer.h>
struct mie_attribute *mie_type_attr_create(
struct mie_ctx *ctx, const struct mie_type *ty)
{
struct mie_type_attr *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->ty_base.a_def
= mie_ctx_get_attribute_definition(ctx, "builtin", "type");
out->ty_value = ty;
return (struct mie_attribute *)out;
}
static enum mie_status print(
const struct mie_attribute *value, struct mie_printer *out)
{
@@ -25,25 +42,11 @@ static enum mie_status print(
return MIE_SUCCESS;
}
static struct mie_type_attr *type_attr_create(struct mie_ctx *ctx)
{
struct mie_type_attr *ty = malloc(sizeof *ty);
if (!ty) {
return NULL;
}
memset(ty, 0x0, sizeof *ty);
ty->ty_base.a_def
= mie_ctx_get_attribute_definition(ctx, "builtin", "type");
return ty;
}
static enum mie_status parse(
struct mie_parser *ctx, const struct mie_attribute **out)
{
struct mie_type_attr *ty = type_attr_create(mie_parser_get_mie_ctx(ctx));
struct mie_type_attr *ty = (struct mie_type_attr *)mie_type_attr_create(
mie_parser_get_mie_ctx(ctx), NULL);
if (!ty) {
return MIE_ERR_NO_MEMORY;
}

View File

@@ -84,17 +84,17 @@ struct mie_attribute *mie_ctx_get_index(struct mie_ctx *ctx, size_t val)
MIE_DIALECT_BEGIN(mie_builtin, struct builtin_dialect, "builtin")
MIE_DIALECT_INIT(init);
MIE_DIALECT_CLEANUP(cleanup);
MIE_DIALECT_ADD_OP(mie_builtin_module);
MIE_DIALECT_ADD_TYPE(mie_builtin_string);
MIE_DIALECT_ADD_TRAIT(mie_builtin_isolated_from_above);
MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table);
MIE_DIALECT_ADD_TYPE(mie_builtin_int);
MIE_DIALECT_ADD_TYPE(mie_builtin_float);
MIE_DIALECT_ADD_TYPE(mie_builtin_index);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_string);
MIE_DIALECT_ADD_TYPE(mie_builtin_string);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_int);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_float);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_array);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_type);
MIE_DIALECT_ADD_TRAIT(mie_builtin_isolated_from_above);
MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_string);
MIE_DIALECT_ADD_INTERFACE(mie_builtin_symbol);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_array);
MIE_DIALECT_ADD_OP(mie_builtin_module);
MIE_DIALECT_END()

View File

@@ -1,3 +1,4 @@
#include <mie/ctx.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
@@ -8,12 +9,11 @@
static enum mie_status print(struct mie_printer *out, const struct mie_op *op)
{
b_stream_write_char(out->p_stream, ' ');
if (MIE_VECTOR_COUNT(op->op_regions) == 0) {
return MIE_SUCCESS;
}
struct mie_region *region = &op->op_regions.items[0];
mie_printer_print_region(out, region, 0);
struct mie_region *region = mie_op_get_first_region(op);
if (region) {
mie_printer_print_region(out, region, 0);
}
return MIE_SUCCESS;
}
@@ -26,4 +26,5 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
MIE_OP_DEFINITION_BEGIN(mie_builtin_module, "module")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);
MIE_OP_DEFINITION_TRAIT("builtin", "isolated-from-above");
MIE_OP_DEFINITION_END()

View File

@@ -1,4 +1,5 @@
#include <mie/dialect/dialect.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/macros.h>
@@ -33,6 +34,23 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_op *mie_cf_br_cond_put(
struct mie_emitter *e, struct mie_register *cond,
struct mie_block *true_block, struct mie_register **true_args,
size_t nr_true_args, struct mie_block *false_block,
struct mie_register **false_args, size_t nr_false_args)
{
struct mie_op *op = mie_emitter_put_op(e, "cf", "br-cond", &cond, 1);
if (!op) {
return NULL;
}
mie_op_add_successor(op, true_block, true_args, nr_true_args);
mie_op_add_successor(op, false_block, false_args, nr_false_args);
return op;
}
MIE_OP_DEFINITION_BEGIN(mie_cf_br_cond, "br-cond")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -1,5 +1,6 @@
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/macros.h>
@@ -20,6 +21,21 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_op *mie_cf_br_put(
struct mie_emitter *e, struct mie_block *dest,
struct mie_register **dest_args, size_t nr_dest_args)
{
struct mie_op *op = mie_emitter_put_op(e, "cf", "br", NULL, 0);
if (!op) {
return NULL;
}
struct mie_op_successor *s
= mie_op_add_successor(op, dest, dest_args, nr_dest_args);
return op;
}
MIE_OP_DEFINITION_BEGIN(mie_cf_br, "br")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -2,9 +2,11 @@
#include <mie/ctx.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
#include <mie/dialect/func.h>
#include <mie/interface/interface-definition.h>
#include <mie/interface/interface.h>
#include <mie/ir/block.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
@@ -26,8 +28,8 @@ 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_region *code = mie_op_get_first_region(op);
const struct mie_block *entry = mie_region_get_first_block(code);
for (size_t i = 0; i < MIE_VECTOR_COUNT(entry->b_params); i++) {
if (i > 0) {
@@ -72,9 +74,62 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_op *mie_func_func_put(
struct mie_emitter *e, const char *name, struct mie_func_parameter *params,
size_t nr_params, const struct mie_type **ret_types, size_t nr_ret_types)
{
const struct mie_type **param_types
= calloc(nr_params, sizeof *param_types);
if (!param_types) {
return NULL;
}
for (size_t i = 0; i < nr_params; i++) {
param_types[i] = params[i].param_type;
}
const struct mie_type *func_type = mie_ctx_get_function_type(
mie_emitter_get_ctx(e), param_types, nr_params, ret_types,
nr_ret_types);
free(param_types);
if (!func_type) {
return NULL;
}
struct mie_op *op = mie_emitter_put_op(e, "func", "func", NULL, 0);
struct mie_region *region = mie_op_add_region(op);
struct mie_block *entry = mie_region_add_block(region);
mie_name_map_put(region->r_names, &entry->b_name, "entry", 0);
for (size_t i = 0; i < nr_params; i++) {
struct mie_register *param_reg = mie_block_add_param(entry);
mie_name_map_put(
region->r_names, &param_reg->reg_name,
params[i].param_name, 0);
param_reg->reg_type = params[i].param_type;
params[i].param_reg = param_reg;
}
struct mie_attribute *sym_name
= mie_ctx_get_string(mie_emitter_get_ctx(e), name);
struct mie_attribute *function_type
= mie_type_attr_create(mie_emitter_get_ctx(e), func_type);
mie_attribute_map_put(
&op->op_attrib, "sym_name", sym_name, MIE_ATTRMAP_F_REPLACE);
mie_attribute_map_put(
&op->op_attrib, "function_type", function_type,
MIE_ATTRMAP_F_REPLACE);
return op;
}
MIE_OP_DEFINITION_BEGIN(mie_func_func, "func")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);
MIE_OP_DEFINITION_TRAIT("builtin", "isolated-from-above");
MIE_OP_INTERFACE_BEGIN("builtin", "symbol", struct mie_symbol)
MIE_OP_INTERFACE_FUNC(sym_get_name) = NULL;
MIE_OP_INTERFACE_END()

View File

@@ -1,9 +1,48 @@
#include <mie/dialect/dialect.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/macros.h>
#include <mie/print/printer.h>
static enum mie_status print(struct mie_printer *printer, const struct mie_op *op)
{
b_stream_write_char(printer->p_stream, ' ');
mie_printer_print_op_arg(printer, &op->op_args.items[0], false);
if (MIE_VECTOR_COUNT(op->op_result) > 0) {
b_stream_write_string(printer->p_stream, " -> ", NULL);
if (MIE_VECTOR_COUNT(op->op_result) > 1) {
b_stream_write_char(printer->p_stream, '(');
}
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_type(printer, op->op_result.items[i].reg_type);
}
if (MIE_VECTOR_COUNT(op->op_result) > 1) {
b_stream_write_char(printer->p_stream, '(');
}
b_stream_write_char(printer->p_stream, ' ');
struct mie_region *if_region = mie_op_get_first_region(op);
struct mie_region *else_region = mie_op_get_next_region(op, if_region);
mie_printer_print_region(printer, if_region, 0);
if (else_region) {
b_stream_write_string(printer->p_stream, " else ", NULL);
mie_printer_print_region(printer, else_region, 0);
}
return MIE_SUCCESS;
}
@@ -12,6 +51,35 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_op *mie_scf_if_put(
struct mie_emitter *e, struct mie_register *cond,
const struct mie_type *result_type, struct mie_region **out_true,
struct mie_region **out_false, const char *name)
{
struct mie_op *op = mie_emitter_put_op(e, "scf", "if", &cond, 1);
if (!op) {
return NULL;
}
if (result_type) {
struct mie_register *result = mie_op_add_result(op, result_type);
mie_emitter_put_name(e, &result->reg_name, name);
}
struct mie_region *r_true = mie_op_add_region(op);
struct mie_region *r_false = mie_op_add_region(op);
if (out_true) {
*out_true = r_true;
}
if (out_false) {
*out_false = r_false;
}
return op;
}
MIE_OP_DEFINITION_BEGIN(mie_scf_if, "if")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -1,9 +1,32 @@
#include <mie/dialect/dialect.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/macros.h>
#include <mie/print/printer.h>
static enum mie_status print(struct mie_printer *printer, const struct mie_op *op)
{
b_stream_write_char(printer->p_stream, ' ');
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_op_arg(printer, &op->op_args.items[i], false);
}
b_stream_write_string(printer->p_stream, " : ", NULL);
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_type(
printer, mie_op_arg_get_type(&op->op_args.items[i]));
}
return MIE_SUCCESS;
}
@@ -12,6 +35,11 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
return MIE_SUCCESS;
}
struct mie_op *mie_scf_yield_put(struct mie_emitter *e, struct mie_register *value)
{
return mie_emitter_put_op(e, "scf", "yield", &value, 1);
}
MIE_OP_DEFINITION_BEGIN(mie_scf_yield, "yield")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);

View File

@@ -36,6 +36,8 @@ struct mie_ctx {
MIE_API struct mie_ctx *mie_ctx_create(void);
MIE_API void mie_ctx_destroy(struct mie_ctx *ctx);
MIE_API struct mie_op *mie_ctx_create_op(
const struct mie_ctx *ctx, const char *dialect, const char *op);
MIE_API bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op);
MIE_API struct mie_dialect *mie_ctx_get_dialect(

View File

@@ -8,7 +8,19 @@
struct mie_ctx;
struct mie_dialect;
struct mie_emitter;
MIE_API struct mie_dialect *mie_arith_dialect_create(struct mie_ctx *ctx);
MIE_API struct mie_register *mie_arith_constant_i_put(
struct mie_emitter *e, long long value, const char *name);
MIE_API struct mie_register *mie_arith_constant_f_put(
struct mie_emitter *e, long long value, const char *name);
MIE_API struct mie_register *mie_arith_addi_put(
struct mie_emitter *e, struct mie_register *left,
struct mie_register *right, const char *name);
MIE_API struct mie_register *mie_arith_addf_put(
struct mie_emitter *e, struct mie_register *left,
struct mie_register *right, const char *name);
#endif

View File

@@ -121,6 +121,9 @@ MIE_API struct mie_type *mie_ctx_get_int_type(struct mie_ctx *ctx, size_t bit_wi
MIE_API struct mie_type *mie_ctx_get_float_type(
struct mie_ctx *ctx, size_t bit_width);
MIE_API struct mie_attribute *mie_type_attr_create(
struct mie_ctx *ctx, const struct mie_type *ty);
MIE_API size_t mie_int_type_get_width(const struct mie_type *type);
MIE_API size_t mie_float_type_get_width(const struct mie_type *type);

View File

@@ -2,10 +2,23 @@
#define MIE_DIALECT_CF_H_
#include <mie/misc.h>
#include <stddef.h>
struct mie_ctx;
struct mie_block;
struct mie_dialect;
struct mie_emitter;
struct mie_register;
MIE_API struct mie_dialect *mie_cf_dialect_create(struct mie_ctx *ctx);
MIE_API struct mie_op *mie_cf_br_put(
struct mie_emitter *e, struct mie_block *dest,
struct mie_register **dest_args, size_t nr_dest_args);
MIE_API struct mie_op *mie_cf_br_cond_put(
struct mie_emitter *e, struct mie_register *cond,
struct mie_block *true_block, struct mie_register **true_args,
size_t nr_true_args, struct mie_block *false_block,
struct mie_register **false_args, size_t nr_false_args);
#endif

View File

@@ -2,10 +2,24 @@
#define MIE_DIALECT_FUNC_H_
#include <mie/misc.h>
#include <stddef.h>
struct mie_ctx;
struct mie_type;
struct mie_dialect;
struct mie_emitter;
struct mie_register;
struct mie_func_parameter {
const char *param_name;
const struct mie_type *param_type;
struct mie_register *param_reg;
};
MIE_API struct mie_dialect *mie_func_dialect_create(struct mie_ctx *ctx);
MIE_API struct mie_op *mie_func_func_put(
struct mie_emitter *e, const char *name, struct mie_func_parameter *params,
size_t nr_params, const struct mie_type **ret_types, size_t nr_ret_types);
#endif

View File

@@ -4,8 +4,19 @@
#include <mie/misc.h>
struct mie_ctx;
struct mie_type;
struct mie_region;
struct mie_dialect;
struct mie_emitter;
struct mie_register;
MIE_API struct mie_dialect *mie_scf_dialect_create(struct mie_ctx *ctx);
MIE_API struct mie_op *mie_scf_if_put(
struct mie_emitter *e, struct mie_register *cond,
const struct mie_type *result_type, struct mie_region **out_true,
struct mie_region **out_false, const char *name);
MIE_API struct mie_op *mie_scf_yield_put(
struct mie_emitter *e, struct mie_register *value);
#endif

View File

@@ -12,13 +12,26 @@ struct mie_register;
struct mie_block {
struct mie_name b_name;
struct mie_region *b_parent;
/* used by struct mie_region */
b_queue_entry b_entry;
MIE_VECTOR_DECLARE(struct mie_register, b_params);
MIE_VECTOR_DECLARE(struct mie_op, b_ops);
/* queue of struct mie_op */
b_queue b_ops;
};
extern struct mie_vector_ops mie_block_vector_ops;
MIE_API struct mie_op *mie_block_get_first_op(const struct mie_block *block);
MIE_API struct mie_op *mie_block_get_prev_op(
const struct mie_block *block, const struct mie_op *before);
MIE_API struct mie_op *mie_block_get_next_op(
const struct mie_block *block, const struct mie_op *after);
MIE_API struct mie_op *mie_block_get_last_op(const struct mie_block *block);
MIE_API struct mie_op *mie_block_add_op(struct mie_block *block);
MIE_API struct mie_op *mie_block_add_op_after(
struct mie_block *block, struct mie_op *after);
MIE_API struct mie_register *mie_block_add_param(struct mie_block *block);
#endif

View File

@@ -0,0 +1,39 @@
#ifndef MIE_IR_BUILDER_H_
#define MIE_IR_BUILDER_H_
#include <mie/ir/emit.h>
#include <mie/misc.h>
#include <stddef.h>
struct mie_op;
struct mie_ctx;
struct mie_type;
struct mie_name;
struct mie_block;
struct mie_region;
struct mie_register;
struct mie_builder;
MIE_API struct mie_builder *mie_builder_create(
struct mie_ctx *ctx, struct mie_op *root);
MIE_API void mie_builder_destroy(struct mie_builder *builder);
MIE_API struct mie_ctx *mie_builder_get_ctx(struct mie_builder *builder);
MIE_API struct mie_block *mie_builder_get_current_block(struct mie_builder *builder);
MIE_API void mie_builder_step_into_op(
struct mie_builder *builder, struct mie_op *op);
MIE_API void mie_builder_step_into_region(
struct mie_builder *builder, struct mie_region *region);
MIE_API void mie_builder_step_into_block(
struct mie_builder *builder, struct mie_block *block);
MIE_API void mie_builder_step_out(struct mie_builder *builder);
MIE_API struct mie_op *mie_builder_put_op(
struct mie_builder *builder, const char *dialect, const char *op,
struct mie_register **args, size_t nr_args);
MIE_API enum mie_status mie_builder_put_name(
struct mie_builder *builder, struct mie_name *name, const char *hint);
#endif

42
mie/include/mie/ir/emit.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef MIE_IR_EMIT_H_
#define MIE_IR_EMIT_H_
#include <mie/misc.h>
#include <mie/status.h>
#include <stddef.h>
#define MIE_EMITTER(p) ((struct mie_emitter *)(p))
struct mie_op;
struct mie_name;
struct mie_block;
struct mie_register;
struct mie_emitter;
typedef struct mie_ctx *(*mie_emit_get_ctx)(const struct mie_emitter *);
typedef enum mie_status (*mie_emit_put_name)(
struct mie_emitter *, struct mie_name *, const char *);
typedef struct mie_op *(*mie_emit_put_op)(
struct mie_emitter *, const char *, const char *,
struct mie_register **, size_t);
typedef struct mie_block *(*mie_emit_put_block)(
struct mie_emitter *, struct mie_block *);
struct mie_emitter {
mie_emit_get_ctx e_get_ctx;
mie_emit_put_name e_put_name;
mie_emit_put_op e_put_op;
mie_emit_put_block e_put_block;
};
MIE_API struct mie_ctx *mie_emitter_get_ctx(struct mie_emitter *emitter);
MIE_API enum mie_status mie_emitter_put_name(
struct mie_emitter *emitter, struct mie_name *name, const char *hint);
MIE_API struct mie_op *mie_emitter_put_op(
struct mie_emitter *emitter, const char *dialect_name,
const char *op_name, struct mie_register **args, size_t nr_args);
MIE_API struct mie_block *mie_emitter_put_block(
struct mie_emitter *emitter, struct mie_block *insert_point);
#endif

View File

@@ -50,16 +50,20 @@ struct mie_op_successor {
struct mie_op {
enum mie_op_flags op_flags;
/* used by struct mie_block */
b_queue_entry op_entry;
/* these pointers are only valid if the F_OP_RESOLVED flag is set */
const struct mie_dialect *op_dialect;
const struct mie_op_definition *op_info;
struct mie_block *op_container;
struct mie_file_span op_name_span;
/* only valid if the F_RESOLVED flag is NOT set */
char *op_name;
MIE_VECTOR_DECLARE(struct mie_region, op_regions);
b_queue op_regions;
MIE_VECTOR_DECLARE(struct mie_op_successor, op_successors);
struct mie_attribute_map op_attrib;
MIE_VECTOR_DECLARE(struct mie_op_arg, op_args);
@@ -72,11 +76,34 @@ MIE_API void mie_op_destroy(struct mie_op *op);
MIE_API void mie_op_init(struct mie_op *op);
MIE_API void mie_op_cleanup(struct mie_op *op);
MIE_API struct mie_op_arg *mie_op_add_arg(struct mie_op *op);
MIE_API struct mie_register *mie_op_add_result(
struct mie_op *op, const struct mie_type *ty);
MIE_API struct mie_op_successor *mie_op_add_successor(
struct mie_op *op, struct mie_block *block, struct mie_register **args,
size_t nr_args);
MIE_API struct mie_region *mie_op_add_region(struct mie_op *op);
MIE_API bool mie_op_is(
const struct mie_op *op, const char *dialect_name, const char *op_name);
MIE_API bool mie_op_has_trait(
const struct mie_op *op, const char *dialect_name, const char *trait_name);
MIE_API bool mie_op_has_interface(
const struct mie_op *op, const char *dialect_name, const char *iface_name);
MIE_API struct mie_op *mie_op_get_parent(const struct mie_op *op);
MIE_API struct mie_region *mie_op_get_first_region(const struct mie_op *op);
MIE_API struct mie_region *mie_op_get_prev_region(
const struct mie_op *op, const struct mie_region *before);
MIE_API struct mie_region *mie_op_get_next_region(
const struct mie_op *op, const struct mie_region *after);
MIE_API struct mie_region *mie_op_get_last_region(const struct mie_op *op);
MIE_API struct mie_register *mie_op_get_arg(const struct mie_op *op, size_t index);
MIE_API struct mie_op *mie_op_get_first_child_op(const struct mie_op *op);
MIE_API struct mie_op *mie_op_get_last_child_op(const struct mie_op *op);
MIE_API const struct mie_type *mie_op_arg_get_type(const struct mie_op_arg *arg);
#endif

View File

@@ -1,6 +1,7 @@
#ifndef MIE_IR_REGION_H_
#define MIE_IR_REGION_H_
#include <blue/core/queue.h>
#include <mie/misc.h>
#include <mie/vector.h>
#include <stddef.h>
@@ -11,9 +12,22 @@ struct mie_block;
struct mie_region {
struct mie_name_map *r_names;
struct mie_op *r_parent;
MIE_VECTOR_DECLARE(struct mie_block, r_blocks);
/* used by struct mie_op */
b_queue_entry r_entry;
/* queue of struct mie_block */
b_queue r_blocks;
};
MIE_API struct mie_block *mie_region_get_first_block(
const struct mie_region *region);
MIE_API struct mie_block *mie_region_get_prev_block(
const struct mie_region *region, const struct mie_block *before);
MIE_API struct mie_block *mie_region_get_next_block(
const struct mie_region *region, const struct mie_block *after);
MIE_API struct mie_block *mie_region_get_last_block(const struct mie_region *region);
MIE_API struct mie_block *mie_region_add_block(struct mie_region *region);
MIE_API struct mie_block *mie_region_add_block_after(
struct mie_region *region, struct mie_block *after);
#endif

View File

@@ -62,8 +62,13 @@ struct mie_register {
};
extern struct mie_vector_ops mie_register_vector_ops;
extern struct mie_vector_ops mie_register_use_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);
MIE_API void mie_register_use_move(
struct mie_register_use *dest, struct mie_register_use *src);
MIE_API void mie_register_use_cleanup(struct mie_register_use *reg);
#endif

View File

@@ -1,6 +0,0 @@
#ifndef MIE_IR_REWRITE_H_
#define MIE_IR_REWRITE_H_
struct mie_rewriter;
#endif

View File

@@ -1,12 +1,12 @@
#ifndef MIE_IR_WALK_H_
#define MIE_IR_WALK_H_
#include <blue/core/queue.h>
#include <mie/misc.h>
#include <mie/status.h>
#include <stddef.h>
struct mie_op;
struct mie_walker;
enum mie_walker_flags {
MIE_WALKER_F_NONE = 0x00u,
@@ -26,19 +26,45 @@ enum mie_walker_flags {
MIE_WALKER_F_INCLUDE_BLOCKS = 0x20u,
};
struct mie_walker_item {
size_t i_depth;
struct mie_op *i_op;
struct mie_block *i_block;
struct mie_region *i_region;
enum mie_walk_item_type {
MIE_WALK_ITEM_NONE = 0,
MIE_WALK_ITEM_OP,
MIE_WALK_ITEM_BLOCK,
MIE_WALK_ITEM_REGION,
};
MIE_API struct mie_walker *mie_walker_begin(
struct mie_op *op, enum mie_walker_flags flags);
struct mie_walk_item {
int _f;
b_queue_entry _e;
enum mie_walk_item_type i_type;
// size_t i_index;
size_t i_depth;
union {
struct mie_op *i_op;
struct mie_block *i_block;
struct mie_region *i_region;
};
};
struct mie_walker {
enum mie_walker_flags w_flags;
union {
/* used for recursive walks */
b_queue w_stack;
/* used for non-recursive walks */
struct {
struct mie_walk_item w_region, w_block, w_op;
};
};
};
MIE_API void mie_walker_begin(
struct mie_walker *walker, const struct mie_op *op,
enum mie_walker_flags flags);
MIE_API void mie_walker_end(struct mie_walker *walker);
MIE_API enum mie_status mie_walker_step(struct mie_walker *walker);
MIE_API struct mie_walker_item *mie_walker_get(struct mie_walker *walker);
MIE_API struct mie_walk_item *mie_walker_get(struct mie_walker *walker);
#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

@@ -107,8 +107,7 @@ MIE_API bool mie_parser_parse_register_list(
MIE_API bool mie_parser_parse_region(
struct mie_parser *ctx, struct mie_op *parent, struct mie_region *region);
MIE_API bool mie_parser_parse_region_list(
struct mie_parser *ctx, struct mie_op *parent,
MIE_VECTOR_REF_PARAM(struct mie_region, out));
struct mie_parser *ctx, struct mie_op *parent);
MIE_API bool mie_parser_parse_anonymous_block(
struct mie_parser *ctx, struct mie_name_map *names,
struct mie_block *block);

View File

@@ -14,6 +14,7 @@
struct mie_op;
struct mie_ctx;
struct mie_pass;
struct mie_dialect;
struct mie_op_definition;
struct mie_trait_definition;
struct mie_interface_definition;
@@ -40,6 +41,7 @@ struct mie_pass_args {
};
struct mie_pass_filter {
const struct mie_dialect *f_dialect;
const struct mie_op_definition *f_op;
const struct mie_trait_definition *f_trait;
const struct mie_interface_definition *f_iface;

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

102
mie/ir/block.c Normal file
View File

@@ -0,0 +1,102 @@
#include <mie/ir/block.h>
#include <mie/ir/op.h>
#include <mie/ir/register.h>
struct mie_op *mie_block_get_first_op(const struct mie_block *block)
{
b_queue_entry *entry = b_queue_first(&block->b_ops);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_op, entry, op_entry);
}
struct mie_op *mie_block_get_prev_op(
const struct mie_block *block, const struct mie_op *before)
{
if (!before || before->op_container != block) {
return NULL;
}
b_queue_entry *entry = b_queue_prev(&before->op_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_op, entry, op_entry);
}
struct mie_op *mie_block_get_next_op(
const struct mie_block *block, const struct mie_op *after)
{
if (!after || after->op_container != block) {
return NULL;
}
b_queue_entry *entry = b_queue_next(&after->op_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_op, entry, op_entry);
}
struct mie_op *mie_block_get_last_op(const struct mie_block *block)
{
b_queue_entry *entry = b_queue_last(&block->b_ops);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_op, entry, op_entry);
}
struct mie_op *mie_block_add_op(struct mie_block *block)
{
struct mie_op *op = malloc(sizeof *op);
if (!op) {
return NULL;
}
mie_op_init(op);
op->op_container = block;
b_queue_push_back(&block->b_ops, &op->op_entry);
return op;
}
struct mie_op *mie_block_add_op_after(struct mie_block *block, struct mie_op *after)
{
if (after && after->op_container != block) {
return NULL;
}
struct mie_op *op = malloc(sizeof *op);
if (!op) {
return NULL;
}
mie_op_init(op);
op->op_container = block;
if (after) {
b_queue_insert_after(&block->b_ops, &op->op_entry, &after->op_entry);
} else {
b_queue_push_back(&block->b_ops, &op->op_entry);
}
return op;
}
struct mie_register *mie_block_add_param(struct mie_block *block)
{
struct mie_register *result = mie_vector_emplace_back(
block->b_params, &mie_register_vector_ops);
result->reg_flags = MIE_REGISTER_F_VIRTUAL | MIE_REGISTER_F_BLOCK_PARAM;
result->reg_block = block;
result->reg_op = NULL;
return result;
}

172
mie/ir/builder.c Normal file
View File

@@ -0,0 +1,172 @@
#include <mie/ctx.h>
#include <mie/ir/block.h>
#include <mie/ir/builder.h>
#include <mie/ir/emit.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
struct builder_scope {
b_queue_entry s_entry;
struct mie_op *s_op;
struct mie_region *s_region;
struct mie_block *s_block;
};
struct mie_builder {
struct mie_emitter b_base;
struct mie_ctx *b_ctx;
b_queue b_scope_stack;
struct mie_op *b_root;
struct mie_op *b_prev_op;
};
struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_op *root)
{
struct mie_builder *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->b_base.e_get_ctx = (mie_emit_get_ctx)mie_builder_get_ctx;
out->b_base.e_put_op = (mie_emit_put_op)mie_builder_put_op;
out->b_base.e_put_name = (mie_emit_put_name)mie_builder_put_name;
out->b_base.e_put_block = NULL;
out->b_ctx = ctx;
out->b_root = root;
mie_builder_step_into_op(out, root);
return out;
}
struct mie_ctx *mie_builder_get_ctx(struct mie_builder *builder)
{
return builder->b_ctx;
}
static struct mie_name_map *get_current_name_map(struct mie_builder *builder)
{
b_queue_entry *cur = b_queue_last(&builder->b_scope_stack);
while (cur) {
struct builder_scope *scope
= b_unbox(struct builder_scope, cur, s_entry);
if (scope->s_region && scope->s_region->r_names) {
return scope->s_region->r_names;
}
cur = b_queue_prev(cur);
}
return NULL;
}
struct mie_block *mie_builder_get_current_block(struct mie_builder *builder)
{
b_queue_entry *entry = b_queue_last(&builder->b_scope_stack);
if (!entry) {
return NULL;
}
struct builder_scope *scope
= b_unbox(struct builder_scope, entry, s_entry);
return scope->s_block;
}
void mie_builder_step_into_op(struct mie_builder *builder, struct mie_op *op)
{
struct mie_region *region = mie_op_get_last_region(op);
if (!region) {
region = mie_op_add_region(op);
}
mie_builder_step_into_region(builder, region);
}
void mie_builder_step_into_region(
struct mie_builder *builder, struct mie_region *region)
{
struct mie_block *block = mie_region_get_last_block(region);
if (!block) {
block = mie_region_add_block(region);
}
mie_builder_step_into_block(builder, block);
}
void mie_builder_step_into_block(struct mie_builder *builder, struct mie_block *block)
{
struct builder_scope *scope = malloc(sizeof *scope);
if (!scope) {
return;
}
memset(scope, 0x0, sizeof *scope);
scope->s_block = block;
scope->s_region = block->b_parent;
scope->s_op = scope->s_region->r_parent;
b_queue_push_back(&builder->b_scope_stack, &scope->s_entry);
}
void mie_builder_step_out(struct mie_builder *builder)
{
b_queue_entry *entry = b_queue_last(&builder->b_scope_stack);
if (!entry) {
return;
}
struct builder_scope *scope
= b_unbox(struct builder_scope, entry, s_entry);
b_queue_delete(&builder->b_scope_stack, entry);
free(scope);
}
struct mie_op *mie_builder_put_op(
struct mie_builder *builder, const char *dialect, const char *op_name,
struct mie_register **args, size_t nr_args)
{
struct mie_block *block = mie_builder_get_current_block(builder);
const struct mie_op_definition *op_def
= mie_ctx_get_op_definition(builder->b_ctx, dialect, op_name);
if (!op_def) {
return NULL;
}
struct mie_op *op = mie_block_add_op(block);
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;
}
enum mie_status mie_builder_put_name(
struct mie_builder *builder, struct mie_name *name, const char *hint)
{
struct mie_name_map *map = get_current_name_map(builder);
if (!map) {
return MIE_ERR_BAD_STATE;
}
struct mie_name *result = mie_name_map_put(map, name, hint, 0);
return result ? MIE_SUCCESS : MIE_ERR_NAME_EXISTS;
}

42
mie/ir/emit.c Normal file
View File

@@ -0,0 +1,42 @@
#include <mie/ir/emit.h>
struct mie_ctx *mie_emitter_get_ctx(struct mie_emitter *emitter)
{
if (emitter->e_get_ctx) {
return emitter->e_get_ctx(emitter);
}
return NULL;
}
enum mie_status mie_emitter_put_name(
struct mie_emitter *emitter, struct mie_name *name, const char *hint)
{
if (emitter->e_put_name) {
return emitter->e_put_name(emitter, name, hint);
}
return MIE_ERR_NOT_SUPPORTED;
}
struct mie_op *mie_emitter_put_op(
struct mie_emitter *emitter, const char *dialect_name,
const char *op_name, struct mie_register **args, size_t nr_args)
{
if (emitter->e_put_op) {
return emitter->e_put_op(
emitter, dialect_name, op_name, args, nr_args);
}
return NULL;
}
struct mie_block *mie_emitter_put_block(
struct mie_emitter *emitter, struct mie_block *insert_point)
{
if (emitter->e_put_block) {
return emitter->e_put_block(emitter, insert_point);
}
return NULL;
}

View File

@@ -1,7 +1,41 @@
#include <assert.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <stdlib.h>
static enum mie_status op_arg_cleanup(void *p)
{
struct mie_op_arg *arg = p;
if (arg->arg_flags & MIE_OP_F_ARG_RESOLVED) {
b_queue_delete(
&arg->arg_value.u_reg->reg_use, &arg->arg_value.u_entry);
}
return MIE_SUCCESS;
}
static enum mie_status op_arg_move(void *dst, void *src, size_t itemsz)
{
assert(itemsz == sizeof(struct mie_op_arg));
struct mie_op_arg *dest_arg = dst, *src_arg = src;
memmove(dest_arg, src_arg, sizeof *src_arg);
if (src_arg->arg_flags & MIE_OP_F_ARG_RESOLVED) {
mie_register_use_move(&dest_arg->arg_value, &src_arg->arg_value);
}
return MIE_SUCCESS;
}
struct mie_vector_ops op_arg_vector_ops = {
.v_destroy = op_arg_cleanup,
.v_move = op_arg_move,
};
struct mie_op *mie_op_create(void)
{
struct mie_op *out = malloc(sizeof *out);
@@ -32,6 +66,94 @@ void mie_op_cleanup(struct mie_op *op)
/* TODO */
}
struct mie_op_arg *mie_op_add_arg(struct mie_op *op)
{
return mie_vector_emplace_back(op->op_args, &op_arg_vector_ops);
}
struct mie_register *mie_op_add_result(struct mie_op *op, const struct mie_type *ty)
{
struct mie_register *result = mie_vector_emplace_back(
op->op_result, &mie_register_vector_ops);
result->reg_flags = MIE_REGISTER_F_VIRTUAL | MIE_REGISTER_F_OP_RESULT;
result->reg_type = ty;
result->reg_op = op;
result->reg_block = op->op_container;
return result;
}
struct mie_op_successor *mie_op_add_successor(
struct mie_op *op, struct mie_block *block, struct mie_register **args,
size_t nr_args)
{
struct mie_op_successor *s
= mie_vector_emplace_back(op->op_successors, NULL);
s->s_flags = MIE_OP_F_SUCCESSOR_RESOLVED;
s->s_block = block;
for (size_t i = 0; i < nr_args; i++) {
struct mie_op_arg *arg
= mie_vector_emplace_back(s->s_args, &op_arg_vector_ops);
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 s;
}
static bool is_isolated(const struct mie_op *op)
{
if (!(op->op_flags & MIE_OP_F_OP_RESOLVED)) {
return false;
}
const struct mie_trait *isolated = mie_trait_table_get_unique(
&op->op_info->op_traits, "builtin", "isolated-from-above");
return isolated != NULL;
}
struct mie_region *mie_op_add_region(struct mie_op *op)
{
bool isolated = is_isolated(op);
struct mie_region *region = malloc(sizeof *region);
if (!region) {
return NULL;
}
region->r_parent = op;
if (isolated) {
region->r_names = mie_name_map_create(NULL);
}
b_queue_push_back(&op->op_regions, &region->r_entry);
return region;
}
bool mie_op_is(const struct mie_op *op, const char *dialect_name, const char *op_name)
{
if (!op->op_info || !op->op_dialect) {
return false;
}
if (strcmp(op->op_dialect->d_name, dialect_name) != 0) {
return false;
}
if (strcmp(op->op_info->op_name, op_name) != 0) {
return false;
}
return true;
}
bool mie_op_has_trait(
const struct mie_op *op, const char *dialect_name, const char *trait_name)
{
@@ -62,3 +184,97 @@ bool mie_op_has_interface(
&op->op_info->op_iface, dialect_name, iface_name);
return p != NULL;
}
struct mie_region *mie_op_get_first_region(const struct mie_op *op)
{
b_queue_entry *entry = b_queue_first(&op->op_regions);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_region, entry, r_entry);
}
struct mie_region *mie_op_get_prev_region(
const struct mie_op *op, const struct mie_region *before)
{
if (!before || before->r_parent != op) {
return NULL;
}
b_queue_entry *entry = b_queue_prev(&before->r_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_region, entry, r_entry);
}
struct mie_region *mie_op_get_next_region(
const struct mie_op *op, const struct mie_region *after)
{
if (!after || after->r_parent != op) {
return NULL;
}
b_queue_entry *entry = b_queue_next(&after->r_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_region, entry, r_entry);
}
struct mie_region *mie_op_get_last_region(const struct mie_op *op)
{
b_queue_entry *entry = b_queue_last(&op->op_regions);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_region, entry, r_entry);
}
struct mie_register *mie_op_get_arg(const struct mie_op *op, size_t index)
{
if (MIE_VECTOR_COUNT(op->op_args) <= index) {
return NULL;
}
const struct mie_op_arg *arg = &op->op_args.items[index];
if (!(arg->arg_flags & MIE_OP_F_ARG_RESOLVED)) {
return NULL;
}
return arg->arg_value.u_reg;
}
struct mie_op *mie_op_get_first_child_op(const struct mie_op *op)
{
struct mie_region *first_region = mie_op_get_first_region(op);
if (!first_region) {
return NULL;
}
struct mie_block *first_block = mie_region_get_first_block(first_region);
if (!first_block) {
return NULL;
}
return mie_block_get_first_op(first_block);
}
struct mie_op *mie_op_get_last_child_op(const struct mie_op *op)
{
struct mie_region *last_region = mie_op_get_last_region(op);
if (!last_region) {
return NULL;
}
struct mie_block *last_block = mie_region_get_last_block(last_region);
if (!last_block) {
return NULL;
}
return mie_block_get_last_op(last_block);
}

View File

@@ -3,16 +3,89 @@
#include <stdlib.h>
#include <string.h>
struct mie_block *mie_region_get_first_block(const struct mie_region *region)
{
b_queue_entry *entry = b_queue_first(&region->r_blocks);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_prev_block(
const struct mie_region *region, const struct mie_block *before)
{
if (!before || before->b_parent != region) {
return NULL;
}
b_queue_entry *entry = b_queue_prev(&before->b_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_next_block(
const struct mie_region *region, const struct mie_block *after)
{
if (!after || after->b_parent != region) {
return NULL;
}
b_queue_entry *entry = b_queue_next(&after->b_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_last_block(const struct mie_region *region)
{
b_queue_entry *entry = b_queue_last(&region->r_blocks);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_add_block(struct mie_region *region)
{
struct mie_block *block = mie_vector_emplace_back(
region->r_blocks, &mie_block_vector_ops);
struct mie_block *block = malloc(sizeof *block);
if (!block) {
return NULL;
}
memset(block, 0x0, sizeof *block);
block->b_parent = region;
b_queue_push_back(&region->r_blocks, &block->b_entry);
return block;
}
struct mie_block *mie_region_add_block_after(
struct mie_region *region, struct mie_block *after)
{
if (after->b_parent != region) {
return NULL;
}
struct mie_block *block = malloc(sizeof *block);
if (!block) {
return NULL;
}
memset(block, 0x0, sizeof *block);
block->b_parent = region;
b_queue_insert_after(&region->r_blocks, &block->b_entry, &after->b_entry);
return block;
}

View File

@@ -1,13 +1,14 @@
#include <assert.h>
#include <blue/core/queue.h>
#include <mie/ir/register.h>
static enum mie_status cleanup(void *p)
static enum mie_status reg_cleanup(void *p)
{
mie_register_cleanup(p);
return MIE_SUCCESS;
}
static enum mie_status move(void *dst, void *src, size_t itemsz)
static enum mie_status reg_move(void *dst, void *src, size_t itemsz)
{
assert(itemsz == sizeof(struct mie_register));
struct mie_register *dest_reg = dst, *src_reg = src;
@@ -15,9 +16,23 @@ static enum mie_status move(void *dst, void *src, size_t itemsz)
return MIE_SUCCESS;
}
static enum mie_status reg_use_cleanup(void *p)
{
mie_register_use_cleanup(p);
return MIE_SUCCESS;
}
static enum mie_status reg_use_move(void *dst, void *src, size_t itemsz)
{
assert(itemsz == sizeof(struct mie_register_use));
struct mie_register_use *dest_reg = dst, *src_reg = src;
mie_register_use_move(dest_reg, src_reg);
return MIE_SUCCESS;
}
struct mie_vector_ops mie_register_vector_ops = {
.v_destroy = cleanup,
.v_move = move,
.v_destroy = reg_cleanup,
.v_move = reg_move,
};
void mie_register_move(struct mie_register *dest, struct mie_register *src)
@@ -35,3 +50,20 @@ void mie_register_cleanup(struct mie_register *reg)
mie_name_destroy(&reg->reg_name);
}
}
void mie_register_use_move(
struct mie_register_use *dest, struct mie_register_use *src)
{
memmove(dest, src, sizeof *dest);
if (src->u_reg) {
b_queue_move(&src->u_reg->reg_use, &src->u_entry, &dest->u_entry);
}
}
void mie_register_use_cleanup(struct mie_register_use *use)
{
if (use->u_reg) {
b_queue_delete(&use->u_reg->reg_use, &use->u_entry);
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -305,6 +305,10 @@ void mie_name_move(struct mie_name *dst, struct mie_name *src)
void mie_name_destroy(struct mie_name *name)
{
struct mie_name_map *parent = name->n_parent;
if (!parent) {
return;
}
struct mie_name_map_entry *entry
= get_entry(&parent->m_entries, name->n_base.e_hash);
struct mie_name_bucket *bucket = NULL;

View File

@@ -798,15 +798,13 @@ bool mie_parser_parse_region(
return true;
}
bool mie_parser_parse_region_list(
struct mie_parser *ctx, struct mie_op *parent,
MIE_VECTOR_REF_PARAM(struct mie_region, out))
bool mie_parser_parse_region_list(struct mie_parser *ctx, struct mie_op *parent)
{
if (!mie_parser_check_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
return false;
}
struct mie_region *region = mie_vector_ref_emplace_back(out, NULL);
struct mie_region *region = mie_op_add_region(parent);
if (!mie_parser_parse_region(ctx, parent, region)) {
return false;
@@ -821,7 +819,7 @@ bool mie_parser_parse_region_list(
break;
}
struct mie_region *region = mie_vector_ref_emplace_back(out, NULL);
struct mie_region *region = mie_op_add_region(parent);
if (!mie_parser_parse_region(ctx, parent, region)) {
@@ -837,8 +835,7 @@ bool mie_parser_parse_anonymous_block(
{
mie_parser_parse_linefeed(ctx);
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
@@ -855,8 +852,7 @@ bool mie_parser_parse_anonymous_block(
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
@@ -950,8 +946,7 @@ bool mie_parser_parse_block(
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
}
@@ -1090,8 +1085,7 @@ static bool parse_generic_op(
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
mie_parser_parse_linefeed(ctx);
if (!mie_parser_parse_region_list(
ctx, dest, MIE_VECTOR_REF(dest->op_regions))) {
if (!mie_parser_parse_region_list(ctx, dest)) {
return false;
}
@@ -1150,9 +1144,6 @@ static bool parse_graph_op(
bool mie_parser_parse_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
memset(dest, 0x0, sizeof *dest);
mie_attribute_map_init(&dest->op_attrib);
if (mie_parser_check_eof(ctx)) {
return false;
}

View File

@@ -4,4 +4,5 @@
MIE_PASS_GROUP_BEGIN(mie_builtin)
MIE_PASS_GROUP_ADD_PASS(prefix_func_with_underscore);
MIE_PASS_GROUP_ADD_PASS(convert_scf_to_cf);
MIE_PASS_GROUP_END()

View File

@@ -0,0 +1,136 @@
#include <mie/ctx.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/ir/walk.h>
#include <mie/macros.h>
#include <mie/pass/pass-definition.h>
#include <mie/pass/pass.h>
#include <mie/rewrite/convert.h>
#include <mie/rewrite/pattern.h>
#include <mie/rewrite/rewriter.h>
static bool op_is_flat(const struct mie_op *op)
{
return false;
}
static enum mie_match_result if_match(const struct mie_op *op)
{
if (!mie_op_is(op, "scf", "if")) {
return MIE_NO_MATCH_FOUND;
}
return MIE_MATCH_FOUND;
}
static struct mie_rewrite_result if_rewrite(
struct mie_op *op, struct mie_rewriter *rewriter)
{
printf("if: rewriting %p %s.%s\n", op, op->op_dialect->d_name,
op->op_info->op_name);
struct mie_register *cond = mie_op_get_arg(op, 0);
struct mie_region *parent_region = op->op_container->b_parent;
struct mie_region *if_region = mie_op_get_first_region(op);
struct mie_block *if_start = mie_region_get_first_block(if_region);
struct mie_block *if_end = mie_region_get_last_block(if_region);
struct mie_region *else_region = mie_op_get_next_region(op, if_region);
struct mie_block *else_start = mie_region_get_first_block(else_region);
struct mie_block *pre_block = op->op_container;
struct mie_block *end_block
= mie_rewriter_split_block(rewriter, pre_block, op, "if.end");
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
struct mie_register *old_reg = &op->op_result.items[i];
struct mie_register *new_reg = mie_block_add_param(end_block);
new_reg->reg_type = old_reg->reg_type;
char *name = b_strdup(old_reg->reg_name.n_str);
mie_name_destroy(&old_reg->reg_name);
mie_rewriter_rename_register(rewriter, new_reg, name);
mie_rewriter_replace_register(rewriter, old_reg, new_reg);
free(name);
}
struct mie_walker walker;
mie_walker_begin(&walker, op, MIE_WALKER_F_INCLUDE_OPS);
do {
const struct mie_walk_item *item = mie_walker_get(&walker);
if (!mie_op_is(item->i_op, "scf", "yield")) {
continue;
}
printf("if: found scf.yield %p\n", item->i_op);
struct mie_op *br = mie_rewriter_replace_op(
rewriter, item->i_op, "cf", "br");
struct mie_op_successor *s = mie_rewriter_add_op_successor(
rewriter, br, end_block, NULL, 0);
mie_rewriter_move_op_args_to_successor(rewriter, br, s);
} while (mie_walker_step(&walker) == MIE_SUCCESS);
mie_walker_end(&walker);
mie_rewriter_move_blocks_after(
rewriter, if_region, parent_region, pre_block);
mie_rewriter_rename_block(rewriter, if_start, "if.then");
if (else_region) {
mie_rewriter_move_blocks_after(
rewriter, else_region, parent_region, if_end);
mie_rewriter_rename_block(rewriter, else_start, "if.else");
}
mie_rewriter_erase_op(rewriter, op);
mie_rewriter_set_insertion_block(rewriter, pre_block);
mie_rewriter_set_insertion_point(rewriter, NULL);
mie_cf_br_cond_put(
MIE_EMITTER(rewriter), cond, if_start, NULL, 0, else_start,
NULL, 0);
return MIE_REWRITE_RESULT(MIE_REWRITE_SUCCESS, MIE_SUCCESS);
}
MIE_REWRITE_PATTERN_BEGIN(if_pattern)
MIE_REWRITE_PATTERN_ROOT("scf", "if");
MIE_REWRITE_PATTERN_MATCH(if_match);
MIE_REWRITE_PATTERN_REWRITE(if_rewrite);
MIE_REWRITE_PATTERN_END()
static struct mie_pass_result transform(
struct mie_pass *pass, struct mie_op *op, struct mie_pass_args *args)
{
printf("%s: taking a look at %p %s.%s\n", mie_pass_get_name(pass), op,
op->op_dialect->d_name, op->op_info->op_name);
struct mie_convert_config *cfg = mie_convert_config_create(args->p_ctx);
mie_convert_config_add_illegal_op(cfg, "scf", "if");
struct mie_pattern_set patterns = {};
if_pattern_create(&patterns);
mie_convert_apply(op, cfg, &patterns);
mie_pattern_set_cleanup(&patterns);
mie_convert_config_destroy(cfg);
return MIE_PASS_CONTINUE;
}
MIE_PASS_DEFINITION_BEGIN(convert_scf_to_cf)
MIE_PASS_NAME("convert-scf-to-cf");
MIE_PASS_DESCRIPTION(
"Convert high-level SCF constructs to low-level CF operations "
"and blocks.");
MIE_PASS_TRANSFORM(transform);
MIE_PASS_FILTER_OP("func", "func");
MIE_PASS_DEFINITION_END()

View File

@@ -87,18 +87,19 @@ enum mie_status mie_pass_manager_filter_op(
return MIE_SUCCESS;
}
if (!dialect_name || !op_name) {
if (!dialect_name) {
return MIE_ERR_INVALID_ARGUMENT;
}
const struct mie_op_definition *op
= mie_ctx_get_op_definition(pm->pm_ctx, dialect_name, op_name);
if (!op) {
return MIE_ERR_NO_ENTRY;
if (!op_name) {
pm->pm_filter.f_dialect
= mie_ctx_get_dialect(pm->pm_ctx, dialect_name);
return pm->pm_filter.f_dialect ? MIE_SUCCESS : MIE_ERR_NO_ENTRY;
}
pm->pm_filter.f_op = op;
return MIE_SUCCESS;
pm->pm_filter.f_op
= mie_ctx_get_op_definition(pm->pm_ctx, dialect_name, op_name);
return pm->pm_filter.f_op ? MIE_SUCCESS : MIE_ERR_NO_ENTRY;
}
enum mie_status mie_pass_manager_filter_trait(
@@ -152,6 +153,10 @@ static bool filter_check_op(
return false;
}
if (filter->f_dialect && op->op_dialect != filter->f_dialect) {
return false;
}
if (filter->f_trait
&& !mie_op_has_trait(
op, filter->f_trait->tr_parent->d_name,
@@ -199,16 +204,17 @@ static void schedule_passes(
b_queue_push_back(schedule, &sched->s_entry);
}
struct mie_walker *walker = mie_walker_begin(op, MIE_WALKER_F_INCLUDE_OPS);
while (mie_walker_step(walker) == MIE_SUCCESS) {
struct mie_walker walker;
mie_walker_begin(&walker, op, MIE_WALKER_F_INCLUDE_OPS);
do {
for (size_t i = 0; i < MIE_VECTOR_COUNT(pm->pm_nested); i++) {
struct mie_pass_manager *nested = pm->pm_nested.items[i];
struct mie_walker_item *item = mie_walker_get(walker);
struct mie_walk_item *item = mie_walker_get(&walker);
schedule_passes(nested, schedule, item->i_op, depth + 1);
}
}
} while (mie_walker_step(&walker) == MIE_SUCCESS);
mie_walker_end(walker);
mie_walker_end(&walker);
}
static void sched_item_execute(

View File

@@ -51,7 +51,8 @@ static void print_block_header_params(
static void print_block_header(
struct mie_printer *printer, const struct mie_block *block)
{
if (!block->b_name.n_str && !MIE_VECTOR_COUNT(block->b_params)) {
bool first_block = b_queue_prev(&block->b_entry) == NULL;
if (first_block && !block->b_name.n_str) {
return;
}
@@ -59,6 +60,8 @@ static void print_block_header(
if (block->b_name.n_str) {
b_stream_write_string(printer->p_stream, block->b_name.n_str, NULL);
} else {
b_stream_write_string(printer->p_stream, "<UNNAMED>", NULL);
}
print_block_header_params(printer, block);
@@ -76,10 +79,11 @@ void mie_printer_print_block(
b_stream_push_indent(printer->p_stream, 4);
for (size_t i = 0; i < MIE_VECTOR_COUNT(block->b_ops); i++) {
const struct mie_op *op = &block->b_ops.items[i];
struct mie_op *op = mie_block_get_first_op(block);
while (op) {
mie_printer_print_op(printer, op);
b_stream_write_char(printer->p_stream, '\n');
op = mie_block_get_next_op(block, op);
}
b_stream_pop_indent(printer->p_stream);

View File

@@ -13,9 +13,15 @@ void mie_printer_print_op_arg(
const struct mie_type *arg_type = NULL;
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
arg_flags = arg->arg_value.u_reg->reg_flags;
arg_name = arg->arg_value.u_reg->reg_name.n_str;
arg_type = arg->arg_value.u_reg->reg_type;
if (!arg->arg_value.u_reg) {
arg_flags = 0;
arg_name = "<NULL>";
arg_type = NULL;
} else {
arg_flags = arg->arg_value.u_reg->reg_flags;
arg_name = arg->arg_value.u_reg->reg_name.n_str;
arg_type = arg->arg_value.u_reg->reg_type;
}
} else {
arg_flags = arg->arg_unresolved.reg_flags;
arg_name = arg->arg_unresolved.reg_name;
@@ -30,7 +36,7 @@ void mie_printer_print_op_arg(
b_stream_write_string(printer->p_stream, arg_name, NULL);
if (!include_type) {
if (!include_type || !arg_type) {
return;
}
@@ -96,18 +102,24 @@ static void print_successor_list(
static void print_region_list(struct mie_printer *printer, const struct mie_op *op)
{
if (!MIE_VECTOR_COUNT(op->op_regions)) {
if (b_queue_empty(&op->op_regions)) {
return;
}
b_stream_write_string(printer->p_stream, " (", NULL);
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_regions); i++) {
struct mie_region *region = mie_op_get_first_region(op);
size_t i = 0;
while (region) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_region(printer, &op->op_regions.items[i], 0);
mie_printer_print_region(printer, region, 0);
region = mie_op_get_next_region(op, region);
i++;
}
b_stream_write_string(printer->p_stream, ")", NULL);

View File

@@ -8,15 +8,20 @@ void mie_printer_print_region(
{
b_stream_write_string(printer->p_stream, "{\n", NULL);
for (size_t i = 0; i < MIE_VECTOR_COUNT(region->r_blocks); i++) {
struct mie_block *block = mie_region_get_first_block(region);
size_t i = 0;
while (block) {
enum mie_print_flags block_flags = 0;
if ((flags & MIE_PRINT_F_EXCLUDE_FIRST_BLOCK_HEADER) && (i == 0)) {
block_flags = MIE_PRINT_F_EXCLUDE_BLOCK_HEADER;
}
const struct mie_block *block = &region->r_blocks.items[i];
mie_printer_print_block(printer, block, block_flags);
block = mie_region_get_next_block(region, block);
i++;
}
b_stream_write_string(printer->p_stream, "}", NULL);

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;
}

View File

@@ -106,7 +106,7 @@ const struct mie_trait *mie_trait_table_get_unique(
const mie_id *result = mie_id_map_get(&table->tr_unique, &id);
const struct unique_trait *entry
= b_unbox(struct unique_trait, entry, u_id);
= b_unbox(struct unique_trait, result, u_id);
return entry ? entry->u_trait : NULL;
}