Compare commits
13 Commits
e9d2c0fbc7
...
00152cac56
| Author | SHA1 | Date | |
|---|---|---|---|
| 00152cac56 | |||
| 287983fa95 | |||
| 8cdbf5389c | |||
| 00c7c3d5ea | |||
| 9e546ee32f | |||
| 00ba3a3d87 | |||
| d44bc8c5c0 | |||
| a22e95d88d | |||
| 0a791fdfb2 | |||
| fe511011ec | |||
| e8534f8d70 | |||
| bf8c966c03 | |||
| 7d30e8f3ff |
@@ -1,7 +1,7 @@
|
||||
#include <mie/ctx.h>
|
||||
#include <mie/dialect/builtin.h>
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/ir/builder.h>
|
||||
#include <mie/ir/emit.h>
|
||||
#include <mie/ir/op-definition.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/macros.h>
|
||||
@@ -32,20 +32,18 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
struct mie_register *mie_arith_put_addi(
|
||||
struct mie_builder *builder, struct mie_register *left,
|
||||
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_builder_put_op(builder, "arith", "addi", args, nr_args);
|
||||
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);
|
||||
result->reg_block = mie_builder_get_current_block(builder);
|
||||
mie_builder_put_name(builder, &result->reg_name, name);
|
||||
mie_emitter_put_name(e, &result->reg_name, name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <mie/attribute/attribute.h>
|
||||
#include <mie/dialect/builtin.h>
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/ir/builder.h>
|
||||
#include <mie/ir/emit.h>
|
||||
#include <mie/ir/op-definition.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/macros.h>
|
||||
@@ -41,39 +41,35 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
struct mie_register *mie_arith_put_constant_i(
|
||||
struct mie_builder *builder, long long value, const char *name)
|
||||
struct mie_register *mie_arith_constant_i_put(
|
||||
struct mie_emitter *e, long long value, const char *name)
|
||||
{
|
||||
struct mie_op *op
|
||||
= mie_builder_put_op(builder, "arith", "constant", NULL, 0);
|
||||
struct mie_op *op = mie_emitter_put_op(e, "arith", "constant", NULL, 0);
|
||||
const struct mie_type *ty
|
||||
= mie_ctx_get_int_type(mie_builder_get_ctx(builder), 32);
|
||||
= mie_ctx_get_int_type(mie_emitter_get_ctx(e), 32);
|
||||
struct mie_register *result = mie_op_add_result(op, ty);
|
||||
|
||||
result->reg_block = mie_builder_get_current_block(builder);
|
||||
mie_builder_put_name(builder, &result->reg_name, name);
|
||||
mie_emitter_put_name(e, &result->reg_name, name);
|
||||
|
||||
struct mie_attribute *val
|
||||
= mie_ctx_get_int(mie_builder_get_ctx(builder), value, 32);
|
||||
= 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_put_constant_f(
|
||||
struct mie_builder *builder, long long value, const char *name)
|
||||
struct mie_register *mie_arith_constant_f_put(
|
||||
struct mie_emitter *e, long long value, const char *name)
|
||||
{
|
||||
struct mie_op *op
|
||||
= mie_builder_put_op(builder, "arith", "constant", NULL, 0);
|
||||
struct mie_op *op = mie_emitter_put_op(e, "arith", "constant", NULL, 0);
|
||||
const struct mie_type *ty
|
||||
= mie_ctx_get_int_type(mie_builder_get_ctx(builder), 32);
|
||||
= mie_ctx_get_int_type(mie_emitter_get_ctx(e), 32);
|
||||
struct mie_register *result = mie_op_add_result(op, ty);
|
||||
|
||||
result->reg_block = mie_builder_get_current_block(builder);
|
||||
mie_builder_put_name(builder, &result->reg_name, name);
|
||||
mie_emitter_put_name(e, &result->reg_name, name);
|
||||
|
||||
struct mie_attribute *val
|
||||
= mie_ctx_get_float(mie_builder_get_ctx(builder), value, 32);
|
||||
= 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;
|
||||
|
||||
@@ -9,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];
|
||||
struct mie_region *region = mie_op_get_first_region(op);
|
||||
if (region) {
|
||||
mie_printer_print_region(out, region, 0);
|
||||
}
|
||||
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <mie/interface/interface-definition.h>
|
||||
#include <mie/interface/interface.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>
|
||||
@@ -28,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) {
|
||||
@@ -74,10 +74,9 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
struct mie_op *mie_func_put_func(
|
||||
struct mie_builder *builder, const char *name,
|
||||
struct mie_func_parameter *params, size_t nr_params,
|
||||
const struct mie_type **ret_types, size_t nr_ret_types)
|
||||
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);
|
||||
@@ -90,7 +89,7 @@ struct mie_op *mie_func_put_func(
|
||||
}
|
||||
|
||||
const struct mie_type *func_type = mie_ctx_get_function_type(
|
||||
mie_builder_get_ctx(builder), param_types, nr_params, ret_types,
|
||||
mie_emitter_get_ctx(e), param_types, nr_params, ret_types,
|
||||
nr_ret_types);
|
||||
free(param_types);
|
||||
|
||||
@@ -98,7 +97,7 @@ struct mie_op *mie_func_put_func(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mie_op *op = mie_builder_put_op(builder, "func", "func", NULL, 0);
|
||||
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);
|
||||
@@ -114,9 +113,9 @@ struct mie_op *mie_func_put_func(
|
||||
}
|
||||
|
||||
struct mie_attribute *sym_name
|
||||
= mie_ctx_get_string(mie_builder_get_ctx(builder), name);
|
||||
= mie_ctx_get_string(mie_emitter_get_ctx(e), name);
|
||||
struct mie_attribute *function_type
|
||||
= mie_type_attr_create(mie_builder_get_ctx(builder), func_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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mie/dialect/dialect.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>
|
||||
@@ -33,11 +33,14 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o
|
||||
|
||||
b_stream_write_char(printer->p_stream, ' ');
|
||||
|
||||
mie_printer_print_region(printer, &op->op_regions.items[0], 0);
|
||||
struct mie_region *if_region = mie_op_get_first_region(op);
|
||||
struct mie_region *else_region = mie_op_get_next_region(op, if_region);
|
||||
|
||||
if (MIE_VECTOR_COUNT(op->op_regions) > 1) {
|
||||
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, &op->op_regions.items[1], 0);
|
||||
mie_printer_print_region(printer, else_region, 0);
|
||||
}
|
||||
|
||||
return MIE_SUCCESS;
|
||||
@@ -48,19 +51,19 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
struct mie_op *mie_scf_put_if(
|
||||
struct mie_builder *builder, struct mie_register *cond,
|
||||
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_builder_put_op(builder, "scf", "if", &cond, 1);
|
||||
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_builder_put_name(builder, &result->reg_name, name);
|
||||
mie_emitter_put_name(e, &result->reg_name, name);
|
||||
}
|
||||
|
||||
struct mie_region *r_true = mie_op_add_region(op);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/ir/builder.h>
|
||||
#include <mie/ir/emit.h>
|
||||
#include <mie/ir/op-definition.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/macros.h>
|
||||
@@ -35,10 +35,9 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
struct mie_op *mie_scf_put_yield(
|
||||
struct mie_builder *builder, struct mie_register *value)
|
||||
struct mie_op *mie_scf_yield_put(struct mie_emitter *e, struct mie_register *value)
|
||||
{
|
||||
return mie_builder_put_op(builder, "scf", "yield", &value, 1);
|
||||
return mie_emitter_put_op(e, "scf", "yield", &value, 1);
|
||||
}
|
||||
|
||||
MIE_OP_DEFINITION_BEGIN(mie_scf_yield, "yield")
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
|
||||
struct mie_ctx;
|
||||
struct mie_dialect;
|
||||
struct mie_builder;
|
||||
struct mie_emitter;
|
||||
|
||||
MIE_API struct mie_dialect *mie_arith_dialect_create(struct mie_ctx *ctx);
|
||||
|
||||
MIE_API struct mie_register *mie_arith_put_constant_i(
|
||||
struct mie_builder *builder, long long value, const char *name);
|
||||
MIE_API struct mie_register *mie_arith_put_constant_f(
|
||||
struct mie_builder *builder, long long value, const char *name);
|
||||
MIE_API struct mie_register *mie_arith_put_addi(
|
||||
struct mie_builder *builder, struct mie_register *left,
|
||||
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_put_addf(
|
||||
struct mie_builder *builder, struct mie_register *left,
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
struct mie_ctx;
|
||||
struct mie_type;
|
||||
struct mie_dialect;
|
||||
struct mie_emitter;
|
||||
struct mie_register;
|
||||
struct mie_builder;
|
||||
|
||||
struct mie_func_parameter {
|
||||
const char *param_name;
|
||||
@@ -18,9 +18,8 @@ struct mie_func_parameter {
|
||||
|
||||
MIE_API struct mie_dialect *mie_func_dialect_create(struct mie_ctx *ctx);
|
||||
|
||||
MIE_API struct mie_op *mie_func_put_func(
|
||||
struct mie_builder *builder, const char *name,
|
||||
struct mie_func_parameter *params, size_t nr_params,
|
||||
const struct mie_type **ret_types, size_t nr_ret_types);
|
||||
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
|
||||
|
||||
@@ -7,16 +7,16 @@ struct mie_ctx;
|
||||
struct mie_type;
|
||||
struct mie_region;
|
||||
struct mie_dialect;
|
||||
struct mie_builder;
|
||||
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_put_if(
|
||||
struct mie_builder *builder, struct mie_register *cond,
|
||||
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_put_yield(
|
||||
struct mie_builder *builder, struct mie_register *value);
|
||||
MIE_API struct mie_op *mie_scf_yield_put(
|
||||
struct mie_emitter *e, struct mie_register *value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,14 +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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef MIE_IR_BUILDER_H_
|
||||
#define MIE_IR_BUILDER_H_
|
||||
|
||||
#include <mie/ir/emit.h>
|
||||
#include <mie/misc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -30,9 +31,9 @@ MIE_API void mie_builder_step_into_block(
|
||||
MIE_API void mie_builder_step_out(struct mie_builder *builder);
|
||||
|
||||
MIE_API struct mie_op *mie_builder_put_op(
|
||||
struct mie_builder *, const char *dialect, const char *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 *, struct mie_name *name, const char *hint);
|
||||
struct mie_builder *builder, struct mie_name *name, const char *hint);
|
||||
|
||||
#endif
|
||||
|
||||
42
mie/include/mie/ir/emit.h
Normal file
42
mie/include/mie/ir/emit.h
Normal 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
|
||||
@@ -50,6 +50,8 @@ 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;
|
||||
@@ -60,7 +62,8 @@ struct mie_op {
|
||||
/* 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);
|
||||
@@ -76,13 +79,31 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <stddef.h>
|
||||
|
||||
struct mie_op;
|
||||
struct mie_walker;
|
||||
|
||||
enum mie_walker_flags {
|
||||
MIE_WALKER_F_NONE = 0x00u,
|
||||
@@ -38,7 +37,7 @@ struct mie_walk_item {
|
||||
int _f;
|
||||
b_queue_entry _e;
|
||||
enum mie_walk_item_type i_type;
|
||||
size_t i_index;
|
||||
// size_t i_index;
|
||||
size_t i_depth;
|
||||
union {
|
||||
struct mie_op *i_op;
|
||||
@@ -47,8 +46,21 @@ struct mie_walk_item {
|
||||
};
|
||||
};
|
||||
|
||||
MIE_API struct mie_walker *mie_walker_begin(
|
||||
struct mie_op *op, enum mie_walker_flags flags);
|
||||
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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
20
mie/include/mie/rewrite/convert.h
Normal file
20
mie/include/mie/rewrite/convert.h
Normal 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
|
||||
16
mie/include/mie/rewrite/greedy.h
Normal file
16
mie/include/mie/rewrite/greedy.h
Normal 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
|
||||
54
mie/include/mie/rewrite/pattern.h
Normal file
54
mie/include/mie/rewrite/pattern.h
Normal 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
|
||||
108
mie/include/mie/rewrite/rewriter.h
Normal file
108
mie/include/mie/rewrite/rewriter.h
Normal 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
|
||||
@@ -2,9 +2,59 @@
|
||||
#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 = mie_vector_emplace_back(block->b_ops, NULL);
|
||||
struct mie_op *op = malloc(sizeof *op);
|
||||
if (!op) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -12,6 +62,31 @@ struct mie_op *mie_block_add_op(struct mie_block *block)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#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>
|
||||
@@ -13,6 +14,7 @@ struct builder_scope {
|
||||
};
|
||||
|
||||
struct mie_builder {
|
||||
struct mie_emitter b_base;
|
||||
struct mie_ctx *b_ctx;
|
||||
b_queue b_scope_stack;
|
||||
struct mie_op *b_root;
|
||||
@@ -28,6 +30,11 @@ struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_op *root)
|
||||
|
||||
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;
|
||||
|
||||
@@ -73,12 +80,10 @@ struct mie_block *mie_builder_get_current_block(struct mie_builder *builder)
|
||||
|
||||
void mie_builder_step_into_op(struct mie_builder *builder, struct mie_op *op)
|
||||
{
|
||||
struct mie_region *region = NULL;
|
||||
struct mie_region *region = mie_op_get_last_region(op);
|
||||
|
||||
if (MIE_VECTOR_COUNT(op->op_regions) == 0) {
|
||||
if (!region) {
|
||||
region = mie_op_add_region(op);
|
||||
} else {
|
||||
region = &op->op_regions.items[MIE_VECTOR_COUNT(op->op_regions) - 1];
|
||||
}
|
||||
|
||||
mie_builder_step_into_region(builder, region);
|
||||
@@ -87,12 +92,10 @@ void mie_builder_step_into_op(struct mie_builder *builder, struct mie_op *op)
|
||||
void mie_builder_step_into_region(
|
||||
struct mie_builder *builder, struct mie_region *region)
|
||||
{
|
||||
struct mie_block *block = NULL;
|
||||
struct mie_block *block = mie_region_get_last_block(region);
|
||||
|
||||
if (MIE_VECTOR_COUNT(region->r_blocks) == 0) {
|
||||
if (!block) {
|
||||
block = mie_region_add_block(region);
|
||||
} else {
|
||||
block = ®ion->r_blocks.items[MIE_VECTOR_COUNT(region->r_blocks) - 1];
|
||||
}
|
||||
|
||||
mie_builder_step_into_block(builder, block);
|
||||
@@ -127,28 +130,6 @@ void mie_builder_step_out(struct mie_builder *builder)
|
||||
free(scope);
|
||||
}
|
||||
|
||||
static struct mie_block *create_current_block(struct mie_builder *builder)
|
||||
{
|
||||
struct mie_region *region = NULL;
|
||||
|
||||
if (MIE_VECTOR_COUNT(builder->b_root->op_regions) == 0) {
|
||||
region = mie_op_add_region(builder->b_root);
|
||||
} else {
|
||||
region = &builder->b_root->op_regions
|
||||
.items[MIE_VECTOR_COUNT(builder->b_root->op_result) - 1];
|
||||
}
|
||||
|
||||
struct mie_block *block = NULL;
|
||||
|
||||
if (MIE_VECTOR_COUNT(region->r_blocks) == 0) {
|
||||
block = mie_region_add_block(region);
|
||||
} else {
|
||||
block = ®ion->r_blocks.items[MIE_VECTOR_COUNT(region->r_blocks)];
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
42
mie/ir/emit.c
Normal file
42
mie/ir/emit.c
Normal 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;
|
||||
}
|
||||
149
mie/ir/op.c
149
mie/ir/op.c
@@ -1,4 +1,6 @@
|
||||
#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>
|
||||
@@ -76,12 +78,40 @@ struct mie_register *mie_op_add_result(struct mie_op *op, const struct mie_type
|
||||
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;
|
||||
@@ -91,16 +121,39 @@ struct mie_region *mie_op_add_region(struct mie_op *op)
|
||||
{
|
||||
bool isolated = is_isolated(op);
|
||||
|
||||
struct mie_region *region = mie_vector_emplace_back(op->op_regions, NULL);
|
||||
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, ®ion->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)
|
||||
{
|
||||
@@ -131,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);
|
||||
}
|
||||
|
||||
@@ -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(®ion->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(®ion->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(®ion->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(®ion->r_blocks, &block->b_entry, &after->b_entry);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
376
mie/ir/walk.c
376
mie/ir/walk.c
@@ -11,12 +11,6 @@
|
||||
|
||||
#define ITEM_TYPE(f) ((f) & 0x0Fu)
|
||||
|
||||
struct mie_walker {
|
||||
enum mie_walker_flags w_flags;
|
||||
struct mie_op *w_root;
|
||||
b_queue w_stack;
|
||||
};
|
||||
|
||||
static bool should_ignore_item(
|
||||
const struct mie_walker *walker, const struct mie_walk_item *item)
|
||||
{
|
||||
@@ -56,15 +50,31 @@ static void pop_walk_item(struct mie_walker *walker)
|
||||
|
||||
static struct mie_walk_item *current_item(struct mie_walker *walker)
|
||||
{
|
||||
struct mie_walk_item *item = NULL;
|
||||
bool recursive = (walker->w_flags & MIE_WALKER_F_RECURSIVE) != 0;
|
||||
if (!recursive) {
|
||||
if (walker->w_flags & MIE_WALKER_F_INCLUDE_REGIONS) {
|
||||
item = &walker->w_region;
|
||||
} else if (walker->w_flags & MIE_WALKER_F_INCLUDE_BLOCKS) {
|
||||
item = &walker->w_block;
|
||||
} else {
|
||||
item = &walker->w_op;
|
||||
}
|
||||
|
||||
bool eof = !item || item->i_type != MIE_WALK_ITEM_NONE;
|
||||
return eof ? item : NULL;
|
||||
}
|
||||
|
||||
b_queue_entry *entry = b_queue_last(&walker->w_stack);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mie_walk_item *item = b_unbox(struct mie_walk_item, entry, _e);
|
||||
item = b_unbox(struct mie_walk_item, entry, _e);
|
||||
return item->i_type != MIE_WALK_ITEM_NONE ? item : NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static struct mie_op *get_first_child(struct mie_walker *walker, struct mie_op *op)
|
||||
{
|
||||
bool backwards = (walker->w_flags & MIE_WALKER_F_BACKWARD) != 0;
|
||||
@@ -95,16 +105,17 @@ static struct mie_op *get_first_child(struct mie_walker *walker, struct mie_op *
|
||||
|
||||
return op;
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t walk_item_get_nr_children(const struct mie_walk_item *item)
|
||||
static bool walk_item_has_children(const struct mie_walk_item *item)
|
||||
{
|
||||
switch (item->i_type) {
|
||||
case MIE_WALK_ITEM_OP:
|
||||
return MIE_VECTOR_COUNT(item->i_op->op_regions);
|
||||
return mie_op_get_first_region(item->i_op) != NULL;
|
||||
case MIE_WALK_ITEM_BLOCK:
|
||||
return MIE_VECTOR_COUNT(item->i_block->b_ops);
|
||||
return mie_block_get_first_op(item->i_block) != NULL;
|
||||
case MIE_WALK_ITEM_REGION:
|
||||
return MIE_VECTOR_COUNT(item->i_region->r_blocks);
|
||||
return mie_region_get_first_block(item->i_region) != NULL;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -128,42 +139,68 @@ static bool should_correct_depth(
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool walk_item_get_child(
|
||||
static bool walk_item_get_first_child(
|
||||
struct mie_walker *walker, const struct mie_walk_item *item,
|
||||
size_t index, struct mie_walk_item *child)
|
||||
struct mie_walk_item *child)
|
||||
{
|
||||
bool ok = false;
|
||||
b_queue_entry *entry = NULL;
|
||||
|
||||
switch (item->i_type) {
|
||||
case MIE_WALK_ITEM_OP:
|
||||
if (MIE_VECTOR_COUNT(item->i_op->op_regions) <= index) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
child->i_type = MIE_WALK_ITEM_REGION;
|
||||
child->i_region = &item->i_op->op_regions.items[index];
|
||||
ok = true;
|
||||
child->i_region = mie_op_get_first_region(item->i_op);
|
||||
ok = child->i_region != NULL;
|
||||
break;
|
||||
case MIE_WALK_ITEM_BLOCK:
|
||||
if (MIE_VECTOR_COUNT(item->i_block->b_ops) <= index) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
child->i_type = MIE_WALK_ITEM_OP;
|
||||
child->i_op = &item->i_block->b_ops.items[index];
|
||||
ok = true;
|
||||
child->i_op = mie_block_get_first_op(item->i_block);
|
||||
ok = child->i_op != NULL;
|
||||
break;
|
||||
case MIE_WALK_ITEM_REGION:
|
||||
if (MIE_VECTOR_COUNT(item->i_region->r_blocks) <= index) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
child->i_type = MIE_WALK_ITEM_BLOCK;
|
||||
child->i_block = &item->i_region->r_blocks.items[index];
|
||||
ok = true;
|
||||
child->i_block = mie_region_get_first_block(item->i_region);
|
||||
ok = child->i_block != NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
child->i_depth = item->i_depth + 1;
|
||||
|
||||
if (should_correct_depth(walker, item)) {
|
||||
child->i_depth--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool walk_item_get_last_child(
|
||||
struct mie_walker *walker, const struct mie_walk_item *item,
|
||||
struct mie_walk_item *child)
|
||||
{
|
||||
bool ok = false;
|
||||
b_queue_entry *entry = NULL;
|
||||
|
||||
switch (item->i_type) {
|
||||
case MIE_WALK_ITEM_OP:
|
||||
child->i_type = MIE_WALK_ITEM_REGION;
|
||||
child->i_region = mie_op_get_last_region(item->i_op);
|
||||
ok = child->i_region != NULL;
|
||||
break;
|
||||
case MIE_WALK_ITEM_BLOCK:
|
||||
child->i_type = MIE_WALK_ITEM_OP;
|
||||
child->i_op = mie_block_get_last_op(item->i_block);
|
||||
ok = child->i_op != NULL;
|
||||
break;
|
||||
case MIE_WALK_ITEM_REGION:
|
||||
child->i_type = MIE_WALK_ITEM_BLOCK;
|
||||
child->i_block = mie_region_get_last_block(item->i_region);
|
||||
ok = child->i_block != NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -174,7 +211,6 @@ static bool walk_item_get_child(
|
||||
}
|
||||
|
||||
child->i_depth = item->i_depth + 1;
|
||||
child->i_index = index;
|
||||
|
||||
if (should_correct_depth(walker, item)) {
|
||||
child->i_depth--;
|
||||
@@ -192,8 +228,9 @@ static bool walk_item_get_next_sibling(
|
||||
|
||||
sibling->i_depth = item->i_depth;
|
||||
sibling->i_type = item->i_type;
|
||||
sibling->i_index = item->i_index + 1;
|
||||
|
||||
size_t index = 0;
|
||||
b_queue_entry *entry = NULL;
|
||||
struct mie_region *parent_r = NULL;
|
||||
struct mie_block *parent_b = NULL;
|
||||
struct mie_op *parent_o = NULL;
|
||||
@@ -205,36 +242,26 @@ static bool walk_item_get_next_sibling(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item->i_index + 1 >= MIE_VECTOR_COUNT(parent_b->b_ops)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_op = &parent_b->b_ops.items[item->i_index + 1];
|
||||
return true;
|
||||
sibling->i_op = mie_block_get_next_op(parent_b, item->i_op);
|
||||
return sibling->i_op != NULL;
|
||||
case MIE_WALK_ITEM_BLOCK:
|
||||
parent_r = item->i_block->b_parent;
|
||||
if (!parent_r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item->i_index + 1 >= MIE_VECTOR_COUNT(parent_r->r_blocks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_block = &parent_r->r_blocks.items[item->i_index + 1];
|
||||
return true;
|
||||
sibling->i_block
|
||||
= mie_region_get_next_block(parent_r, item->i_block);
|
||||
return sibling->i_block != NULL;
|
||||
case MIE_WALK_ITEM_REGION:
|
||||
parent_o = item->i_region->r_parent;
|
||||
if (!parent_o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item->i_index + 1 >= MIE_VECTOR_COUNT(parent_o->op_regions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_region = &parent_o->op_regions.items[item->i_index + 1];
|
||||
return true;
|
||||
sibling->i_region
|
||||
= mie_op_get_next_region(parent_o, item->i_region);
|
||||
return sibling->i_region != NULL;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -243,14 +270,14 @@ static bool walk_item_get_next_sibling(
|
||||
static bool walk_item_get_prev_sibling(
|
||||
const struct mie_walk_item *item, struct mie_walk_item *sibling)
|
||||
{
|
||||
if (item->i_depth == 0 || item->i_index == 0) {
|
||||
if (item->i_depth == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_depth = item->i_depth;
|
||||
sibling->i_type = item->i_type;
|
||||
sibling->i_index = item->i_index - 1;
|
||||
|
||||
size_t index = 0;
|
||||
struct mie_region *parent_r = NULL;
|
||||
struct mie_block *parent_b = NULL;
|
||||
struct mie_op *parent_o = NULL;
|
||||
@@ -262,24 +289,26 @@ static bool walk_item_get_prev_sibling(
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_op = &parent_b->b_ops.items[item->i_index - 1];
|
||||
return true;
|
||||
sibling->i_op = mie_block_get_prev_op(parent_b, item->i_op);
|
||||
return sibling->i_op != NULL;
|
||||
case MIE_WALK_ITEM_BLOCK:
|
||||
parent_r = item->i_block->b_parent;
|
||||
if (!parent_r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_block = &parent_r->r_blocks.items[item->i_index - 1];
|
||||
return true;
|
||||
sibling->i_block
|
||||
= mie_region_get_prev_block(parent_r, item->i_block);
|
||||
return sibling->i_block != NULL;
|
||||
case MIE_WALK_ITEM_REGION:
|
||||
parent_o = item->i_region->r_parent;
|
||||
if (!parent_o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sibling->i_region = &parent_o->op_regions.items[item->i_index - 1];
|
||||
return true;
|
||||
sibling->i_region
|
||||
= mie_op_get_prev_region(parent_o, item->i_region);
|
||||
return sibling->i_region != NULL;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -334,9 +363,9 @@ static bool step_pre_f(struct mie_walker *walker)
|
||||
struct mie_walk_item next;
|
||||
|
||||
bool ok = false;
|
||||
size_t nr_children = walk_item_get_nr_children(item);
|
||||
if (nr_children > 0) {
|
||||
ok = walk_item_get_child(walker, item, 0, &next);
|
||||
bool has_children = walk_item_has_children(item);
|
||||
if (has_children) {
|
||||
ok = walk_item_get_first_child(walker, item, &next);
|
||||
|
||||
if (ok) {
|
||||
push_walk_item(walker, &next);
|
||||
@@ -384,9 +413,9 @@ static bool step_pre_b(struct mie_walker *walker)
|
||||
struct mie_walk_item next;
|
||||
|
||||
bool ok = false;
|
||||
size_t nr_children = walk_item_get_nr_children(item);
|
||||
if (nr_children > 0) {
|
||||
ok = walk_item_get_child(walker, item, nr_children - 1, &next);
|
||||
bool has_children = walk_item_has_children(item);
|
||||
if (has_children) {
|
||||
ok = walk_item_get_last_child(walker, item, &next);
|
||||
|
||||
if (ok) {
|
||||
push_walk_item(walker, &next);
|
||||
@@ -437,10 +466,10 @@ static bool step_post_f(struct mie_walker *walker)
|
||||
|
||||
while (1) {
|
||||
item = current_item(walker);
|
||||
size_t nr_children = walk_item_get_nr_children(item);
|
||||
bool has_children = walk_item_has_children(item);
|
||||
|
||||
if (nr_children > 0 && !(item->_f & WALK_ITEM_F_CHILDREN_VISITED)) {
|
||||
ok = walk_item_get_child(walker, item, 0, &next);
|
||||
if (has_children && !(item->_f & WALK_ITEM_F_CHILDREN_VISITED)) {
|
||||
ok = walk_item_get_first_child(walker, item, &next);
|
||||
|
||||
if (ok) {
|
||||
push_walk_item(walker, &next);
|
||||
@@ -449,7 +478,7 @@ static bool step_post_f(struct mie_walker *walker)
|
||||
return ok;
|
||||
}
|
||||
|
||||
if (nr_children == 0 && !(item->_f & WALK_ITEM_F_VISITED)) {
|
||||
if (!has_children && !(item->_f & WALK_ITEM_F_VISITED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -469,6 +498,55 @@ static bool step_post_f(struct mie_walker *walker)
|
||||
}
|
||||
}
|
||||
|
||||
static bool step_flat_f(struct mie_walker *walker)
|
||||
{
|
||||
struct mie_walk_item *stack[] = {
|
||||
&walker->w_region,
|
||||
&walker->w_block,
|
||||
&walker->w_op,
|
||||
};
|
||||
const int stack_size = sizeof stack / sizeof stack[0];
|
||||
|
||||
int start;
|
||||
if (walker->w_flags & MIE_WALKER_F_INCLUDE_REGIONS) {
|
||||
start = 0;
|
||||
} else if (walker->w_flags & MIE_WALKER_F_INCLUDE_BLOCKS) {
|
||||
start = 1;
|
||||
} else {
|
||||
start = 2;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = start; i >= 0; i--) {
|
||||
struct mie_walk_item *item = stack[i];
|
||||
struct mie_walk_item next;
|
||||
if (walk_item_get_next_sibling(item, &next)) {
|
||||
*item = next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int k = i; k < stack_size - 1; k++) {
|
||||
struct mie_walk_item *parent = stack[k];
|
||||
struct mie_walk_item *child = stack[k + 1];
|
||||
|
||||
if (!walk_item_get_first_child(walker, parent, child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool step_flat_b(struct mie_walker *walker)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool step_post_b(struct mie_walker *walker)
|
||||
{
|
||||
/* backward, post-order traversal:
|
||||
@@ -485,11 +563,10 @@ static bool step_post_b(struct mie_walker *walker)
|
||||
|
||||
while (1) {
|
||||
item = current_item(walker);
|
||||
size_t nr_children = walk_item_get_nr_children(item);
|
||||
bool has_children = walk_item_has_children(item);
|
||||
|
||||
if (nr_children > 0 && !(item->_f & WALK_ITEM_F_CHILDREN_VISITED)) {
|
||||
ok = walk_item_get_child(
|
||||
walker, item, nr_children - 1, &next);
|
||||
if (has_children && !(item->_f & WALK_ITEM_F_CHILDREN_VISITED)) {
|
||||
ok = walk_item_get_last_child(walker, item, &next);
|
||||
|
||||
if (ok) {
|
||||
push_walk_item(walker, &next);
|
||||
@@ -498,7 +575,7 @@ static bool step_post_b(struct mie_walker *walker)
|
||||
return ok;
|
||||
}
|
||||
|
||||
if (nr_children == 0 && !(item->_f & WALK_ITEM_F_VISITED)) {
|
||||
if (!has_children && !(item->_f & WALK_ITEM_F_VISITED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -520,25 +597,106 @@ static bool step_post_b(struct mie_walker *walker)
|
||||
|
||||
static bool step(struct mie_walker *walker)
|
||||
{
|
||||
bool recursive = (walker->w_flags & MIE_WALKER_F_RECURSIVE) != 0;
|
||||
bool backward = (walker->w_flags & MIE_WALKER_F_BACKWARD) != 0;
|
||||
bool postorder = (walker->w_flags & MIE_WALKER_F_POSTORDER) != 0;
|
||||
|
||||
if (!recursive) {
|
||||
return backward ? step_flat_b(walker) : step_flat_f(walker);
|
||||
} else if (postorder) {
|
||||
return backward ? step_post_b(walker) : step_post_f(walker);
|
||||
} else {
|
||||
return backward ? step_pre_b(walker) : step_pre_f(walker);
|
||||
}
|
||||
}
|
||||
|
||||
static enum mie_status prepare_flat_traversal(
|
||||
struct mie_walker *walker, const struct mie_op *op)
|
||||
{
|
||||
bool backward = (walker->w_flags & MIE_WALKER_F_BACKWARD) != 0;
|
||||
bool ok = false;
|
||||
enum mie_walk_item_type target_type = MIE_WALK_ITEM_NONE;
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
|
||||
struct mie_walk_item root = {};
|
||||
root.i_op = (struct mie_op *)op;
|
||||
root.i_type = MIE_WALK_ITEM_OP;
|
||||
|
||||
if (walker->w_flags & MIE_WALKER_F_INCLUDE_REGIONS) {
|
||||
target_type = MIE_WALK_ITEM_REGION;
|
||||
} else if (walker->w_flags & MIE_WALKER_F_INCLUDE_BLOCKS) {
|
||||
target_type = MIE_WALK_ITEM_BLOCK;
|
||||
} else {
|
||||
target_type = MIE_WALK_ITEM_OP;
|
||||
}
|
||||
|
||||
bool has_children = walk_item_has_children(&root);
|
||||
if (!has_children) {
|
||||
return MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
if (backward) {
|
||||
if (postorder) {
|
||||
return step_post_b(walker);
|
||||
ok = walk_item_get_last_child(walker, &root, &walker->w_region);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
} else {
|
||||
ok = walk_item_get_first_child(walker, &root, &walker->w_region);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
return step_pre_b(walker);
|
||||
if (status != MIE_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (postorder) {
|
||||
return step_post_f(walker);
|
||||
if (target_type == MIE_WALK_ITEM_REGION) {
|
||||
walker->w_region.i_depth = 1;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
return step_pre_f(walker);
|
||||
has_children = walk_item_has_children(&walker->w_region);
|
||||
if (!has_children) {
|
||||
return MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
static enum mie_status prepare_preorder_traversal(struct mie_walker *walker)
|
||||
if (backward) {
|
||||
ok = walk_item_get_last_child(
|
||||
walker, &walker->w_region, &walker->w_block);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
} else {
|
||||
ok = walk_item_get_first_child(
|
||||
walker, &walker->w_region, &walker->w_block);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (target_type == MIE_WALK_ITEM_BLOCK) {
|
||||
walker->w_block.i_depth = 1;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
has_children = walk_item_has_children(&walker->w_block);
|
||||
if (!has_children) {
|
||||
return MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
if (backward) {
|
||||
ok = walk_item_get_last_child(
|
||||
walker, &walker->w_block, &walker->w_op);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
} else {
|
||||
ok = walk_item_get_first_child(
|
||||
walker, &walker->w_block, &walker->w_op);
|
||||
status = ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
walker->w_op.i_depth = 1;
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum mie_status prepare_preorder_traversal(
|
||||
struct mie_walker *walker, const struct mie_op *root)
|
||||
{
|
||||
struct mie_walk_item *item = malloc(sizeof *item);
|
||||
if (!item) {
|
||||
@@ -546,7 +704,7 @@ static enum mie_status prepare_preorder_traversal(struct mie_walker *walker)
|
||||
}
|
||||
|
||||
memset(item, 0x0, sizeof *item);
|
||||
item->i_op = walker->w_root;
|
||||
item->i_op = (struct mie_op *)root;
|
||||
item->i_type = MIE_WALK_ITEM_OP;
|
||||
|
||||
push_walk_item(walker, item);
|
||||
@@ -554,10 +712,11 @@ static enum mie_status prepare_preorder_traversal(struct mie_walker *walker)
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mie_status prepare_postorder_traversal(struct mie_walker *walker)
|
||||
static enum mie_status prepare_postorder_traversal(
|
||||
struct mie_walker *walker, const struct mie_op *root)
|
||||
{
|
||||
struct mie_walk_item item = {};
|
||||
item.i_op = walker->w_root;
|
||||
item.i_op = (struct mie_op *)root;
|
||||
item.i_type = MIE_WALK_ITEM_OP;
|
||||
|
||||
push_walk_item(walker, &item);
|
||||
@@ -568,18 +727,17 @@ static enum mie_status prepare_postorder_traversal(struct mie_walker *walker)
|
||||
while (1) {
|
||||
struct mie_walk_item *current = current_item(walker);
|
||||
struct mie_walk_item child;
|
||||
size_t nr_children = walk_item_get_nr_children(current);
|
||||
if (!nr_children) {
|
||||
bool has_children = walk_item_has_children(current);
|
||||
if (!has_children) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
if (backward) {
|
||||
ok = walk_item_get_child(
|
||||
walker, current, nr_children - 1, &child);
|
||||
ok = walk_item_get_last_child(walker, current, &child);
|
||||
} else {
|
||||
ok = walk_item_get_child(walker, current, 0, &child);
|
||||
ok = walk_item_get_first_child(walker, current, &child);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
@@ -592,30 +750,26 @@ static enum mie_status prepare_postorder_traversal(struct mie_walker *walker)
|
||||
return ok ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
struct mie_walker *mie_walker_begin(struct mie_op *op, enum mie_walker_flags flags)
|
||||
void mie_walker_begin(
|
||||
struct mie_walker *walker, const struct mie_op *op,
|
||||
enum mie_walker_flags flags)
|
||||
{
|
||||
struct mie_walker *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
memset(walker, 0x0, sizeof *walker);
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
walker->w_flags = flags;
|
||||
|
||||
out->w_flags = flags;
|
||||
out->w_root = op;
|
||||
|
||||
if (flags & MIE_WALKER_F_POSTORDER) {
|
||||
prepare_postorder_traversal(out);
|
||||
if (!(flags & MIE_WALKER_F_RECURSIVE)) {
|
||||
prepare_flat_traversal(walker, op);
|
||||
} else if (flags & MIE_WALKER_F_POSTORDER) {
|
||||
prepare_postorder_traversal(walker, op);
|
||||
} else {
|
||||
prepare_preorder_traversal(out);
|
||||
prepare_preorder_traversal(walker, op);
|
||||
}
|
||||
|
||||
struct mie_walk_item *cur = current_item(out);
|
||||
if (should_ignore_item(out, cur)) {
|
||||
mie_walker_step(out);
|
||||
struct mie_walk_item *cur = current_item(walker);
|
||||
if (cur && should_ignore_item(walker, cur)) {
|
||||
mie_walker_step(walker);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void mie_walker_end(struct mie_walker *walker)
|
||||
@@ -631,9 +785,9 @@ enum mie_status mie_walker_step(struct mie_walker *walker)
|
||||
do {
|
||||
ok = step(walker);
|
||||
cur = current_item(walker);
|
||||
} while (cur && should_ignore_item(walker, cur));
|
||||
} while (ok && cur && should_ignore_item(walker, cur));
|
||||
|
||||
return cur ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
return (ok && cur) ? MIE_SUCCESS : MIE_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
struct mie_walk_item *mie_walker_get(struct mie_walker *walker)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1087,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
136
mie/pass/builtin/convert-scf-to-cf.c
Normal file
136
mie/pass/builtin/convert-scf-to-cf.c
Normal 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()
|
||||
@@ -204,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_walk_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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
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);
|
||||
|
||||
@@ -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 = ®ion->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
88
mie/rewrite/convert.c
Normal 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
30
mie/rewrite/pattern-set.c
Normal 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
23
mie/rewrite/pattern.c
Normal 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
591
mie/rewrite/rewriter.c
Normal 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, ®ion->r_entry);
|
||||
b_queue_push_front(&to->op_regions, ®ion->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, ®ion->r_entry);
|
||||
b_queue_push_back(&to->op_regions, ®ion->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, ®ion->r_entry);
|
||||
b_queue_insert_before(&to->op_regions, ®ion->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, ®ion->r_entry);
|
||||
b_queue_insert_after(&to->op_regions, ®ion->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_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_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_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_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_name);
|
||||
struct mie_name *result = mie_name_map_put(names, ®->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;
|
||||
}
|
||||
Reference in New Issue
Block a user