mie: ir: Op->Region, Region->Block, and Block->Op lists are now b_queues rather than mie_vectors
this change has two key benefits:
1. we no longer need to allocate large contigious buffers for Regions with lots
of Blocks, or Blocks with lots of Ops.
2. this simplifies re-arranging, inserting, and moving parts of the IR structure.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -83,6 +86,19 @@ MIE_API bool mie_op_has_trait(
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,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);
|
||||
@@ -94,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);
|
||||
@@ -134,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)
|
||||
|
||||
97
mie/ir/op.c
97
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,6 +78,7 @@ 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;
|
||||
}
|
||||
@@ -131,3 +134,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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -76,10 +77,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);
|
||||
|
||||
@@ -96,18 +96,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);
|
||||
|
||||
Reference in New Issue
Block a user