Compare commits

39 Commits

Author SHA1 Message Date
6abdf8f993 mie: implement block dominance calculation using lengauer-tarjan algorithm 2026-02-01 10:33:36 +00:00
870b2bfbac mie: memref: add load op 2026-02-01 10:33:03 +00:00
5344c02b48 mie: builtin: add some diagnostics for value resolution 2026-02-01 10:25:43 +00:00
4a4f0c483a mie: ir: op: remove redundant op_dialect pointer 2026-02-01 10:24:06 +00:00
f37ee90b0e mie: func: add function-like trait 2026-01-31 23:29:17 +00:00
3f901ed83a doc: update type prefix in sample graph files 2026-01-27 20:52:35 +00:00
b28efa2d08 tool: optimise: update mie_lex usage 2026-01-27 20:51:31 +00:00
5835d25679 tool: validate: if parse fails, print any diagnostic messages 2026-01-27 20:51:18 +00:00
d4fbd75a59 tool: implement a diagnostic message printer 2026-01-27 20:48:04 +00:00
0b1d4697a2 tool: ctx-dump: show registered diag classes/messages 2026-01-27 20:47:10 +00:00
cd49417972 mie: add a system for registering and producing detailed diagnostic messages 2026-01-27 20:46:44 +00:00
bd5ba9e9fd mie: lex: move file i/o handling to a separate struct 2026-01-27 20:46:08 +00:00
b5fa40d4d8 mie: tool: add command to run optimisations on an input IR file 2026-01-25 15:12:07 +00:00
a67e4b6688 mie: tool: validate: remove functionality that was moved to internal subcommands 2026-01-25 15:11:06 +00:00
5873326138 mie: tool: split internal command into several different subcommands 2026-01-25 15:10:23 +00:00
00152cac56 mie: convert-scf-to-cf: implement if match/rewrite using new interface 2026-01-25 15:08:19 +00:00
287983fa95 mie: implement a full rewriter with pattern-matching and rewriting support
the new rewriter interface supports running patterns over an Op's children
matching Ops that conform to a pattern, and rewriting Ops in arbitrary ways.
2026-01-25 15:06:43 +00:00
8cdbf5389c mie: pass: manager: update mie_walker usage 2026-01-25 15:05:44 +00:00
00c7c3d5ea mie: parse: update parse_region_list to use new Op->Region linking mechanism 2026-01-25 15:05:18 +00:00
9e546ee32f mie: name: fix crash when destroying a zeroed mie_name 2026-01-25 15:04:37 +00:00
00ba3a3d87 mie: print: implement exception-printing of resolved, but null, op args
this is to make it easier to spot mistakes made when modifying IR.
2026-01-25 15:02:48 +00:00
d44bc8c5c0 mie: ir: op: fix crash when checking if an unresolved op is isolated 2026-01-25 15:02:17 +00:00
a22e95d88d mie: ir: op: add functions to check what an Op is, and add successors with args 2026-01-25 15:01:41 +00:00
0a791fdfb2 mie: dialect: update Op emitter functions to use mie_emitter 2026-01-25 15:00:37 +00:00
fe511011ec mie: ir: walk: implement non-recursive traversal
struct mie_walker is now a public struct that can (and should) be stack
allocated. this means that non-recursive traversal of an Op's children
uses no dynamically allocated memory.
2026-01-25 14:58:51 +00:00
e8534f8d70 mie: ir: Op->Region, Region->Block, and Block->Op lists are now b_queues rather than mie_vectors
this change has two key benefits:
 1. we no longer need to allocate large contigious buffers for Regions with lots
    of Blocks, or Blocks with lots of Ops.
 2. this simplifies re-arranging, inserting, and moving parts of the IR structure.
2026-01-25 14:56:47 +00:00
bf8c966c03 mie: ir: builder: add mie_emitter support 2026-01-25 14:53:24 +00:00
7d30e8f3ff mie: ir: add an emitter interface for emitting IR constructs
mie_emitter can be inherited from by any structure that supports
emitting IR constructs like Ops and Blocks. Dialect Op emitter
functions can wrap mie_emitter to simplify emitting specific Ops,
and these functions can then be used with any struct that inherits
from mie_emitter.
2026-01-25 14:51:36 +00:00
e9d2c0fbc7 mie: scf: implement lots of print and emit functions 2026-01-23 23:33:16 +00:00
a710ef0b24 mie: func: implement lots of print and emit functions 2026-01-23 23:22:57 +00:00
0277931ca1 mie: builtin: implement lots of print and emit functions 2026-01-23 23:22:47 +00:00
ac7860b6bd mie: ir: rewrite: add pattern and rewriter interface 2026-01-23 23:21:42 +00:00
29984307aa mie: pass: support filtering passes to any op of a given dialect 2026-01-23 23:21:16 +00:00
ac96248d7e mie: ir: builder: support adding names to non-isolated op regions 2026-01-23 23:19:29 +00:00
593eda2797 mie: trait: table: fix get_unique() unboxing the wrong pointer 2026-01-23 23:17:39 +00:00
d0ac8a9fed mie: ir: walk: re-implement walker with a stack rather than a queue 2026-01-23 22:50:05 +00:00
89ebbcc462 mie: parse: replace all op-creation with mie_block_add_op calls 2026-01-23 22:42:39 +00:00
554a1e7342 mie: ir: op: keep a pointer to the block that contains the op 2026-01-23 22:42:05 +00:00
6d1e308ff1 mie: ir: op: only create a name map if the op is isolated-from-above 2026-01-23 22:41:03 +00:00
89 changed files with 5835 additions and 1192 deletions

View File

