2025-04-17 21:43:02 +01:00
|
|
|
#include <blue/object/hashmap.h>
|
2025-04-11 13:40:54 +01:00
|
|
|
#include <blue/object/string.h>
|
2025-04-13 18:34:02 +01:00
|
|
|
#include <mie/alloca.h>
|
|
|
|
|
#include <mie/block.h>
|
|
|
|
|
#include <mie/branch.h>
|
2025-04-11 13:40:54 +01:00
|
|
|
#include <mie/builder.h>
|
|
|
|
|
#include <mie/data.h>
|
2025-04-13 18:34:02 +01:00
|
|
|
#include <mie/func.h>
|
2025-04-11 13:40:54 +01:00
|
|
|
#include <mie/module.h>
|
2025-04-17 21:43:02 +01:00
|
|
|
#include <mie/msg.h>
|
2025-04-13 18:34:02 +01:00
|
|
|
#include <mie/op.h>
|
|
|
|
|
#include <mie/ptr.h>
|
2025-04-11 13:40:54 +01:00
|
|
|
#include <mie/record.h>
|
|
|
|
|
#include <mie/type.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_cache_entry {
|
2025-04-11 13:40:54 +01:00
|
|
|
b_btree_node i_node;
|
2025-04-13 18:34:02 +01:00
|
|
|
struct mie_type i_type;
|
|
|
|
|
b_btree i_values;
|
2025-04-11 13:40:54 +01:00
|
|
|
};
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_value_cache_entry {
|
|
|
|
|
b_btree_node i_node;
|
|
|
|
|
struct mie_const i_value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
B_BTREE_DEFINE_SIMPLE_INSERT(
|
|
|
|
|
struct ctx_int_cache_entry, i_node, i_type.t_width, put_cached_int_type)
|
|
|
|
|
B_BTREE_DEFINE_SIMPLE_GET(
|
|
|
|
|
struct ctx_int_cache_entry, unsigned int, i_node, i_type.t_width,
|
|
|
|
|
get_cached_int_type)
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
B_BTREE_DEFINE_SIMPLE_INSERT(
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_value_cache_entry, i_node, i_value.c_v.v_int,
|
|
|
|
|
put_cached_int_value)
|
2025-04-11 13:40:54 +01:00
|
|
|
B_BTREE_DEFINE_SIMPLE_GET(
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_value_cache_entry, int64_t, i_node, i_value.c_v.v_int,
|
|
|
|
|
get_cached_int_value)
|
2025-04-11 13:40:54 +01:00
|
|
|
|
|
|
|
|
struct mie_ctx *mie_ctx_create(void)
|
|
|
|
|
{
|
|
|
|
|
struct mie_ctx *out = malloc(sizeof *out);
|
|
|
|
|
|
|
|
|
|
if (!out) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(out, 0x0, sizeof *out);
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1));
|
|
|
|
|
out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1));
|
2025-04-11 13:40:54 +01:00
|
|
|
|
2025-04-17 21:43:02 +01:00
|
|
|
out->ctx_sel_cache = b_hashmap_create(free, free);
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mie_ctx_destroy(struct mie_ctx *ctx)
|
|
|
|
|
{
|
2025-04-13 19:25:23 +01:00
|
|
|
ctx->ctx_true = NULL;
|
|
|
|
|
ctx->ctx_false = NULL;
|
2025-04-11 13:40:54 +01:00
|
|
|
|
|
|
|
|
b_btree_iterator it = {};
|
2025-04-13 18:34:02 +01:00
|
|
|
b_btree_iterator_begin(&ctx->ctx_int_cache, &it);
|
2025-04-11 13:40:54 +01:00
|
|
|
while (b_btree_iterator_is_valid(&it)) {
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_cache_entry *entry
|
|
|
|
|
= b_unbox(struct ctx_int_cache_entry, it.node, i_node);
|
2025-04-11 13:40:54 +01:00
|
|
|
b_btree_iterator_erase(&it);
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
b_btree_iterator it2 = {};
|
|
|
|
|
b_btree_iterator_begin(&entry->i_values, &it2);
|
|
|
|
|
while (b_btree_iterator_is_valid(&it2)) {
|
|
|
|
|
struct ctx_int_value_cache_entry *value = b_unbox(
|
|
|
|
|
struct ctx_int_value_cache_entry, it2.node, i_node);
|
|
|
|
|
b_btree_iterator_erase(&it2);
|
|
|
|
|
free(value);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
free(entry);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 19:25:23 +01:00
|
|
|
const size_t nr_types = sizeof ctx->ctx_types / sizeof ctx->ctx_types[0];
|
|
|
|
|
for (size_t i = 0; i < nr_types; i++) {
|
2025-04-14 20:13:13 +01:00
|
|
|
if (ctx->ctx_types[i]) {
|
|
|
|
|
mie_value_destroy(MIE_VALUE(ctx->ctx_types[i]));
|
|
|
|
|
ctx->ctx_types[i] = NULL;
|
|
|
|
|
}
|
2025-04-13 19:25:23 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-17 21:43:02 +01:00
|
|
|
b_hashmap_release(ctx->ctx_sel_cache);
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
free(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
struct mie_type *mie_ctx_get_type(struct mie_ctx *ctx, enum mie_type_id type_id)
|
|
|
|
|
{
|
|
|
|
|
if (type_id == MIE_TYPE_INT) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ctx->ctx_types[type_id]) {
|
|
|
|
|
return ctx->ctx_types[type_id];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_type *type = malloc(sizeof *type);
|
|
|
|
|
if (!type) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(type, 0x0, sizeof *type);
|
|
|
|
|
|
|
|
|
|
mie_value_init(&type->t_base, MIE_VALUE_TYPE);
|
|
|
|
|
type->t_id = type_id;
|
|
|
|
|
|
|
|
|
|
ctx->ctx_types[type_id] = type;
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_type *mie_ctx_get_int_type(struct mie_ctx *ctx, unsigned int nr_bits)
|
|
|
|
|
{
|
|
|
|
|
struct ctx_int_cache_entry *entry
|
|
|
|
|
= get_cached_int_type(&ctx->ctx_int_cache, nr_bits);
|
|
|
|
|
|
|
|
|
|
if (entry) {
|
|
|
|
|
return &entry->i_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entry = malloc(sizeof *entry);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(entry, 0x0, sizeof *entry);
|
|
|
|
|
|
|
|
|
|
mie_value_init(&entry->i_type.t_base, MIE_VALUE_TYPE);
|
|
|
|
|
entry->i_type.t_id = MIE_TYPE_INT;
|
|
|
|
|
entry->i_type.t_width = nr_bits;
|
|
|
|
|
|
|
|
|
|
put_cached_int_type(&ctx->ctx_int_cache, entry);
|
|
|
|
|
return &entry->i_type;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val)
|
|
|
|
|
{
|
|
|
|
|
return MIE_VALUE(val ? ctx->ctx_true : ctx->ctx_false);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
struct mie_value *mie_ctx_get_int(
|
|
|
|
|
struct mie_ctx *ctx, long long val, unsigned int nr_bits)
|
2025-04-11 13:40:54 +01:00
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
struct ctx_int_cache_entry *entry
|
|
|
|
|
= get_cached_int_type(&ctx->ctx_int_cache, nr_bits);
|
|
|
|
|
|
|
|
|
|
if (!entry) {
|
|
|
|
|
entry = malloc(sizeof *entry);
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(entry, 0x0, sizeof *entry);
|
|
|
|
|
|
|
|
|
|
mie_value_init(&entry->i_type.t_base, MIE_VALUE_TYPE);
|
|
|
|
|
entry->i_type.t_id = MIE_TYPE_INT;
|
|
|
|
|
entry->i_type.t_width = nr_bits;
|
|
|
|
|
|
|
|
|
|
put_cached_int_type(&ctx->ctx_int_cache, entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ctx_int_value_cache_entry *value
|
|
|
|
|
= get_cached_int_value(&entry->i_values, val);
|
|
|
|
|
if (value) {
|
|
|
|
|
return MIE_VALUE(&value->i_value);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
value = malloc(sizeof *value);
|
|
|
|
|
if (!value) {
|
2025-04-11 13:40:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
memset(value, 0x0, sizeof *value);
|
|
|
|
|
|
|
|
|
|
mie_value_init(&value->i_value.c_base, MIE_VALUE_CONST);
|
|
|
|
|
value->i_value.c_type = &entry->i_type;
|
|
|
|
|
value->i_value.c_v.v_int = val;
|
2025-04-11 13:40:54 +01:00
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
put_cached_int_value(&entry->i_values, value);
|
2025-04-11 13:40:54 +01:00
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
return MIE_VALUE(&value->i_value);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-17 21:43:02 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_module *mod)
|
|
|
|
|
{
|
|
|
|
|
struct mie_builder *out = malloc(sizeof *out);
|
|
|
|
|
if (!out) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(out, 0x0, sizeof *out);
|
|
|
|
|
out->b_ctx = ctx;
|
|
|
|
|
out->b_module = mod;
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mie_builder_destroy(struct mie_builder *builder)
|
|
|
|
|
{
|
|
|
|
|
free(builder);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 20:14:28 +01:00
|
|
|
struct mie_func *mie_builder_get_current_func(struct mie_builder *builder)
|
|
|
|
|
{
|
|
|
|
|
struct mie_block *block = builder->b_current_block;
|
|
|
|
|
if (!block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return block->b_parent;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
void mie_builder_put_record(
|
|
|
|
|
struct mie_builder *builder, struct mie_const *val, const char *name)
|
|
|
|
|
{
|
|
|
|
|
if (!builder->b_module) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b_queue_iterator it = {};
|
|
|
|
|
b_queue_foreach (&it, &builder->b_module->m_records) {
|
|
|
|
|
struct mie_value *rec
|
|
|
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
|
|
|
|
|
|
|
|
if (!strcmp(rec->v_name.n_str, name)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_record *rec = mie_record_create(val);
|
|
|
|
|
rec->r_base.v_name.n_str = b_strdup(name);
|
|
|
|
|
b_queue_push_back(&builder->b_module->m_records, &rec->r_base.v_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data)
|
|
|
|
|
{
|
|
|
|
|
if (!builder->b_module) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b_queue_iterator it = {};
|
|
|
|
|
b_queue_foreach (&it, &builder->b_module->m_data) {
|
|
|
|
|
struct mie_value *cur
|
|
|
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
|
|
|
|
|
|
|
|
if (!strcmp(cur->v_name.n_str, data->d_base.v_name.n_str)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b_queue_push_back(&builder->b_module->m_data, &data->d_base.v_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type)
|
|
|
|
|
{
|
|
|
|
|
if (!builder->b_module) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b_queue_iterator it = {};
|
|
|
|
|
b_queue_foreach (&it, &builder->b_module->m_types) {
|
|
|
|
|
struct mie_value *cur
|
|
|
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
|
|
|
|
|
|
|
|
if (!strcmp(cur->v_name.n_str, type->t_base.v_name.n_str)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b_queue_push_back(&builder->b_module->m_data, &type->t_base.v_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mie_builder_set_insert_point(
|
|
|
|
|
struct mie_builder *builder, struct mie_block *block)
|
|
|
|
|
{
|
|
|
|
|
builder->b_current_block = block;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-17 21:43:02 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
struct mie_value *mie_builder_ret(struct mie_builder *builder, struct mie_value *val)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 13:40:54 +01:00
|
|
|
struct mie_ret *ret = malloc(sizeof *ret);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&ret->r_base, MIE_INSTR_RET);
|
2025-04-13 18:34:02 +01:00
|
|
|
ret->r_val = val;
|
2025-04-11 13:40:54 +01:00
|
|
|
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &ret->r_base)) {
|
|
|
|
|
free(ret);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(ret);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_add(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_binary_op *add = malloc(sizeof *add);
|
|
|
|
|
if (!add) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(add, 0x0, sizeof *add);
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&add->op_base, MIE_INSTR_ADD);
|
|
|
|
|
|
|
|
|
|
add->op_left = left;
|
|
|
|
|
add->op_right = right;
|
|
|
|
|
add->op_type = mie_value_get_type(left);
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &add->op_base)) {
|
|
|
|
|
free(add);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(add), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(add);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_sub(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
2025-04-14 20:14:28 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_binary_op *sub = malloc(sizeof *sub);
|
|
|
|
|
if (!sub) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(sub, 0x0, sizeof *sub);
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&sub->op_base, MIE_INSTR_SUB);
|
|
|
|
|
|
|
|
|
|
sub->op_left = left;
|
|
|
|
|
sub->op_right = right;
|
|
|
|
|
sub->op_type = mie_value_get_type(left);
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &sub->op_base)) {
|
|
|
|
|
free(sub);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(sub), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(sub);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_mul(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
2025-04-14 20:14:28 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_binary_op *mul = malloc(sizeof *mul);
|
|
|
|
|
if (!mul) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(mul, 0x0, sizeof *mul);
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&mul->op_base, MIE_INSTR_MUL);
|
|
|
|
|
|
|
|
|
|
mul->op_left = left;
|
|
|
|
|
mul->op_right = right;
|
|
|
|
|
mul->op_type = mie_value_get_type(left);
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &mul->op_base)) {
|
|
|
|
|
free(mul);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(mul), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(mul);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_div(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
2025-04-14 20:14:28 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_binary_op *div = malloc(sizeof *div);
|
|
|
|
|
if (!div) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(div, 0x0, sizeof *div);
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&div->op_base, MIE_INSTR_DIV);
|
|
|
|
|
|
|
|
|
|
div->op_left = left;
|
|
|
|
|
div->op_right = right;
|
|
|
|
|
div->op_type = mie_value_get_type(left);
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &div->op_base)) {
|
|
|
|
|
free(div);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(div), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(div);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_load(
|
2025-04-13 18:34:02 +01:00
|
|
|
struct mie_builder *builder, struct mie_type *type,
|
2025-04-11 13:40:54 +01:00
|
|
|
struct mie_value *src, const char *name)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_load *load = malloc(sizeof *load);
|
|
|
|
|
if (!load) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&load->l_base, MIE_INSTR_LOAD);
|
|
|
|
|
load->l_src = src;
|
|
|
|
|
load->l_type = type;
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &load->l_base)) {
|
|
|
|
|
free(load);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(load), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(load);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_store(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *val, struct mie_value *dest)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_store *store = malloc(sizeof *store);
|
|
|
|
|
if (!store) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&store->s_base, MIE_INSTR_STORE);
|
|
|
|
|
store->s_val = val;
|
|
|
|
|
store->s_dest = dest;
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &store->s_base)) {
|
|
|
|
|
free(store);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(store);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_alloca(
|
|
|
|
|
struct mie_builder *builder, struct mie_type *type, const char *name)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_alloca *alloca = malloc(sizeof *alloca);
|
|
|
|
|
if (!alloca) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&alloca->a_base, MIE_INSTR_ALLOCA);
|
|
|
|
|
alloca->a_type = type;
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &alloca->a_base)) {
|
|
|
|
|
free(alloca);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_func_generate_value_name(
|
|
|
|
|
builder->b_current_block->b_parent, MIE_VALUE(alloca), name);
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(alloca);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_switch(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *cond,
|
|
|
|
|
struct mie_switch_branch *branches, size_t nr_branches,
|
|
|
|
|
struct mie_block *default_block)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_br(struct mie_builder *builder, struct mie_block *dest)
|
|
|
|
|
{
|
2025-04-13 18:34:02 +01:00
|
|
|
if (!builder->b_current_block) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (builder->b_current_block->b_terminator) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_branch *br = malloc(sizeof *br);
|
|
|
|
|
if (!br) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(br, 0x0, sizeof *br);
|
|
|
|
|
|
|
|
|
|
mie_instr_init(&br->b_base, MIE_INSTR_BR);
|
|
|
|
|
|
|
|
|
|
br->b_dest = dest;
|
|
|
|
|
|
|
|
|
|
if (!mie_block_add_instr(builder->b_current_block, &br->b_base)) {
|
|
|
|
|
free(br);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MIE_VALUE(br);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_msg(
|
2025-04-17 21:43:02 +01:00
|
|
|
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)
|
2025-04-11 13:40:54 +01:00
|
|
|
{
|
2025-04-17 21:43:02 +01:00
|
|
|
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);
|
2025-04-11 13:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_cmp_eq(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_cmp_lt(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_cmp_gt(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_cmp_leq(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_cmp_geq(
|
|
|
|
|
struct mie_builder *builder, struct mie_value *left,
|
|
|
|
|
struct mie_value *right, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_getelementptr(
|
|
|
|
|
struct mie_builder *builder, struct mie_type *container_type,
|
|
|
|
|
struct mie_value *container, struct mie_value *index, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_value *mie_builder_setelementptr(
|
|
|
|
|
struct mie_builder *builder, struct mie_type *container_type,
|
|
|
|
|
struct mie_value *container, struct mie_value *index)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct mie_phi *mie_builder_phi(
|
|
|
|
|
struct mie_builder *builder, struct mie_type *type,
|
|
|
|
|
unsigned int nr_edges, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|