mie: implement ir generation for message sending
This commit is contained in:
109
mie/builder.c
109
mie/builder.c
@@ -1,3 +1,4 @@
|
||||
#include <blue/object/hashmap.h>
|
||||
#include <blue/object/string.h>
|
||||
#include <mie/alloca.h>
|
||||
#include <mie/block.h>
|
||||
@@ -6,6 +7,7 @@
|
||||
#include <mie/data.h>
|
||||
#include <mie/func.h>
|
||||
#include <mie/module.h>
|
||||
#include <mie/msg.h>
|
||||
#include <mie/op.h>
|
||||
#include <mie/ptr.h>
|
||||
#include <mie/record.h>
|
||||
@@ -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)
|
||||
{
|
||||
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(
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
#include <mie/block.h>
|
||||
#include <mie/branch.h>
|
||||
#include <mie/const.h>
|
||||
#include <mie/data.h>
|
||||
#include <mie/func.h>
|
||||
#include <mie/instr.h>
|
||||
#include <mie/module.h>
|
||||
#include <mie/msg.h>
|
||||
#include <mie/op.h>
|
||||
#include <mie/ptr.h>
|
||||
#include <mie/type.h>
|
||||
@@ -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, "<unknown-type>");
|
||||
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, "<unknown>");
|
||||
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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <mie/type.h>
|
||||
#include <mie/value.h>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
#include <mie/instr.h>
|
||||
#include <mie/type.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <mie/instr.h>
|
||||
#include <mie/msg.h>
|
||||
#include <mie/op.h>
|
||||
#include <mie/ptr.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
22
mie/module.c
22
mie/module.c
@@ -1,3 +1,4 @@
|
||||
#include <mie/data.h>
|
||||
#include <mie/func.h>
|
||||
#include <mie/module.h>
|
||||
#include <stdlib.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user