mie: ir: add ir builder interface
This commit is contained in:
38
mie/include/mie/ir/builder.h
Normal file
38
mie/include/mie/ir/builder.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MIE_IR_BUILDER_H_
|
||||
#define MIE_IR_BUILDER_H_
|
||||
|
||||
#include <mie/misc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct mie_op;
|
||||
struct mie_ctx;
|
||||
struct mie_type;
|
||||
struct mie_name;
|
||||
struct mie_block;
|
||||
struct mie_region;
|
||||
struct mie_register;
|
||||
|
||||
struct mie_builder;
|
||||
|
||||
MIE_API struct mie_builder *mie_builder_create(
|
||||
struct mie_ctx *ctx, struct mie_op *root);
|
||||
MIE_API void mie_builder_destroy(struct mie_builder *builder);
|
||||
|
||||
MIE_API struct mie_ctx *mie_builder_get_ctx(struct mie_builder *builder);
|
||||
MIE_API struct mie_block *mie_builder_get_current_block(struct mie_builder *builder);
|
||||
|
||||
MIE_API void mie_builder_step_into_op(
|
||||
struct mie_builder *builder, struct mie_op *op);
|
||||
MIE_API void mie_builder_step_into_region(
|
||||
struct mie_builder *builder, struct mie_region *region);
|
||||
MIE_API void mie_builder_step_into_block(
|
||||
struct mie_builder *builder, struct mie_block *block);
|
||||
MIE_API void mie_builder_step_out(struct mie_builder *builder);
|
||||
|
||||
MIE_API struct mie_op *mie_builder_put_op(
|
||||
struct mie_builder *, 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);
|
||||
|
||||
#endif
|
||||
171
mie/ir/builder.c
Normal file
171
mie/ir/builder.c
Normal file
@@ -0,0 +1,171 @@
|
||||
#include <mie/ctx.h>
|
||||
#include <mie/ir/block.h>
|
||||
#include <mie/ir/builder.h>
|
||||
#include <mie/ir/op-definition.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/ir/region.h>
|
||||
|
||||
struct builder_scope {
|
||||
b_queue_entry s_entry;
|
||||
struct mie_op *s_op;
|
||||
struct mie_region *s_region;
|
||||
struct mie_block *s_block;
|
||||
};
|
||||
|
||||
struct mie_builder {
|
||||
struct mie_ctx *b_ctx;
|
||||
b_queue b_scope_stack;
|
||||
struct mie_op *b_root;
|
||||
struct mie_op *b_prev_op;
|
||||
};
|
||||
|
||||
struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_op *root)
|
||||
{
|
||||
struct mie_builder *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
out->b_ctx = ctx;
|
||||
out->b_root = root;
|
||||
|
||||
mie_builder_step_into_op(out, root);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
struct mie_ctx *mie_builder_get_ctx(struct mie_builder *builder)
|
||||
{
|
||||
return builder->b_ctx;
|
||||
}
|
||||
|
||||
struct mie_block *mie_builder_get_current_block(struct mie_builder *builder)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_last(&builder->b_scope_stack);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct builder_scope *scope
|
||||
= b_unbox(struct builder_scope, entry, s_entry);
|
||||
|
||||
return scope->s_block;
|
||||
}
|
||||
|
||||
void mie_builder_step_into_op(struct mie_builder *builder, struct mie_op *op)
|
||||
{
|
||||
struct mie_region *region = NULL;
|
||||
|
||||
if (MIE_VECTOR_COUNT(op->op_regions) == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
void mie_builder_step_into_region(
|
||||
struct mie_builder *builder, struct mie_region *region)
|
||||
{
|
||||
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) - 1];
|
||||
}
|
||||
|
||||
mie_builder_step_into_block(builder, block);
|
||||
}
|
||||
|
||||
void mie_builder_step_into_block(struct mie_builder *builder, struct mie_block *block)
|
||||
{
|
||||
struct builder_scope *scope = malloc(sizeof *scope);
|
||||
if (!scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(scope, 0x0, sizeof *scope);
|
||||
|
||||
scope->s_block = block;
|
||||
scope->s_region = block->b_parent;
|
||||
scope->s_op = scope->s_region->r_parent;
|
||||
|
||||
b_queue_push_back(&builder->b_scope_stack, &scope->s_entry);
|
||||
}
|
||||
|
||||
void mie_builder_step_out(struct mie_builder *builder)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_last(&builder->b_scope_stack);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct builder_scope *scope
|
||||
= b_unbox(struct builder_scope, entry, s_entry);
|
||||
b_queue_delete(&builder->b_scope_stack, entry);
|
||||
free(scope);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct mie_block *block = mie_builder_get_current_block(builder);
|
||||
|
||||
const struct mie_op_definition *op_def
|
||||
= mie_ctx_get_op_definition(builder->b_ctx, dialect, op_name);
|
||||
if (!op_def) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mie_op *op = mie_block_add_op(block);
|
||||
op->op_flags = MIE_OP_F_OP_RESOLVED;
|
||||
op->op_info = op_def;
|
||||
op->op_dialect = op_def->op_parent;
|
||||
|
||||
for (size_t i = 0; i < nr_args; i++) {
|
||||
struct mie_op_arg *arg = mie_op_add_arg(op);
|
||||
arg->arg_flags = MIE_OP_F_ARG_RESOLVED;
|
||||
arg->arg_value.u_reg = args[i];
|
||||
arg->arg_value.u_user = op;
|
||||
b_queue_push_back(&args[i]->reg_use, &arg->arg_value.u_entry);
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
enum mie_status mie_builder_put_name(
|
||||
struct mie_builder *builder, struct mie_name *name, const char *hint)
|
||||
{
|
||||
struct mie_block *block = mie_builder_get_current_block(builder);
|
||||
struct mie_region *scope = block->b_parent;
|
||||
return mie_name_map_put(scope->r_names, name, hint, 0)
|
||||
? MIE_SUCCESS
|
||||
: MIE_ERR_NAME_EXISTS;
|
||||
}
|
||||
Reference in New Issue
Block a user