From 8388dfeb79dd8dc4345b995830940362fa0d031e Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 17 Apr 2025 21:43:02 +0100 Subject: [PATCH] mie: implement ir generation for message sending --- mie/builder.c | 111 ++++++++++++++++++++++++++++++++++++-- mie/convert/text-write.c | 95 ++++++++++++++++++++++++++++++-- mie/include/mie/builder.h | 17 ++++-- mie/include/mie/module.h | 4 ++ mie/include/mie/msg.h | 5 +- mie/include/mie/value.h | 1 + mie/instr.c | 5 ++ mie/module.c | 22 ++++++++ mie/value.c | 2 + 9 files changed, 252 insertions(+), 10 deletions(-) diff --git a/mie/builder.c b/mie/builder.c index f584c64..a2b1f8d 100644 --- a/mie/builder.c +++ b/mie/builder.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +52,8 @@ struct mie_ctx *mie_ctx_create(void) out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1)); out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1)); + out->ctx_sel_cache = b_hashmap_create(free, free); + return out; } @@ -85,6 +89,8 @@ void mie_ctx_destroy(struct mie_ctx *ctx) } } + b_hashmap_release(ctx->ctx_sel_cache); + free(ctx); } @@ -184,6 +190,41 @@ struct mie_value *mie_ctx_get_int( return MIE_VALUE(&value->i_value); } +struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel) +{ + b_hashmap_key key = { + .key_data = sel, + .key_size = strlen(sel), + }; + + const b_hashmap_value *cache_entry + = b_hashmap_get(ctx->ctx_sel_cache, &key); + + if (cache_entry) { + return cache_entry->value_data; + } + + struct mie_const *sel_value = malloc(sizeof *sel_value); + if (!sel_value) { + return NULL; + } + + mie_value_init(&sel_value->c_base, MIE_VALUE_CONST); + sel_value->c_type = mie_ctx_get_type(ctx, MIE_TYPE_SELECTOR); + sel_value->c_v.v_selector = b_strdup(sel); + + key.key_data = sel_value->c_v.v_selector; + + b_hashmap_value hashmap_value = { + .value_data = sel_value, + .value_size = sizeof *sel_value, + }; + + b_hashmap_put(ctx->ctx_sel_cache, &key, &hashmap_value); + + return MIE_VALUE(sel_value); +} + struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_module *mod) { struct mie_builder *out = malloc(sizeof *out); @@ -279,6 +320,29 @@ void mie_builder_set_insert_point( builder->b_current_block = block; } +struct mie_value *mie_builder_get_data_ptr( + struct mie_builder *builder, const char *data_ident) +{ + if (!builder->b_module) { + return NULL; + } + + struct mie_data *data = mie_module_get_data(builder->b_module, data_ident); + if (!data) { + struct mie_type *id + = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_ID); + data = mie_data_create_extern_global(id, data_ident); + + if (!data) { + return NULL; + } + + mie_module_put_data(builder->b_module, data); + } + + return MIE_VALUE(data); +} + struct mie_value *mie_builder_ret(struct mie_builder *builder, struct mie_value *val) { if (!builder->b_current_block) { @@ -584,10 +648,51 @@ struct mie_value *mie_builder_br_if( } struct mie_value *mie_builder_msg( - struct mie_builder *builder, struct mie_value *ret_type, - struct mie_value *dest, struct mie_value *src, const char *name) + struct mie_builder *builder, struct mie_type *ret_type, + struct mie_value *recipient, struct mie_value *selector, + struct mie_value **args, size_t nr_args, enum mie_builder_flags flags, + const char *name) { - return NULL; + if (!builder->b_current_block) { + return NULL; + } + + if (builder->b_current_block->b_terminator) { + return NULL; + } + + if ((flags & MIE_BUILDER_IGNORE_RESULT) && name) { + return NULL; + } + + struct mie_msg *msg = malloc(sizeof *msg); + if (!msg) { + return NULL; + } + + memset(msg, 0x0, sizeof *msg); + + mie_instr_init(&msg->msg_base, MIE_INSTR_MSG); + + msg->msg_ret_type = ret_type; + msg->msg_recipient = recipient; + msg->msg_selector = selector; + + msg->msg_nr_args = nr_args; + msg->msg_args = calloc(nr_args, sizeof(struct mie_value *)); + memcpy(msg->msg_args, args, nr_args * sizeof(struct mie_value *)); + + if (!mie_block_add_instr(builder->b_current_block, &msg->msg_base)) { + free(msg); + return NULL; + } + + if (!(flags & MIE_BUILDER_IGNORE_RESULT)) { + mie_func_generate_value_name( + builder->b_current_block->b_parent, MIE_VALUE(msg), name); + } + + return MIE_VALUE(msg); } struct mie_value *mie_builder_cmp_eq( diff --git a/mie/convert/text-write.c b/mie/convert/text-write.c index 69cbe46..0bdf08e 100644 --- a/mie/convert/text-write.c +++ b/mie/convert/text-write.c @@ -6,9 +6,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -43,6 +45,9 @@ static void mie_type_to_string(struct mie_type *type, char *out, size_t max) case MIE_TYPE_LABEL: snprintf(out, max, "label"); break; + case MIE_TYPE_SELECTOR: + snprintf(out, max, ""); + break; default: snprintf(out, max, ""); break; @@ -131,7 +136,11 @@ static b_status write_operand_const( if (flags & F_INCLUDE_TYPE) { char type_name[64]; mie_type_to_string(c->c_type, type_name, sizeof type_name); - write_string_f(converter, "%s ", type_name); + write_string_f(converter, "%s", type_name); + + if (type_name[0] != 0) { + write_char(converter, ' '); + } } switch (c->c_type->t_id) { @@ -149,6 +158,9 @@ static b_status write_operand_const( case MIE_TYPE_CLASS: write_string_f(converter, "@%s", value->v_name.n_str); break; + case MIE_TYPE_SELECTOR: + write_string_f(converter, "@%s", c->c_v.v_selector); + break; default: break; } @@ -188,6 +200,20 @@ static b_status write_operand_block( return B_SUCCESS; } +static b_status write_operand_data( + struct mie_ir_converter *converter, struct mie_value *value, int flags) +{ + struct mie_const *c = MIE_CONST(value); + + if (flags & F_INCLUDE_TYPE) { + write_string(converter, "ptr "); + } + + write_string_f(converter, "@%s", value->v_name.n_str); + + return B_SUCCESS; +} + static b_status write_operand( struct mie_ir_converter *converter, struct mie_value *value, int flags) { @@ -198,6 +224,8 @@ static b_status write_operand( return write_operand_instr(converter, value, flags); case MIE_VALUE_BLOCK: return write_operand_block(converter, value, flags); + case MIE_VALUE_DATA: + return write_operand_data(converter, value, flags); default: return B_SUCCESS; } @@ -220,6 +248,10 @@ static b_status write_module( } } + if (!b_queue_empty(&mod->m_records)) { + write_char(converter, '\n'); + } + b_queue_foreach (&it, &mod->m_types) { struct mie_value *type = b_unbox(struct mie_value, it.entry, v_entry); @@ -230,6 +262,10 @@ static b_status write_module( } } + if (!b_queue_empty(&mod->m_types)) { + write_char(converter, '\n'); + } + b_queue_foreach (&it, &mod->m_data) { struct mie_value *data = b_unbox(struct mie_value, it.entry, v_entry); @@ -240,6 +276,10 @@ static b_status write_module( } } + if (!b_queue_empty(&mod->m_data)) { + write_char(converter, '\n'); + } + b_queue_foreach (&it, &mod->m_func) { struct mie_value *func = b_unbox(struct mie_value, it.entry, v_entry); @@ -439,9 +479,30 @@ static b_status write_instr( write_operand(converter, MIE_VALUE(br->b_dest), F_INCLUDE_TYPE); break; } - case MIE_INSTR_MSG: - write_string(converter, "msg"); + case MIE_INSTR_MSG: { + struct mie_msg *msg = (struct mie_msg *)instr; + mie_type_to_string(msg->msg_ret_type, type, sizeof type); + write_string_f(converter, "msg %s, ", type); + write_operand(converter, msg->msg_recipient, F_INCLUDE_TYPE); + write_string(converter, ", "); + write_operand(converter, msg->msg_selector, F_INCLUDE_TYPE); + + if (msg->msg_nr_args == 0) { + break; + } + + write_string(converter, " ["); + for (size_t i = 0; i < msg->msg_nr_args; i++) { + if (i > 0) { + write_string(converter, ", "); + } + + write_operand(converter, msg->msg_args[i], F_INCLUDE_TYPE); + } + write_string(converter, "]"); + break; + } case MIE_INSTR_CMP_EQ: write_string(converter, "cmp eq"); break; @@ -475,6 +536,33 @@ static b_status write_instr( return B_SUCCESS; } +static b_status write_data( + struct mie_ir_converter *converter, struct mie_value *value) +{ + char type_name[128]; + + struct mie_data *data = MIE_DATA(value); + write_string_f(converter, "data @%s = ", value->v_name.n_str); + + switch (data->d_type) { + case MIE_DATA_EXTERN_GLOBAL: + mie_type_to_string( + data->d_extern_global.g_type, type_name, sizeof type_name); + write_string_f(converter, "extern global %s", type_name); + break; + case MIE_DATA_CONST: + write_operand_const( + converter, data->d_const.c_value, F_INCLUDE_TYPE); + break; + default: + write_string(converter, ""); + break; + } + + write_char(converter, '\n'); + return B_SUCCESS; +} + static const write_function value_writers[] = { [MIE_VALUE_MODULE] = write_module, [MIE_VALUE_TYPE] = write_type_definition, @@ -483,6 +571,7 @@ static const write_function value_writers[] = { [MIE_VALUE_ARG] = NULL, [MIE_VALUE_BLOCK] = write_block_definition, [MIE_VALUE_INSTR] = write_instr, + [MIE_VALUE_DATA] = write_data, [MIE_VALUE_CONST] = NULL, }; static const size_t nr_value_printers diff --git a/mie/include/mie/builder.h b/mie/include/mie/builder.h index b60add2..74f77fa 100644 --- a/mie/include/mie/builder.h +++ b/mie/include/mie/builder.h @@ -7,7 +7,7 @@ #include #include -struct b_dict; +struct b_hashmap; struct mie_block; struct mie_module; @@ -19,6 +19,7 @@ struct mie_ctx { struct mie_const *ctx_true, *ctx_false; struct mie_type *ctx_types[__MIE_TYPE_COUNT]; b_btree ctx_int_cache; + struct b_hashmap *ctx_sel_cache; }; struct mie_builder { @@ -28,6 +29,10 @@ struct mie_builder { struct mie_instr *b_prev_instr; }; +enum mie_builder_flags { + MIE_BUILDER_IGNORE_RESULT = 0x01u, +}; + extern struct mie_ctx *mie_ctx_create(void); extern void mie_ctx_destroy(struct mie_ctx *ctx); @@ -38,6 +43,7 @@ extern struct mie_type *mie_ctx_get_int_type( extern struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val); extern struct mie_value *mie_ctx_get_int( struct mie_ctx *ctx, long long val, unsigned int nr_bits); +extern struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel); extern struct mie_builder *mie_builder_create( struct mie_ctx *ctx, struct mie_module *mod); @@ -57,6 +63,9 @@ extern void mie_builder_put_type(struct mie_builder *builder, struct mie_type *t extern void mie_builder_set_insert_point( struct mie_builder *builder, struct mie_block *block); +extern struct mie_value *mie_builder_get_data_ptr( + struct mie_builder *builder, const char *data_ident); + extern struct mie_value *mie_builder_ret( struct mie_builder *builder, struct mie_value *val); extern struct mie_value *mie_builder_add( @@ -88,8 +97,10 @@ extern struct mie_value *mie_builder_br_if( struct mie_builder *builder, struct mie_value *cond, struct mie_block *if_true, struct mie_block *if_false); extern struct mie_value *mie_builder_msg( - struct mie_builder *builder, struct mie_value *ret_type, - struct mie_value *dest, struct mie_value *src, const char *name); + struct mie_builder *builder, struct mie_type *ret_type, + struct mie_value *recipient, struct mie_value *selector, + struct mie_value **args, size_t nr_args, enum mie_builder_flags flags, + const char *name); extern struct mie_value *mie_builder_cmp_eq( struct mie_builder *builder, struct mie_value *left, struct mie_value *right, const char *name); diff --git a/mie/include/mie/module.h b/mie/include/mie/module.h index 041e3b8..50fd6b2 100644 --- a/mie/include/mie/module.h +++ b/mie/include/mie/module.h @@ -18,5 +18,9 @@ struct mie_module { extern struct mie_module *mie_module_create(void); extern void mie_module_add_function(struct mie_module *mod, struct mie_func *func); +extern struct mie_data *mie_module_get_data( + struct mie_module *mod, const char *name); +extern enum b_status mie_module_put_data( + struct mie_module *mod, struct mie_data *data); #endif diff --git a/mie/include/mie/msg.h b/mie/include/mie/msg.h index 7401bfc..ef08194 100644 --- a/mie/include/mie/msg.h +++ b/mie/include/mie/msg.h @@ -4,12 +4,15 @@ #include #include +#define MIE_MSG(p) ((struct mie_msg *)(p)) + struct mie_msg { struct mie_instr msg_base; struct mie_type *msg_ret_type; struct mie_value *msg_recipient; struct mie_value *msg_selector; - b_queue msg_args; + size_t msg_nr_args; + struct mie_value **msg_args; }; #endif diff --git a/mie/include/mie/value.h b/mie/include/mie/value.h index 1d931ef..f2f99c0 100644 --- a/mie/include/mie/value.h +++ b/mie/include/mie/value.h @@ -19,6 +19,7 @@ enum mie_value_type_id { MIE_VALUE_BLOCK, MIE_VALUE_INSTR, MIE_VALUE_CONST, + MIE_VALUE_DATA, }; enum mie_value_flags { diff --git a/mie/instr.c b/mie/instr.c index 8bfd49e..8871121 100644 --- a/mie/instr.c +++ b/mie/instr.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -44,6 +45,10 @@ static struct mie_type *get_type(struct mie_value *v) } case MIE_INSTR_ALLOCA: return &ptr_type; + case MIE_INSTR_MSG: { + struct mie_msg *msg = (struct mie_msg *)instr; + return msg->msg_ret_type; + } default: return NULL; } diff --git a/mie/module.c b/mie/module.c index d91706b..65a4131 100644 --- a/mie/module.c +++ b/mie/module.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -22,6 +23,27 @@ void mie_module_add_function(struct mie_module *mod, struct mie_func *func) b_queue_push_back(&mod->m_func, &func->f_base.v_entry); } +struct mie_data *mie_module_get_data(struct mie_module *mod, const char *name) +{ + b_queue_iterator it; + b_queue_foreach (&it, &mod->m_data) { + struct mie_data *data = (struct mie_data *)b_unbox( + struct mie_value, it.entry, v_entry); + if (!strcmp(data->d_base.v_name.n_str, name)) { + return data; + } + } + + return NULL; +} + +enum b_status mie_module_put_data(struct mie_module *mod, struct mie_data *data) +{ + /* TODO enforce unique names */ + b_queue_push_back(&mod->m_data, &data->d_base.v_entry); + return B_SUCCESS; +} + static void cleanup(struct mie_value *value) { struct mie_module *module = MIE_MODULE(value); diff --git a/mie/value.c b/mie/value.c index bf6efa4..9851393 100644 --- a/mie/value.c +++ b/mie/value.c @@ -10,6 +10,7 @@ extern const struct mie_value_type arg_value_type; extern const struct mie_value_type block_value_type; extern const struct mie_value_type instr_value_type; extern const struct mie_value_type const_value_type; +extern const struct mie_value_type data_value_type; static const struct mie_value_type *value_types[] = { [MIE_VALUE_NONE] = NULL, @@ -21,6 +22,7 @@ static const struct mie_value_type *value_types[] = { [MIE_VALUE_BLOCK] = &block_value_type, [MIE_VALUE_INSTR] = &instr_value_type, [MIE_VALUE_CONST] = &const_value_type, + [MIE_VALUE_DATA] = &data_value_type, }; static const size_t nr_value_types = sizeof value_types / sizeof value_types[0];