mie: implement more ir building functionality

This commit is contained in:
2025-04-13 18:34:02 +01:00
parent 7f0d8b87c5
commit deb1232bf9
21 changed files with 694 additions and 132 deletions

View File

@@ -1,21 +1,41 @@
#include <blue/object/string.h>
#include <mie/alloca.h>
#include <mie/block.h>
#include <mie/branch.h>
#include <mie/builder.h>
#include <mie/data.h>
#include <mie/func.h>
#include <mie/module.h>
#include <mie/op.h>
#include <mie/ptr.h>
#include <mie/record.h>
#include <mie/type.h>
#include <stdlib.h>
#include <string.h>
struct ctx_cached_int {
struct mie_int i_val;
struct ctx_int_cache_entry {
b_btree_node i_node;
struct mie_type i_type;
b_btree i_values;
};
struct ctx_int_value_cache_entry {
b_btree_node i_node;
struct mie_const i_value;
};
B_BTREE_DEFINE_SIMPLE_INSERT(
struct ctx_cached_int, i_node, i_val.i_value, put_cached_int)
struct ctx_int_cache_entry, i_node, i_type.t_width, put_cached_int_type)
B_BTREE_DEFINE_SIMPLE_GET(
struct ctx_cached_int, long long, i_node, i_val.i_value, get_cached_int)
struct ctx_int_cache_entry, unsigned int, i_node, i_type.t_width,
get_cached_int_type)
B_BTREE_DEFINE_SIMPLE_INSERT(
struct ctx_int_value_cache_entry, i_node, i_value.c_v.v_int,
put_cached_int_value)
B_BTREE_DEFINE_SIMPLE_GET(
struct ctx_int_value_cache_entry, int64_t, i_node, i_value.c_v.v_int,
get_cached_int_value)
struct mie_ctx *mie_ctx_create(void)
{
@@ -27,8 +47,8 @@ struct mie_ctx *mie_ctx_create(void)
memset(out, 0x0, sizeof *out);
out->ctx_true = mie_int_create(1, 1);
out->ctx_false = mie_int_create(0, 1);
out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1));
out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1));
return out;
}
@@ -36,52 +56,131 @@ struct mie_ctx *mie_ctx_create(void)
void mie_ctx_destroy(struct mie_ctx *ctx)
{
if (ctx->ctx_true) {
mie_value_release(MIE_VALUE(ctx->ctx_true));
mie_value_destroy(MIE_VALUE(ctx->ctx_true));
ctx->ctx_true = NULL;
}
if (ctx->ctx_false) {
mie_value_release(MIE_VALUE(ctx->ctx_false));
mie_value_destroy(MIE_VALUE(ctx->ctx_false));
ctx->ctx_false = NULL;
}
b_btree_iterator it = {};
b_btree_iterator_begin(&ctx->ctx_ints, &it);
b_btree_iterator_begin(&ctx->ctx_int_cache, &it);
while (b_btree_iterator_is_valid(&it)) {
b_btree_node *node = it.node;
struct ctx_int_cache_entry *entry
= b_unbox(struct ctx_int_cache_entry, it.node, i_node);
b_btree_iterator_erase(&it);
struct ctx_cached_int *entry
= b_unbox(struct ctx_cached_int, node, i_node);
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);
}
free(entry);
}
free(ctx);
}
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;
}
struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val)
{
return MIE_VALUE(val ? ctx->ctx_true : ctx->ctx_false);
}
struct mie_value *mie_ctx_get_int(struct mie_ctx *ctx, long long val)
struct mie_value *mie_ctx_get_int(
struct mie_ctx *ctx, long long val, unsigned int nr_bits)
{
struct ctx_cached_int *cache_entry = get_cached_int(&ctx->ctx_ints, val);
if (cache_entry) {
return MIE_VALUE(&cache_entry->i_val);
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);
}
cache_entry = malloc(sizeof *cache_entry);
if (!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);
}
value = malloc(sizeof *value);
if (!value) {
return NULL;
}
memset(cache_entry, 0x0, sizeof *cache_entry);
memset(value, 0x0, sizeof *value);
mie_int_init(&cache_entry->i_val, val, 32);
cache_entry->i_val.i_base.c_base.v_flags |= MIE_VALUE_F_STATIC;
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;
return MIE_VALUE(&cache_entry->i_val);
put_cached_int_value(&entry->i_values, value);
return MIE_VALUE(&value->i_value);
}
struct mie_builder *mie_builder_create(struct mie_ctx *ctx, struct mie_module *mod)
@@ -171,22 +270,64 @@ void mie_builder_set_insert_point(
struct mie_value *mie_builder_ret(struct mie_builder *builder, struct mie_value *val)
{
if (!builder->b_current_block) {
return NULL;
}
if (builder->b_current_block->b_terminator) {
return NULL;
}
struct mie_ret *ret = malloc(sizeof *ret);
if (!ret) {
return NULL;
}
mie_instr_init(&ret->r_base, MIE_INSTR_RET);
ret->r_val = mie_value_retain(val);
ret->r_val = val;
return NULL;
if (!mie_block_add_instr(builder->b_current_block, &ret->r_base)) {
free(ret);
return NULL;
}
return MIE_VALUE(ret);
}
struct mie_value *mie_builder_add(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
return NULL;
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);
}
struct mie_value *mie_builder_sub(
@@ -211,22 +352,93 @@ struct mie_value *mie_builder_div(
}
struct mie_value *mie_builder_load(
struct mie_builder *builder, struct mie_value *type,
struct mie_builder *builder, struct mie_type *type,
struct mie_value *src, const char *name)
{
return NULL;
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);
}
struct mie_value *mie_builder_store(
struct mie_builder *builder, struct mie_value *val, struct mie_value *dest)
{
return NULL;
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);
}
struct mie_value *mie_builder_alloca(
struct mie_builder *builder, struct mie_type *type, const char *name)
{
return NULL;
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);
}
struct mie_value *mie_builder_switch(
@@ -239,7 +451,31 @@ struct mie_value *mie_builder_switch(
struct mie_value *mie_builder_br(struct mie_builder *builder, struct mie_block *dest)
{
return NULL;
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);
}
struct mie_value *mie_builder_br_if(