@@ -1,22 +1,22 @@
select.graph {
%entry = +select.entry -> #select.chain
%entry = +select.entry -> !select.chain
%0 = +select.register @0 : i32 -> #select.register
%1 = +select.register @1 : i32 -> #select.register
%0 = +select.register @0 : i32 -> !select.register
%1 = +select.register @1 : i32 -> !select.register
%v.0, %c.0 = +select.register.read %entry, %0 \
: (#select.chain, #select.register) \
-> (i32, #select.chain)
: (!select.chain, !select.register) \
-> (i32, !select.chain)
%v.1, %c.1 = +select.register.read %entry, %1 \
: (#select.chain, #select.register) \
-> (i32, #select.chain)
: (!select.chain, !select.register) \
-> (i32, !select.chain)
%2 = +select.register @2 : i32
%v.2, %c.2 = +select.register.read %entry, %2 \
: (#select.chain, #select.register) \
-> (#select.register, #select.chain)
: (!select.chain, !select.register) \
-> (!select.register, !select.chain)
%v.3 = arith.build-pair %v.0, %v.1 : (i32, i32) -> i64
@@ -24,15 +24,15 @@ select.graph {
%v.5 = arith.mul %v.4, %v.3 : (i32, i32) -> i32
%x0 = +select.mach-register @x0 : i32 -> #select.register
%x0 = +select.mach-register @x0 : i32 -> !select.register
%c.3, %g.0 = +select.register.write %entry, %x0, %v.5 \
: (#select.chain, #select.register, i32) \
-> (#select.chain, #select.glue)
: (!select.chain, !select.register, i32) \
-> (!select.chain, !select.glue)
%c.4 = *risc-v.RET %c.3, %x0, %g.0 \
: (#select.chain, #select.register, #select.glue) \
-> #select.chain
: (!select.chain, !select.register, !select.glue) \
-> !select.chain
+select.graph-root %c.4 : #select.chain
+select.graph-root %c.4 : !select.chain
}

View File

@@ -1,31 +1,31 @@
select.graph {
%entry = +select.entry -> #select.chain
%entry = +select.entry -> !select.chain
%N1 = ptr.alloca i32 -> ptr
%N2 = i32.constant 3 -> i32
%N3.c = +ptr.store %entry, %N2, %N1 : (#select.chain, i32, ptr) -> #select.chain
%N3.c = +ptr.store %entry, %N2, %N1 : (!select.chain, i32, ptr) -> !select.chain
%N4 = ptr.alloca i32 -> ptr
%N5 = i32.constant 0 -> i32
%N6.c = +ptr.store %entry, %N5, %N4 : (#select.chain, i32, ptr) -> #select.chain
%N6.c = +ptr.store %entry, %N5, %N4 : (!select.chain, i32, ptr) -> !select.chain
%N7, %N7.c = +ptr.load %N6.c, %N1 : (#select.chain, ptr) -> (#ivy.id, #select.chain)
%N7, %N7.c = +ptr.load %N6.c, %N1 : (!select.chain, ptr) -> (!ivy.id, !select.chain)
%N8 = i32.constant 10 -> i32
%N9 = arith.cmp gt %N7, %N8 : (#ivy.id, i32) -> i1
%N9 = arith.cmp gt %N7, %N8 : (!ivy.id, i32) -> i1
%N10.c = +select.chain-group %N7.c, %N6.c : (#select.chain, #select.chain) -> #select.chain
%N10.c = +select.chain-group %N7.c, %N6.c : (!select.chain, !select.chain) -> !select.chain
%N11 = +select.block-ref @if.true -> #select.block
%N11 = +select.block-ref @if.true -> !select.block
%N12.c = +cf.br-cond %N10.c, %N9, %N11 : (#select.chain, i1, #select.block) -> #select.chain
%N12.c = +cf.br-cond %N10.c, %N9, %N11 : (!select.chain, i1, !select.block) -> !select.chain
%N13 = +select.block-ref @if.false -> #select.block
%N13 = +select.block-ref @if.false -> !select.block
%N14.c = cf.br %N12.c, %N13

View File

@@ -4,6 +4,8 @@
#include <blue/ds/string.h>
#include <mie/attribute/attribute-definition.h>
#include <mie/ctx.h>
#include <mie/diag/class.h>
#include <mie/diag/diag.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
@@ -86,7 +88,6 @@ struct mie_op *mie_ctx_create_op(
out->op_flags |= MIE_OP_F_OP_RESOLVED;
out->op_info = def;
out->op_dialect = def->op_parent;
return out;
}
@@ -127,7 +128,6 @@ bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op)
return false;
}
op->op_dialect = dialect;
op->op_info = op_info;
free(op->op_name);
@@ -484,3 +484,44 @@ enum mie_status mie_ctx_get_pass(
*out = pass;
return status;
}
struct mie_diag *mie_ctx_push_diag(
struct mie_ctx *ctx, struct mie_line_source *src,
const struct mie_file_cell *loc, const char *dialect_name,
unsigned long diag_class)
{
struct mie_diag *diag = malloc(sizeof *diag);
if (!diag) {
return NULL;
}
struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name);
if (!dialect) {
return NULL;
}
if (diag_class >= dialect->d_nr_diag_classes) {
return NULL;
}
memset(diag, 0x0, sizeof *diag);
diag->diag_src = src;
diag->diag_loc = *loc;
diag->diag_parent = dialect;
diag->diag_class = &dialect->d_diag_classes[diag_class];
b_queue_push_back(&ctx->ctx_diag, &diag->diag_entry);
return diag;
}
struct mie_diag *mie_ctx_pop_diag(struct mie_ctx *ctx)
{
b_queue_entry *entry = b_queue_pop_front(&ctx->ctx_diag);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_diag, entry, diag_entry);
}

106
mie/diag/diag.c Normal file
View File

@@ -0,0 +1,106 @@
#include <blue/ds/string.h>
#include <mie/ctx.h>
#include <mie/diag/amendment.h>
#include <mie/diag/component.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/diag/msg.h>
#include <mie/dialect/dialect.h>
#include <stdlib.h>
#include <string.h>
struct mie_diag_c_msg *diag_msg_create(const struct mie_diag_msg *content)
{
struct mie_diag_c_msg *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->msg_base.c_type = MIE_DIAG_COMPONENT_MSG;
out->msg_content = b_strdup(content->msg_content);
return out;
}
struct mie_diag_c_snippet *diag_snippet_create(
unsigned long first_line, unsigned long last_line,
const struct mie_diag_amendment *amendments, size_t nr_amendments,
const struct mie_diag_highlight *highlights, size_t nr_highlights)
{
struct mie_diag_c_snippet *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->s_base.c_type = MIE_DIAG_COMPONENT_SNIPPET;
out->s_first_line = first_line;
out->s_last_line = last_line;
out->s_nr_amendments = nr_amendments;
out->s_amendments = calloc(nr_amendments, sizeof *amendments);
if (!out->s_amendments) {
free(out);
return NULL;
}
memcpy(out->s_amendments, amendments, nr_amendments * sizeof *amendments);
out->s_nr_highlights = nr_highlights;
out->s_highlights = calloc(nr_highlights, sizeof *highlights);
if (!out->s_highlights) {
free(out->s_amendments);
free(out);
return NULL;
}
memcpy(out->s_highlights, highlights, nr_highlights * sizeof *highlights);
return out;
}
void mie_diag_set_location(
struct mie_diag *diag, unsigned long row, unsigned long col)
{
diag->diag_loc.c_row = row;
diag->diag_loc.c_row = col;
}
void mie_diag_push_msg(
struct mie_diag *diag, struct mie_ctx *ctx, const char *dialect_name,
unsigned long msg, ...)
{
struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name);
if (!dialect) {
return;
}
if (msg >= dialect->d_nr_diag_msgs) {
return;
}
const struct mie_diag_msg *msg_info = &dialect->d_diag_msgs[msg];
struct mie_diag_c_msg *c_msg = diag_msg_create(msg_info);
if (!c_msg) {
return;
}
b_queue_push_back(&diag->diag_components, &c_msg->msg_base.c_entry);
}
void mie_diag_push_snippet(
struct mie_diag *diag, unsigned long first_line, unsigned long last_line,
const struct mie_diag_amendment *amendments, size_t nr_amendments,
const struct mie_diag_highlight *highlights, size_t nr_highlights)
{
struct mie_diag_c_snippet *c_snippet = diag_snippet_create(
first_line, last_line, amendments, nr_amendments, highlights,
nr_highlights);
if (!c_snippet) {
return;
}
b_queue_push_back(&diag->diag_components, &c_snippet->s_base.c_entry);
}

6
mie/diag/diag.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _DIAG_DIAG_H_
#define _DIAG_DIAG_H_
#include <blue/core/queue.h>
#endif

View File

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

View File

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

View File

@@ -1,4 +1,6 @@
#include <mie/ctx.h>
#include <mie/diag/class.h>
#include <mie/diag/msg.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
#include <mie/macros.h>
@@ -81,20 +83,25 @@ struct mie_attribute *mie_ctx_get_index(struct mie_ctx *ctx, size_t val)
dialect->ctx_indices, ctx, val);
}
MIE_DIAG_CLASS_LIST_EXTERN(mie_builtin_diag);
MIE_DIAG_MSG_LIST_EXTERN(mie_builtin_msg);
MIE_DIALECT_BEGIN(mie_builtin, struct builtin_dialect, "builtin")
MIE_DIALECT_INIT(init);
MIE_DIALECT_CLEANUP(cleanup);
MIE_DIALECT_ADD_OP(mie_builtin_module);
MIE_DIALECT_ADD_TYPE(mie_builtin_string);
MIE_DIALECT_DIAG_CLASS_LIST(mie_builtin_diag);
MIE_DIALECT_DIAG_MSG_LIST(mie_builtin_msg);
MIE_DIALECT_ADD_TRAIT(mie_builtin_isolated_from_above);
MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table);
MIE_DIALECT_ADD_TYPE(mie_builtin_int);
MIE_DIALECT_ADD_TYPE(mie_builtin_float);
MIE_DIALECT_ADD_TYPE(mie_builtin_index);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_string);
MIE_DIALECT_ADD_TYPE(mie_builtin_string);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_int);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_float);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_array);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_type);
MIE_DIALECT_ADD_TRAIT(mie_builtin_isolated_from_above);
MIE_DIALECT_ADD_TRAIT(mie_builtin_symbol_table);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_string);
MIE_DIALECT_ADD_INTERFACE(mie_builtin_symbol);
MIE_DIALECT_ADD_ATTRIBUTE(mie_builtin_array);
MIE_DIALECT_ADD_OP(mie_builtin_module);
MIE_DIALECT_END()

View File

@@ -0,0 +1,36 @@
#include <mie/diag/class.h>
#include <mie/diag/msg.h>
#include <mie/dialect/builtin.h>
#include <mie/macros.h>
#define MIE_DIAG_CLASS_PREFIX MIE_BUILTIN_E
#define MIE_DIAG_MSG_PREFIX MIE_BUILTIN_MSG
MIE_DIAG_CLASS_LIST_BEGIN(mie_builtin_diag)
MIE_DIAG_CLASS(UNRECOGNISED_TOKEN, ERROR, "Unrecognised token")
MIE_DIAG_CLASS(UNRESOLVED_VALUE, ERROR, "Unresolved value")
MIE_DIAG_CLASS(UNRESOLVED_SUCCESSOR, ERROR, "Unresolved successor")
MIE_DIAG_CLASS_LIST_END(mie_builtin_diag)
MIE_DIAG_MSG_LIST_BEGIN(mie_builtin_msg)
MIE_DIAG_MSG(UNRECOGNISED_TOKEN, "encountered an unrecognised token.")
MIE_DIAG_MSG(UNRESOLVED_VALUE, "cannot resolve this value reference.")
MIE_DIAG_MSG(
CANNOT_FIND_BLOCK,
"cannot find a block with this name in this region.")
MIE_DIAG_MSG(
VALUE_DEFINED_IN_NON_DOMINANT_BLOCK,
"this value cannot be referenced here, as it is defined in a "
"block that does not dominate this block.")
MIE_DIAG_MSG(
VALUE_DEFINED_AFTER_USE,
"this value cannot be referenced here, as it is not defined "
"until later in this block.")
MIE_DIAG_MSG(
VALUE_DEFINED_OUTSIDE_ISOLATED_REGION,
"this value cannot be referenced here, as this region is "
"isolated from above, and the definition for this value is "
"outside of this region.")
MIE_DIAG_MSG(
VALUE_DEFINED_IN_BLOCK, "the value is defined in this block.")
MIE_DIAG_MSG_LIST_END(mie_builtin_msg)

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@
#include <mie/macros.h>
MIE_DIALECT_BEGIN(mie_func, struct mie_dialect, "func")
MIE_DIALECT_ADD_TRAIT(mie_func_function_like);
MIE_DIALECT_ADD_OP(mie_func_func);
MIE_DIALECT_ADD_OP(mie_func_return);
MIE_DIALECT_END()

View File

@@ -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);
@@ -130,6 +129,8 @@ struct mie_op *mie_func_put_func(
MIE_OP_DEFINITION_BEGIN(mie_func_func, "func")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);
MIE_OP_DEFINITION_TRAIT("builtin", "isolated-from-above");
MIE_OP_DEFINITION_TRAIT("func", "function-like");
MIE_OP_INTERFACE_BEGIN("builtin", "symbol", struct mie_symbol)
MIE_OP_INTERFACE_FUNC(sym_get_name) = NULL;
MIE_OP_INTERFACE_END()

View File

@@ -0,0 +1,23 @@
#include <mie/dialect/dialect.h>
#include <mie/macros.h>
#include <mie/trait/trait-definition.h>
#include <mie/trait/trait.h>
static enum mie_status validate(
const struct mie_trait_definition *trait_def,
const struct mie_trait *trait, const struct mie_trait_target *target)
{
return MIE_SUCCESS;
}
/* func.function-like trait:
* the op behaves like a func.func. this means that it:
* a) has a single region
* b) that region has one or more blocks representing the body of a function.
* c) the op has sym_name, function_type, and other function-related attributes.
*/
MIE_TRAIT_DEFINITION_BEGIN(mie_func_function_like, "function-like")
MIE_TRAIT_DEFINITION_TARGETS(MIE_TRAIT_TARGET_OP);
MIE_TRAIT_DEFINITION_STRUCT(struct mie_trait);
MIE_TRAIT_DEFINITION_VALIDATE(validate);
MIE_TRAIT_DEFINITION_END()

View File

@@ -7,4 +7,5 @@
MIE_DIALECT_BEGIN(mie_memref, struct mie_dialect, "memref")
MIE_DIALECT_ADD_TYPE(mie_memref_memref);
MIE_DIALECT_ADD_OP(mie_memref_load);
MIE_DIALECT_END()

View File

@@ -0,0 +1,18 @@
#include <mie/ctx.h>
#include <mie/ir/op-definition.h>
#include <mie/macros.h>
static enum mie_status print(struct mie_printer *printer, const struct mie_op *op)
{
return MIE_SUCCESS;
}
static enum mie_status parse(struct mie_parser *parser, struct mie_op *out)
{
return MIE_SUCCESS;
}
MIE_OP_DEFINITION_BEGIN(mie_memref_load, "load")
MIE_OP_DEFINITION_PRINT(print);
MIE_OP_DEFINITION_PARSE(parse);
MIE_OP_DEFINITION_END()

View File

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

View File

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

View File

@@ -7,7 +7,10 @@
struct mie_op;
struct mie_pass;
struct mie_diag;
struct mie_file_cell;
struct mie_int_cache;
struct mie_line_source;
struct mie_index_cache;
struct mie_string_cache;
struct mie_attribute_map;
@@ -31,6 +34,8 @@ struct mie_ctx {
struct mie_id_map ctx_attributes;
/* map of struct mie_pass_definition */
struct mie_id_map ctx_passes;
/* queue of struct mie_diag */
b_queue ctx_diag;
};
MIE_API struct mie_ctx *mie_ctx_create(void);
@@ -38,7 +43,6 @@ MIE_API void mie_ctx_destroy(struct mie_ctx *ctx);
MIE_API struct mie_op *mie_ctx_create_op(
const struct mie_ctx *ctx, const char *dialect, const char *op);
MIE_API bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op);
MIE_API struct mie_dialect *mie_ctx_get_dialect(
const struct mie_ctx *ctx, const char *name);
@@ -73,4 +77,11 @@ MIE_API enum mie_status mie_ctx_get_pass(
struct mie_ctx *ctx, const char *name,
const struct mie_attribute_map *args, struct mie_pass **out);
MIE_API struct mie_diag *mie_ctx_push_diag(
struct mie_ctx *ctx, struct mie_line_source *src,
const struct mie_file_cell *loc, const char *dialect,
unsigned long diag_class);
MIE_API struct mie_diag *mie_ctx_pop_diag(struct mie_ctx *ctx);
#endif

View File

@@ -0,0 +1,36 @@
#ifndef MIE_DIAG_AMENDMENT_H_
#define MIE_DIAG_AMENDMENT_H_
#include <mie/parse/file-span.h>
enum mie_diag_amendment_type {
MIE_DIAG_AMENDMENT_NONE = 0,
MIE_DIAG_AMENDMENT_ADD,
MIE_DIAG_AMENDMENT_REMOVE,
MIE_DIAG_AMENDMENT_REPLACE,
};
struct mie_diag_amendment {
enum mie_diag_amendment_type a_type;
unsigned long __x;
union {
struct {
struct mie_file_cell a_loc;
char *a_str;
} a_add;
struct {
struct mie_file_cell a_loc;
unsigned long a_length;
} a_remove;
struct {
struct mie_file_cell a_loc;
unsigned long a_length;
char *a_str;
} a_replace;
};
};
#endif

View File

@@ -0,0 +1,18 @@
#ifndef MIE_DIAG_CLASS_H_
#define MIE_DIAG_CLASS_H_
enum mie_diag_class_type {
MIE_DIAG_CLASS_NONE = 0,
MIE_DIAG_CLASS_HINT,
MIE_DIAG_CLASS_WARNING,
MIE_DIAG_CLASS_ERROR,
};
struct mie_diag_class {
unsigned int c_id;
const char *c_id_str_short, *c_id_str_long;
enum mie_diag_class_type c_type;
const char *c_title;
};
#endif

View File

@@ -0,0 +1,34 @@
#ifndef MIE_DIAG_COMPONENT_H_
#define MIE_DIAG_COMPONENT_H_
#include <blue/core/queue.h>
#include <stddef.h>
enum mie_diag_component_type {
MIE_DIAG_COMPONENT_NONE = 0,
MIE_DIAG_COMPONENT_MSG,
MIE_DIAG_COMPONENT_SNIPPET,
};
struct mie_diag_component {
enum mie_diag_component_type c_type;
b_queue_entry c_entry;
};
struct mie_diag_c_snippet {
struct mie_diag_component s_base;
unsigned long s_first_line, s_last_line;
struct mie_diag_amendment *s_amendments;
size_t s_nr_amendments;
struct mie_diag_highlight *s_highlights;
size_t s_nr_highlights;
};
struct mie_diag_c_msg {
struct mie_diag_component msg_base;
char *msg_content;
};
#endif

View File

@@ -0,0 +1,39 @@
#ifndef MIE_DIAG_DIAG_H_
#define MIE_DIAG_DIAG_H_
#include <blue/core/queue.h>
#include <mie/parse/file-span.h>
struct mie_ctx;
struct mie_diag_class;
struct mie_diag_amendment;
struct mie_diag_highlight;
enum mie_diag_type {
MIE_DIAG_NONE = 0,
MIE_DIAG_HINT,
MIE_DIAG_WARNING,
MIE_DIAG_ERROR,
};
struct mie_diag {
struct mie_dialect *diag_parent;
const struct mie_diag_class *diag_class;
struct mie_line_source *diag_src;
struct mie_file_cell diag_loc;
b_queue_entry diag_entry;
b_queue diag_components;
};
MIE_API void mie_diag_set_location(
struct mie_diag *diag, unsigned long row, unsigned long col);
MIE_API void mie_diag_push_msg(
struct mie_diag *diag, struct mie_ctx *ctx, const char *dialect,
unsigned long msg, ...);
MIE_API void mie_diag_push_snippet(
struct mie_diag *diag, unsigned long first_line, unsigned long last_line,
const struct mie_diag_amendment *amendmends, size_t nr_amendments,
const struct mie_diag_highlight *highlights, size_t nr_highlights);
#endif

View File

@@ -0,0 +1,18 @@
#ifndef MIE_DIAG_HIGHLIGHT_H_
#define MIE_DIAG_HIGHLIGHT_H_
#include <mie/parse/file-span.h>
enum mie_diag_highlight_type {
MIE_DIAG_HIGHLIGHT_NONE = 0,
MIE_DIAG_HIGHLIGHT_HINT,
MIE_DIAG_HIGHLIGHT_WARNING,
MIE_DIAG_HIGHLIGHT_ERROR,
};
struct mie_diag_highlight {
enum mie_diag_highlight_type hl_type;
struct mie_file_span hl_span;
};
#endif

View File

@@ -0,0 +1,10 @@
#ifndef MIE_DIAG_MSG_H_
#define MIE_DIAG_MSG_H_
struct mie_diag_msg {
unsigned int msg_id;
const char *msg_id_str_short, *msg_id_str_long;
const char *msg_content;
};
#endif

View File

@@ -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

View File

@@ -15,6 +15,22 @@ struct mie_op;
struct mie_int_type;
struct mie_float_type;
enum mie_builtin_diag {
MIE_BUILTIN_E_UNRECOGNISED_TOKEN,
MIE_BUILTIN_E_UNRESOLVED_VALUE,
MIE_BUILTIN_E_UNRESOLVED_SUCCESSOR,
};
enum mie_builtin_msg {
MIE_BUILTIN_MSG_UNRECOGNISED_TOKEN,
MIE_BUILTIN_MSG_UNRESOLVED_VALUE,
MIE_BUILTIN_MSG_CANNOT_FIND_BLOCK,
MIE_BUILTIN_MSG_VALUE_DEFINED_IN_NON_DOMINANT_BLOCK,
MIE_BUILTIN_MSG_VALUE_DEFINED_AFTER_USE,
MIE_BUILTIN_MSG_VALUE_DEFINED_OUTSIDE_ISOLATED_REGION,
MIE_BUILTIN_MSG_VALUE_DEFINED_IN_BLOCK,
};
enum mie_float_width {
MIE_FLOAT_32 = 32,
MIE_FLOAT_64 = 64,

View File

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

View File

@@ -13,6 +13,9 @@ struct mie_op_definition;
struct mie_type_definition;
struct mie_trait_definition;
struct mie_diag_class;
struct mie_diag_msg;
struct mie_dialect {
mie_id d_id;
char *d_name;
@@ -27,6 +30,12 @@ struct mie_dialect {
struct mie_id_map d_attributes;
/* map of struct mie_interface_definition */
struct mie_id_map d_interfaces;
/* array of mie_diag_class */
struct mie_diag_class *d_diag_classes;
size_t d_nr_diag_classes;
/* array of mie_diag_msg */
struct mie_diag_msg *d_diag_msgs;
size_t d_nr_diag_msgs;
enum mie_status (*d_cleanup)(struct mie_dialect *);
};

View File

@@ -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

View File

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

View File

@@ -6,20 +6,69 @@
#include <mie/name.h>
#include <mie/vector.h>
#define MIE_BLOCK_ID_INVALID ((size_t)0)
struct mie_op;
struct mie_register;
struct mie_block_predecessor {
struct mie_block *p_block;
};
struct mie_block {
struct mie_name b_name;
struct mie_region *b_parent;
/* immediate predecessor blocks */
MIE_VECTOR_DECLARE(struct mie_block_predecessor, b_ipred);
/* used by struct mie_region */
unsigned int b_id;
struct mie_block *b_idom;
// struct mie_block *b_sdom, *b_dfs_parent;
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_get_terminator(const struct mie_block *block);
MIE_API struct mie_op_successor *mie_block_get_first_successor(
const struct mie_block *block);
MIE_API struct mie_op_successor *mie_block_get_prev_successor(
const struct mie_block *block, const struct mie_op_successor *before);
MIE_API struct mie_op_successor *mie_block_get_next_successor(
const struct mie_block *block, const struct mie_op_successor *after);
MIE_API struct mie_op_successor *mie_block_get_last_successor(
const struct mie_block *block);
MIE_API struct mie_block_predecessor *mie_block_get_first_predecessor(
const struct mie_block *block);
MIE_API struct mie_block_predecessor *mie_block_get_prev_predecessor(
const struct mie_block *block, const struct mie_block_predecessor *before);
MIE_API struct mie_block_predecessor *mie_block_get_next_predecessor(
const struct mie_block *block, const struct mie_block_predecessor *after);
MIE_API struct mie_block_predecessor *mie_block_get_last_predecessor(
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);
MIE_API struct mie_register *mie_block_find_register(
const struct mie_block *block, const char *name,
const struct mie_op *start_point);
#endif

View File

@@ -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
View File

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

View File

@@ -9,8 +9,8 @@
#include <mie/name.h>
#include <mie/parse/file-span.h>
struct mie_ctx;
struct mie_type;
struct mie_value;
struct mie_block;
struct mie_region;
@@ -37,6 +37,7 @@ struct mie_op_arg {
struct mie_op_successor {
enum mie_op_flags s_flags;
struct mie_file_span s_name_span;
union {
/* only valid if F_SUCCESSOR_RESOLVED is set in s_flags; */
@@ -50,16 +51,20 @@ struct mie_op_successor {
struct mie_op {
enum mie_op_flags op_flags;
/* used by struct mie_block */
b_queue_entry op_entry;
/* these pointers are only valid if the F_OP_RESOLVED flag is set */
const struct mie_dialect *op_dialect;
struct mie_line_source *op_src;
/* this pointer is only valid if the F_OP_RESOLVED flag is set */
const struct mie_op_definition *op_info;
struct mie_block *op_container;
struct mie_file_span op_name_span;
/* only valid if the F_RESOLVED flag is NOT set */
char *op_name;
MIE_VECTOR_DECLARE(struct mie_region, op_regions);
b_queue op_regions;
MIE_VECTOR_DECLARE(struct mie_op_successor, op_successors);
struct mie_attribute_map op_attrib;
MIE_VECTOR_DECLARE(struct mie_op_arg, op_args);
@@ -72,16 +77,42 @@ MIE_API void mie_op_destroy(struct mie_op *op);
MIE_API void mie_op_init(struct mie_op *op);
MIE_API void mie_op_cleanup(struct mie_op *op);
MIE_API size_t mie_op_get_name(const struct mie_op *op, char *out, size_t max);
MIE_API bool mie_op_resolve_self(struct mie_op *op, struct mie_ctx *ctx);
MIE_API bool mie_op_resolve_args(struct mie_op *op, struct mie_ctx *ctx);
MIE_API bool mie_op_resolve_successors(struct mie_op *op, struct mie_ctx *ctx);
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_register *mie_op_get_result_with_name(
const struct mie_op *op, const char *name);
MIE_API struct mie_op *mie_op_get_first_child_op(const struct mie_op *op);
MIE_API struct mie_op *mie_op_get_last_child_op(const struct mie_op *op);
MIE_API const struct mie_type *mie_op_arg_get_type(const struct mie_op_arg *arg);
#endif

View File

@@ -1,19 +1,55 @@
#ifndef MIE_IR_REGION_H_
#define MIE_IR_REGION_H_
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <mie/misc.h>
#include <mie/vector.h>
#include <stddef.h>
struct mie_op;
struct mie_ctx;
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;
/* bst of struct mie_block, as numbered by a depth-first search.
* this ordering is recalculated by mie_region_refresh_dominance */
b_btree r_blocks_s;
};
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);
MIE_API struct mie_block *mie_region_find_block(
const struct mie_region *region, const char *name);
MIE_API struct mie_register *mie_region_find_register(
const struct mie_region *region, const char *name);
/* calculate the dominance-tree of all blocks in a region.
* this function populates the following attributes of every block in the
* region:
* b_id
* b_node
* b_parent
* as well as the following attributes of the region itself:
* r_blocks_s
* only top-level blocks and ops are considered by this function. if an op
* within the region itself contains one/more child regions, these are ignored.
*/
MIE_API void mie_region_refresh_dominance(struct mie_region *region);
#endif

View File

@@ -37,6 +37,7 @@ struct mie_register_use {
struct mie_register {
enum mie_register_flags reg_flags;
struct mie_file_span reg_span;
union {
/* only valid if F_VIRTUAL is set. */
struct mie_name reg_name;

View File

@@ -0,0 +1,14 @@
#ifndef MIE_IR_RESOLVE_H_
#define MIE_IR_RESOLVE_H_
#include <mie/misc.h>
#include <stdbool.h>
struct mie_op;
struct mie_ctx;
MIE_API bool mie_resolve_op_self(struct mie_op *op, struct mie_ctx *ctx);
MIE_API bool mie_resolve_op_args(struct mie_op *op, struct mie_ctx *ctx);
MIE_API bool mie_resolve_op_successors(struct mie_op *op, struct mie_ctx *ctx);
#endif

View File

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

View File

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

View File

@@ -5,180 +5,186 @@
/* DIALECT DEFINITION MACROS */
/******************************************************************************/
#define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \
struct mie_dialect *func_prefix##_dialect_create(struct mie_ctx *ctx) \
{ \
struct mie_dialect *self = mie_dialect_create( \
ctx, dialect_name, sizeof(c_struct)); \
if (!self) { \
return NULL; \
} \
struct mie_op_definition *op = NULL; \
struct mie_type_definition *type = NULL; \
struct mie_trait_definition *trait = NULL; \
struct mie_attribute_definition *attribute = NULL; \
struct mie_interface_definition *interface = NULL;
#define MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \
struct mie_dialect* func_prefix##_dialect_create(struct mie_ctx* ctx) \
{ \
struct mie_dialect* self = mie_dialect_create( \
ctx, dialect_name, sizeof(c_struct)); \
if (!self) { \
return NULL; \
} \
struct mie_op_definition* op = NULL; \
struct mie_type_definition* type = NULL; \
struct mie_trait_definition* trait = NULL; \
struct mie_attribute_definition* attribute = NULL; \
struct mie_interface_definition* interface = NULL;
#define MIE_DIALECT_END() \
return self; \
}
#define MIE_DIALECT_END() \
return self; \
}
#define MIE_DIALECT_INIT(func) func(self)
#define MIE_DIALECT_INIT(func) func(self)
#define MIE_DIALECT_CLEANUP(func) self->d_cleanup = (func)
#define MIE_DIALECT_ADD_OP(op_id) \
extern struct mie_op_definition *op_id##_op_create( \
struct mie_dialect *, struct mie_ctx *); \
op = op_id##_op_create(self, ctx)
#define MIE_DIALECT_ADD_TYPE(type_id) \
extern struct mie_type_definition *type_id##_type_create( \
struct mie_dialect *, struct mie_ctx *); \
type = type_id##_type_create(self, ctx)
#define MIE_DIALECT_ADD_TRAIT(trait_id) \
extern struct mie_trait_definition *trait_id##_trait_create( \
struct mie_dialect *, struct mie_ctx *); \
trait = trait_id##_trait_create(self, ctx)
#define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \
extern struct mie_attribute_definition *attr_id##_attribute_create( \
struct mie_dialect *, struct mie_ctx *); \
attribute = attr_id##_attribute_create(self, ctx)
#define MIE_DIALECT_ADD_INTERFACE(iface_id) \
extern struct mie_interface_definition *iface_id##_interface_create( \
struct mie_dialect *, struct mie_ctx *); \
interface = iface_id##_interface_create(self, ctx)
#define MIE_DIALECT_DIAG_CLASS_LIST(list) \
self->d_diag_classes = (list); \
self->d_nr_diag_classes = (list##_count)
#define MIE_DIALECT_DIAG_MSG_LIST(list) \
self->d_diag_msgs = (list); \
self->d_nr_diag_msgs = (list##_count)
#define MIE_DIALECT_ADD_OP(op_id) \
extern struct mie_op_definition* op_id##_op_create( \
struct mie_dialect*, struct mie_ctx*); \
op = op_id##_op_create(self, ctx)
#define MIE_DIALECT_ADD_TYPE(type_id) \
extern struct mie_type_definition* type_id##_type_create( \
struct mie_dialect*, struct mie_ctx*); \
type = type_id##_type_create(self, ctx)
#define MIE_DIALECT_ADD_TRAIT(trait_id) \
extern struct mie_trait_definition* trait_id##_trait_create( \
struct mie_dialect*, struct mie_ctx*); \
trait = trait_id##_trait_create(self, ctx)
#define MIE_DIALECT_ADD_ATTRIBUTE(attr_id) \
extern struct mie_attribute_definition* attr_id##_attribute_create( \
struct mie_dialect*, struct mie_ctx*); \
attribute = attr_id##_attribute_create(self, ctx)
#define MIE_DIALECT_ADD_INTERFACE(iface_id) \
extern struct mie_interface_definition* iface_id##_interface_create( \
struct mie_dialect*, struct mie_ctx*); \
interface = iface_id##_interface_create(self, ctx)
/******************************************************************************/
/* OP DEFINITION MACROS */
/******************************************************************************/
#define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \
struct mie_op_definition *func_prefix##_op_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \
{ \
struct mie_op_definition *op \
= mie_op_definition_create(d, op_name); \
if (!op) { \
return NULL; \
} \
const struct mie_trait *trait = NULL; \
struct mie_interface *i = NULL; \
const struct mie_interface_definition *id = NULL;
#define MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \
struct mie_op_definition* func_prefix##_op_create( \
struct mie_dialect* d, struct mie_ctx* ctx) \
{ \
struct mie_op_definition* op \
= mie_op_definition_create(d, op_name); \
if (!op) { \
return NULL; \
} \
const struct mie_trait* trait = NULL; \
struct mie_interface* i = NULL; \
const struct mie_interface_definition* id = NULL;
#define MIE_OP_DEFINITION_END() \
return op; \
}
#define MIE_OP_DEFINITION_END() \
return op; \
}
#define MIE_OP_DEFINITION_PRINT(func) op->op_print = (func)
#define MIE_OP_DEFINITION_PARSE(func) op->op_parse = (func)
#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_op_definition_add_trait(op, trait);
#define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \
id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \
if (id) { \
c_struct *iface = (c_struct *)mie_interface_create(id);
#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_op_definition_add_trait(op, trait);
#define MIE_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \
id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \
if (id) { \
c_struct* iface = (c_struct*)mie_interface_create(id);
#define MIE_OP_INTERFACE_FUNC(func_name) iface->func_name
#define MIE_OP_INTERFACE_END() \
mie_op_definition_add_interface(op, (struct mie_interface *)iface); \
}
#define MIE_OP_INTERFACE_END() \
mie_op_definition_add_interface(op, (struct mie_interface*)iface); \
}
/******************************************************************************/
/* TYPE DEFINITION MACROS */
/******************************************************************************/
#define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \
struct mie_type_definition *func_prefix##_type_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \
{ \
struct mie_type_definition *type \
= mie_type_definition_create(d, type_name); \
if (!type) { \
return NULL; \
} \
const struct mie_trait *trait = NULL;
#define MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \
struct mie_type_definition* func_prefix##_type_create( \
struct mie_dialect* d, struct mie_ctx* ctx) \
{ \
struct mie_type_definition* type \
= mie_type_definition_create(d, type_name); \
if (!type) { \
return NULL; \
} \
const struct mie_trait* trait = NULL;
#define MIE_TYPE_DEFINITION_END() \
return type; \
}
#define MIE_TYPE_DEFINITION_END() \
return type; \
}
#define MIE_TYPE_DEFINITION_FLAGS(flags) type->ty_flags = flags
#define MIE_TYPE_DEFINITION_STRUCT(name) type->ty_data_size = sizeof(name)
#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_PRINT(func) type->ty_print = (func)
#define MIE_TYPE_DEFINITION_PARSE(func) type->ty_parse = (func)
#define MIE_TYPE_DEFINITION_FLAGS(flags) type->ty_flags = flags
#define MIE_TYPE_DEFINITION_STRUCT(name) type->ty_data_size = sizeof(name)
#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_PRINT(func) type->ty_print = (func)
#define MIE_TYPE_DEFINITION_PARSE(func) type->ty_parse = (func)
#define MIE_TYPE_DEFINITION_BUILD_ID(func) type->ty_build_id = (func)
#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func)
#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_type_definition_add_trait(type, trait);
#define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func)
#define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func)
#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
mie_type_definition_add_trait(type, trait);
/******************************************************************************/
/* TRAIT DEFINITION MACROS */
/******************************************************************************/
#define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \
struct mie_trait_definition *func_prefix##_trait_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \
{ \
struct mie_trait_definition *trait \
= mie_trait_definition_create(d, trait_name); \
if (!trait) { \
return NULL; \
}
#define MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \
struct mie_trait_definition* func_prefix##_trait_create( \
struct mie_dialect* d, struct mie_ctx* ctx) \
{ \
struct mie_trait_definition* trait \
= mie_trait_definition_create(d, trait_name); \
if (!trait) { \
return NULL; \
}
#define MIE_TRAIT_DEFINITION_END() \
return trait; \
}
#define MIE_TRAIT_DEFINITION_END() \
return trait; \
}
#define MIE_TRAIT_DEFINITION_TARGETS(targets) trait->tr_target = (targets)
#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name)
#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func)
#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func)
#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func)
#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func)
#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name)
#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func)
#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func)
#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func)
#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func)
/******************************************************************************/
/* ATTRIBUTE DEFINITION MACROS */
/******************************************************************************/
#define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \
struct mie_attribute_definition *func_prefix##_attribute_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \
{ \
struct mie_attribute_definition *attribute \
= mie_attribute_definition_create(d, attribute_name); \
if (!attribute) { \
return NULL; \
}
#define MIE_ATTRIBUTE_DEFINITION_BEGIN(func_prefix, attribute_name) \
struct mie_attribute_definition* func_prefix##_attribute_create( \
struct mie_dialect* d, struct mie_ctx* ctx) \
{ \
struct mie_attribute_definition* attribute \
= mie_attribute_definition_create(d, attribute_name); \
if (!attribute) { \
return NULL; \
}
#define MIE_ATTRIBUTE_DEFINITION_END() \
return attribute; \
}
#define MIE_ATTRIBUTE_DEFINITION_END() \
return attribute; \
}
#define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \
attribute->a_data_size = sizeof(name)
#define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func)
#define MIE_ATTRIBUTE_DEFINITION_STRUCT(name) \
attribute->a_data_size = sizeof(name)
#define MIE_ATTRIBUTE_DEFINITION_INIT(func) attribute->a_init = (func)
#define MIE_ATTRIBUTE_DEFINITION_CLEANUP(func) attribute->a_cleanup = (func)
#define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func)
#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func)
#define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func)
#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func)
/******************************************************************************/
/* INTERFACE DEFINITION MACROS */
/******************************************************************************/
#define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \
struct mie_interface_definition *func_prefix##_interface_create( \
struct mie_dialect *d, struct mie_ctx *ctx) \
{ \
struct mie_interface_definition *i \
= mie_interface_definition_create(d, iface_name); \
if (!i) { \
return NULL; \
}
#define MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \
struct mie_interface_definition* func_prefix##_interface_create( \
struct mie_dialect* d, struct mie_ctx* ctx) \
{ \
struct mie_interface_definition* i \
= mie_interface_definition_create(d, iface_name); \
if (!i) { \
return NULL; \
}
#define MIE_INTERFACE_DEFINITION_END() \
return i; \
}
#define MIE_INTERFACE_DEFINITION_END() \
return i; \
}
#define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name)
@@ -186,63 +192,143 @@
/* PASS DEFINITION MACROS */
/******************************************************************************/
#define MIE_PASS_DEFINITION_BEGIN(prefix) \
struct mie_pass_definition *prefix##_pass_create(struct mie_ctx *ctx) \
{ \
struct mie_pass_definition *p = mie_pass_definition_create(); \
if (!p) { \
return NULL; \
}
#define MIE_PASS_DEFINITION_BEGIN(prefix) \
struct mie_pass_definition* prefix##_pass_create(struct mie_ctx* ctx) \
{ \
struct mie_pass_definition* p = mie_pass_definition_create(); \
if (!p) { \
return NULL; \
}
#define MIE_PASS_DEFINITION_END() \
if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \
return NULL; \
} \
return p; \
}
#define MIE_PASS_DEFINITION_END() \
if (mie_ctx_register_pass(ctx, p) != MIE_SUCCESS) { \
return NULL; \
} \
return p; \
}
#define MIE_PASS_NAME(name) p->p_name = (name)
#define MIE_PASS_NAME(name) p->p_name = (name)
#define MIE_PASS_DESCRIPTION(desc) p->p_description = (desc)
#define MIE_PASS_STRUCT(c_struct) p->p_data_size = sizeof(c_struct)
#define MIE_PASS_TYPE(type) p->p_type = (type)
#define MIE_PASS_INIT(func) p->p_init = (func)
#define MIE_PASS_TRANSFORM(func) \
p->p_transform = (func); \
p->p_type = MIE_PASS_TRANSFORM
#define MIE_PASS_ANALYSE(func) \
p->p_analyse = (func); \
p->p_type = MIE_PASS_ANALYSE
#define MIE_PASS_FILTER_OP(dialect, op) \
p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op)
#define MIE_PASS_FILTER_TRAIT(dialect, tr) \
p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr)
#define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \
p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn)
#define MIE_PASS_STRUCT(c_struct) p->p_data_size = sizeof(c_struct)
#define MIE_PASS_TYPE(type) p->p_type = (type)
#define MIE_PASS_INIT(func) p->p_init = (func)
#define MIE_PASS_TRANSFORM(func) \
p->p_transform = (func); \
p->p_type = MIE_PASS_TRANSFORM
#define MIE_PASS_ANALYSE(func) \
p->p_analyse = (func); \
p->p_type = MIE_PASS_ANALYSE
#define MIE_PASS_FILTER_OP(dialect, op) \
p->p_filter.f_op = mie_ctx_get_op_definition(ctx, dialect, op)
#define MIE_PASS_FILTER_TRAIT(dialect, tr) \
p->p_filter.f_trait = mie_ctx_get_trait_definition(ctx, dialect, tr)
#define MIE_PASS_FILTER_INTERFACE(dialect, ifn) \
p->p_filter.f_iface = mie_ctx_get_iface_definition(ctx, dialect, ifn)
/******************************************************************************/
/* PASS GROUP MACROS */
/******************************************************************************/
#define MIE_PASS_GROUP_BEGIN(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx *ctx) \
{ \
struct mie_pass_definition *pass = NULL;
#define MIE_PASS_GROUP_BEGIN(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx* ctx) \
{ \
struct mie_pass_definition* pass = NULL;
#define MIE_PASS_GROUP_END() \
return MIE_SUCCESS; \
}
#define MIE_PASS_GROUP_END() \
return MIE_SUCCESS; \
}
#define MIE_PASS_GROUP_DECLARATION(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx *);
#define MIE_PASS_GROUP_DECLARATION(prefix) \
enum mie_status prefix##_passes_register(struct mie_ctx*);
#define MIE_PASS_GROUP_ADD_PASS(id) \
do { \
extern struct mie_pass_definition *id##_pass_create( \
struct mie_ctx *); \
pass = id##_pass_create(ctx); \
if (!pass) { \
return MIE_ERR_INTERNAL_FAILURE; \
} \
} while (0)
#define MIE_PASS_GROUP_ADD_PASS(id) \
do { \
extern struct mie_pass_definition* id##_pass_create( \
struct mie_ctx*); \
pass = id##_pass_create(ctx); \
if (!pass) { \
return MIE_ERR_INTERNAL_FAILURE; \
} \
} while (0)
#endif
/******************************************************************************/
/* REWRITE PATTERN 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)
/******************************************************************************/
/* DIAG CLASS MACROS */
/******************************************************************************/
#define __MIE_CNAME2(x, y) x##_##y
#define __MIE_CNAME1(x, y) __MIE_CNAME2(x, y)
#define __MIE_CNAME(fun) __MIE_CNAME1(MIE_DIAG_CLASS_PREFIX, fun)
#define __MIE_CSNAME2(x, y) #x #y
#define __MIE_CSNAME1(x, y) __MIE_CSNAME2(x, y)
#define __MIE_CSNAME(fun) __MIE_CSNAME1(MIE_DIAG_CLASS_PREFIX, fun)
#define MIE_DIAG_CLASS_LIST_EXTERN(list_name) \
extern struct mie_diag_class list_name[]; \
extern const size_t list_name##_count
#define MIE_DIAG_CLASS_LIST_BEGIN(list_name) \
struct mie_diag_class list_name[] = {
#define MIE_DIAG_CLASS_LIST_END(list_name) \
} \
; \
const size_t list_name##_count = sizeof(list_name) / sizeof(list_name[0]);
#define MIE_DIAG_CLASS(id, type, title) \
[__MIE_CNAME(id)] = { \
.c_id = __MIE_CNAME(id), \
.c_type = MIE_DIAG_CLASS_##type, \
.c_title = (title), \
.c_id_str_short = #id, \
.c_id_str_long = __MIE_CSNAME(id), \
},
/******************************************************************************/
/* DIAG MSG MACROS */
/******************************************************************************/
#define __MIE_MNAME2(x, y) x##_##y
#define __MIE_MNAME1(x, y) __MIE_CNAME2(x, y)
#define __MIE_MNAME(fun) __MIE_CNAME1(MIE_DIAG_MSG_PREFIX, fun)
#define __MIE_MSNAME2(x, y) #x #y
#define __MIE_MSNAME1(x, y) __MIE_CSNAME2(x, y)
#define __MIE_MSNAME(fun) __MIE_CSNAME1(MIE_DIAG_MSG_PREFIX, fun)
#define MIE_DIAG_MSG_LIST_EXTERN(list_name) \
extern struct mie_diag_msg list_name[]; \
extern const size_t list_name##_count
#define MIE_DIAG_MSG_LIST_BEGIN(list_name) \
struct mie_diag_msg list_name[] = {
#define MIE_DIAG_MSG_LIST_END(list_name) \
} \
; \
const size_t list_name##_count = sizeof(list_name) / sizeof(list_name[0]);
#define MIE_DIAG_MSG(id, content) \
[__MIE_MNAME(id)] = { \
.msg_id = __MIE_MNAME(id), \
.msg_content = (content), \
.msg_id_str_short = #id, \
.msg_id_str_long = __MIE_MSNAME(id), \
},

