diff --git a/mie/ctx.c b/mie/ctx.c index df6a5e7..ec7fc1d 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -9,7 +9,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -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; +} diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index 6474989..0a3ecdc 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -6,10 +6,12 @@ #include 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 diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index b1df773..166c013 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -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 diff --git a/mie/include/mie/pass/pass-definition.h b/mie/include/mie/pass/pass-definition.h new file mode 100644 index 0000000..f458b45 --- /dev/null +++ b/mie/include/mie/pass/pass-definition.h @@ -0,0 +1,67 @@ +#ifndef MIE_PASS_PASS_DEFINITION_H_ +#define MIE_PASS_PASS_DEFINITION_H_ + +#include +#include + +#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 diff --git a/mie/include/mie/pass/pass-manager.h b/mie/include/mie/pass/pass-manager.h new file mode 100644 index 0000000..2f2ae37 --- /dev/null +++ b/mie/include/mie/pass/pass-manager.h @@ -0,0 +1,46 @@ +#ifndef MIE_PASS_PASS_MANAGER_H_ +#define MIE_PASS_PASS_MANAGER_H_ + +#include +#include +#include + +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 diff --git a/mie/include/mie/pass/pass.h b/mie/include/mie/pass/pass.h new file mode 100644 index 0000000..c358a45 --- /dev/null +++ b/mie/include/mie/pass/pass.h @@ -0,0 +1,14 @@ +#ifndef MIE_PASS_PASS_H_ +#define MIE_PASS_PASS_H_ + +#include + +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 diff --git a/mie/pass/pass-definition.c b/mie/pass/pass-definition.c new file mode 100644 index 0000000..5065597 --- /dev/null +++ b/mie/pass/pass-definition.c @@ -0,0 +1,16 @@ +#include +#include + +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; +} diff --git a/mie/pass/pass-manager.c b/mie/pass/pass-manager.c new file mode 100644 index 0000000..fc11c00 --- /dev/null +++ b/mie/pass/pass-manager.c @@ -0,0 +1,271 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/mie/pass/pass.c b/mie/pass/pass.c new file mode 100644 index 0000000..155df32 --- /dev/null +++ b/mie/pass/pass.c @@ -0,0 +1,29 @@ +#include + +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; +}