mie: implement a pass system
passes allow defined units of functionality to be applied on an IR structure. the pass manager can be used to schedule passes at certain depths of the IR structure and/or on or within certain types of ops (or ops that have certain traits/interfaces).
This commit is contained in:
113
mie/ctx.c
113
mie/ctx.c
@@ -9,7 +9,10 @@
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/dialect/index.h>
|
||||
#include <mie/interface/interface-definition.h>
|
||||
#include <mie/ir/op-definition.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/pass/pass-definition.h>
|
||||
#include <mie/pass/pass.h>
|
||||
#include <mie/trait/trait-definition.h>
|
||||
#include <mie/trait/trait.h>
|
||||
#include <mie/type/function.h>
|
||||
@@ -35,6 +38,10 @@
|
||||
MIE_ID(0xc6, 0x94, 0x38, 0x34, 0xdb, 0x08, 0x45, 0xc7, 0xb9, 0x89, \
|
||||
0x69, 0x82, 0x7a, 0x9d, 0x42, 0xd8)
|
||||
|
||||
#define PASS_NS_ID \
|
||||
MIE_ID(0x76, 0xfc, 0xdd, 0xb5, 0xc0, 0x20, 0x47, 0x13, 0x8d, 0xfa, \
|
||||
0x3f, 0x28, 0x2f, 0x81, 0x6d, 0x7d)
|
||||
|
||||
struct mie_ctx *mie_ctx_create(void)
|
||||
{
|
||||
struct mie_ctx *out = malloc(sizeof *out);
|
||||
@@ -57,15 +64,15 @@ struct mie_ctx *mie_ctx_create(void)
|
||||
mie_id attributes_ns = ATTRIBUTE_NS_ID;
|
||||
mie_id_map_init(&out->ctx_attributes, &attributes_ns);
|
||||
|
||||
mie_id pass_ns = PASS_NS_ID;
|
||||
mie_id_map_init(&out->ctx_passes, &pass_ns);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op)
|
||||
{
|
||||
bool fully_resolved = MIE_TEST_FLAGS(
|
||||
op->op_flags, MIE_OP_F_OP_RESOLVED | MIE_OP_F_ARG_RESOLVED);
|
||||
|
||||
if (fully_resolved) {
|
||||
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -120,6 +127,27 @@ struct mie_dialect *mie_ctx_get_dialect(const struct mie_ctx *ctx, const char *n
|
||||
return b_unbox(struct mie_dialect, target, d_id);
|
||||
}
|
||||
|
||||
const struct mie_op_definition *mie_ctx_get_op_definition(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *op_name)
|
||||
{
|
||||
b_rope dialect_name_rope = B_ROPE_CSTR(dialect_name);
|
||||
mie_id id;
|
||||
mie_id_init_ns(
|
||||
&id, mie_id_map_get_ns(&ctx->ctx_dialects), &dialect_name_rope);
|
||||
|
||||
mie_id *target = mie_id_map_get(&ctx->ctx_dialects, &id);
|
||||
struct mie_dialect *dialect = b_unbox(struct mie_dialect, target, d_id);
|
||||
if (!dialect) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b_rope op_name_rope = B_ROPE_CSTR(op_name);
|
||||
mie_id_init_ns(&id, mie_id_map_get_ns(&dialect->d_ops), &op_name_rope);
|
||||
target = mie_id_map_get(&dialect->d_ops, &id);
|
||||
|
||||
return b_unbox(struct mie_op_definition, target, op_id);
|
||||
}
|
||||
|
||||
struct mie_type_definition *mie_ctx_get_type_definition(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *type_name)
|
||||
{
|
||||
@@ -358,3 +386,80 @@ struct mie_type *mie_ctx_get_function_type(
|
||||
mie_id_map_put_id(&ctx->ctx_types, &new_type->func_base.ty_id);
|
||||
return (struct mie_type *)new_type;
|
||||
}
|
||||
|
||||
enum mie_status mie_ctx_register_pass(
|
||||
struct mie_ctx *ctx, struct mie_pass_definition *pass)
|
||||
{
|
||||
if (pass->p_data_size < sizeof(struct mie_pass)) {
|
||||
return MIE_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
switch (pass->p_type) {
|
||||
case MIE_PASS_ANALYSE:
|
||||
case MIE_PASS_TRANSFORM:
|
||||
break;
|
||||
default:
|
||||
return MIE_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
mie_id id;
|
||||
struct mie_id_builder id_builder;
|
||||
mie_id_builder_begin(&id_builder, mie_id_map_get_ns(&ctx->ctx_passes));
|
||||
mie_id_builder_add_cstr(&id_builder, pass->p_name);
|
||||
mie_id_builder_end(&id_builder, &id);
|
||||
|
||||
mie_id *target = mie_id_map_get(&ctx->ctx_passes, &id);
|
||||
if (target) {
|
||||
return MIE_ERR_NAME_EXISTS;
|
||||
}
|
||||
|
||||
pass->p_id = id;
|
||||
mie_id_map_put_id(&ctx->ctx_passes, &pass->p_id);
|
||||
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
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_id id;
|
||||
struct mie_id_builder id_builder;
|
||||
mie_id_builder_begin(&id_builder, mie_id_map_get_ns(&ctx->ctx_passes));
|
||||
mie_id_builder_add_cstr(&id_builder, name);
|
||||
mie_id_builder_end(&id_builder, &id);
|
||||
|
||||
mie_id *target = mie_id_map_get(&ctx->ctx_passes, &id);
|
||||
if (!target) {
|
||||
return MIE_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
struct mie_pass_definition *pass_def
|
||||
= b_unbox(struct mie_pass_definition, target, p_id);
|
||||
|
||||
if (pass_def->p_data_size < sizeof(struct mie_pass)) {
|
||||
return MIE_ERR_BAD_STATE;
|
||||
}
|
||||
|
||||
struct mie_pass *pass = malloc(pass_def->p_data_size);
|
||||
if (!pass) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(pass, 0x0, pass_def->p_data_size);
|
||||
|
||||
pass->p_def = pass_def;
|
||||
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
if (pass_def->p_init) {
|
||||
status = pass_def->p_init(pass, args);
|
||||
}
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
free(pass);
|
||||
pass = NULL;
|
||||
}
|
||||
|
||||
*out = pass;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
#include <mie/id.h>
|
||||
|
||||
struct mie_op;
|
||||
struct mie_pass;
|
||||
struct mie_int_cache;
|
||||
struct mie_index_cache;
|
||||
struct mie_string_cache;
|
||||
;
|
||||
struct mie_attribute_map;
|
||||
struct mie_pass_definition;
|
||||
|
||||
struct mie_ctx {
|
||||
#if 0
|
||||
@@ -27,6 +29,8 @@ struct mie_ctx {
|
||||
struct mie_id_map ctx_traits;
|
||||
/* map of struct mie_attribute */
|
||||
struct mie_id_map ctx_attributes;
|
||||
/* map of struct mie_pass_definition */
|
||||
struct mie_id_map ctx_passes;
|
||||
};
|
||||
|
||||
MIE_API struct mie_ctx *mie_ctx_create(void);
|
||||
@@ -38,6 +42,8 @@ MIE_API struct mie_dialect *mie_ctx_get_dialect(
|
||||
const struct mie_ctx *ctx, const char *name);
|
||||
MIE_API struct mie_type_definition *mie_ctx_get_type_definition(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *type_name);
|
||||
MIE_API const struct mie_op_definition *mie_ctx_get_op_definition(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *op_name);
|
||||
MIE_API const struct mie_trait_definition *mie_ctx_get_trait_definition(
|
||||
const struct mie_ctx *ctx, const char *dialect_name,
|
||||
const char *trait_name);
|
||||
@@ -59,4 +65,10 @@ MIE_API struct mie_type *mie_ctx_get_function_type(
|
||||
|
||||
MIE_API struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx);
|
||||
|
||||
MIE_API enum mie_status mie_ctx_register_pass(
|
||||
struct mie_ctx *ctx, struct mie_pass_definition *pass);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#ifndef MIE_MACROS_H_
|
||||
#define MIE_MACROS_H_
|
||||
|
||||
#define __MIE_DIALECT_BEGIN(func_prefix, c_struct, dialect_name) \
|
||||
/******************************************************************************/
|
||||
/* 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( \
|
||||
@@ -15,11 +19,38 @@
|
||||
struct mie_attribute_definition *attribute = NULL; \
|
||||
struct mie_interface_definition *interface = NULL;
|
||||
|
||||
#define __MIE_DIALECT_END() \
|
||||
#define MIE_DIALECT_END() \
|
||||
return self; \
|
||||
}
|
||||
|
||||
#define __MIE_OP_DEFINITION_BEGIN(func_prefix, op_name) \
|
||||
#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)
|
||||
|
||||
/******************************************************************************/
|
||||
/* 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) \
|
||||
{ \
|
||||
@@ -32,11 +63,29 @@
|
||||
struct mie_interface *i = NULL; \
|
||||
const struct mie_interface_definition *id = NULL;
|
||||
|
||||
#define __MIE_OP_DEFINITION_END() \
|
||||
#define MIE_OP_DEFINITION_END() \
|
||||
return op; \
|
||||
}
|
||||
|
||||
#define __MIE_TYPE_DEFINITION_BEGIN(func_prefix, type_name) \
|
||||
#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_INTERFACE_FUNC(func_name) iface->func_name
|
||||
#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) \
|
||||
{ \
|
||||
@@ -47,106 +96,10 @@
|
||||
} \
|
||||
const struct mie_trait *trait = NULL;
|
||||
|
||||
#define __MIE_TYPE_DEFINITION_END() \
|
||||
#define MIE_TYPE_DEFINITION_END() \
|
||||
return type; \
|
||||
}
|
||||
|
||||
#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_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_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_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(attribute_id) \
|
||||
extern struct mie_attribute_definition *attribute_id##_attribute_create( \
|
||||
struct mie_dialect *, struct mie_ctx *); \
|
||||
attribute = attribute_id##_attribute_create(self, ctx)
|
||||
#define __MIE_DIALECT_ADD_INTERFACE(interface_id) \
|
||||
extern struct mie_interface_definition *interface_id##_interface_create( \
|
||||
struct mie_dialect *, struct mie_ctx *); \
|
||||
interface = interface_id##_interface_create(self, ctx)
|
||||
|
||||
#define MIE_DIALECT_BEGIN(c_sym, c_struct, name) \
|
||||
__MIE_DIALECT_BEGIN(c_sym, c_struct, name)
|
||||
#define MIE_DIALECT_END() __MIE_DIALECT_END()
|
||||
#define MIE_DIALECT_INIT(func) __MIE_DIALECT_INIT(func)
|
||||
#define MIE_DIALECT_CLEANUP(func) __MIE_DIALECT_CLEANUP(func)
|
||||
#define MIE_DIALECT_ADD_OP(c_sym) __MIE_DIALECT_ADD_OP(c_sym)
|
||||
#define MIE_DIALECT_ADD_TYPE(c_sym) __MIE_DIALECT_ADD_TYPE(c_sym)
|
||||
#define MIE_DIALECT_ADD_TRAIT(c_sym) __MIE_DIALECT_ADD_TRAIT(c_sym)
|
||||
#define MIE_DIALECT_ADD_ATTRIBUTE(c_sym) __MIE_DIALECT_ADD_ATTRIBUTE(c_sym)
|
||||
#define MIE_DIALECT_ADD_INTERFACE(c_sym) __MIE_DIALECT_ADD_INTERFACE(c_sym)
|
||||
|
||||
#define MIE_OP_DEFINITION_BEGIN(c_sym, op) __MIE_OP_DEFINITION_BEGIN(c_sym, op)
|
||||
#define MIE_OP_DEFINITION_END() __MIE_OP_DEFINITION_END()
|
||||
#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_INTERFACE_FUNC(func_name) iface->func_name
|
||||
|
||||
#define MIE_OP_INTERFACE_END() \
|
||||
mie_op_definition_add_interface(op, (struct mie_interface *)iface); \
|
||||
}
|
||||
|
||||
#define MIE_TYPE_DEFINITION_BEGIN(c_sym, type) \
|
||||
__MIE_TYPE_DEFINITION_BEGIN(c_sym, type)
|
||||
#define MIE_TYPE_DEFINITION_END() __MIE_TYPE_DEFINITION_END()
|
||||
#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)
|
||||
@@ -159,9 +112,24 @@
|
||||
trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \
|
||||
mie_type_definition_add_trait(type, trait);
|
||||
|
||||
#define MIE_TRAIT_DEFINITION_BEGIN(c_sym, trait) \
|
||||
__MIE_TRAIT_DEFINITION_BEGIN(c_sym, trait)
|
||||
#define MIE_TRAIT_DEFINITION_END() __MIE_TRAIT_DEFINITION_END()
|
||||
/******************************************************************************/
|
||||
/* 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_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)
|
||||
@@ -169,9 +137,24 @@
|
||||
#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func)
|
||||
#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func)
|
||||
|
||||
#define MIE_ATTRIBUTE_DEFINITION_BEGIN(c_sym, attribute) \
|
||||
__MIE_ATTRIBUTE_DEFINITION_BEGIN(c_sym, attribute)
|
||||
#define MIE_ATTRIBUTE_DEFINITION_END() __MIE_ATTRIBUTE_DEFINITION_END()
|
||||
/******************************************************************************/
|
||||
/* 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_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)
|
||||
@@ -179,9 +162,87 @@
|
||||
#define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func)
|
||||
#define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func)
|
||||
|
||||
#define MIE_INTERFACE_DEFINITION_BEGIN(c_sym, iface) \
|
||||
__MIE_INTERFACE_DEFINITION_BEGIN(c_sym, iface)
|
||||
#define MIE_INTERFACE_DEFINITION_END() __MIE_INTERFACE_DEFINITION_END()
|
||||
/******************************************************************************/
|
||||
/* 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_END() \
|
||||
return i; \
|
||||
}
|
||||
|
||||
#define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name)
|
||||
|
||||
/******************************************************************************/
|
||||
/* 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_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_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)
|
||||
|
||||
/******************************************************************************/
|
||||
/* 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_END() \
|
||||
return MIE_SUCCESS; \
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
#endif
|
||||
|
||||
67
mie/include/mie/pass/pass-definition.h
Normal file
67
mie/include/mie/pass/pass-definition.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef MIE_PASS_PASS_DEFINITION_H_
|
||||
#define MIE_PASS_PASS_DEFINITION_H_
|
||||
|
||||
#include <mie/id.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MIE_PASS_CONTINUE \
|
||||
((struct mie_pass_result) {.r_type = MIE_PASS_RESULT_CONTINUE, \
|
||||
.r_status = MIE_SUCCESS})
|
||||
#define MIE_PASS_INTERRUPT(status) \
|
||||
((struct mie_pass_result) {.r_type = MIE_PASS_RESULT_INTERRUPT, \
|
||||
.r_status = (status)})
|
||||
|
||||
struct mie_op;
|
||||
struct mie_ctx;
|
||||
struct mie_pass;
|
||||
struct mie_op_definition;
|
||||
struct mie_trait_definition;
|
||||
struct mie_interface_definition;
|
||||
struct mie_attribute_map;
|
||||
|
||||
enum mie_pass_type {
|
||||
MIE_PASS_NONE = 0,
|
||||
MIE_PASS_TRANSFORM,
|
||||
MIE_PASS_ANALYSE,
|
||||
};
|
||||
|
||||
enum mie_pass_result_type {
|
||||
MIE_PASS_RESULT_CONTINUE = 0,
|
||||
MIE_PASS_RESULT_INTERRUPT,
|
||||
};
|
||||
|
||||
struct mie_pass_result {
|
||||
enum mie_pass_result_type r_type;
|
||||
enum mie_status r_status;
|
||||
};
|
||||
|
||||
struct mie_pass_args {
|
||||
struct mie_ctx *p_ctx;
|
||||
};
|
||||
|
||||
struct mie_pass_filter {
|
||||
const struct mie_op_definition *f_op;
|
||||
const struct mie_trait_definition *f_trait;
|
||||
const struct mie_interface_definition *f_iface;
|
||||
};
|
||||
|
||||
struct mie_pass_definition {
|
||||
mie_id p_id;
|
||||
const char *p_name;
|
||||
const char *p_description;
|
||||
size_t p_data_size;
|
||||
enum mie_pass_type p_type;
|
||||
|
||||
enum mie_status (*p_init)(
|
||||
struct mie_pass *, const struct mie_attribute_map *);
|
||||
struct mie_pass_result (*p_transform)(
|
||||
struct mie_pass *, struct mie_op *, struct mie_pass_args *);
|
||||
struct mie_pass_result (*p_analyse)(
|
||||
struct mie_pass *, const struct mie_op *, struct mie_pass_args *);
|
||||
|
||||
struct mie_pass_filter p_filter;
|
||||
};
|
||||
|
||||
MIE_API struct mie_pass_definition *mie_pass_definition_create(void);
|
||||
|
||||
#endif
|
||||
46
mie/include/mie/pass/pass-manager.h
Normal file
46
mie/include/mie/pass/pass-manager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef MIE_PASS_PASS_MANAGER_H_
|
||||
#define MIE_PASS_PASS_MANAGER_H_
|
||||
|
||||
#include <mie/pass/pass-definition.h>
|
||||
#include <mie/status.h>
|
||||
#include <mie/vector.h>
|
||||
|
||||
struct mie_pass;
|
||||
|
||||
struct mie_op;
|
||||
struct mie_op_pass;
|
||||
|
||||
enum mie_pass_manager_flags {
|
||||
MIE_PASSMGR_F_NONE = 0x00u,
|
||||
};
|
||||
|
||||
struct mie_pass_manager {
|
||||
enum mie_pass_manager_flags pm_flags;
|
||||
struct mie_ctx *pm_ctx;
|
||||
size_t pm_depth;
|
||||
|
||||
MIE_VECTOR_DECLARE(struct mie_pass *, pm_passes);
|
||||
MIE_VECTOR_DECLARE(struct mie_pass_manager *, pm_nested);
|
||||
|
||||
struct mie_pass_filter pm_filter;
|
||||
};
|
||||
|
||||
MIE_API struct mie_pass_manager *mie_pass_manager_create(struct mie_ctx *ctx);
|
||||
MIE_API void mie_pass_manager_destroy(struct mie_pass_manager *pm);
|
||||
|
||||
MIE_API struct mie_pass_manager *mie_pass_manager_nest(struct mie_pass_manager *pm);
|
||||
MIE_API enum mie_status mie_pass_manager_filter_op(
|
||||
struct mie_pass_manager *pm, const char *dialect_name, const char *op_name);
|
||||
MIE_API enum mie_status mie_pass_manager_filter_trait(
|
||||
struct mie_pass_manager *pm, const char *dialect_name,
|
||||
const char *trait_name);
|
||||
MIE_API enum mie_status mie_pass_manager_filter_interface(
|
||||
struct mie_pass_manager *pm, const char *dialect_name,
|
||||
const char *iface_name);
|
||||
|
||||
MIE_API void mie_pass_manager_add_pass(
|
||||
struct mie_pass_manager *pm, struct mie_pass *pass);
|
||||
MIE_API struct mie_pass_result mie_pass_manager_run(
|
||||
struct mie_pass_manager *pm, struct mie_op *target);
|
||||
|
||||
#endif
|
||||
14
mie/include/mie/pass/pass.h
Normal file
14
mie/include/mie/pass/pass.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef MIE_PASS_PASS_H_
|
||||
#define MIE_PASS_PASS_H_
|
||||
|
||||
#include <mie/pass/pass-definition.h>
|
||||
|
||||
struct mie_pass {
|
||||
const struct mie_pass_definition *p_def;
|
||||
};
|
||||
|
||||
MIE_API const char *mie_pass_get_name(const struct mie_pass *pass);
|
||||
MIE_API struct mie_pass_result mie_pass_execute(
|
||||
struct mie_pass *pass, struct mie_op *op, struct mie_pass_args *args);
|
||||
|
||||
#endif
|
||||
16
mie/pass/pass-definition.c
Normal file
16
mie/pass/pass-definition.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <mie/pass/pass-definition.h>
|
||||
#include <mie/pass/pass.h>
|
||||
|
||||
struct mie_pass_definition *mie_pass_definition_create(void)
|
||||
{
|
||||
struct mie_pass_definition *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
out->p_data_size = sizeof(struct mie_pass);
|
||||
|
||||
return out;
|
||||
}
|
||||
271
mie/pass/pass-manager.c
Normal file
271
mie/pass/pass-manager.c
Normal file
@@ -0,0 +1,271 @@
|
||||
#include <blue/core/queue.h>
|
||||
#include <mie/ctx.h>
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/interface/interface-definition.h>
|
||||
#include <mie/ir/block.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/ir/region.h>
|
||||
#include <mie/ir/walk.h>
|
||||
#include <mie/pass/pass-definition.h>
|
||||
#include <mie/pass/pass-manager.h>
|
||||
#include <mie/pass/pass.h>
|
||||
#include <mie/trait/trait-definition.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct pass_sched {
|
||||
struct mie_op *s_op;
|
||||
b_queue_entry s_entry;
|
||||
/* queue of struct pass_sched_item */
|
||||
b_queue s_items;
|
||||
};
|
||||
|
||||
struct pass_sched_item {
|
||||
b_queue_entry i_entry;
|
||||
struct mie_pass *i_pass;
|
||||
};
|
||||
|
||||
static struct pass_sched *pass_sched_create(struct mie_op *op)
|
||||
{
|
||||
struct pass_sched *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
out->s_op = op;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static struct pass_sched_item *pass_sched_item_create(struct mie_pass *pass)
|
||||
{
|
||||
struct pass_sched_item *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
out->i_pass = pass;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
struct mie_pass_manager *mie_pass_manager_create(struct mie_ctx *ctx)
|
||||
{
|
||||
struct mie_pass_manager *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
out->pm_ctx = ctx;
|
||||
return out;
|
||||
}
|
||||
|
||||
void mie_pass_manager_destroy(struct mie_pass_manager *pm)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
struct mie_pass_manager *mie_pass_manager_nest(struct mie_pass_manager *pm)
|
||||
{
|
||||
struct mie_pass_manager *nest = mie_pass_manager_create(pm->pm_ctx);
|
||||
nest->pm_depth = pm->pm_depth + 1;
|
||||
|
||||
mie_vector_push_back(pm->pm_nested, &nest);
|
||||
|
||||
return nest;
|
||||
}
|
||||
|
||||
enum mie_status mie_pass_manager_filter_op(
|
||||
struct mie_pass_manager *pm, const char *dialect_name, const char *op_name)
|
||||
{
|
||||
if (!dialect_name && !op_name) {
|
||||
pm->pm_filter.f_op = NULL;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!dialect_name || !op_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;
|
||||
}
|
||||
|
||||
pm->pm_filter.f_op = op;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
enum mie_status mie_pass_manager_filter_trait(
|
||||
struct mie_pass_manager *pm, const char *dialect_name, const char *trait_name)
|
||||
{
|
||||
if (!dialect_name && !trait_name) {
|
||||
pm->pm_filter.f_trait = NULL;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!dialect_name || !trait_name) {
|
||||
return MIE_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const struct mie_trait_definition *trait = mie_ctx_get_trait_definition(
|
||||
pm->pm_ctx, dialect_name, trait_name);
|
||||
if (!trait) {
|
||||
return MIE_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
pm->pm_filter.f_trait = trait;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
enum mie_status mie_pass_manager_filter_interface(
|
||||
struct mie_pass_manager *pm, const char *dialect_name, const char *iface_name)
|
||||
{
|
||||
if (!dialect_name && !iface_name) {
|
||||
pm->pm_filter.f_iface = NULL;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!dialect_name || !iface_name) {
|
||||
return MIE_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const struct mie_interface_definition *interface = mie_ctx_get_interface_definition(
|
||||
pm->pm_ctx, dialect_name, iface_name);
|
||||
if (!interface) {
|
||||
return MIE_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
pm->pm_filter.f_iface = interface;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool filter_check_op(
|
||||
const struct mie_pass_filter *filter, const struct mie_op *op)
|
||||
{
|
||||
if (filter->f_op && op->op_info != filter->f_op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter->f_trait
|
||||
&& !mie_op_has_trait(
|
||||
op, filter->f_trait->tr_parent->d_name,
|
||||
filter->f_trait->tr_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter->f_iface
|
||||
&& !mie_op_has_interface(
|
||||
op, filter->f_iface->if_parent->d_name,
|
||||
filter->f_iface->if_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mie_pass_manager_add_pass(struct mie_pass_manager *pm, struct mie_pass *pass)
|
||||
{
|
||||
mie_vector_push_back(pm->pm_passes, &pass);
|
||||
}
|
||||
|
||||
static void schedule_passes(
|
||||
struct mie_pass_manager *pm, b_queue *schedule, struct mie_op *op,
|
||||
size_t depth)
|
||||
{
|
||||
b_queue passes = B_QUEUE_INIT;
|
||||
if (!filter_check_op(&pm->pm_filter, op) || depth > pm->pm_depth) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < MIE_VECTOR_COUNT(pm->pm_passes); i++) {
|
||||
struct mie_pass *pass = pm->pm_passes.items[i];
|
||||
if (!filter_check_op(&pass->p_def->p_filter, op)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct pass_sched_item *item = pass_sched_item_create(pass);
|
||||
b_queue_push_back(&passes, &item->i_entry);
|
||||
}
|
||||
|
||||
if (!b_queue_empty(&passes)) {
|
||||
struct pass_sched *sched = pass_sched_create(op);
|
||||
sched->s_items = 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) {
|
||||
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);
|
||||
schedule_passes(nested, schedule, item->i_op, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
mie_walker_end(walker);
|
||||
}
|
||||
|
||||
static void sched_item_execute(
|
||||
struct pass_sched_item *sched_item, struct mie_op *op,
|
||||
struct mie_pass_args *args, struct mie_pass_result *result)
|
||||
{
|
||||
if (result->r_type != MIE_PASS_RESULT_CONTINUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
*result = mie_pass_execute(sched_item->i_pass, op, args);
|
||||
}
|
||||
|
||||
static void sched_execute(
|
||||
struct pass_sched *sched, struct mie_pass_args *args,
|
||||
struct mie_pass_result *result)
|
||||
{
|
||||
b_queue_entry *cur_item = NULL, *next_item = NULL;
|
||||
struct pass_sched_item *sched_item = NULL;
|
||||
|
||||
cur_item = b_queue_first(&sched->s_items);
|
||||
while (cur_item) {
|
||||
sched_item = b_unbox(struct pass_sched_item, cur_item, i_entry);
|
||||
next_item = b_queue_next(cur_item);
|
||||
b_queue_delete(&sched->s_items, cur_item);
|
||||
|
||||
sched_item_execute(sched_item, sched->s_op, args, result);
|
||||
|
||||
free(sched_item);
|
||||
cur_item = next_item;
|
||||
}
|
||||
}
|
||||
|
||||
struct mie_pass_result mie_pass_manager_run(
|
||||
struct mie_pass_manager *pm, struct mie_op *target)
|
||||
{
|
||||
b_queue schedule = B_QUEUE_INIT;
|
||||
schedule_passes(pm, &schedule, target, 0);
|
||||
|
||||
b_queue_entry *cur_sched = b_queue_first(&schedule), *next_sched = NULL;
|
||||
struct pass_sched *sched = NULL;
|
||||
struct mie_pass_result result = MIE_PASS_CONTINUE;
|
||||
|
||||
struct mie_pass_args args = {
|
||||
.p_ctx = pm->pm_ctx,
|
||||
};
|
||||
|
||||
while (cur_sched) {
|
||||
sched = b_unbox(struct pass_sched, cur_sched, s_entry);
|
||||
next_sched = b_queue_next(cur_sched);
|
||||
b_queue_delete(&schedule, cur_sched);
|
||||
|
||||
sched_execute(sched, &args, &result);
|
||||
|
||||
free(sched);
|
||||
cur_sched = next_sched;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
29
mie/pass/pass.c
Normal file
29
mie/pass/pass.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <mie/pass/pass.h>
|
||||
|
||||
const char *mie_pass_get_name(const struct mie_pass *pass)
|
||||
{
|
||||
return pass->p_def ? pass->p_def->p_name : NULL;
|
||||
}
|
||||
|
||||
struct mie_pass_result mie_pass_execute(
|
||||
struct mie_pass *pass, struct mie_op *op, struct mie_pass_args *args)
|
||||
{
|
||||
struct mie_pass_result result = MIE_PASS_INTERRUPT(MIE_ERR_BAD_STATE);
|
||||
|
||||
if (!pass->p_def) {
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (pass->p_def->p_type) {
|
||||
case MIE_PASS_TRANSFORM:
|
||||
result = pass->p_def->p_transform(pass, op, args);
|
||||
break;
|
||||
case MIE_PASS_ANALYSE:
|
||||
result = pass->p_def->p_analyse(pass, op, args);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user