View File

@@ -59,7 +59,7 @@ struct mie_name {
/* if this name was read from a file, these structs can be used to
* record the location within the file where the name is found. */
struct mie_file_span n_start, n_end;
struct mie_file_span n_span;
};
struct mie_name_map {

View File

@@ -1,17 +1,22 @@
#ifndef MIE_PARSE_LEX_H_
#define MIE_PARSE_LEX_H_
#include <blue/core/queue.h>
#include <blue/core/stream.h>
#include <mie/misc.h>
#include <mie/status.h>
struct mie_lex;
struct mie_ctx;
struct mie_token;
struct mie_line_source;
MIE_API struct mie_lex *mie_lex_create(b_stream *src);
MIE_API struct mie_lex *mie_lex_create(
struct mie_line_source *src, struct mie_ctx *ctx);
MIE_API void mie_lex_destroy(struct mie_lex *lex);
MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex);
MIE_API struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex);
MIE_API struct mie_token *mie_lex_peek(struct mie_lex *lex);
MIE_API void mie_lex_advance(struct mie_lex *lex);

View File

@@ -0,0 +1,35 @@
#ifndef MIE_PARSE_LINE_SOURCE_H_
#define MIE_PARSE_LINE_SOURCE_H_
#include <blue/core/stream.h>
#include <blue/ds/array.h>
#include <blue/ds/string.h>
#include <mie/misc.h>
#include <mie/parse/file-span.h>
#include <mie/status.h>
struct mie_line_source {
b_stream *s_stream;
const char *s_path;
b_string *s_linebuf;
b_iterator *s_linebuf_ptr;
b_array *s_lines;
struct mie_file_cell s_cursor;
};
MIE_API enum mie_status mie_line_source_init(
struct mie_line_source *src, const char *path, b_stream *stream);
MIE_API void mie_line_source_cleanup(struct mie_line_source *src);
MIE_API const char *mie_line_source_get_path(const struct mie_line_source *src);
MIE_API const struct mie_file_cell *mie_line_source_get_cursor(
const struct mie_line_source *src);
MIE_API b_wchar mie_line_source_peekc(struct mie_line_source *src);
MIE_API b_wchar mie_line_source_getc(struct mie_line_source *src);
MIE_API enum mie_status mie_line_source_get_row(
struct mie_line_source *src, size_t row, const b_string **out);
MIE_API bool mie_line_source_input_available(struct mie_line_source *src);
#endif

View File

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

View File

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

View File

@@ -23,6 +23,8 @@ enum mie_print_flags {
MIE_PRINT_F_INCLUDE_TYPE = 0x04u,
MIE_PRINT_F_EXCLUDE_BLOCK_HEADER = 0x08u,
MIE_PRINT_F_EXCLUDE_FIRST_BLOCK_HEADER = 0x10u,
MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS = 0x20u,
};
struct mie_printer {

View File

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

View File

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

View File

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

View File

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

View File

@@ -49,8 +49,8 @@ struct mie_vector_ops {
&(vector.max), ops)
#define mie_vector_pop_back(vector, ops) \
__mie_vector_pop_back( \
(void **)&(vector), sizeof *vector, &(vector.count), \
&(vector.max), ops)
(void **)&(vector.items), sizeof *vector.items, \
&(vector.count), &(vector.max), ops)
#define mie_vector_emplace_back(vector, ops) \
__mie_vector_emplace_back( \
(void **)&(vector.items), sizeof *vector.items, \
@@ -86,6 +86,10 @@ struct mie_vector_ops {
__mie_vector_destroy( \
(void **)(vector), sizeof **vector, (vector##_count), \
(vector##_max), ops)
#define mie_vector_ref_get_item(vector, index) (*vector)[index]
#define mie_vector_ref_get_item_ptr(vector, index) (&(*vector)[index])
#define mie_vector_ref_get_count(vector) *(vector##_count)
#define mie_vector_ref_get_max(vector) *(vector##_count)
/* don't use these functions */
MIE_API int __mie_vector_push_back(

View File

@@ -2,9 +2,230 @@
#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_get_terminator(const struct mie_block *block)
{
b_queue_entry *op_entry = b_queue_last(&block->b_ops);
return b_unbox(struct mie_op, op_entry, op_entry);
}
struct mie_op_successor *mie_block_get_first_successor(const struct mie_block *block)
{
struct mie_op *op = mie_block_get_terminator(block);
if (!op) {
return NULL;
}
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
return NULL;
}
return &op->op_successors.items[0];
}
struct mie_op_successor *mie_block_get_prev_successor(
const struct mie_block *block, const struct mie_op_successor *before)
{
struct mie_op *op = mie_block_get_terminator(block);
if (!op) {
return NULL;
}
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
return NULL;
}
size_t i = before - &op->op_successors.items[0];
if (i == 0 || i >= MIE_VECTOR_COUNT(op->op_successors)) {
return NULL;
}
return &op->op_successors.items[i - 1];
}
struct mie_op_successor *mie_block_get_next_successor(
const struct mie_block *block, const struct mie_op_successor *after)
{
struct mie_op *op = mie_block_get_terminator(block);
if (!op) {
return NULL;
}
if (MIE_VECTOR_COUNT(op->op_successors) == 0) {
return NULL;
}
size_t i = after - &op->op_successors.items[0];
if (i >= MIE_VECTOR_COUNT(op->op_successors)) {
return NULL;
}
if (i + 1 >= MIE_VECTOR_COUNT(op->op_successors)) {
return NULL;
}
return &op->op_successors.items[i + 1];
}
struct mie_op_successor *mie_block_get_last_successor(const struct mie_block *block)
{
struct mie_op *op = mie_block_get_terminator(block);
if (!op) {
return NULL;
}
size_t nr_successors = MIE_VECTOR_COUNT(op->op_successors);
if (nr_successors == 0) {
return NULL;
}
return &op->op_successors.items[nr_successors - 1];
}
struct mie_block_predecessor *mie_block_get_first_predecessor(
const struct mie_block *block)
{
size_t nr_predecessors = MIE_VECTOR_COUNT(block->b_ipred);
if (nr_predecessors == 0) {
return NULL;
}
return &block->b_ipred.items[0];
}
struct mie_block_predecessor *mie_block_get_prev_predecessor(
const struct mie_block *block, const struct mie_block_predecessor *before)
{
if (MIE_VECTOR_COUNT(block->b_ipred) == 0) {
return NULL;
}
size_t i = before - &block->b_ipred.items[0];
if (i == 0) {
return NULL;
}
return &block->b_ipred.items[i - 1];
}
struct mie_block_predecessor *mie_block_get_next_predecessor(
const struct mie_block *block, const struct mie_block_predecessor *after)
{
if (MIE_VECTOR_COUNT(block->b_ipred) == 0) {
return NULL;
}
size_t i = after - &block->b_ipred.items[0];
if (i >= MIE_VECTOR_COUNT(block->b_ipred)) {
return NULL;
}
if (i + 1 >= MIE_VECTOR_COUNT(block->b_ipred)) {
return NULL;
}
return &block->b_ipred.items[i + 1];
}
struct mie_block_predecessor *mie_block_get_last_predecessor(
const struct mie_block *block)
{
size_t nr_predecessors = MIE_VECTOR_COUNT(block->b_ipred);
if (nr_predecessors == 0) {
return NULL;
}
return &block->b_ipred.items[nr_predecessors - 1];
}
struct mie_op *mie_block_add_op(struct mie_block *block)
{
return mie_vector_emplace_back(block->b_ops, NULL);
struct mie_op *op = malloc(sizeof *op);
if (!op) {
return NULL;
}
mie_op_init(op);
op->op_container = block;
b_queue_push_back(&block->b_ops, &op->op_entry);
return op;
}
struct mie_op *mie_block_add_op_after(struct mie_block *block, struct mie_op *after)
{
if (after && after->op_container != block) {
return NULL;
}
struct mie_op *op = malloc(sizeof *op);
if (!op) {
return NULL;
}
mie_op_init(op);
op->op_container = block;
if (after) {
b_queue_insert_after(&block->b_ops, &op->op_entry, &after->op_entry);
} else {
b_queue_push_back(&block->b_ops, &op->op_entry);
}
return op;
}
struct mie_register *mie_block_add_param(struct mie_block *block)
@@ -17,3 +238,31 @@ struct mie_register *mie_block_add_param(struct mie_block *block)
return result;
}
struct mie_register *mie_block_find_register(
const struct mie_block *block, const char *name,
const struct mie_op *start_point)
{
const b_queue_entry *entry = b_queue_last(&block->b_ops);
if (start_point) {
entry = &start_point->op_entry;
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(block->b_params); i++) {
if (!strcmp(block->b_params.items[i].reg_name.n_str, name)) {
return &block->b_params.items[i];
}
}
while (entry) {
struct mie_op *op = b_unbox(struct mie_op, entry, op_entry);
struct mie_register *reg = mie_op_get_result_with_name(op, name);
if (reg) {
return reg;
}
entry = b_queue_prev(entry);
}
return NULL;
}

View File

@@ -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;
@@ -41,6 +48,23 @@ struct mie_ctx *mie_builder_get_ctx(struct mie_builder *builder)
return builder->b_ctx;
}
static struct mie_name_map *get_current_name_map(struct mie_builder *builder)
{
b_queue_entry *cur = b_queue_last(&builder->b_scope_stack);
while (cur) {
struct builder_scope *scope
= b_unbox(struct builder_scope, cur, s_entry);
if (scope->s_region && scope->s_region->r_names) {
return scope->s_region->r_names;
}
cur = b_queue_prev(cur);
}
return NULL;
}
struct mie_block *mie_builder_get_current_block(struct mie_builder *builder)
{
b_queue_entry *entry = b_queue_last(&builder->b_scope_stack);
@@ -56,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);
@@ -70,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 = &region->r_blocks.items[MIE_VECTOR_COUNT(region->r_blocks) - 1];
}
mie_builder_step_into_block(builder, block);
@@ -110,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 = &region->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)
@@ -147,7 +145,6 @@ struct mie_op *mie_builder_put_op(
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);
@@ -163,9 +160,12 @@ struct mie_op *mie_builder_put_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;
struct mie_name_map *map = get_current_name_map(builder);
if (!map) {
return MIE_ERR_BAD_STATE;
}
struct mie_name *result = mie_name_map_put(map, name, hint, 0);
return result ? MIE_SUCCESS : MIE_ERR_NAME_EXISTS;
}

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

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

