mie: ir: implement deferred resolution of op arguments

This commit is contained in:
2026-01-08 19:21:50 +00:00
parent c686c31ca0
commit 27e42340de
9 changed files with 182 additions and 36 deletions

View File

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

View File

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

View File

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

View File

@@ -5,16 +5,98 @@
#include <blue/core/stream.h>
#include <mie/id.h>
#include <mie/status.h>
#include <mie/trait/trait-table.h>
#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 *);
};

View File

@@ -5,19 +5,28 @@
#include <blue/core/stream.h>
#include <mie/id.h>
#include <mie/status.h>
#include <mie/trait/trait-table.h>
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 <angle brackets>. */
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;

View File

@@ -3,21 +3,23 @@
#include "mie/vector.h"
#include <mie/ir/register.h>
#include <mie/misc.h>
#include <mie/name.h>
#include <mie/parse/file-span.h>
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);
};

View File

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

View File

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

View File

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