From 27e42340deb950073cdf78cacb5ea5228969b56d Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 8 Jan 2026 19:21:50 +0000 Subject: [PATCH] mie: ir: implement deferred resolution of op arguments --- mie/ctx.c | 9 ++-- mie/include/mie/ctx.h | 6 +++ mie/include/mie/dialect/dialect.h | 7 +++ mie/include/mie/dialect/op.h | 82 +++++++++++++++++++++++++++++++ mie/include/mie/dialect/type.h | 15 ++++-- mie/include/mie/ir/op.h | 21 ++++++-- mie/include/mie/ir/register.h | 21 ++++++-- mie/include/mie/macros.h | 51 +++++++++++-------- mie/include/mie/misc.h | 6 ++- 9 files changed, 182 insertions(+), 36 deletions(-) diff --git a/mie/ctx.c b/mie/ctx.c index 1175e0d..abd744a 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -327,7 +327,10 @@ struct mie_ctx *mie_ctx_create(void) bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op) { - if (op->op_flags & MIE_OP_F_RESOLVED) { + bool fully_resolved = MIE_TEST_FLAGS( + op->op_flags, MIE_OP_F_OP_RESOLVED | MIE_OP_F_ARGS_RESOLVED); + + if (fully_resolved) { return true; } @@ -367,7 +370,7 @@ bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op) free(op->op_name); op->op_name = NULL; - op->op_flags |= MIE_OP_F_RESOLVED; + op->op_flags |= MIE_OP_F_OP_RESOLVED; return true; } @@ -421,7 +424,7 @@ struct mie_type *mie_ctx_get_type( struct mie_dialect_type *type_info = mie_ctx_get_dialect_type(ctx, dialect_name, type_name); - if (!type_info || (type_info->ty_flags & MIE_DIALECT_TYPE_PARAMETISED)) { + if (!type_info /* || (type_info->ty_flags & MIE_DIALECT_TYPE_PARAMETISED) */) { /* cannot initialise unknown or parametised types */ return NULL; } diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index 4052731..ea5edea 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -19,8 +19,12 @@ struct mie_ctx { b_hashmap *ctx_sel_cache; b_hashmap *ctx_string_cache; #endif + /* map of struct mie_dialect */ struct mie_id_map ctx_dialects; + /* map of struct mie_type */ struct mie_id_map ctx_types; + /* map of struct mie_trait */ + struct mie_id_map ctx_traits; struct mie_int_cache *ctx_ints; struct mie_index_cache *ctx_indices; @@ -38,6 +42,8 @@ MIE_API struct mie_dialect_type *mie_ctx_get_dialect_type( const struct mie_ctx *ctx, const char *dialect_name, const char *type_name); MIE_API struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name); +MIE_API struct mie_type *mie_ctx_get_trait( + struct mie_ctx *ctx, const char *dialect_name, const char *trait_name); MIE_API struct mie_type *mie_ctx_get_storage_type( struct mie_ctx *ctx, const struct mie_type **parts, size_t nr_parts); MIE_API struct mie_type *mie_ctx_get_function_type( diff --git a/mie/include/mie/dialect/dialect.h b/mie/include/mie/dialect/dialect.h index 147dfac..443f192 100644 --- a/mie/include/mie/dialect/dialect.h +++ b/mie/include/mie/dialect/dialect.h @@ -11,13 +11,18 @@ struct mie_ctx; struct mie_dialect_op; struct mie_dialect_type; +struct mie_trait_definition; struct mie_dialect { mie_id d_id; char *d_name; + /* map of struct mie_dialect_op */ struct mie_id_map d_ops; + /* map of struct mie_dialect_type */ struct mie_id_map d_types; + /* map of struct mie_trait_definition */ + struct mie_id_map d_traits; }; MIE_API struct mie_dialect *mie_dialect_create( @@ -27,5 +32,7 @@ MIE_API const struct mie_dialect_op *mie_dialect_get_op( const struct mie_dialect *dialect, const char *name); MIE_API const struct mie_dialect_type *mie_dialect_get_type( const struct mie_dialect *dialect, const char *name); +MIE_API const struct mie_trait_definition *mie_dialect_get_trait( + const struct mie_dialect *dialect, const char *name); #endif diff --git a/mie/include/mie/dialect/op.h b/mie/include/mie/dialect/op.h index ccc02f5..034385f 100644 --- a/mie/include/mie/dialect/op.h +++ b/mie/include/mie/dialect/op.h @@ -5,16 +5,98 @@ #include #include #include +#include + +#define MIE_OP_MAX_PARAMS 8 +#define MIE_OP_MAX_RESULTS 8 struct mie_op; struct mie_parser; struct mie_dialect; +enum mie_op_trait { + MIE_OP_TRAIT_NONE = 0x00u, + + /* this is a graph op. references to it by name must be prefixed with + + * and the op can only be used within graph regions. + * a graph op can have the same name as a regular or non-graph op. */ + MIE_OP_TRAIT_GRAPH_ONLY = 0x01u, + + /* this is a non-graph op. this op cannot be used within graph regions */ + MIE_OP_TRAIT_NO_GRAPH = 0x02u, + + /* regions of an op that has this trait are graph regions. graph regions + * cannot have more than one block, and the entry block must be unnamed + * with no parameters. However, graph ops can be used. */ + MIE_OP_TRAIT_GRAPH_SCOPE = 0x04u, + + /* regions of an op that has this trait cannot capture or reference + * values defined in the enclosing scope. */ + MIE_OP_TRAIT_ISOLATED_FROM_ABOVE = 0x08u, +}; + +enum mie_op_param_type { + /* op has no parameter */ + MIE_OP_PARTYPE_NONE = 0, + /* op has a parameter of any type. */ + MIE_OP_PARTYPE_ANY, + /* op has a parameter of a fixed, named type. */ + MIE_OP_PARTYPE_TYPE_NAME, + /* op has a parameter whose type matches the type of an attribute value */ + MIE_OP_PARTYPE_ATTRIB_VAL, +}; + +enum mie_op_result_type { + /* op has no result */ + MIE_OP_RESTYPE_NONE = 0, + /* op has a result of any type. */ + MIE_OP_RESTYPE_ANY, + /* op has a result of a fixed, named type. */ + MIE_OP_RESTYPE_TYPE_NAME, + /* op has a result whose type matches the type of an input parameter */ + MIE_OP_RESTYPE_IN_VAL, + /* op has a result whose type matches the type of an attribute value */ + MIE_OP_RESTYPE_ATTRIB_VAL, +}; + +struct mie_op_param { + enum mie_op_param_type param_type; + + union { + struct { + const char *t_dialect; + /* this can be NULL, in which case any type from the + * dialect named in t_dialect will be accepted. */ + const char *t_name; + } param_type_name; + + const char *param_attrib; + }; +}; + +struct mie_op_result { + enum mie_op_result_type r_type; + + union { + struct { + const char *t_dialect; + const char *t_name; + } r_type_name; + + unsigned int r_in_index; + const char *r_attrib; + }; +}; + struct mie_dialect_op { mie_id op_id; struct mie_dialect *op_parent; char *op_name; + struct mie_trait_table op_traits; + const struct mie_op_param op_params[MIE_OP_MAX_PARAMS]; + const struct mie_op_result op_results[MIE_OP_MAX_RESULTS]; + enum mie_status (*op_print)(const struct mie_op *, b_stream *); enum mie_status (*op_parse)(struct mie_parser *, struct mie_op *); }; diff --git a/mie/include/mie/dialect/type.h b/mie/include/mie/dialect/type.h index 110e6c8..8a4f038 100644 --- a/mie/include/mie/dialect/type.h +++ b/mie/include/mie/dialect/type.h @@ -5,19 +5,28 @@ #include #include #include +#include struct mie_type; struct mie_value; struct mie_parser; struct mie_dialect; -enum mie_dialect_type_flags { - MIE_DIALECT_TYPE_PARAMETISED = 0x01u, +enum mie_type_trait { + /* this type is parametised. one or more arguments are required to create + * a corresponding mie_type instance. in textual IR, references to this + * type will be followed by a set of arguments surrounded + * by . */ + MIE_TYPE_TRAIT_PARAMETISED = 0x01u, + + /* this type can only be used within graph regions. unlike graph ops, + * no special prefix is required */ + MIE_TYPE_TRAIT_GRAPH_TYPE = 0x02u, }; struct mie_dialect_type { mie_id ty_id; - enum mie_dialect_type_flags ty_flags; + struct mie_trait_table ty_traits; struct mie_dialect *ty_parent; char *ty_name; diff --git a/mie/include/mie/ir/op.h b/mie/include/mie/ir/op.h index fb33239..b8e3586 100644 --- a/mie/include/mie/ir/op.h +++ b/mie/include/mie/ir/op.h @@ -3,21 +3,23 @@ #include "mie/vector.h" +#include #include #include +#include struct mie_type; struct mie_value; struct mie_block; struct mie_region; -struct mie_register; struct mie_dialect; struct mie_dialect_op; enum mie_op_flags { - MIE_OP_F_RESOLVED = 0x01u, + MIE_OP_F_OP_RESOLVED = 0x01u, + MIE_OP_F_ARGS_RESOLVED = 0x02u, }; struct mie_op_successor { @@ -30,6 +32,16 @@ struct mie_op_attribute { struct mie_value *attrib_value; }; +struct mie_op_arg { + struct mie_file_span arg_span; + union { + /* only valid if the parent op's F_ARGS_RESOLVED flag is set */ + struct mie_register *arg_value; + /* only valid if the parent op's F_ARGS_RESOLVED flag is NOT set */ + struct mie_register_ref arg_unresolved; + }; +}; + struct mie_op { enum mie_op_flags op_flags; @@ -37,13 +49,14 @@ struct mie_op { const struct mie_dialect *op_dialect; const struct mie_dialect_op *op_info; - /* this pointer is only valid if the F_RESOLVED flag is NOT set */ + 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); MIE_VECTOR_DECLARE(struct mie_op_successor, op_successors); MIE_VECTOR_DECLARE(struct mie_op_attribute, op_attrib); - MIE_VECTOR_DECLARE(struct mie_register *, op_args); + MIE_VECTOR_DECLARE(struct mie_op_arg, op_args); MIE_VECTOR_DECLARE(struct mie_register, op_result); }; diff --git a/mie/include/mie/ir/register.h b/mie/include/mie/ir/register.h index 0ff67f7..bf0176b 100644 --- a/mie/include/mie/ir/register.h +++ b/mie/include/mie/ir/register.h @@ -11,16 +11,29 @@ enum mie_register_flags { MIE_REGISTER_F_OP_PARAM = 0x02u, MIE_REGISTER_F_BLOCK_PARAM = 0x04u, + /* only ONE of these two flags can be set at a time */ MIE_REGISTER_F_VIRTUAL = 0x10u, MIE_REGISTER_F_MACHINE = 0x20u, }; +/* represents a yet-to-be-resolved reference to a mie_register */ +struct mie_register_ref { + enum mie_register_flags reg_flags; + char *reg_name; + /* what we THINK the type of the register is. + * if this is set, it gets checked during the register resolution process. */ + const struct mie_type *reg_type; +}; + struct mie_register { enum mie_register_flags reg_flags; - struct mie_name reg_name; - /* only valid if F_MACHINE is set. */ - struct mie_target_register *reg_mach; - struct mie_type *reg_value_type; + union { + /* only valid if F_VIRTUAL is set. */ + struct mie_name reg_name; + /* only valid if F_MACHINE is set. */ + struct mie_target_register *reg_mach; + }; + const struct mie_type *reg_type; /* if this is an OP_RESULT register, this points to the block within * which this register is defined. * if this is an OP_PARAM register, this pointer is NULL. diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index 48dbead..b52ad7d 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -16,7 +16,8 @@ } #define __MIE_DIALECT_OP_BEGIN(func_prefix, op_name) \ - struct mie_dialect_op *func_prefix##_op_create(struct mie_dialect *d) \ + struct mie_dialect_op *func_prefix##_op_create( \ + struct mie_dialect *d, struct mie_ctx *ctx) \ { \ struct mie_dialect_op *op = mie_dialect_op_create(d, op_name); \ if (!op) { \ @@ -27,13 +28,14 @@ return op; \ } -#define __MIE_DIALECT_TYPE_BEGIN(func_prefix, type_name) \ - struct mie_dialect_type *func_prefix##_type_create(struct mie_dialect *d) \ - { \ - struct mie_dialect_type *type \ - = mie_dialect_type_create(d, type_name); \ - if (!type) { \ - return NULL; \ +#define __MIE_DIALECT_TYPE_BEGIN(func_prefix, type_name) \ + struct mie_dialect_type *func_prefix##_type_create( \ + struct mie_dialect *d, struct mie_ctx *ctx) \ + { \ + struct mie_dialect_type *type \ + = mie_dialect_type_create(d, type_name); \ + if (!type) { \ + return NULL; \ } #define __MIE_DIALECT_TYPE_END() \ @@ -41,12 +43,13 @@ } #define __MIE_DIALECT_ADD_OP(op_id) \ - extern struct mie_dialect_op *op_id##_op_create(struct mie_dialect *); \ - op = op_id##_op_create(self) + extern struct mie_dialect_op *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_dialect_type *type_id##_type_create( \ - struct mie_dialect *); \ - type = type_id##_type_create(self) + struct mie_dialect *, struct mie_ctx *); \ + type = type_id##_type_create(self, ctx) #define MIE_DIALECT_BEGIN(c_sym, name) __MIE_DIALECT_BEGIN(c_sym, name) #define MIE_DIALECT_END() __MIE_DIALECT_END() @@ -60,13 +63,21 @@ #define MIE_DIALECT_TYPE_BEGIN(c_sym, type) \ __MIE_DIALECT_TYPE_BEGIN(c_sym, type) -#define MIE_DIALECT_TYPE_END() __MIE_DIALECT_TYPE_END() -#define MIE_DIALECT_TYPE_FLAGS(flags) type->ty_flags = flags -#define MIE_DIALECT_TYPE_STRUCT(name) type->ty_data_size = sizeof(name) -#define MIE_DIALECT_TYPE_INIT(func) type->ty_init = (func) -#define MIE_DIALECT_TYPE_PRINT(func) type->ty_print = (func) -#define MIE_DIALECT_TYPE_PARSE(func) type->ty_parse = (func) -#define MIE_DIALECT_TYPE_INIT(func) type->ty_init = (func) -#define MIE_DIALECT_TYPE_CLEANUP(func) type->ty_cleanup = (func) +#define MIE_DIALECT_TYPE_END() __MIE_DIALECT_TYPE_END() +#define MIE_DIALECT_TYPE_FLAGS(flags) type->ty_flags = flags +#define MIE_DIALECT_TYPE_STRUCT(name) type->ty_data_size = sizeof(name) +#define MIE_DIALECT_TYPE_INIT(func) type->ty_init = (func) +#define MIE_DIALECT_TYPE_PRINT(func) type->ty_print = (func) +#define MIE_DIALECT_TYPE_VALUE_PRINT(func) type->ty_value_print = (func) +#define MIE_DIALECT_TYPE_PARSE(func) type->ty_parse = (func) +#define MIE_DIALECT_TYPE_BUILD_ID(func) type->ty_build_id = (func) +#define MIE_DIALECT_TYPE_INIT(func) type->ty_init = (func) +#define MIE_DIALECT_TYPE_CLEANUP(func) type->ty_cleanup = (func) + +#define MIE_DIALECT_TRAIT_BEGIN(c_sym, trait) +#define MIE_DIALECT_TRAIT_END() +#define MIE_DIALECT_TRAIT_STRUCT(name) +#define MIE_DIALECT_TRAIT_PRINT(func) +#define MIE_DIALECT_TRAIT_CLEANUP(func) #endif diff --git a/mie/include/mie/misc.h b/mie/include/mie/misc.h index b0f9df9..7ce8de9 100644 --- a/mie/include/mie/misc.h +++ b/mie/include/mie/misc.h @@ -11,7 +11,9 @@ #define MIE_API extern #endif -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +#define MIE_TEST_FLAGS(value, flags) (((value) & (flags)) == (flags)) #endif