View File

@@ -1,4 +1,10 @@
#include <assert.h>
#include <mie/ctx.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/dialect/builtin.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>
@@ -64,6 +70,17 @@ void mie_op_cleanup(struct mie_op *op)
/* TODO */
}
size_t mie_op_get_name(const struct mie_op *op, char *out, size_t max)
{
if (!(op->op_flags & MIE_OP_F_OP_RESOLVED)) {
return snprintf(out, max, "%s", op->op_name);
}
return snprintf(
out, max, "%s.%s", op->op_info->op_parent->d_name,
op->op_info->op_name);
}
struct mie_op_arg *mie_op_add_arg(struct mie_op *op)
{
return mie_vector_emplace_back(op->op_args, &op_arg_vector_ops);
@@ -76,19 +93,82 @@ 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;
}
struct mie_region *mie_op_add_region(struct mie_op *op)
{
struct mie_region *region = mie_vector_emplace_back(op->op_regions, NULL);
region->r_names = mie_name_map_create(NULL);
bool isolated = is_isolated(op);
struct mie_region *region = malloc(sizeof *region);
if (!region) {
return NULL;
}
region->r_parent = op;
if (isolated) {
region->r_names = mie_name_map_create(NULL);
}
b_queue_push_back(&op->op_regions, &region->r_entry);
return region;
}
bool mie_op_is(const struct mie_op *op, const char *dialect_name, const char *op_name)
{
if (!op->op_info || !op->op_info->op_parent) {
return false;
}
if (strcmp(op->op_info->op_parent->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)
{
@@ -119,3 +199,109 @@ 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_register *mie_op_get_result_with_name(
const struct mie_op *op, const char *name)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
if (!strcmp(op->op_result.items[i].reg_name.n_str, name)) {
return &op->op_result.items[i];
}
}
return NULL;
}
struct mie_op *mie_op_get_first_child_op(const struct mie_op *op)
{
struct mie_region *first_region = mie_op_get_first_region(op);
if (!first_region) {
return NULL;
}
struct mie_block *first_block = mie_region_get_first_block(first_region);
if (!first_block) {
return NULL;
}
return mie_block_get_first_op(first_block);
}
struct mie_op *mie_op_get_last_child_op(const struct mie_op *op)
{
struct mie_region *last_region = mie_op_get_last_region(op);
if (!last_region) {
return NULL;
}
struct mie_block *last_block = mie_region_get_last_block(last_region);
if (!last_block) {
return NULL;
}
return mie_block_get_last_op(last_block);
}

View File

@@ -1,18 +1,132 @@
#include <limits.h>
#include <mie/ctx.h>
#include <mie/diag/diag.h>
#include <mie/dialect/builtin.h>
#include <mie/ir/block.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <stdlib.h>
#include <string.h>
struct mie_block *mie_region_get_first_block(const struct mie_region *region)
{
b_queue_entry *entry = b_queue_first(&region->r_blocks);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_prev_block(
const struct mie_region *region, const struct mie_block *before)
{
if (!before || before->b_parent != region) {
return NULL;
}
b_queue_entry *entry = b_queue_prev(&before->b_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_next_block(
const struct mie_region *region, const struct mie_block *after)
{
if (!after || after->b_parent != region) {
return NULL;
}
b_queue_entry *entry = b_queue_next(&after->b_entry);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_get_last_block(const struct mie_region *region)
{
b_queue_entry *entry = b_queue_last(&region->r_blocks);
if (!entry) {
return NULL;
}
return b_unbox(struct mie_block, entry, b_entry);
}
struct mie_block *mie_region_add_block(struct mie_region *region)
{
struct mie_block *block = mie_vector_emplace_back(
region->r_blocks, &mie_block_vector_ops);
struct mie_block *block = malloc(sizeof *block);
if (!block) {
return NULL;
}
memset(block, 0x0, sizeof *block);
block->b_parent = region;
block->b_id = MIE_BLOCK_ID_INVALID;
b_queue_push_back(&region->r_blocks, &block->b_entry);
return block;
}
struct mie_block *mie_region_add_block_after(
struct mie_region *region, struct mie_block *after)
{
if (after->b_parent != region) {
return NULL;
}
struct mie_block *block = malloc(sizeof *block);
if (!block) {
return NULL;
}
memset(block, 0x0, sizeof *block);
block->b_parent = region;
b_queue_insert_after(&region->r_blocks, &block->b_entry, &after->b_entry);
return block;
}
struct mie_block *mie_region_find_block(
const struct mie_region *region, const char *name)
{
b_queue_entry *cur = b_queue_first(&region->r_blocks);
while (cur) {
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
if (!strcmp(block->b_name.n_str, name)) {
return block;
}
cur = b_queue_next(cur);
}
return NULL;
}
struct mie_register *mie_region_find_register(
const struct mie_region *region, const char *name)
{
b_queue_entry *cur = b_queue_first(&region->r_blocks);
while (cur) {
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
struct mie_register *reg
= mie_block_find_register(block, name, NULL);
if (reg) {
return reg;
}
cur = b_queue_next(cur);
}
return NULL;
}

264
mie/ir/resolve.c Normal file
View File

@@ -0,0 +1,264 @@
#include <mie/ctx.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/ir/register.h>
enum register_find_result {
REG_FIND_NONE = 0,
REG_FIND_USE_BEFORE_DEFINE,
REG_FIND_UNDOMINATED,
REG_FIND_ISOLATED,
};
bool mie_op_resolve_self(struct mie_op *op, struct mie_ctx *ctx)
{
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
return true;
}
const char *dialect_name = NULL, *op_name = NULL;
char *dot = strchr(op->op_name, '.');
if (dot) {
*dot = 0;
dialect_name = op->op_name;
op_name = dot + 1;
} else {
dialect_name = NULL;
op_name = op->op_name;
}
const struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name);
if (dot) {
*dot = '.';
}
/* dialect_name is no longer valid after this point */
dialect_name = NULL;
if (!dialect) {
return false;
}
const struct mie_op_definition *op_info
= mie_dialect_get_op(dialect, op_name);
if (!op_info) {
return false;
}
op->op_info = op_info;
free(op->op_name);
op->op_name = NULL;
op->op_flags |= MIE_OP_F_OP_RESOLVED;
return true;
}
static enum register_find_result find_register_wide(
struct mie_op *op, const char *name, struct mie_register **out)
{
struct mie_region *region = op->op_container->b_parent;
enum register_find_result result = REG_FIND_UNDOMINATED;
struct mie_register *reg = NULL;
while (region) {
reg = mie_region_find_register(region, name);
if (reg) {
*out = reg;
break;
}
struct mie_op *op = region->r_parent;
if (mie_op_has_trait(op, "builtin", "isolated-from-above")) {
result = REG_FIND_ISOLATED;
}
region = op->op_container ? op->op_container->b_parent : NULL;
}
if (!reg) {
return result;
}
if (reg->reg_block == op->op_container) {
return REG_FIND_USE_BEFORE_DEFINE;
}
return result;
}
static bool resolve_arg(
struct mie_op *op, struct mie_op_arg *arg, struct mie_ctx *ctx)
{
const char *arg_name = arg->arg_unresolved.reg_name;
struct mie_block *block = op->op_container;
struct mie_op *search_start = op;
struct mie_register *reg = NULL;
while (block) {
reg = mie_block_find_register(block, arg_name, search_start);
if (reg) {
break;
}
search_start = NULL;
block = block->b_idom;
}
if (reg) {
free(arg->arg_unresolved.reg_name);
arg->arg_flags |= MIE_OP_F_ARG_RESOLVED;
memset(&arg->arg_value, 0x0, sizeof arg->arg_value);
arg->arg_value.u_reg = reg;
arg->arg_value.u_user = op;
b_queue_push_back(&reg->reg_use, &arg->arg_value.u_entry);
return true;
}
enum register_find_result find_result
= find_register_wide(op, arg_name, &reg);
struct mie_diag *diag = mie_ctx_push_diag(
ctx, op->op_src, &arg->arg_span.s_start, "builtin",
MIE_BUILTIN_E_UNRESOLVED_VALUE);
mie_diag_push_msg(diag, ctx, "builtin", MIE_BUILTIN_MSG_UNRESOLVED_VALUE);
struct mie_diag_highlight hl[] = {
{
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
.hl_span = arg->arg_span,
},
};
mie_diag_push_snippet(
diag, arg->arg_span.s_start.c_row, arg->arg_span.s_end.c_row,
NULL, 0, hl, 1);
if (!reg) {
return false;
}
struct mie_block *reg_container = reg->reg_block;
switch (find_result) {
case REG_FIND_ISOLATED:
mie_diag_push_msg(
diag, ctx, "builtin",
MIE_BUILTIN_MSG_VALUE_DEFINED_OUTSIDE_ISOLATED_REGION);
break;
case REG_FIND_UNDOMINATED:
mie_diag_push_msg(
diag, ctx, "builtin",
MIE_BUILTIN_MSG_VALUE_DEFINED_IN_NON_DOMINANT_BLOCK);
break;
case REG_FIND_USE_BEFORE_DEFINE:
mie_diag_push_msg(
diag, ctx, "builtin",
MIE_BUILTIN_MSG_VALUE_DEFINED_AFTER_USE);
break;
default:
return false;
}
hl[0].hl_type = MIE_DIAG_HIGHLIGHT_HINT;
hl[0].hl_span = reg->reg_span;
mie_diag_push_snippet(
diag, reg->reg_span.s_start.c_row, reg->reg_span.s_end.c_row,
NULL, 0, hl, 1);
if (!reg_container) {
return false;
}
hl[0].hl_span = reg_container->b_name.n_span;
mie_diag_push_snippet(
diag, reg_container->b_name.n_span.s_start.c_row,
reg_container->b_name.n_span.s_end.c_row, NULL, 0, hl, 1);
return false;
}
static bool resolve_successor(
struct mie_op *op, struct mie_op_successor *s, struct mie_ctx *ctx)
{
if (s->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
return true;
}
struct mie_block *container = op->op_container;
struct mie_region *region = container ? container->b_parent : NULL;
if (!region) {
return false;
}
struct mie_diag *diag = NULL;
struct mie_block *dest = mie_region_find_block(region, s->s_block_name);
if (!dest) {
diag = mie_ctx_push_diag(
ctx, op->op_src, &s->s_name_span.s_start, "builtin",
MIE_BUILTIN_E_UNRESOLVED_SUCCESSOR);
mie_diag_push_msg(
diag, ctx, "builtin", MIE_BUILTIN_MSG_CANNOT_FIND_BLOCK);
const struct mie_diag_highlight hl[] = {
{
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
.hl_span = s->s_name_span,
},
};
mie_diag_push_snippet(
diag, s->s_name_span.s_start.c_row,
s->s_name_span.s_end.c_row, NULL, 0, hl, 1);
return false;
}
free(s->s_block_name);
s->s_block = dest;
s->s_flags |= MIE_OP_F_SUCCESSOR_RESOLVED;
return true;
}
bool mie_op_resolve_args(struct mie_op *op, struct mie_ctx *ctx)
{
bool ok = true;
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
if (!resolve_arg(op, &op->op_args.items[i], ctx)) {
ok = false;
}
}
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++) {
if (!resolve_arg(op, &s->s_args.items[k], ctx)) {
ok = false;
}
}
}
return ok;
}
bool mie_op_resolve_successors(struct mie_op *op, struct mie_ctx *ctx)
{
bool ok = true;
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
if (!resolve_successor(op, &op->op_successors.items[i], ctx)) {
ok = false;
}
}
return ok;
}

File diff suppressed because it is too large Load Diff

254
mie/lt-idom.c Normal file
View File

@@ -0,0 +1,254 @@
#include <mie/ir/block.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <stdio.h>
struct set {
MIE_VECTOR_DECLARE(unsigned int, v);
};
struct dfs_stack_item {
struct mie_block *i_parent, *i_node;
};
struct lt_ctx {
size_t nr_nodes;
struct mie_block **vertex;
struct set *bucket;
unsigned int *semi;
unsigned int *idom;
unsigned int *samedom;
unsigned int *parent;
unsigned int *ancestor;
unsigned int *label;
MIE_VECTOR_DECLARE(struct dfs_stack_item, dfstack);
};
#if 0
static B_BTREE_DEFINE_SIMPLE_INSERT(struct mie_block, b_node, b_id, put_block_by_id);
static B_BTREE_DEFINE_SIMPLE_GET(
struct mie_block, size_t, b_node, b_id, get_block_by_id);
#endif
static void set_add(struct set *set, unsigned int val)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(set->v); i++) {
if (set->v.items[i] == val) {
return;
}
}
mie_vector_push_back(set->v, &val, NULL);
}
static struct mie_block *pop_block_successor(
MIE_VECTOR_REF_PARAM(struct mie_block *, successors))
{
size_t count = mie_vector_ref_get_count(successors);
if (count == 0) {
return false;
}
struct mie_block *out = mie_vector_ref_get_item(successors, count - 1);
mie_vector_ref_pop_back(successors, NULL);
return out;
}
static void enqueue_block_successors(
struct mie_block *block,
MIE_VECTOR_REF_PARAM(struct mie_block *, successors))
{
struct mie_op_successor *s = mie_block_get_first_successor(block);
struct mie_block_predecessor pred = {.p_block = block};
while (s) {
if (s->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
mie_vector_ref_push_back(successors, &s->s_block, NULL);
mie_vector_push_back(s->s_block->b_ipred, &pred, NULL);
}
s = mie_block_get_next_successor(block, s);
}
}
static void dfs_stack_pop(
struct lt_ctx *ctx, struct mie_block **parent, struct mie_block **node)
{
size_t nr = MIE_VECTOR_COUNT(ctx->dfstack);
if (!nr) {
return;
}
struct dfs_stack_item *item = &ctx->dfstack.items[nr - 1];
*parent = item->i_parent;
*node = item->i_node;
mie_vector_pop_back(ctx->dfstack, NULL);
}
static void dfs_stack_push(
struct lt_ctx *ctx, struct mie_block *parent, struct mie_block *node)
{
struct dfs_stack_item item = {.i_node = node, .i_parent = parent};
mie_vector_push_back(ctx->dfstack, &item, NULL);
}
static void dfs(struct lt_ctx *ctx, struct mie_block *root)
{
dfs_stack_push(ctx, NULL, root);
unsigned int id = 1;
while (MIE_VECTOR_COUNT(ctx->dfstack) > 0) {
struct mie_block *p, *n;
dfs_stack_pop(ctx, &p, &n);
if (n->b_id != MIE_BLOCK_ID_INVALID) {
continue;
}
#if 0
printf("dfs(p=%s, n=%s)\n", p ? p->b_name.n_str : "NA",
n->b_name.n_str);
#endif
n->b_id = id++;
ctx->vertex[n->b_id] = n;
ctx->semi[n->b_id] = n->b_id;
ctx->parent[n->b_id] = p ? p->b_id : MIE_BLOCK_ID_INVALID;
struct mie_op_successor *s = mie_block_get_first_successor(n);
while (s) {
dfs_stack_push(ctx, n, s->s_block);
mie_vector_push_back(s->s_block->b_ipred, &n, NULL);
s = mie_block_get_next_successor(n, s);
}
}
}
static void link(struct lt_ctx *ctx, unsigned int parent, unsigned int node)
{
ctx->ancestor[node] = parent;
ctx->label[node] = node;
}
static unsigned int eval(struct lt_ctx *ctx, unsigned int v)
{
unsigned int a = ctx->ancestor[v];
if (ctx->ancestor[a] > MIE_BLOCK_ID_INVALID) {
unsigned int b = eval(ctx, a);
ctx->ancestor[v] = ctx->ancestor[a];
if (ctx->semi[b] < ctx->semi[ctx->label[v]]) {
ctx->label[v] = b;
}
}
return ctx->label[v];
}
static void reset_block_relationship_metadata(struct mie_region *region)
{
b_queue_entry *cur = b_queue_first(&region->r_blocks);
while (cur) {
struct mie_block *block = b_unbox(struct mie_block, cur, b_entry);
block->b_id = MIE_BLOCK_ID_INVALID;
block->b_idom = NULL;
// block->b_sdom = block->b_dfs_parent = NULL;
mie_vector_destroy(block->b_ipred, NULL);
cur = b_queue_next(cur);
}
memset(&region->r_blocks_s, 0x0, sizeof region->r_blocks_s);
}
static void lt_ctx_init(struct lt_ctx *ctx, size_t nr_nodes)
{
memset(ctx, 0x0, sizeof *ctx);
ctx->idom = calloc(nr_nodes + 1, sizeof(unsigned int));
ctx->samedom = calloc(nr_nodes + 1, sizeof(unsigned int));
ctx->vertex = calloc(nr_nodes + 1, sizeof(struct mie_block *));
ctx->bucket = calloc(nr_nodes + 1, sizeof(struct set));
ctx->semi = calloc(nr_nodes + 1, sizeof(unsigned int));
ctx->parent = calloc(nr_nodes + 1, sizeof(unsigned int));
ctx->ancestor = calloc(nr_nodes + 1, sizeof(unsigned int));
ctx->label = calloc(nr_nodes + 1, sizeof(unsigned int));
}
static void lt_ctx_cleanup(struct lt_ctx *ctx)
{
free(ctx->idom);
free(ctx->samedom);
free(ctx->vertex);
free(ctx->bucket);
free(ctx->semi);
free(ctx->parent);
free(ctx->ancestor);
free(ctx->label);
}
void mie_region_refresh_dominance(struct mie_region *region)
{
struct lt_ctx ctx;
size_t nr_nodes = b_queue_length(&region->r_blocks);
lt_ctx_init(&ctx, nr_nodes);
struct mie_block *root = mie_region_get_first_block(region);
reset_block_relationship_metadata(region);
dfs(&ctx, root);
for (size_t i = nr_nodes; i > 0; i--) {
struct mie_block *n = ctx.vertex[i];
unsigned int p = ctx.parent[i];
unsigned int s = p;
struct mie_block_predecessor *pred
= mie_block_get_first_predecessor(n);
while (pred) {
struct mie_block *v = pred->p_block;
unsigned int s_prime = MIE_BLOCK_ID_INVALID;
if (v->b_id <= n->b_id) {
s_prime = v->b_id;
} else {
s_prime = eval(&ctx, v->b_id);
s_prime = ctx.semi[s_prime];
}
if (s_prime < s) {
s = s_prime;
}
pred = mie_block_get_next_predecessor(n, pred);
}
ctx.semi[n->b_id] = s;
set_add(&ctx.bucket[s], n->b_id);
link(&ctx, p, n->b_id);
for (size_t k = 0; k < MIE_VECTOR_COUNT(ctx.bucket[p].v); k++) {
unsigned int v = ctx.bucket[p].v.items[k];
unsigned int y = eval(&ctx, v);
if (ctx.semi[y] == ctx.semi[p]) {
ctx.idom[v] = p;
} else {
ctx.samedom[v] = y;
}
}
}
for (size_t i = 1; i <= nr_nodes; i++) {
struct mie_block *n = ctx.vertex[i];
if (ctx.samedom[i] > 0) {
ctx.idom[i] = ctx.idom[ctx.samedom[i]];
}
n->b_idom = ctx.vertex[ctx.idom[i]];
// n->b_sdom = ctx.vertex[ctx.semi[i]];
// n->b_dfs_parent = ctx.vertex[ctx.parent[i]];
}
lt_ctx_cleanup(&ctx);
}

View File

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

View File

@@ -7,6 +7,10 @@
#include <blue/ds/number.h>
#include <blue/ds/string.h>
#include <ctype.h>
#include <mie/ctx.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/dialect/builtin.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -66,6 +70,14 @@ static struct mie_lex_symbol_node *get_symbol_node(
return NULL;
}
static struct mie_diag *push_diag(struct mie_lex *lex, unsigned long diag_class)
{
return mie_ctx_push_diag(
lex->lex_ctx, lex->lex_source,
mie_line_source_get_cursor(lex->lex_source), "builtin",
diag_class);
}
static b_string *get_temp_string(struct mie_lex *lex)
{
if (!lex->lex_temp) {
@@ -145,7 +157,7 @@ static struct mie_lex_symbol_node *build_symbol_tree(void)
return root;
}
struct mie_lex *mie_lex_create(b_stream *src)
struct mie_lex *mie_lex_create(struct mie_line_source *src, struct mie_ctx *ctx)
{
struct mie_lex *lex = malloc(sizeof *lex);
if (!lex) {
@@ -154,11 +166,10 @@ struct mie_lex *mie_lex_create(b_stream *src)
memset(lex, 0x0, sizeof *lex);
lex->lex_cursor_row = lex->lex_cursor_col = 1;
lex->lex_ctx = ctx;
lex->lex_status = MIE_SUCCESS;
lex->lex_source = src;
lex->lex_linebuf = b_string_create();
lex->lex_sym_tree = build_symbol_tree();
if (!lex->lex_sym_tree) {
@@ -184,10 +195,6 @@ void mie_lex_destroy(struct mie_lex *lex)
entry = next;
}
if (lex->lex_linebuf) {
free(lex->lex_linebuf);
}
if (lex->lex_sym_tree) {
destroy_symbol_tree(lex->lex_sym_tree);
}
@@ -204,87 +211,9 @@ enum mie_status mie_lex_get_status(const struct mie_lex *lex)
return lex->lex_status;
}
static enum mie_status refill_linebuf(struct mie_lex *lex)
struct mie_line_source *mie_lex_get_line_source(const struct mie_lex *lex)
{
if (!lex->lex_source) {
return MIE_ERR_EOF;
}
if (lex->lex_linebuf_ptr) {
b_iterator_unref(lex->lex_linebuf_ptr);
lex->lex_linebuf_ptr = NULL;
}
b_stringstream *s = b_stringstream_create();
b_status status = b_stream_read_line_s(lex->lex_source, s);
if (status == B_ERR_NO_DATA) {
return MIE_ERR_EOF;
}
if (!B_OK(status)) {
return MIE_ERR_INTERNAL_FAILURE;
}
b_string_replace_all_with_stringstream(lex->lex_linebuf, s);
b_stringstream_unref(s);
lex->lex_linebuf_ptr = b_iterator_begin(lex->lex_linebuf);
return MIE_SUCCESS;
}
static int peek(struct mie_lex *lex)
{
enum mie_status status = MIE_SUCCESS;
if (!lex->lex_linebuf_ptr || !b_iterator_is_valid(lex->lex_linebuf_ptr)) {
status = refill_linebuf(lex);
}
if (status != MIE_SUCCESS) {
return -status;
}
if (b_string_get_size(lex->lex_linebuf, B_STRLEN_NORMAL) == 0) {
return -MIE_ERR_EOF;
}
b_wchar c = b_iterator_get_value(lex->lex_linebuf_ptr).v_int;
return c;
}
static int advance(struct mie_lex *lex)
{
enum mie_status status = MIE_SUCCESS;
if (!b_iterator_is_valid(lex->lex_linebuf_ptr)) {
status = refill_linebuf(lex);
}
if (status != MIE_SUCCESS) {
return -status;
}
if (b_string_get_size(lex->lex_linebuf, B_STRLEN_NORMAL) == 0) {
return -MIE_ERR_EOF;
}
b_wchar c = b_iterator_get_value(lex->lex_linebuf_ptr).v_int;
b_iterator_move_next(lex->lex_linebuf_ptr);
lex->lex_cursor_col++;
if (c == '\n') {
lex->lex_cursor_col = 1;
lex->lex_cursor_row++;
}
return c;
}
static bool input_available(struct mie_lex *lex)
{
return lex->lex_linebuf_ptr && b_iterator_is_valid(lex->lex_linebuf_ptr);
return lex->lex_source;
}
static bool char_can_begin_symbol(char c)
@@ -313,22 +242,18 @@ static struct mie_token *create_token(enum mie_token_type type)
static void set_token_start(struct mie_lex *lex)
{
lex->lex_token_start_row = lex->lex_cursor_row;
lex->lex_token_start_col = lex->lex_cursor_col;
lex->lex_token_start = *mie_line_source_get_cursor(lex->lex_source);
}
static void set_token_end(struct mie_lex *lex)
{
lex->lex_token_end_row = lex->lex_cursor_row;
lex->lex_token_end_col = lex->lex_cursor_col;
lex->lex_token_end = *mie_line_source_get_cursor(lex->lex_source);
}
static enum mie_status push_token(struct mie_lex *lex, struct mie_token *tok)
{
tok->tok_location.s_start.c_row = lex->lex_token_start_row;
tok->tok_location.s_start.c_col = lex->lex_token_start_col;
tok->tok_location.s_end.c_row = lex->lex_token_end_row;
tok->tok_location.s_end.c_col = lex->lex_token_end_col;
tok->tok_location.s_start = lex->lex_token_start;
tok->tok_location.s_end = lex->lex_token_end;
b_queue_push_back(&lex->lex_queue, &tok->tok_entry);
return MIE_SUCCESS;
@@ -423,7 +348,7 @@ static enum mie_status push_float(struct mie_lex *lex, double v)
static enum mie_status read_line_comment(struct mie_lex *lex)
{
while (true) {
b_wchar c = advance(lex);
b_wchar c = mie_line_source_getc(lex->lex_source);
if (c == -MIE_ERR_EOF || c == '\n') {
break;
@@ -449,7 +374,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
}
while (true) {
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
if (c == -MIE_ERR_EOF) {
break;
}
@@ -461,7 +386,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
if (c == '_') {
token_len++;
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
@@ -479,7 +404,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
char s[] = {c, 0};
b_string_append_cstr(str, s);
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
@@ -491,7 +416,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
base = 16;
token_len++;
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
@@ -499,7 +424,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
base = 2;
token_len++;
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
@@ -517,7 +442,7 @@ static enum mie_status read_number(struct mie_lex *lex, bool negate)
b_string_append_wc(str, c);
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
token_len++;
}
@@ -569,7 +494,7 @@ static enum mie_status read_ident(struct mie_lex *lex, enum mie_token_type type)
}
while (1) {
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
if ((c == '.' || c == '-') && prev == c) {
return MIE_ERR_BAD_SYNTAX;
@@ -586,7 +511,7 @@ static enum mie_status read_ident(struct mie_lex *lex, enum mie_token_type type)
prev = c;
b_string_append_wc(str, c);
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
}
if (type == MIE_TOK_NONE) {
@@ -613,17 +538,17 @@ static enum mie_status read_string(struct mie_lex *lex)
{
b_string *str = get_temp_string(lex);
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
bool esc = false;
if (c != '"') {
return MIE_ERR_BAD_SYNTAX;
}
advance(lex);
mie_line_source_getc(lex->lex_source);
while (1) {
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
if (esc) {
switch (c) {
@@ -636,23 +561,23 @@ static enum mie_status read_string(struct mie_lex *lex)
}
esc = false;
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
if (c == '\\') {
esc = true;
advance(lex);
mie_line_source_getc(lex->lex_source);
continue;
}
if (c == '"') {
advance(lex);
mie_line_source_getc(lex->lex_source);
break;
}
b_string_append_wc(str, c);
advance(lex);
mie_line_source_getc(lex->lex_source);
}
char *s = b_string_steal(str);
@@ -666,7 +591,7 @@ static enum mie_status read_symbol(struct mie_lex *lex)
b_wchar prev = 0;
while (true) {
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
if (c < 0) {
break;
}
@@ -679,11 +604,12 @@ static enum mie_status read_symbol(struct mie_lex *lex)
node = next;
set_token_end(lex);
advance(lex);
mie_line_source_getc(lex->lex_source);
prev = c;
}
if (!node || node->s_def == NULL) {
push_diag(lex, MIE_BUILTIN_E_UNRECOGNISED_TOKEN);
return MIE_ERR_BAD_SYNTAX;
}
@@ -734,11 +660,11 @@ static enum mie_status read_symbol(struct mie_lex *lex)
static void skip_whitespace(struct mie_lex *lex)
{
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
while (b_wchar_is_space(c)) {
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
}
}
@@ -755,34 +681,34 @@ static bool should_skip(b_wchar c, bool skip_linefeeds)
static void skip_ignored_chars(struct mie_lex *lex, bool include_linefeeds)
{
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
while (1) {
while (should_skip(c, include_linefeeds)) {
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
}
if (c != ';') {
break;
}
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
while (c != '\n') {
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
}
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
}
}
static enum mie_status pump_tokens(struct mie_lex *lex)
{
b_wchar c = peek(lex);
b_wchar c = mie_line_source_peekc(lex->lex_source);
if (c < 0) {
return -c;
@@ -795,13 +721,13 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
break;
}
c = peek(lex);
c = mie_line_source_peekc(lex->lex_source);
}
if (c == '\\') {
advance(lex);
mie_line_source_getc(lex->lex_source);
skip_ignored_chars(lex, true);
c = peek(lex);
c = mie_line_source_peekc(lex->lex_source);
}
if (c == '\n') {
@@ -809,13 +735,13 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
set_token_end(lex);
while (c == '\n') {
advance(lex);
mie_line_source_getc(lex->lex_source);
if (!input_available(lex)) {
if (!mie_line_source_input_available(lex->lex_source)) {
break;
}
c = peek(lex);
c = mie_line_source_peekc(lex->lex_source);
}
if (c < 0) {
@@ -826,8 +752,8 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
}
while (b_wchar_is_space(c) && c != '\n') {
advance(lex);
c = peek(lex);
mie_line_source_getc(lex->lex_source);
c = mie_line_source_peekc(lex->lex_source);
}
if (IS_VALID_IDENT_START_CHAR(c)) {
@@ -846,6 +772,20 @@ static enum mie_status pump_tokens(struct mie_lex *lex)
return read_number(lex, false);
}
struct mie_diag *diag = push_diag(lex, MIE_BUILTIN_E_UNRECOGNISED_TOKEN);
mie_diag_push_msg(
diag, lex->lex_ctx, "builtin", MIE_BUILTIN_MSG_UNRECOGNISED_TOKEN);
const struct mie_file_cell *cursor
= mie_line_source_get_cursor(lex->lex_source);
unsigned long line = cursor->c_row;
const struct mie_diag_highlight hl[] = {
{
.hl_type = MIE_DIAG_HIGHLIGHT_ERROR,
.hl_span = {.s_start = *cursor, .s_end = *cursor},
},
};
const size_t nr_hl = sizeof hl / sizeof hl[0];
mie_diag_push_snippet(diag, line, line, NULL, 0, hl, nr_hl);
return MIE_ERR_BAD_SYNTAX;
}
@@ -893,7 +833,7 @@ bool mie_lex_tokens_available(struct mie_lex *lex)
return true;
}
if (input_available(lex)) {
if (mie_line_source_input_available(lex->lex_source)) {
return true;
}

View File

@@ -5,27 +5,24 @@
#include <blue/ds/dict.h>
#include <blue/ds/string.h>
#include <mie/parse/lex.h>
#include <mie/parse/line-source.h>
#include <mie/parse/token.h>
#include <mie/status.h>
#include <stdint.h>
struct mie_lex {
struct mie_lex_symbol_node *lex_sym_tree;
b_stream *lex_source;
struct mie_line_source *lex_source;
enum mie_status lex_status;
struct mie_ctx *lex_ctx;
b_queue lex_queue;
b_string *lex_temp;
b_queue lex_state;
unsigned int lex_brace_depth;
unsigned long lex_token_start_row, lex_token_start_col;
unsigned long lex_token_end_row, lex_token_end_col;
unsigned long lex_cursor_row, lex_cursor_col;
b_string *lex_linebuf;
b_iterator *lex_linebuf_ptr;
struct mie_file_cell lex_token_start, lex_token_end;
};
struct mie_lex_symbol_node {

161
mie/parse/line-source.c Normal file
View File

@@ -0,0 +1,161 @@
#include <mie/parse/line-source.h>
enum mie_status mie_line_source_init(
struct mie_line_source *src, const char *path, b_stream *stream)
{
memset(src, 0x0, sizeof *src);
src->s_lines = b_array_create();
if (!src->s_lines) {
return MIE_ERR_NO_MEMORY;
}
src->s_stream = stream;
src->s_path = path;
src->s_cursor.c_col = 1;
src->s_cursor.c_row = 1;
return MIE_SUCCESS;
}
void mie_line_source_cleanup(struct mie_line_source *src)
{
if (src->s_linebuf_ptr) {
b_iterator_unref(src->s_linebuf_ptr);
}
if (src->s_lines) {
b_array_unref(src->s_lines);
}
memset(src, 0x0, sizeof *src);
}
const char *mie_line_source_get_path(const struct mie_line_source *src)
{
return src->s_path;
}
const struct mie_file_cell *mie_line_source_get_cursor(
const struct mie_line_source *src)
{
return &src->s_cursor;
}
static enum mie_status refill_linebuf(struct mie_line_source *src)
{
if (!src->s_stream) {
return MIE_ERR_EOF;
}
if (src->s_linebuf_ptr) {
b_iterator_unref(src->s_linebuf_ptr);
src->s_linebuf_ptr = NULL;
}
b_stringstream *s = b_stringstream_create();
b_status status = b_stream_read_line_s(src->s_stream, s);
if (status == B_ERR_NO_DATA) {
return MIE_ERR_EOF;
}
if (!B_OK(status)) {
return MIE_ERR_INTERNAL_FAILURE;
}
b_string *line = b_string_create();
b_string_replace_all_with_stringstream(line, s);
b_stringstream_unref(s);
b_array_append(src->s_lines, line);
b_string_unref(line);
src->s_linebuf = line;
src->s_linebuf_ptr = b_iterator_begin(src->s_linebuf);
return MIE_SUCCESS;
}
static int peek(struct mie_line_source *src)
{
enum mie_status status = MIE_SUCCESS;
if (!src->s_linebuf_ptr || !b_iterator_is_valid(src->s_linebuf_ptr)) {
status = refill_linebuf(src);
}
if (status != MIE_SUCCESS) {
return -status;
}
if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) {
return -MIE_ERR_EOF;
}
b_wchar c = b_iterator_get_value(src->s_linebuf_ptr).v_int;
return c;
}
static int advance(struct mie_line_source *src)
{
enum mie_status status = MIE_SUCCESS;
if (!b_iterator_is_valid(src->s_linebuf_ptr)) {
status = refill_linebuf(src);
}
if (status != MIE_SUCCESS) {
return -status;
}
if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) {
return -MIE_ERR_EOF;
}
b_wchar c = b_iterator_get_value(src->s_linebuf_ptr).v_int;
b_iterator_move_next(src->s_linebuf_ptr);
src->s_cursor.c_col++;
if (c == '\n') {
src->s_cursor.c_col = 1;
src->s_cursor.c_row++;
}
return c;
}
b_wchar mie_line_source_peekc(struct mie_line_source *src)
{
return peek(src);
}
b_wchar mie_line_source_getc(struct mie_line_source *src)
{
return advance(src);
}
enum mie_status mie_line_source_get_row(
struct mie_line_source *src, size_t row, const b_string **out)
{
if (row == 0) {
return MIE_ERR_INVALID_ARGUMENT;
}
row--;
if (row >= b_array_size(src->s_lines)) {
return MIE_ERR_EOF;
}
b_string *line = b_array_at(src->s_lines, row);
*out = line;
return MIE_SUCCESS;
}
bool mie_line_source_input_available(struct mie_line_source *src)
{
return src->s_linebuf_ptr && b_iterator_is_valid(src->s_linebuf_ptr);
}

View File

@@ -260,11 +260,11 @@ bool mie_parser_parse_symbol(struct mie_parser *ctx, enum mie_token_symbol sym)
bool mie_parser_parse_linefeed(struct mie_parser *ctx)
{
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
if (tok->tok_type != MIE_TOK_LINEFEED) {
if (!MIE_TOKEN_IS(tok, MIE_TOK_LINEFEED)) {
return false;
}
while (tok && tok->tok_type == MIE_TOK_LINEFEED) {
while (MIE_TOKEN_IS(tok, MIE_TOK_LINEFEED)) {
mie_lex_advance(ctx->p_lex);
tok = mie_lex_peek(ctx->p_lex);
}
@@ -543,6 +543,8 @@ bool mie_parser_parse_operand(struct mie_parser *ctx, struct mie_op_arg *out)
result = true;
}
out->arg_span = loc;
return result;
}
@@ -611,6 +613,8 @@ bool mie_parser_parse_parameter(struct mie_parser *ctx, struct mie_op_arg *out)
return false;
}
out->arg_span = loc;
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
return false;
}
@@ -710,6 +714,7 @@ bool mie_parser_parse_register(
break;
}
out->reg_span = tok->tok_location;
mie_parser_advance(ctx);
return name != NULL;
@@ -798,15 +803,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 +824,7 @@ bool mie_parser_parse_region_list(
break;
}
struct mie_region *region = mie_vector_ref_emplace_back(out, NULL);
struct mie_region *region = mie_op_add_region(parent);
if (!mie_parser_parse_region(ctx, parent, region)) {
@@ -837,8 +840,7 @@ bool mie_parser_parse_anonymous_block(
{
mie_parser_parse_linefeed(ctx);
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
@@ -855,8 +857,7 @@ bool mie_parser_parse_anonymous_block(
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
@@ -931,6 +932,8 @@ bool mie_parser_parse_block(
return false;
}
memcpy(&block->b_name.n_span, &span, sizeof span);
if (mie_parser_peek_symbol(ctx) == MIE_SYM_LEFT_PAREN
&& !parse_block_parameters(ctx, names, block)) {
return false;
@@ -950,8 +953,7 @@ bool mie_parser_parse_block(
break;
}
struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL);
mie_op_init(op);
struct mie_op *op = mie_block_add_op(block);
if (!mie_parser_parse_op(ctx, names, op)) {
return false;
}
@@ -969,9 +971,8 @@ bool mie_parser_parse_successor(struct mie_parser *ctx, struct mie_op_successor
memset(out, 0x0, sizeof *out);
b_string *str = get_temp_string(ctx);
bool result = false;
struct mie_file_span span;
if (!mie_parser_parse_blockname(ctx, str, &span)) {
if (!mie_parser_parse_blockname(ctx, str, &out->s_name_span)) {
return false;
}
@@ -1090,8 +1091,7 @@ static bool parse_generic_op(
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
mie_parser_parse_linefeed(ctx);
if (!mie_parser_parse_region_list(
ctx, dest, MIE_VECTOR_REF(dest->op_regions))) {
if (!mie_parser_parse_region_list(ctx, dest)) {
return false;
}
@@ -1150,9 +1150,6 @@ static bool parse_graph_op(
bool mie_parser_parse_op(
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
{
memset(dest, 0x0, sizeof *dest);
mie_attribute_map_init(&dest->op_attrib);
if (mie_parser_check_eof(ctx)) {
return false;
}
@@ -1168,6 +1165,15 @@ bool mie_parser_parse_op(
}
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(dest->op_result); i++) {
struct mie_register *reg = &dest->op_result.items[i];
reg->reg_flags |= MIE_REGISTER_F_OP_RESULT;
reg->reg_op = dest;
reg->reg_block = dest->op_container;
}
dest->op_src = mie_lex_get_line_source(ctx->p_lex);
if (mie_parser_check_type(ctx, MIE_TOK_NAME)) {
/* custom-format operation */
return parse_custom_op(ctx, names, dest);

View File

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

View File

@@ -0,0 +1,136 @@
#include <mie/ctx.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/ir/walk.h>
#include <mie/macros.h>
#include <mie/pass/pass-definition.h>
#include <mie/pass/pass.h>
#include <mie/rewrite/convert.h>
#include <mie/rewrite/pattern.h>
#include <mie/rewrite/rewriter.h>
static bool op_is_flat(const struct mie_op *op)
{
return false;
}
static enum mie_match_result if_match(const struct mie_op *op)
{
if (!mie_op_is(op, "scf", "if")) {
return MIE_NO_MATCH_FOUND;
}
return MIE_MATCH_FOUND;
}
static struct mie_rewrite_result if_rewrite(
struct mie_op *op, struct mie_rewriter *rewriter)
{
printf("if: rewriting %p %s.%s\n", op, op->op_info->op_parent->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_info->op_parent->d_name, op->op_info->op_name);
struct mie_convert_config *cfg = mie_convert_config_create(args->p_ctx);
mie_convert_config_add_illegal_op(cfg, "scf", "if");
struct mie_pattern_set patterns = {};
if_pattern_create(&patterns);
mie_convert_apply(op, cfg, &patterns);
mie_pattern_set_cleanup(&patterns);
mie_convert_config_destroy(cfg);
return MIE_PASS_CONTINUE;
}
MIE_PASS_DEFINITION_BEGIN(convert_scf_to_cf)
MIE_PASS_NAME("convert-scf-to-cf");
MIE_PASS_DESCRIPTION(
"Convert high-level SCF constructs to low-level CF operations "
"and blocks.");
MIE_PASS_TRANSFORM(transform);
MIE_PASS_FILTER_OP("func", "func");
MIE_PASS_DEFINITION_END()

View File

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

View File

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

View File

@@ -11,11 +11,21 @@ void mie_printer_print_op_arg(
enum mie_register_flags arg_flags = 0;
const char *arg_name = NULL;
const struct mie_type *arg_type = NULL;
bool resolved = false;
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
arg_flags = arg->arg_value.u_reg->reg_flags;
arg_name = arg->arg_value.u_reg->reg_name.n_str;
arg_type = arg->arg_value.u_reg->reg_type;
resolved = true;
if (!arg->arg_value.u_reg) {
/* this should only be caused by an internal parser/rewriter bug */
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 +40,13 @@ void mie_printer_print_op_arg(
b_stream_write_string(printer->p_stream, arg_name, NULL);
if (!include_type) {
if (!resolved
&& MIE_TEST_FLAGS(
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
b_stream_write_char(printer->p_stream, '?');
}
if (!include_type || !arg_type) {
return;
}
@@ -44,14 +60,23 @@ void mie_printer_print_op_successor(
bool compact)
{
b_stream_write_char(printer->p_stream, '^');
bool resolved = false;
if (successor->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
b_stream_write_string(
printer->p_stream, successor->s_block->b_name.n_str, NULL);
resolved = true;
} else {
b_stream_write_string(
printer->p_stream, successor->s_block_name, NULL);
}
if (!resolved
&& MIE_TEST_FLAGS(
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
b_stream_write_char(printer->p_stream, '?');
}
if (MIE_VECTOR_COUNT(successor->s_args) == 0) {
return;
}
@@ -96,18 +121,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);
@@ -195,9 +226,14 @@ static void print_generic_op(struct mie_printer *printer, const struct mie_op *o
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
b_stream_write_fmt(
printer->p_stream, NULL, "%s.%s",
op->op_dialect->d_name, op->op_info->op_name);
op->op_info->op_parent->d_name, op->op_info->op_name);
} else {
b_stream_write_string(printer->p_stream, op->op_name, NULL);
if (MIE_TEST_FLAGS(
printer->p_flags, MIE_PRINT_F_MARK_UNRESOLVED_ELEMENTS)) {
b_stream_write_char(printer->p_stream, '?');
}
}
b_stream_write_char(printer->p_stream, '(');
@@ -263,7 +299,7 @@ void mie_printer_print_op_name(struct mie_printer *printer, const struct mie_op
if (printer->p_flags & MIE_PRINT_F_GENERIC) {
generic = true;
b_stream_write_char(printer->p_stream, '~');
} else if (!strcmp(op->op_dialect->d_name, "builtin")) {
} else if (!strcmp(op->op_info->op_parent->d_name, "builtin")) {
builtin = true;
}
@@ -274,7 +310,8 @@ void mie_printer_print_op_name(struct mie_printer *printer, const struct mie_op
if (generic || !builtin || !abbreviate) {
b_stream_write_fmt(
printer->p_stream, NULL, "%s.", op->op_dialect->d_name);
printer->p_stream, NULL, "%s.",
op->op_info->op_parent->d_name);
}
b_stream_write_string(printer->p_stream, op->op_info->op_name, NULL);

View File

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

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

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

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

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

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

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

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

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

View File

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

View File

@@ -1,6 +1,8 @@
file(GLOB tool_sources
*.c *.h
cmd/*.c cmd/*.h)
cmd/*.c cmd/*.h
diag/*.c diag/*.h
cmd/internal/*.c)
if (WIN32)
set(rc_file ${CMAKE_CURRENT_SOURCE_DIR}/../res/win32/frontend.rc)

View File

@@ -4,7 +4,11 @@
enum command_id {
CMD_ROOT,
CMD_VALIDATE,
CMD_OPTIMISE,
CMD_INTERNAL,
CMD_INTERNAL_BUILDER_TEST,
CMD_INTERNAL_CTX_DUMP,
};
#endif

View File

@@ -1,50 +0,0 @@
#include "cmd.h"
#include <blue/cmd.h>
#include <blue/term.h>
enum {
OPT_PRINT_SYMBOLS = 0x1000,
OPT_PRINT_KEYWORDS,
};
static int internal(const b_command* cmd, const b_arglist* args, const b_array* _)
{
#if 0
if (b_arglist_get_count(args, OPT_PRINT_SYMBOLS, B_COMMAND_INVALID_ID)) {
internal_lexer_print_symbol_tree(lex);
}
if (b_arglist_get_count(args, OPT_PRINT_KEYWORDS, B_COMMAND_INVALID_ID)) {
internal_lexer_print_keyword_dict(lex);
}
#endif
return 0;
}
B_COMMAND(CMD_INTERNAL, CMD_ROOT)
{
B_COMMAND_NAME("internal");
B_COMMAND_SHORT_NAME('X');
B_COMMAND_DESC("internal frontend debugging tools.");
B_COMMAND_FUNCTION(internal);
B_COMMAND_OPTION(OPT_PRINT_SYMBOLS)
{
B_OPTION_LONG_NAME("print-symbols");
B_OPTION_SHORT_NAME('s');
B_OPTION_DESC(
"print the symbol tree used by the language lexer.");
}
B_COMMAND_OPTION(OPT_PRINT_KEYWORDS)
{
B_OPTION_LONG_NAME("print-keywords");
B_OPTION_SHORT_NAME('k');
B_OPTION_DESC(
"print the keyword dictionary used by the language lexer.");
}
B_COMMAND_HELP_OPTION();
}

View File

@@ -0,0 +1,182 @@
#include "../cmd.h"
#include <blue/cmd.h>
#include <blue/term.h>
#include <mie/attribute/attribute-definition.h>
#include <mie/ctx.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/dialect/func.h>
#include <mie/dialect/index.h>
#include <mie/dialect/meta.h>
#include <mie/dialect/ptr.h>
#include <mie/dialect/scf.h>
#include <mie/dialect/select.h>
#include <mie/ir/builder.h>
#include <mie/ir/op.h>
#include <mie/pass/builtin.h>
#include <mie/pass/pass-manager.h>
#include <mie/print/printer.h>
enum {
OPT_GENERIC,
OPT_NO_ABBREV,
OPT_PASS_OFFSET = 100,
};
static int builder_test(
const b_command *cmd, const b_arglist *args, const b_array *_)
{
struct mie_ctx *ctx = mie_ctx_create();
mie_builtin_dialect_create(ctx);
mie_meta_dialect_create(ctx);
mie_select_dialect_create(ctx);
mie_ptr_dialect_create(ctx);
mie_arith_dialect_create(ctx);
mie_func_dialect_create(ctx);
mie_cf_dialect_create(ctx);
mie_scf_dialect_create(ctx);
mie_index_dialect_create(ctx);
mie_builtin_passes_register(ctx);
struct mie_op *module = mie_ctx_create_op(ctx, "builtin", "module");
struct mie_builder *builder = mie_builder_create(ctx, module);
const struct mie_type *i32 = mie_ctx_get_int_type(ctx, 32);
const struct mie_type *i64 = mie_ctx_get_int_type(ctx, 64);
struct mie_func_parameter params[] = {
{.param_name = "p1", .param_type = i32},
{.param_name = "p2", .param_type = i64},
};
size_t nr_params = sizeof params / sizeof params[0];
const struct mie_type *ret_type = mie_ctx_get_int_type(ctx, 64);
struct mie_op *func = mie_func_func_put(
MIE_EMITTER(builder), "test_func", params, nr_params, &ret_type, 1);
mie_builder_step_into_op(builder, func);
struct mie_region *r_true, *r_false;
struct mie_op *if_op = mie_scf_if_put(
MIE_EMITTER(builder), params[0].param_reg, i32, &r_true,
&r_false, NULL);
struct mie_register *tmp = NULL;
mie_builder_step_into_region(builder, r_true);
tmp = mie_arith_constant_i_put(MIE_EMITTER(builder), 10, NULL);
mie_scf_yield_put(MIE_EMITTER(builder), tmp);
mie_builder_step_out(builder);
mie_builder_step_into_region(builder, r_false);
tmp = mie_arith_constant_i_put(MIE_EMITTER(builder), 20, NULL);
mie_scf_yield_put(MIE_EMITTER(builder), tmp);
mie_builder_step_out(builder);
struct mie_register *v1
= mie_arith_constant_i_put(MIE_EMITTER(builder), 1024, NULL);
struct mie_register *v2
= mie_arith_constant_i_put(MIE_EMITTER(builder), 2048, NULL);
struct mie_register *add
= mie_arith_addi_put(MIE_EMITTER(builder), v1, v2, NULL);
struct mie_register *add2 = mie_arith_addi_put(
MIE_EMITTER(builder), add, &if_op->op_result.items[0], NULL);
mie_builder_step_out(builder);
struct mie_pass_manager *pm = mie_pass_manager_create(ctx);
struct mie_pass_manager *module_pm = mie_pass_manager_nest(pm);
mie_pass_manager_filter_op(module_pm, "builtin", "module");
struct mie_pass_manager *func_pm = mie_pass_manager_nest(pm);
mie_pass_manager_filter_op(module_pm, "func", "func");
b_arglist_iterator it;
b_arglist_foreach(&it, args)
{
if (it.opt_id < OPT_PASS_OFFSET) {
continue;
}
const b_command_option *opt = b_command_get_option(cmd, it.opt_id);
if (!opt) {
continue;
}
const char *pass_name = b_command_option_get_long_name(opt);
struct mie_pass *pass = NULL;
enum mie_status status
= mie_ctx_get_pass(ctx, pass_name, NULL, &pass);
if (status != MIE_SUCCESS) {
printf("cannot load pass %s\n", pass_name);
return -1;
}
mie_pass_manager_add_pass(func_pm, pass);
}
mie_pass_manager_run(pm, module);
enum mie_print_flags flags = 0;
if (b_arglist_get_count(args, OPT_GENERIC, B_COMMAND_INVALID_ID) > 0) {
flags |= MIE_PRINT_F_GENERIC;
}
if (b_arglist_get_count(args, OPT_NO_ABBREV, B_COMMAND_INVALID_ID) == 0) {
flags |= MIE_PRINT_F_ABBREVIATED;
}
struct mie_printer printer;
mie_printer_init(&printer, ctx, b_stdout, flags);
mie_printer_print_op(&printer, module);
printf("\n");
return 0;
}
B_COMMAND(CMD_INTERNAL_BUILDER_TEST, CMD_INTERNAL)
{
B_COMMAND_NAME("builder-test");
B_COMMAND_DESC("mie_builder test");
B_COMMAND_FUNCTION(builder_test);
B_COMMAND_OPTION(OPT_GENERIC)
{
B_OPTION_LONG_NAME("generic");
B_OPTION_SHORT_NAME('g');
B_OPTION_DESC("print operations in generic format.");
}
B_COMMAND_OPTION(OPT_NO_ABBREV)
{
B_OPTION_LONG_NAME("no-abbrev");
B_OPTION_SHORT_NAME('n');
B_OPTION_DESC(
"don't use abbreviations for builtin types and ops.");
}
B_COMMAND_HELP_OPTION();
struct mie_ctx *ctx = mie_ctx_create();
mie_builtin_passes_register(ctx);
size_t i = 0;
b_btree_node *node = b_btree_first(&ctx->ctx_passes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_pass_definition *pass
= b_unbox(struct mie_pass_definition, id, p_id);
B_COMMAND_OPTION_GEN(OPT_PASS_OFFSET + i)
{
B_OPTION_LONG_NAME(pass->p_name);
B_OPTION_DESC(pass->p_description);
}
node = b_btree_next(node);
i++;
}
}

View File

@@ -0,0 +1,314 @@
#include "../cmd.h"
#include <assert.h>
#include <blue/cmd.h>
#include <blue/term.h>
#include <mie/attribute/attribute-definition.h>
#include <mie/ctx.h>
#include <mie/diag/class.h>
#include <mie/diag/msg.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/dialect/func.h>
#include <mie/dialect/index.h>
#include <mie/dialect/meta.h>
#include <mie/dialect/ptr.h>
#include <mie/dialect/scf.h>
#include <mie/dialect/select.h>
#include <mie/interface/interface-definition.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/register.h>
#include <mie/pass/builtin.h>
#include <mie/pass/pass-manager.h>
#include <mie/print/printer.h>
#include <mie/trait/trait-definition.h>
#include <mie/trait/trait.h>
#include <mie/type/type-definition.h>
#include <mie/type/type.h>
static void mie_op_definition_print(const struct mie_op_definition *op)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&op->op_id, id_str, sizeof id_str);
b_printf(
" [bold,red]Op:[reset]%-20s [dark_grey]{%s}[reset]\n",
op->op_name, id_str);
}
static void mie_type_definition_print(const struct mie_type_definition *type)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&type->ty_id, id_str, sizeof id_str);
b_printf(
" [bold,blue]Ty:[reset]%-20s [dark_grey]{%s}[reset]\n",
type->ty_name, id_str);
}
static void mie_trait_definition_print(const struct mie_trait_definition *trait)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&trait->tr_id, id_str, sizeof id_str);
b_printf(
" [bold,yellow]Tr:[reset]%-20s [dark_grey]{%s}[reset]\n",
trait->tr_name, id_str);
}
static void mie_attribute_definition_print(
const struct mie_attribute_definition *attribute)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&attribute->a_id, id_str, sizeof id_str);
b_printf(
" [bold,magenta]At:[reset]%-20s [dark_grey]{%s}[reset]\n",
attribute->a_name, id_str);
}
static void mie_interface_definition_print(
const struct mie_interface_definition *interface)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&interface->if_id, id_str, sizeof id_str);
b_printf(
" [bold,cyan]If:[reset]%-20s [dark_grey]{%s}[reset]\n",
interface->if_name, id_str);
}
static void mie_pass_definition_print(const struct mie_pass_definition *interface)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&interface->p_id, id_str, sizeof id_str);
b_printf(
" [bold,cyan]Ps:[reset]%-20s [dark_grey]{%s}[reset]\n",
interface->p_name, id_str);
}
static void mie_diag_class_print(
const struct mie_dialect *dialect, const struct mie_diag_class *c)
{
switch (c->c_type) {
case MIE_DIAG_CLASS_HINT:
b_printf(" [bold,cyan]Hint:[reset]");
break;
case MIE_DIAG_CLASS_WARNING:
b_printf(" [bold,yellow]Warn:[reset]");
break;
case MIE_DIAG_CLASS_ERROR:
b_printf(" [bold,red]Err: [reset]");
break;
default:
return;
}
b_printf(
"%s.%-25s [green]%s[reset]\n", dialect->d_name,
c->c_id_str_short, c->c_title);
}
static void mie_diag_msg_print(
const struct mie_dialect *dialect, const struct mie_diag_msg *msg)
{
b_printf(
" [bold,blue]Msg: [reset]%s.%-25s [green]%s[reset]\n",
dialect->d_name, msg->msg_id_str_short, msg->msg_content);
}
static void mie_dialect_print(const struct mie_dialect *dialect)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&dialect->d_id, id_str, sizeof id_str);
b_printf(
"[bold,green]D:[reset]%-20s [dark_grey]{%s}[reset]\n",
dialect->d_name, id_str);
b_btree_node *node = b_btree_first(&dialect->d_ops.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_op_definition *op
= b_unbox(struct mie_op_definition, id, op_id);
mie_op_definition_print(op);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_types.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_type_definition *type
= b_unbox(struct mie_type_definition, id, ty_id);
mie_type_definition_print(type);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_traits.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_trait_definition *trait
= b_unbox(struct mie_trait_definition, id, tr_id);
mie_trait_definition_print(trait);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_attributes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_attribute_definition *attribute
= b_unbox(struct mie_attribute_definition, id, a_id);
mie_attribute_definition_print(attribute);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_interfaces.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_interface_definition *interface = b_unbox(
struct mie_interface_definition, id, if_id);
mie_interface_definition_print(interface);
node = b_btree_next(node);
}
}
static void mie_ctx_print(const struct mie_ctx *ctx)
{
printf("Dialects:\n");
b_btree_node *node = b_btree_first(&ctx->ctx_dialects.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_dialect *dialect
= b_unbox(struct mie_dialect, id, d_id);
mie_dialect_print(dialect);
node = b_btree_next(node);
}
printf("\nPasses:\n");
node = b_btree_first(&ctx->ctx_passes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_pass_definition *pass
= b_unbox(struct mie_pass_definition, id, p_id);
mie_pass_definition_print(pass);
node = b_btree_next(node);
}
printf("\nDiagnostics:\n");
node = b_btree_first(&ctx->ctx_dialects.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_dialect *dialect
= b_unbox(struct mie_dialect, id, d_id);
for (size_t i = 0; i < dialect->d_nr_diag_classes; i++) {
mie_diag_class_print(dialect, &dialect->d_diag_classes[i]);
}
for (size_t i = 0; i < dialect->d_nr_diag_msgs; i++) {
mie_diag_msg_print(dialect, &dialect->d_diag_msgs[i]);
}
node = b_btree_next(node);
}
}
static int ctx_dump(const b_command *cmd, const b_arglist *args, const b_array *_)
{
struct mie_ctx *ctx = mie_ctx_create();
mie_builtin_dialect_create(ctx);
mie_meta_dialect_create(ctx);
mie_select_dialect_create(ctx);
mie_ptr_dialect_create(ctx);
mie_arith_dialect_create(ctx);
mie_func_dialect_create(ctx);
mie_cf_dialect_create(ctx);
mie_scf_dialect_create(ctx);
mie_index_dialect_create(ctx);
mie_builtin_passes_register(ctx);
mie_ctx_print(ctx);
struct mie_type *i32 = mie_ctx_get_int_type(ctx, 32);
struct mie_type *str = mie_ctx_get_type(ctx, "builtin", "string");
struct mie_type *index = mie_ctx_get_type(ctx, "builtin", "index");
struct mie_attribute *i32_value = mie_ctx_get_int(ctx, 1024, 32);
struct mie_attribute *index_value = mie_ctx_get_index(ctx, 25000);
struct mie_attribute *str_value
= mie_ctx_get_string(ctx, "Hello, world!");
const struct mie_type *storage_type_parts[] = {i32, str, index};
struct mie_type *storage_type = mie_ctx_get_storage_type(
ctx, storage_type_parts,
sizeof storage_type_parts / sizeof *storage_type_parts);
const struct mie_type *func_in_parts[] = {i32, str};
const struct mie_type *func_out_parts[] = {index};
struct mie_type *func_type = mie_ctx_get_function_type(
ctx, func_in_parts, sizeof func_in_parts / sizeof *func_in_parts,
func_out_parts, sizeof func_out_parts / sizeof *func_out_parts);
/* make sure storage/function type caching is working */
assert(storage_type
== mie_ctx_get_storage_type(
ctx, storage_type_parts,
sizeof storage_type_parts / sizeof *storage_type_parts));
assert(func_type
== mie_ctx_get_function_type(
ctx, func_in_parts,
sizeof func_in_parts / sizeof *func_in_parts, func_out_parts,
sizeof func_out_parts / sizeof *func_out_parts));
struct mie_printer printer;
mie_printer_init(&printer, ctx, b_stdout, MIE_PRINT_F_ABBREVIATED);
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&i32->ty_id, id_str, sizeof id_str);
printf("i32 type: {%s} %s (instance of %s.%s)\n", id_str, i32->ty_name,
i32->ty_def->ty_parent->d_name, i32->ty_def->ty_name);
mie_id_to_string(&str->ty_id, id_str, sizeof id_str);
printf("str type: {%s} %s (instance of %s.%s)\n", id_str, str->ty_name,
str->ty_def->ty_parent->d_name, str->ty_def->ty_name);
mie_id_to_string(&index->ty_id, id_str, sizeof id_str);
printf("index type: {%s} %s (instance of %s.%s)\n", id_str, index->ty_name,
index->ty_def->ty_parent->d_name, index->ty_def->ty_name);
mie_id_to_string(&storage_type->ty_id, id_str, sizeof id_str);
printf("storage type: {%s} ", id_str);
mie_printer_print_type(&printer, storage_type);
printf("\n");
mie_id_to_string(&func_type->ty_id, id_str, sizeof id_str);
printf("function type: {%s} ", id_str);
mie_printer_print_type(&printer, func_type);
printf("\n");
printf("i32 value: ");
mie_printer_print_attribute(&printer, i32_value);
printf("\n");
printf("index value: ");
mie_printer_print_attribute(&printer, index_value);
printf("\n");
printf("str value: ");
mie_printer_print_attribute(&printer, str_value);
printf("\n");
return 0;
}
B_COMMAND(CMD_INTERNAL_CTX_DUMP, CMD_INTERNAL)
{
B_COMMAND_NAME("ctx-dump");
B_COMMAND_DESC("mie_ctx dump");
B_COMMAND_FUNCTION(ctx_dump);
B_COMMAND_HELP_OPTION();
}

View File

@@ -0,0 +1,20 @@
#include "../cmd.h"
#include <blue/cmd.h>
#include <blue/term.h>
static int internal(const b_command *cmd, const b_arglist *args, const b_array *_)
{
return 0;
}
B_COMMAND(CMD_INTERNAL, CMD_ROOT)
{
B_COMMAND_SHORT_NAME('X');
B_COMMAND_DESC("internal frontend debugging tools.");
B_COMMAND_FUNCTION(internal);
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
}

248
tool/cmd/optimise.c Normal file
View File

@@ -0,0 +1,248 @@
#include "cmd.h"
#include <assert.h>
#include <blue/cmd.h>
#include <blue/io/file.h>
#include <blue/io/path.h>
#include <blue/term.h>
#include <mie/attribute/attribute-definition.h>
#include <mie/ctx.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/dialect/func.h>
#include <mie/dialect/index.h>
#include <mie/dialect/meta.h>
#include <mie/dialect/ptr.h>
#include <mie/dialect/scf.h>
#include <mie/dialect/select.h>
#include <mie/interface/interface-definition.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/register.h>
#include <mie/ir/walk.h>
#include <mie/name.h>
#include <mie/parse/lex.h>
#include <mie/parse/line-source.h>
#include <mie/parse/parser.h>
#include <mie/parse/token.h>
#include <mie/pass/builtin.h>
#include <mie/pass/pass-manager.h>
#include <mie/print/printer.h>
#include <mie/trait/trait-definition.h>
#include <mie/trait/trait.h>
#include <mie/type/type-definition.h>
#include <mie/type/type.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
enum {
ARG_FILEPATH,
OPT_PASS_OFFSET = 200,
};
static int optimise_file(
const b_command *cmd, const char *path, const b_arglist *args)
{
b_file *file = NULL;
b_result result
= b_file_open(NULL, B_RV_PATH(path), B_FILE_READ_ONLY, &file);
if (b_result_is_error(result)) {
b_throw(result);
return -1;
}
printf("File OK\n");
b_arglist_iterator it;
b_arglist_foreach(&it, args)
{
if (it.opt_id < OPT_PASS_OFFSET) {
continue;
}
const b_command_option *opt = b_command_get_option(cmd, it.opt_id);
if (!opt) {
continue;
}
printf("running pass %s\n", b_command_option_get_long_name(opt));
}
struct mie_ctx *ctx = mie_ctx_create();
mie_builtin_dialect_create(ctx);
mie_meta_dialect_create(ctx);
mie_select_dialect_create(ctx);
mie_ptr_dialect_create(ctx);
mie_arith_dialect_create(ctx);
mie_func_dialect_create(ctx);
mie_cf_dialect_create(ctx);
mie_scf_dialect_create(ctx);
mie_index_dialect_create(ctx);
mie_builtin_passes_register(ctx);
struct mie_line_source src;
mie_line_source_init(&src, path, file);
struct mie_lex *lex = mie_lex_create(&src, ctx);
struct mie_parser *parse = mie_parser_create(ctx, lex);
struct mie_name_map *names = mie_name_map_create(NULL);
struct mie_op *root = mie_op_create();
if (!mie_parser_parse_op(parse, NULL, root)) {
printf("parse failed\n");
return -1;
}
enum mie_walker_flags flags = MIE_WALKER_F_INCLUDE_OPS
| MIE_WALKER_F_PREORDER | MIE_WALKER_F_FORWARD
| MIE_WALKER_F_RECURSIVE;
struct mie_walker walker;
mie_walker_begin(&walker, root, flags);
do {
const struct mie_walk_item *item = mie_walker_get(&walker);
for (size_t i = 0; i < item->i_depth; i++) {
fputs(" ", stdout);
}
printf("resolving %p %s... ", item->i_op, item->i_op->op_name);
bool ok = mie_ctx_resolve_op(ctx, item->i_op);
printf("%s\n", ok ? "OK" : "FAIL");
} while (mie_walker_step(&walker) == MIE_SUCCESS);
struct mie_pass *prefix_func_with_underscore = NULL;
if (mie_ctx_get_pass(
ctx, "prefix-func-with-underscore", NULL,
&prefix_func_with_underscore)
!= MIE_SUCCESS) {
printf("cannot load pass prefix-func-with-underscore\n");
return -1;
}
struct mie_pass_manager *pm = mie_pass_manager_create(ctx);
struct mie_pass_manager *module_pm = mie_pass_manager_nest(pm);
mie_pass_manager_filter_op(module_pm, "builtin", "module");
struct mie_pass_manager *func_pm = mie_pass_manager_nest(pm);
mie_pass_manager_filter_op(module_pm, "func", "func");
mie_pass_manager_add_pass(func_pm, prefix_func_with_underscore);
#if 0
mie_pass_manager_parse(
pm, "builtin.module(func.func(prefix-func-with-underscore))");
#endif
mie_pass_manager_run(pm, root);
struct mie_printer printer;
mie_printer_init(&printer, ctx, b_stdout, MIE_PRINT_F_ABBREVIATED);
mie_printer_print_op(&printer, root);
printf("\n");
#if 0
while (1) {
struct mie_token *tok = mie_lex_peek(lex);
if (!tok) {
break;
}
printf("%s[%d:%d -> %d:%d]",
mie_token_type_to_string(tok->tok_type),
tok->tok_start.c_row, tok->tok_start.c_col,
tok->tok_end.c_row, tok->tok_end.c_col);
switch (tok->tok_value_type) {
case MIE_TOK_V_STRING:
printf(" S:%s", tok->tok_str);
break;
case MIE_TOK_V_INT:
printf(" I:%lld", tok->tok_int);
break;
case MIE_TOK_V_DOUBLE:
printf(" D:%lf", tok->tok_double);
break;
case MIE_TOK_V_SYMBOL:
printf(" SYM:%s", mie_token_symbol_to_string(tok->tok_sym));
break;
default:
break;
}
printf("\n");
mie_lex_advance(lex);
}
#endif
mie_lex_destroy(lex);
mie_line_source_cleanup(&src);
b_file_unref(file);
return 0;
}
int optimise(const b_command *cmd, const b_arglist *args, const b_array *_)
{
b_arglist_iterator it;
b_arglist_foreach_filtered(&it, args, B_COMMAND_INVALID_ID, ARG_FILEPATH)
{
b_arglist_value *path = it.value;
if (path->val_type != B_COMMAND_ARG_STRING) {
continue;
}
int r = optimise_file(cmd, path->val_str, args);
if (r != 0) {
return r;
}
}
return 0;
}
B_COMMAND(CMD_OPTIMISE, CMD_ROOT)
{
B_COMMAND_NAME("optimise");
B_COMMAND_SHORT_NAME('O');
B_COMMAND_DESC("optimise a mie ir file.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(optimise);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_FILEPATH)
{
B_ARG_NAME("filepath");
B_ARG_DESC("the mie file to optimise");
B_ARG_NR_VALUES(1);
}
struct mie_ctx *ctx = mie_ctx_create();
mie_builtin_passes_register(ctx);
size_t i = 0;
b_btree_node *node = b_btree_first(&ctx->ctx_passes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_pass_definition *pass
= b_unbox(struct mie_pass_definition, id, p_id);
B_COMMAND_OPTION_GEN(OPT_PASS_OFFSET + 1)
{
B_OPTION_LONG_NAME(pass->p_name);
B_OPTION_DESC(pass->p_description);
}
node = b_btree_next(node);
}
}

View File

@@ -1,3 +1,4 @@
#include "../diag/diag.h"
#include "cmd.h"
#include <assert.h>
@@ -26,6 +27,7 @@
#include <mie/ir/walk.h>
#include <mie/name.h>
#include <mie/parse/lex.h>
#include <mie/parse/line-source.h>
#include <mie/parse/parser.h>
#include <mie/parse/token.h>
#include <mie/pass/builtin.h>
@@ -43,248 +45,6 @@ enum {
ARG_FILEPATH,
};
static int trait_ref_print(const struct mie_trait *trait, void *arg)
{
fputc(' ', stdout);
mie_trait_print(trait, b_stdout);
return 0;
}
static void op_arg_dump(struct mie_printer *printer, const struct mie_op_arg *arg)
{
enum mie_register_flags arg_flags = 0;
const char *arg_name = NULL;
const struct mie_type *arg_type = NULL;
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
arg_flags = arg->arg_value.u_reg->reg_flags;
arg_name = arg->arg_value.u_reg->reg_name.n_str;
arg_type = arg->arg_value.u_reg->reg_type;
} else {
arg_flags = arg->arg_unresolved.reg_flags;
arg_name = arg->arg_unresolved.reg_name;
arg_type = arg->arg_unresolved.reg_type;
}
if (arg_flags & MIE_REGISTER_F_MACHINE) {
b_printf(" [bold,red]MR");
} else {
b_printf(" [bold,magenta]VR");
}
printf(":(");
mie_printer_print_type(printer, arg_type);
b_printf(")%s[reset]", arg_name);
}
static void op_dump(const struct mie_op *op)
{
b_stringstream *tmp = b_stringstream_create();
struct mie_printer printer;
mie_printer_init(&printer, NULL, b_stdout, MIE_PRINT_F_GENERIC);
printf("FLAGS:");
(op->op_flags & MIE_OP_F_OP_RESOLVED) && printf(" OP_RESOLVED");
(op->op_flags & MIE_OP_F_ARG_RESOLVED) && printf(" ARG_RESOLVED");
printf("\n");
printf("DIALECT: %s\n",
op->op_dialect ? op->op_dialect->d_name : "<unknown>");
printf("OP: %s\n", op->op_info ? op->op_info->op_name : "<unknown>");
printf("NAME: %s\n", op->op_name ? op->op_name : "<unknown>");
printf("TRAITS:");
mie_trait_table_iterate(&op->op_info->op_traits, trait_ref_print, NULL);
printf("\n");
printf("ATTRIBUTES:");
#if 0
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_attrib); i++) {
printf(" (%s = ", op->op_attrib.items[i].attrib_name);
mie_printer_print_value(
&printer, op->op_attrib.items[i].attrib_value);
printf(")");
}
#endif
printf("\n");
printf("REGIONS: %zu\n", MIE_VECTOR_COUNT(op->op_regions));
printf("SUCCESSORS:");
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
const struct mie_op_successor *s = &op->op_successors.items[i];
if (MIE_TEST_FLAGS(s->s_flags, MIE_OP_F_SUCCESSOR_RESOLVED)) {
printf(" ^%s", s->s_block->b_name.n_str);
} else {
printf(" ^%s?", s->s_block_name);
}
printf(":(");
for (size_t i = 0; i < MIE_VECTOR_COUNT(s->s_args); i++) {
const struct mie_op_arg *arg = &s->s_args.items[i];
op_arg_dump(&printer, arg);
}
printf(" )");
}
printf("\n");
printf("ARGS:");
for (size_t i = 0; i < op->op_args.count; i++) {
const struct mie_op_arg *arg = &op->op_args.items[i];
op_arg_dump(&printer, arg);
}
printf("\n");
printf("RESULT:");
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
const struct mie_register *reg = &op->op_result.items[i];
printf(" %s:(",
(reg->reg_flags & MIE_REGISTER_F_MACHINE) ? "MR" : "VR");
mie_printer_print_type(&printer, reg->reg_type);
printf(")%s", reg->reg_name.n_str);
}
printf("\n");
}
static void mie_op_definition_print(const struct mie_op_definition *op)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&op->op_id, id_str, sizeof id_str);
b_printf(
" [bold,red]Op:[reset]%-20s [dark_grey]{%s}[reset]\n",
op->op_name, id_str);
}
static void mie_type_definition_print(const struct mie_type_definition *type)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&type->ty_id, id_str, sizeof id_str);
b_printf(
" [bold,blue]Ty:[reset]%-20s [dark_grey]{%s}[reset]\n",
type->ty_name, id_str);
}
static void mie_trait_definition_print(const struct mie_trait_definition *trait)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&trait->tr_id, id_str, sizeof id_str);
b_printf(
" [bold,yellow]Tr:[reset]%-20s [dark_grey]{%s}[reset]\n",
trait->tr_name, id_str);
}
static void mie_attribute_definition_print(
const struct mie_attribute_definition *attribute)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&attribute->a_id, id_str, sizeof id_str);
b_printf(
" [bold,magenta]At:[reset]%-20s [dark_grey]{%s}[reset]\n",
attribute->a_name, id_str);
}
static void mie_interface_definition_print(
const struct mie_interface_definition *interface)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&interface->if_id, id_str, sizeof id_str);
b_printf(
" [bold,cyan]If:[reset]%-20s [dark_grey]{%s}[reset]\n",
interface->if_name, id_str);
}
static void mie_pass_definition_print(const struct mie_pass_definition *interface)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&interface->p_id, id_str, sizeof id_str);
b_printf(
" [bold,cyan]Ps:[reset]%-20s [dark_grey]{%s}[reset]\n",
interface->p_name, id_str);
}
static void mie_dialect_print(const struct mie_dialect *dialect)
{
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&dialect->d_id, id_str, sizeof id_str);
b_printf(
"[bold,green]D:[reset]%-20s [dark_grey]{%s}[reset]\n",
dialect->d_name, id_str);
b_btree_node *node = b_btree_first(&dialect->d_ops.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_op_definition *op
= b_unbox(struct mie_op_definition, id, op_id);
mie_op_definition_print(op);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_types.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_type_definition *type
= b_unbox(struct mie_type_definition, id, ty_id);
mie_type_definition_print(type);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_traits.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_trait_definition *trait
= b_unbox(struct mie_trait_definition, id, tr_id);
mie_trait_definition_print(trait);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_attributes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_attribute_definition *attribute
= b_unbox(struct mie_attribute_definition, id, a_id);
mie_attribute_definition_print(attribute);
node = b_btree_next(node);
}
node = b_btree_first(&dialect->d_interfaces.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_interface_definition *interface = b_unbox(
struct mie_interface_definition, id, if_id);
mie_interface_definition_print(interface);
node = b_btree_next(node);
}
}
static void mie_ctx_print(const struct mie_ctx *ctx)
{
printf("Dialects:\n");
b_btree_node *node = b_btree_first(&ctx->ctx_dialects.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_dialect *dialect
= b_unbox(struct mie_dialect, id, d_id);
mie_dialect_print(dialect);
node = b_btree_next(node);
}
printf("\nPasses:\n");
node = b_btree_first(&ctx->ctx_passes.map_entries);
while (node) {
mie_id *id = b_unbox(mie_id, node, e_node);
struct mie_pass_definition *pass
= b_unbox(struct mie_pass_definition, id, p_id);
mie_pass_definition_print(pass);
node = b_btree_next(node);
}
}
static int validate_file(const char *path, const b_arglist *args)
{
b_file *file = NULL;
@@ -310,76 +70,10 @@ static int validate_file(const char *path, const b_arglist *args)
mie_builtin_passes_register(ctx);
mie_ctx_print(ctx);
struct mie_line_source src;
mie_line_source_init(&src, path, file);
struct mie_type *i32 = mie_ctx_get_int_type(ctx, 32);
struct mie_type *str = mie_ctx_get_type(ctx, "builtin", "string");
struct mie_type *index = mie_ctx_get_type(ctx, "builtin", "index");
struct mie_attribute *i32_value = mie_ctx_get_int(ctx, 1024, 32);
struct mie_attribute *index_value = mie_ctx_get_index(ctx, 25000);
struct mie_attribute *str_value
= mie_ctx_get_string(ctx, "Hello, world!");
printf("%zu\n", sizeof(struct mie_op));
const struct mie_type *storage_type_parts[] = {i32, str, index};
struct mie_type *storage_type = mie_ctx_get_storage_type(
ctx, storage_type_parts,
sizeof storage_type_parts / sizeof *storage_type_parts);
const struct mie_type *func_in_parts[] = {i32, str};
const struct mie_type *func_out_parts[] = {index};
struct mie_type *func_type = mie_ctx_get_function_type(
ctx, func_in_parts, sizeof func_in_parts / sizeof *func_in_parts,
func_out_parts, sizeof func_out_parts / sizeof *func_out_parts);
/* make sure storage/function type caching is working */
assert(storage_type
== mie_ctx_get_storage_type(
ctx, storage_type_parts,
sizeof storage_type_parts / sizeof *storage_type_parts));
assert(func_type
== mie_ctx_get_function_type(
ctx, func_in_parts,
sizeof func_in_parts / sizeof *func_in_parts, func_out_parts,
sizeof func_out_parts / sizeof *func_out_parts));
struct mie_printer printer;
mie_printer_init(&printer, ctx, b_stdout, MIE_PRINT_F_ABBREVIATED);
char id_str[MIE_ID_STRING_MAX];
mie_id_to_string(&i32->ty_id, id_str, sizeof id_str);
printf("i32 type: {%s} %s (instance of %s.%s)\n", id_str, i32->ty_name,
i32->ty_def->ty_parent->d_name, i32->ty_def->ty_name);
mie_id_to_string(&str->ty_id, id_str, sizeof id_str);
printf("str type: {%s} %s (instance of %s.%s)\n", id_str, str->ty_name,
str->ty_def->ty_parent->d_name, str->ty_def->ty_name);
mie_id_to_string(&index->ty_id, id_str, sizeof id_str);
printf("index type: {%s} %s (instance of %s.%s)\n", id_str, index->ty_name,
index->ty_def->ty_parent->d_name, index->ty_def->ty_name);
mie_id_to_string(&storage_type->ty_id, id_str, sizeof id_str);
printf("storage type: {%s} ", id_str);
mie_printer_print_type(&printer, storage_type);
printf("\n");
mie_id_to_string(&func_type->ty_id, id_str, sizeof id_str);
printf("function type: {%s} ", id_str);
mie_printer_print_type(&printer, func_type);
printf("\n");
printf("i32 value: ");
mie_printer_print_attribute(&printer, i32_value);
printf("\n");
printf("index value: ");
mie_printer_print_attribute(&printer, index_value);
printf("\n");
printf("str value: ");
mie_printer_print_attribute(&printer, str_value);
printf("\n");
struct mie_lex *lex = mie_lex_create(file);
struct mie_lex *lex = mie_lex_create(&src, ctx);
struct mie_parser *parse = mie_parser_create(ctx, lex);
struct mie_name_map *names = mie_name_map_create(NULL);
@@ -387,30 +81,55 @@ static int validate_file(const char *path, const b_arglist *args)
struct mie_op *root = mie_op_create();
if (!mie_parser_parse_op(parse, NULL, root)) {
struct mie_diag *diag = mie_ctx_pop_diag(ctx);
while (diag) {
mie_diag_write_pretty(diag, b_stdtty_err);
/* TODO cleanup */
diag = mie_ctx_pop_diag(ctx);
}
printf("parse failed\n");
return -1;
}
struct mie_walker *walker = mie_walker_begin(
root, MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_PREORDER
| MIE_WALKER_F_FORWARD | MIE_WALKER_F_RECURSIVE);
enum mie_walker_flags walk_flags
= MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_PREORDER
| MIE_WALKER_F_FORWARD | MIE_WALKER_F_RECURSIVE;
struct mie_walker walker;
mie_walker_begin(&walker, root, walk_flags);
do {
const struct mie_walker_item *item = mie_walker_get(walker);
const struct mie_walk_item *item = mie_walker_get(&walker);
for (size_t i = 0; i < item->i_depth; i++) {
fputs(" ", stdout);
}
printf("resolving %p %s... ", item->i_op, item->i_op->op_name);
bool ok = mie_ctx_resolve_op(ctx, item->i_op);
printf("%s\n", ok ? "OK" : "FAIL");
} while (mie_walker_step(walker) == MIE_SUCCESS);
switch (item->i_type) {
case MIE_WALK_ITEM_REGION:
printf("looking at region %p...\n", item->i_region);
continue;
case MIE_WALK_ITEM_BLOCK:
printf("looking at block %p %s...\n", item->i_block,
item->i_block->b_name.n_str);
continue;
case MIE_WALK_ITEM_OP:
printf("resolving %p %s... ", item->i_op,
item->i_op->op_name);
bool ok = mie_ctx_resolve_op(ctx, item->i_op);
printf("%s\n", ok ? "OK" : "FAIL");
break;
default:
break;
}
} while (mie_walker_step(&walker) == MIE_SUCCESS);
mie_walker_end(&walker);
struct mie_pass *prefix_func_with_underscore = NULL;
if (mie_ctx_get_pass(
ctx, "prefix-func-with-underscore", NULL,
&prefix_func_with_underscore)
!= MIE_SUCCESS) {
enum mie_status status = mie_ctx_get_pass(
ctx, "prefix-func-with-underscore", NULL,
&prefix_func_with_underscore);
if (status != MIE_SUCCESS) {
printf("cannot load pass prefix-func-with-underscore\n");
return -1;
}
@@ -424,13 +143,52 @@ static int validate_file(const char *path, const b_arglist *args)
mie_pass_manager_add_pass(func_pm, prefix_func_with_underscore);
#if 0
mie_pass_manager_parse(
pm, "builtin.module(func.func(prefix-func-with-underscore))");
#endif
mie_pass_manager_run(pm, root);
struct mie_printer printer;
mie_printer_init(&printer, ctx, b_stdout, MIE_PRINT_F_ABBREVIATED);
mie_printer_print_op(&printer, root);
printf("\n");
struct mie_op *func = mie_op_get_first_child_op(root);
walk_flags = MIE_WALKER_F_INCLUDE_OPS | MIE_WALKER_F_PREORDER
| MIE_WALKER_F_FORWARD;
mie_walker_begin(&walker, func, walk_flags);
do {
const struct mie_walk_item *item = mie_walker_get(&walker);
for (size_t i = 0; i < item->i_depth; i++) {
fputs(" ", stdout);
}
switch (item->i_type) {
case MIE_WALK_ITEM_REGION:
printf("looking at region %p...\n", item->i_region);
break;
case MIE_WALK_ITEM_BLOCK:
printf("looking at block %p %s...\n", item->i_block,
item->i_block->b_name.n_str);
break;
case MIE_WALK_ITEM_OP:
if (item->i_op->op_flags & MIE_OP_F_OP_RESOLVED) {
printf("looking at %p %s.%s...\n", item->i_op,
item->i_op->op_dialect->d_name,
item->i_op->op_info->op_name);
} else {
printf("looking at %p %s...\n", item->i_op,
item->i_op->op_name);
}
break;
default:
break;
}
} while (mie_walker_step(&walker) == MIE_SUCCESS);
mie_walker_end(&walker);
#if 0
while (1) {
@@ -469,6 +227,8 @@ static int validate_file(const char *path, const b_arglist *args)
mie_lex_destroy(lex);
mie_line_source_cleanup(&src);
b_file_unref(file);
return 0;

11
tool/diag/diag.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _TOOL_DIAG_DIAG_H_
#define _TOOL_DIAG_DIAG_H_
#include <blue/term/tty.h>
#include <mie/status.h>
struct mie_diag;
extern enum mie_status mie_diag_write_pretty(struct mie_diag *diag, b_tty *stream);
#endif

0
tool/diag/json.c Normal file
View File

461
tool/diag/pretty.c Normal file
View File

@@ -0,0 +1,461 @@
#include <assert.h>
#include <blue/core/stringstream.h>
#include <blue/term/print.h>
#include <blue/term/tty.h>
#include <ctype.h>
#include <mie/diag/amendment.h>
#include <mie/diag/class.h>
#include <mie/diag/component.h>
#include <mie/diag/diag.h>
#include <mie/diag/highlight.h>
#include <mie/parse/line-source.h>
#include <stdlib.h>
#define GET_CHAR_STOP 0
#define GET_CHAR_CONTINUE -1
struct snippet_print_ctx {
b_tty *ctx_stream;
struct mie_line_source *ctx_line_source;
size_t ctx_row, ctx_col;
bool ctx_has_underline;
b_stringstream *ctx_underline;
const b_string *ctx_linebuf;
const b_iterator *ctx_linebuf_ptr;
struct mie_diag_c_snippet *ctx_snippet;
const struct mie_diag_highlight *ctx_hl;
const struct mie_diag_amendment *ctx_amendment;
};
#define __STREAM_COLOUR_ERROR "[red,bold]"
#define __STREAM_COLOUR_WARN "[yellow,bold]"
#define __STREAM_COLOUR_HINT "[blue,bold]"
#define __STREAM_COLOUR_LINE_NO "[cyan]"
#define __STREAM_COLOUR_ACCENT "[cyan]"
#define __STREAM_COLOUR_RESET "[reset]"
#define STREAM_COLOUR_ERROR(stream) \
b_tty_puts(stream, 0, __STREAM_COLOUR_ERROR);
#define STREAM_COLOUR_WARN(stream) b_tty_puts(stream, 0, __STREAM_COLOUR_WARN);
#define STREAM_COLOUR_HINT(stream) b_tty_puts(stream, 0, __STREAM_COLOUR_HINT);
#define STREAM_COLOUR_ACCENT(stream) \
b_tty_puts(stream, 0, __STREAM_COLOUR_ACCENT);
#define STREAM_COLOUR_LINE_NO(stream) \
b_tty_puts(stream, 0, __STREAM_COLOUR_LINE_NO);
#define STREAM_COLOUR_RESET(stream) \
b_tty_puts(stream, 0, __STREAM_COLOUR_RESET);
#define STREAM_COLOUR_ERROR_B(stream, str) \
b_stream_write_string(str, __STREAM_COLOUR_ERROR, NULL);
#define STREAM_COLOUR_WARN_B(stream, str) \
b_stream_write_string(str, __STREAM_COLOUR_WARN, NULL);
#define STREAM_COLOUR_HINT_B(stream, str) \
b_stream_write_string(str, __STREAM_COLOUR_HINT, NULL);
#define STREAM_COLOUR_ACCENT_B(stream, str) \
b_stream_write_string(str, __STREAM_COLOUR_ACCENT, NULL);
#define STREAM_COLOUR_RESET_B(stream, str) \
b_stream_write_string(str, __STREAM_COLOUR_RESET, NULL);
static void print_header(struct mie_diag *diag, b_tty *dest)
{
unsigned int w;
b_tty_get_dimensions(dest, &w, NULL);
const struct mie_diag_class *diag_class = diag->diag_class;
assert(diag_class);
STREAM_COLOUR_ACCENT(dest);
size_t nr_written = 0;
nr_written += b_tty_puts(dest, 0, "--- ");
const char *s = diag_class->c_title;
while (*s) {
b_tty_putc(dest, 0, toupper(*s));
s++;
nr_written++;
}
b_tty_putc(dest, 0, ' ');
nr_written++;
while (nr_written < w) {
b_tty_putc(dest, 0, '-');
nr_written++;
}
STREAM_COLOUR_RESET(dest);
b_tty_putc(dest, 0, '\n');
}
static void print_location(struct mie_diag *diag, b_tty *out)
{
size_t x;
const char *name = mie_line_source_get_path(diag->diag_src);
b_tty_puts(out, 0, " ");
STREAM_COLOUR_ACCENT(out);
b_tty_puts(out, 0, "> ");
STREAM_COLOUR_RESET(out);
b_tty_printf(
out, 0, "%s:%lu:%lu\n", name, diag->diag_loc.c_row,
diag->diag_loc.c_col);
}
static void print_msg(
struct mie_diag *diag, struct mie_diag_c_msg *msg, b_tty *stream)
{
b_paragraph_format format = {
.p_left_margin = 2,
.p_right_margin = 2,
};
b_print_paragraph(msg->msg_content, stream, &format);
}
static bool highlight_contains_cell(
const struct mie_diag_highlight *hl, size_t row, size_t col)
{
if (row < hl->hl_span.s_start.c_row || row > hl->hl_span.s_end.c_row) {
return false;
}
if (row == hl->hl_span.s_start.c_row && col < hl->hl_span.s_start.c_col) {
return false;
}
if (row == hl->hl_span.s_end.c_row && col > hl->hl_span.s_end.c_col) {
return false;
}
return true;
}
static bool amendment_contains_cell(
const struct mie_diag_amendment *a, size_t row, size_t col)
{
unsigned long limit = 0;
switch (a->a_type) {
case MIE_DIAG_AMENDMENT_ADD:
if (a->a_add.a_loc.c_row != row) {
return false;
}
if (col < a->a_add.a_loc.c_col) {
return false;
}
if (col > a->a_add.a_loc.c_col + a->__x - 1) {
return false;
}
return true;
case MIE_DIAG_AMENDMENT_REMOVE:
if (a->a_remove.a_loc.c_row != row) {
return false;
}
if (col < a->a_remove.a_loc.c_row) {
return false;
}
if (col > a->a_remove.a_length) {
return false;
}
return true;
case MIE_DIAG_AMENDMENT_REPLACE:
if (a->a_replace.a_loc.c_row != row) {
return false;
}
if (col < a->a_replace.a_loc.c_row) {
return false;
}
limit = a->a_replace.a_loc.c_row
+ b_max(ulong, a->a_replace.a_length, a->__x) - 1;
if (col > limit) {
return false;
}
return true;
default:
return false;
}
}
static struct mie_diag_highlight *find_highlight(
struct mie_diag_c_snippet *snippet, size_t row, size_t col)
{
for (size_t i = 0; i < snippet->s_nr_highlights; i++) {
struct mie_diag_highlight *hl = &snippet->s_highlights[i];
if (highlight_contains_cell(hl, row, col)) {
return hl;
}
}
return NULL;
}
static struct mie_diag_amendment *find_amendment(
struct mie_diag_c_snippet *snippet, size_t row, size_t col)
{
for (size_t i = 0; i < snippet->s_nr_amendments; i++) {
struct mie_diag_amendment *a = &snippet->s_amendments[i];
if (amendment_contains_cell(a, row, col)) {
return a;
}
}
return NULL;
}
static void update_amendment(struct snippet_print_ctx *ctx)
{
if (ctx->ctx_amendment
&& amendment_contains_cell(
ctx->ctx_amendment, ctx->ctx_row, ctx->ctx_col)) {
return;
}
ctx->ctx_amendment
= find_amendment(ctx->ctx_snippet, ctx->ctx_row, ctx->ctx_col);
}
static void update_highlighting(struct snippet_print_ctx *ctx)
{
if (ctx->ctx_hl
&& highlight_contains_cell(ctx->ctx_hl, ctx->ctx_row, ctx->ctx_col)) {
return;
}
ctx->ctx_hl = NULL;
STREAM_COLOUR_RESET(ctx->ctx_stream);
const struct mie_diag_highlight *new_hl
= find_highlight(ctx->ctx_snippet, ctx->ctx_row, ctx->ctx_col);
if (!new_hl) {
return;
}
ctx->ctx_has_underline = true;
ctx->ctx_hl = new_hl;
switch (ctx->ctx_hl->hl_type) {
case MIE_DIAG_HIGHLIGHT_ERROR:
STREAM_COLOUR_ERROR(ctx->ctx_stream);
STREAM_COLOUR_ERROR_B(ctx->ctx_stream, ctx->ctx_underline);
break;
case MIE_DIAG_HIGHLIGHT_WARNING:
STREAM_COLOUR_WARN(ctx->ctx_stream);
STREAM_COLOUR_WARN_B(ctx->ctx_stream, ctx->ctx_underline);
break;
case MIE_DIAG_HIGHLIGHT_HINT:
STREAM_COLOUR_HINT(ctx->ctx_stream);
STREAM_COLOUR_HINT_B(ctx->ctx_stream, ctx->ctx_underline);
break;
default:
break;
}
}
static enum mie_status read_row(struct snippet_print_ctx *ctx, size_t row)
{
if (ctx->ctx_linebuf_ptr) {
b_iterator_unref(ctx->ctx_linebuf_ptr);
ctx->ctx_linebuf_ptr = NULL;
}
ctx->ctx_has_underline = false;
size_t nr_read;
enum mie_status status = mie_line_source_get_row(
ctx->ctx_line_source, row, &ctx->ctx_linebuf);
if (status != MIE_SUCCESS) {
return status;
}
ctx->ctx_linebuf_ptr = b_iterator_cbegin(ctx->ctx_linebuf);
return MIE_SUCCESS;
}
static int get_char_amendment(struct snippet_print_ctx *ctx)
{
const struct mie_diag_amendment *a = ctx->ctx_amendment;
size_t i = 0;
int c = 0;
switch (a->a_type) {
case MIE_DIAG_AMENDMENT_ADD:
i = ctx->ctx_col - a->a_add.a_loc.c_row;
return a->a_add.a_str[i];
case MIE_DIAG_AMENDMENT_REMOVE:
b_iterator_move_next(ctx->ctx_linebuf_ptr);
return GET_CHAR_CONTINUE;
case MIE_DIAG_AMENDMENT_REPLACE:
i = ctx->ctx_col - a->a_add.a_loc.c_col;
if (i > a->__x) {
i = a->__x;
}
c = a->a_replace.a_str[i];
if (i < a->a_replace.a_length) {
b_iterator_move_next(ctx->ctx_linebuf_ptr);
}
if (c != 0) {
return c;
}
return GET_CHAR_CONTINUE;
default:
break;
}
return GET_CHAR_CONTINUE;
}
static int get_char(struct snippet_print_ctx *ctx)
{
if (ctx->ctx_amendment) {
return get_char_amendment(ctx);
}
b_wchar c = b_iterator_get_cvalue(ctx->ctx_linebuf_ptr).v_int;
if (c == B_WCHAR_INVALID) {
return GET_CHAR_STOP;
};
b_iterator_move_next(ctx->ctx_linebuf_ptr);
return c;
}
static void update_underline(struct snippet_print_ctx *ctx)
{
if (!ctx->ctx_hl) {
b_stream_write_char(ctx->ctx_underline, ' ');
return;
}
switch (ctx->ctx_hl->hl_type) {
case MIE_DIAG_HIGHLIGHT_ERROR:
case MIE_DIAG_HIGHLIGHT_WARNING:
case MIE_DIAG_HIGHLIGHT_HINT:
b_stream_write_char(ctx->ctx_underline, '^');
break;
default:
b_stream_write_char(ctx->ctx_underline, ' ');
break;
}
}
static void write_underline(struct snippet_print_ctx *ctx)
{
if (!ctx->ctx_has_underline) {
return;
}
STREAM_COLOUR_RESET(ctx->ctx_stream);
STREAM_COLOUR_LINE_NO(ctx->ctx_stream);
b_tty_puts(ctx->ctx_stream, 0, " : ");
b_tty_puts(ctx->ctx_stream, 0, b_stringstream_ptr(ctx->ctx_underline));
STREAM_COLOUR_RESET(ctx->ctx_stream);
b_tty_putc(ctx->ctx_stream, 0, '\n');
}
static void print_snippet(
struct mie_diag *diag, struct mie_diag_c_snippet *snippet, b_tty *stream)
{
enum mie_status status = MIE_SUCCESS;
struct snippet_print_ctx printer = {
.ctx_stream = stream,
.ctx_snippet = snippet,
.ctx_underline = b_stringstream_create(),
.ctx_line_source = diag->diag_src,
};
for (unsigned long row = snippet->s_first_line;
row <= snippet->s_last_line; row++) {
STREAM_COLOUR_LINE_NO(stream);
b_tty_printf(stream, 0, " %4lu | ", row);
printer.ctx_row = row;
status = read_row(&printer, row);
if (status != MIE_SUCCESS) {
break;
}
for (size_t i = 0;; i++) {
printer.ctx_col = i + 1;
update_amendment(&printer);
int c = get_char(&printer);
if (c == GET_CHAR_CONTINUE) {
continue;
} else if (c == GET_CHAR_STOP || c == '\n') {
break;
}
update_highlighting(&printer);
b_tty_putc(stream, 0, c);
update_underline(&printer);
}
b_tty_putc(stream, 0, '\n');
write_underline(&printer);
}
b_stringstream_unref(printer.ctx_underline);
}
static void print_component(
struct mie_diag *diag, struct mie_diag_component *component, b_tty *stream)
{
switch (component->c_type) {
case MIE_DIAG_COMPONENT_MSG:
print_msg(diag, (struct mie_diag_c_msg *)component, stream);
break;
case MIE_DIAG_COMPONENT_SNIPPET:
print_snippet(diag, (struct mie_diag_c_snippet *)component, stream);
break;
default:
abort();
}
}
enum mie_status mie_diag_write_pretty(struct mie_diag *diag, b_tty *stream)
{
print_header(diag, stream);
print_location(diag, stream);
b_queue_entry *entry = b_queue_first(&diag->diag_components);
while (entry) {
struct mie_diag_component *c
= b_unbox(struct mie_diag_component, entry, c_entry);
b_tty_putc(stream, 0, '\n');
print_component(diag, c, stream);
entry = b_queue_next(entry);
}
return MIE_SUCCESS;
}