Compare commits

1 Commits

Author SHA1 Message Date
d2abb6faa3 meta: replace in-repo copy of mie with git submodule 2026-01-19 14:28:02 +00:00
72 changed files with 4 additions and 6019 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "mie"]
path = mie
url = https://g.wash.red/wash/mie.git

1
mie Submodule

Submodule mie added at 937dc57c4e

View File

@@ -1,15 +0,0 @@
file(GLOB_RECURSE mie_sources *.c *.h include/mie/*.h)
if (WIN32)
set(rc_file ${CMAKE_CURRENT_SOURCE_DIR}/../res/win32/mie.rc)
endif ()
if (IVY_STATIC)
add_library(mie STATIC ${mie_sources} ${rc_file})
else ()
add_library(mie SHARED ${mie_sources} ${rc_file})
endif ()
target_include_directories(mie PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
target_link_libraries(mie Bluelib::Core Bluelib::Ds)
target_compile_definitions(mie PRIVATE MIE_EXPORT=1 MIE_STATIC=${IVY_STATIC})

View File

@@ -1,14 +0,0 @@
METACOMPUTE INSTRUCTION ENGINE
==============================
Mie is an abstract virtual machine and intermediate representation manipulation
toolkit. It includes facilities for building, manipulating, and optimising
intermediate representations of programs, as well as converting IR to/from
different formats.
The Mie virtual machine features an infinite amount of memory and registers.
A Mie program can be emitted by a simple front-end compiler that makes use of
these infinite resources, and Mie's optimisers will convert this program into a
form that can efficiently use and re-use a more finite set of resources.
Finally, a Mie backend can convert the program into a concrete implementation
for a particular system.

283
mie/ctx.c
View File

@@ -1,283 +0,0 @@
#include <blue/ds/hashmap.h>
#include <blue/ds/list.h>
#include <blue/ds/string.h>
#include <mie/ctx.h>
#include <mie/ir/const.h>
#include <stdlib.h>
#include <string.h>
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_int 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)
B_BTREE_DEFINE_SIMPLE_INSERT(
struct ctx_int_value_cache_entry, i_node, i_value.i_value,
put_cached_int_value)
B_BTREE_DEFINE_SIMPLE_GET(
struct ctx_int_value_cache_entry, int64_t, i_node, i_value.i_value,
get_cached_int_value)
struct mie_ctx *mie_ctx_create(void)
{
struct mie_ctx *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
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_null = malloc(sizeof *out->ctx_null);
if (!out->ctx_null) {
mie_ctx_destroy(out);
return NULL;
}
mie_value_init(out->ctx_null, MIE_VALUE_NONE);
out->ctx_sel_cache = b_hashmap_create(free, free);
out->ctx_string_cache = b_hashmap_create(free, free);
return out;
}
void mie_ctx_destroy(struct mie_ctx *ctx)
{
ctx->ctx_true = NULL;
ctx->ctx_false = NULL;
b_btree_node *node = b_btree_first(&ctx->ctx_int_cache);
while (node) {
struct ctx_int_cache_entry *entry
= b_unbox(struct ctx_int_cache_entry, node, i_node);
b_btree_node *next = b_btree_next(node);
b_btree_delete(&ctx->ctx_int_cache, node);
b_btree_node *node2 = b_btree_first(&entry->i_values);
while (node2) {
struct ctx_int_value_cache_entry *value = b_unbox(
struct ctx_int_value_cache_entry, node2, i_node);
b_btree_node *next2 = b_btree_next(node2);
b_btree_delete(&entry->i_values, node2);
free(value);
node2 = next2;
}
free(entry);
node = next;
}
const size_t nr_types = sizeof ctx->ctx_types / sizeof ctx->ctx_types[0];
for (size_t i = 0; i < nr_types; i++) {
if (ctx->ctx_types[i]) {
mie_value_destroy(MIE_VALUE(ctx->ctx_types[i]));
ctx->ctx_types[i] = NULL;
}
}
if (ctx->ctx_null) {
mie_value_destroy(ctx->ctx_null);
}
b_hashmap_unref(ctx->ctx_sel_cache);
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 = mie_type_create();
if (!type) {
return NULL;
}
type->t_id = type_id;
ctx->ctx_types[type_id] = type;
return type;
}
struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx)
{
return ctx->ctx_null;
}
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);
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, unsigned int nr_bits)
{
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);
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);
}
value = malloc(sizeof *value);
if (!value) {
return NULL;
}
memset(value, 0x0, sizeof *value);
mie_const_init(&value->i_value.i_base, &entry->i_type);
value->i_value.i_value = val;
put_cached_int_value(&entry->i_values, value);
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_selector *sel_value = malloc(sizeof *sel_value);
if (!sel_value) {
return NULL;
}
struct mie_type *sel_type = mie_ctx_get_type(ctx, MIE_TYPE_SELECTOR);
mie_const_init(&sel_value->sel_base, sel_type);
sel_value->sel_value = b_strdup(sel);
key.key_data = sel_value->sel_value;
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_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s)
{
b_hashmap_key key = {
.key_data = s,
.key_size = strlen(s),
};
const b_hashmap_value *cache_entry
= b_hashmap_get(ctx->ctx_string_cache, &key);
if (cache_entry) {
return cache_entry->value_data;
}
struct mie_string *string_value = malloc(sizeof *string_value);
if (!string_value) {
return NULL;
}
struct mie_type *string_type = mie_ctx_get_type(ctx, MIE_TYPE_STR);
mie_const_init(&string_value->s_base, string_type);
string_value->s_value = b_strdup(s);
key.key_data = string_value->s_value;
b_hashmap_value hashmap_value = {
.value_data = string_value,
.value_size = sizeof *string_value,
};
b_hashmap_put(ctx->ctx_string_cache, &key, &hashmap_value);
return MIE_VALUE(string_value);
}
struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx)
{
struct mie_type *array_type = mie_ctx_get_type(ctx, MIE_TYPE_ARRAY);
struct mie_array *array = malloc(sizeof *array);
if (!array) {
return NULL;
}
memset(array, 0x0, sizeof *array);
mie_const_init(&array->a_base, array_type);
array->a_values = b_list_create();
return MIE_VALUE(array);
}

View File

@@ -1,32 +0,0 @@
#ifndef MIE_CTX_H_
#define MIE_CTX_H_
#include <blue/core/btree.h>
#include <blue/ds/hashmap.h>
#include <mie/type.h>
struct mie_ctx {
struct mie_const *ctx_true, *ctx_false;
struct mie_value *ctx_null;
struct mie_type *ctx_types[__MIE_TYPE_COUNT];
b_btree ctx_int_cache;
b_hashmap *ctx_sel_cache;
b_hashmap *ctx_string_cache;
};
extern struct mie_ctx *mie_ctx_create(void);
extern void mie_ctx_destroy(struct mie_ctx *ctx);
extern struct mie_type *mie_ctx_get_type(
struct mie_ctx *ctx, enum mie_type_id type_id);
extern struct mie_type *mie_ctx_get_int_type(
struct mie_ctx *ctx, unsigned int nr_bits);
extern struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx);
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_string(struct mie_ctx *ctx, const char *s);
extern struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel);
extern struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx);
#endif

View File

@@ -1,12 +0,0 @@
#ifndef MIE_ALLOCA_H_
#define MIE_ALLOCA_H_
#include <mie/ir/instr.h>
#include <mie/type.h>
struct mie_alloca {
struct mie_instr a_base;
struct mie_type *a_type;
};
#endif

View File

@@ -1,15 +0,0 @@
#ifndef MIE_ARG_H_
#define MIE_ARG_H_
#include <mie/ir/value.h>
#define MIE_ARG(p) ((struct mie_arg *)(p))
struct mie_arg {
struct mie_value arg_base;
struct mie_type *arg_type;
};
extern struct mie_arg *mie_arg_create(struct mie_type *type);
#endif

View File

@@ -1,30 +0,0 @@
#ifndef MIE_BLOCK_H_
#define MIE_BLOCK_H_
#define MIE_BLOCK(p) ((struct mie_block *)(p))
#include <mie/ir/value.h>
struct mie_block {
struct mie_value b_base;
struct mie_func *b_parent;
/* the phi instruction(s). these must appear at the start of the block
* and are separated to make traversing the CFG easier */
b_queue b_phi;
/* the rest of the instructions in the block */
b_queue b_instr;
/* the instruction that transfers control to the next block,
* could be a switch, branch, or ret */
struct mie_instr *b_terminator;
};
MIE_API struct mie_block *mie_block_create(
struct mie_func *parent, const char *name);
MIE_API bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr);
static inline bool mie_block_is_terminated(const struct mie_block *block)
{
return block->b_terminator != NULL;
}
#endif

View File

@@ -1,19 +0,0 @@
#ifndef MIE_BRANCH_H_
#define MIE_BRANCH_H_
#include <mie/ir/const.h>
#include <mie/ir/instr.h>
struct mie_branch {
struct mie_instr b_base;
struct mie_block *b_dest;
};
struct mie_branch_if {
struct mie_instr b_base;
struct mie_value *b_cond;
struct mie_block *b_true_block;
struct mie_block *b_false_block;
};
#endif

View File

@@ -1,119 +0,0 @@
#ifndef MIE_BUILDER_H_
#define MIE_BUILDER_H_
#include <blue/core/btree.h>
#include <mie/ir/switch.h>
#include <mie/ir/value.h>
#include <mie/misc.h>
#include <mie/type.h>
struct b_hashmap;
struct mie_block;
struct mie_module;
struct mie_data;
struct mie_type;
struct mie_phi;
struct mie_phi_edge;
struct mie_ctx;
struct mie_builder {
struct mie_ctx *b_ctx;
struct mie_module *b_module;
struct mie_block *b_current_block;
struct mie_instr *b_prev_instr;
};
enum mie_builder_flags {
MIE_BUILDER_IGNORE_RESULT = 0x01u,
};
extern struct mie_builder *mie_builder_create(
struct mie_ctx *ctx, struct mie_module *mod);
extern void mie_builder_destroy(struct mie_builder *builder);
extern struct mie_func *mie_builder_get_current_func(struct mie_builder *builder);
static inline struct mie_block *mie_builder_get_current_block(
struct mie_builder *builder)
{
return builder->b_current_block;
}
extern struct mie_record *mie_builder_put_record(
struct mie_builder *builder, struct mie_const *val, const char *name);
extern struct mie_record *mie_builder_get_record(
struct mie_builder *builder, const char *name);
extern void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data);
extern void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type);
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_get_string_ptr(
struct mie_builder *builder, const char *s);
extern struct mie_value *mie_builder_ret(
struct mie_builder *builder, struct mie_value *val);
extern struct mie_value *mie_builder_add(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_sub(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_mul(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_div(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_load(
struct mie_builder *builder, struct mie_type *type,
struct mie_value *src, const char *name);
extern struct mie_value *mie_builder_store(
struct mie_builder *builder, struct mie_value *val, struct mie_value *dest);
extern struct mie_value *mie_builder_alloca(
struct mie_builder *builder, struct mie_type *type, const char *name);
extern 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);
extern struct mie_value *mie_builder_br(
struct mie_builder *builder, struct mie_block *dest);
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_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);
extern struct mie_value *mie_builder_cmp_neq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_cmp_lt(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_cmp_gt(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_cmp_leq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern struct mie_value *mie_builder_cmp_geq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name);
extern 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);
extern struct mie_value *mie_builder_setelementptr(
struct mie_builder *builder, struct mie_type *container_type,
struct mie_value *container, struct mie_value *index);
extern struct mie_value *mie_builder_phi(
struct mie_builder *builder, struct mie_type *type,
struct mie_phi_edge *edges, unsigned int nr_edges, const char *name);
#endif

View File

@@ -1,65 +0,0 @@
#ifndef MIE_CONST_H_
#define MIE_CONST_H_
#include <blue/ds/list.h>
#include <mie/ir/value.h>
#include <mie/type.h>
#define MIE_CONST(p) ((struct mie_const *)(p))
#define MIE_INT(p) ((struct mie_int *)(p))
#define MIE_DOUBLE(p) ((struct mie_double *)(p))
#define MIE_STRING(p) ((struct mie_string *)(p))
#define MIE_ATOM(p) ((struct mie_atom *)(p))
#define MIE_SELECTOR(p) ((struct mie_selector *)(p))
#define MIE_ARRAY(p) ((struct mie_array *)(p))
struct mie_const {
struct mie_value c_base;
struct mie_type *c_type;
};
struct mie_int {
struct mie_const i_base;
int64_t i_value;
};
struct mie_double {
struct mie_const d_base;
double d_value;
};
struct mie_string {
struct mie_const s_base;
char *s_value;
};
struct mie_atom {
struct mie_const a_base;
char *a_value;
};
struct mie_selector {
struct mie_const sel_base;
char *sel_value;
};
struct mie_array {
struct mie_const a_base;
b_list *a_values;
};
extern void mie_const_init(struct mie_const *c, struct mie_type *type);
static inline bool mie_value_is_selector(const struct mie_value *v)
{
if (v->v_type->t_id != MIE_VALUE_CONST) {
return false;
}
const struct mie_const *c = MIE_CONST(v);
return c->c_type->t_id == MIE_TYPE_SELECTOR;
}
#endif

View File

@@ -1,82 +0,0 @@
#ifndef MIE_CONVERT_H_
#define MIE_CONVERT_H_
#include <blue/core/stringstream.h>
#include <blue/ds/bitbuffer.h>
#include <blue/ds/string.h>
#include <mie/misc.h>
#include <stdio.h>
struct mie_value;
struct mie_ctx;
enum mie_ir_format {
MIE_IR_NONE = 0,
MIE_IR_MEM,
MIE_IR_BITCODE,
MIE_IR_TEXT,
};
enum mie_ir_converter_medium {
MIE_IR_CONVERTER_NONE = 0,
MIE_IR_CONVERTER_MIE_VALUE,
MIE_IR_CONVERTER_BITSTREAM,
MIE_IR_CONVERTER_BITBUFFER,
MIE_IR_CONVERTER_STRINGSTREAM,
MIE_IR_CONVERTER_STRING,
MIE_IR_CONVERTER_FILE,
};
struct mie_ir_converter {
struct mie_ctx *c_ctx;
enum mie_ir_format c_src_format, c_dest_format;
enum mie_ir_converter_medium c_src_medium, c_dest_medium;
union {
/* TODO bitstream */
struct mie_value *value;
b_bitbuffer *bitbuffer;
b_stringstream *stringstream;
b_string *string;
FILE *file;
} c_src;
union {
/* TODO bitstream */
struct mie_value **value;
b_bitbuffer *bitbuffer;
b_stringstream *stringstream;
b_string *string;
FILE *file;
} c_dest;
};
MIE_API struct mie_ir_converter *mie_ir_converter_create(
struct mie_ctx *ctx, enum mie_ir_format src, enum mie_ir_format dest);
MIE_API void mie_ir_converter_destroy(struct mie_ir_converter *converter);
MIE_API b_status mie_ir_converter_set_src_value(
struct mie_ir_converter *converter, struct mie_value *value);
MIE_API b_status mie_ir_converter_set_src_bitbuffer(
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer);
MIE_API b_status mie_ir_converter_set_src_stringstream(
struct mie_ir_converter *converter, b_stringstream *stringstream);
MIE_API b_status mie_ir_converter_set_src_string(
struct mie_ir_converter *converter, b_string *string);
MIE_API b_status mie_ir_converter_set_src_file(
struct mie_ir_converter *converter, FILE *file);
MIE_API b_status mie_ir_converter_set_dest_value(
struct mie_ir_converter *converter, struct mie_value **value);
MIE_API b_status mie_ir_converter_set_dest_bitbuffer(
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer);
MIE_API b_status mie_ir_converter_set_dest_stringstream(
struct mie_ir_converter *converter, b_stringstream *stringstream);
MIE_API b_status mie_ir_converter_set_dest_string(
struct mie_ir_converter *converter, b_string *string);
MIE_API b_status mie_ir_converter_set_dest_file(
struct mie_ir_converter *converter, FILE *file);
MIE_API b_status mie_ir_converter_process(struct mie_ir_converter *converter);
#endif

View File

@@ -1,32 +0,0 @@
#ifndef MIE_DATA_H_
#define MIE_DATA_H_
#include <mie/ir/value.h>
#define MIE_DATA(p) ((struct mie_data *)(p))
enum mie_data_type {
MIE_DATA_NONE = 0,
MIE_DATA_EXTERN_GLOBAL,
MIE_DATA_CONST,
};
struct mie_data {
struct mie_value d_base;
enum mie_data_type d_type;
union {
struct {
struct mie_const *c_value;
} d_const;
struct {
struct mie_type *g_type;
} d_extern_global;
};
};
extern struct mie_data *mie_data_create_extern_global(
struct mie_type *type, const char *ident);
extern struct mie_data *mie_data_create_const(struct mie_const *value);
#endif

View File

@@ -1,47 +0,0 @@
#ifndef MIE_FUNC_H_
#define MIE_FUNC_H_
#define MIE_FUNC(p) ((struct mie_func *)(p))
#include <mie/ir/value.h>
struct mie_name_map;
struct mie_type;
struct mie_arg;
struct mie_block;
struct b_dict;
enum mie_func_type {
MIE_FUNC_NONE = 0x00u,
MIE_FUNC_STATIC = 0x01u,
MIE_FUNC_INSTANCE = 0x02u,
MIE_FUNC_LAMBDA = 0x03u,
};
struct mie_func {
struct mie_value f_base;
enum mie_func_type f_type;
struct mie_type *f_ret;
struct mie_name_map *f_names;
b_queue f_args;
b_queue f_blocks;
};
extern struct mie_func *mie_func_create(
enum mie_func_type type, struct mie_type *ret_type);
extern struct mie_value *mie_func_add_arg(
struct mie_func *func, struct mie_type *type, const char *name);
extern struct mie_block *mie_func_create_block(
struct mie_func *func, const char *name);
extern void mie_func_insert_block(
struct mie_func *func, struct mie_block *block, struct mie_block *after);
extern struct mie_value *mie_func_generate_value_name(
struct mie_func *func, struct mie_value *val, const char *hint);
extern struct mie_block *mie_func_get_first_block(struct mie_func *func);
extern struct mie_block *mie_func_get_last_block(struct mie_func *func);
#endif

View File

@@ -1,45 +0,0 @@
#ifndef MIE_INSTR_H_
#define MIE_INSTR_H_
#include <mie/ir/value.h>
#define MIE_INSTR(p) ((struct mie_instr *)(p))
enum mie_instr_type {
MIE_INSTR_NONE = 0,
MIE_INSTR_RET,
MIE_INSTR_ADD,
MIE_INSTR_SUB,
MIE_INSTR_MUL,
MIE_INSTR_DIV,
MIE_INSTR_LOAD,
MIE_INSTR_STORE,
MIE_INSTR_ALLOCA,
MIE_INSTR_SWITCH,
MIE_INSTR_BR,
MIE_INSTR_BR_IF,
MIE_INSTR_MSG,
MIE_INSTR_CMP_EQ,
MIE_INSTR_CMP_NEQ,
MIE_INSTR_CMP_LT,
MIE_INSTR_CMP_GT,
MIE_INSTR_CMP_LEQ,
MIE_INSTR_CMP_GEQ,
MIE_INSTR_GETELEMENTPTR,
MIE_INSTR_SETELEMENTPTR,
MIE_INSTR_PHI,
};
struct mie_instr {
struct mie_value i_base;
enum mie_instr_type i_type;
};
struct mie_ret {
struct mie_instr r_base;
struct mie_value *r_val;
};
extern void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type);
#endif

View File

@@ -1,37 +0,0 @@
#ifndef MIE_MODULE_H_
#define MIE_MODULE_H_
#define MIE_MODULE(p) ((struct mie_module *)(p))
#include <blue/core/queue.h>
#include <blue/ds/hashmap.h>
#include <mie/ir/value.h>
#include <mie/name.h>
struct mie_func;
struct mie_module {
struct mie_value m_base;
struct mie_name_map *m_names;
b_queue m_records;
b_queue m_types;
b_queue m_func;
b_hashmap *m_data;
b_hashmap *m_data_strings;
};
extern struct mie_module *mie_module_create(void);
extern void mie_module_add_function(
struct mie_module *mod, struct mie_func *func, const char *name);
extern struct mie_data *mie_module_get_string_ptr(
struct mie_module *mod, const char *s);
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, const char *name);
extern struct mie_value *mie_module_generate_value_name(
struct mie_module *mod, struct mie_value *val, const char *hint);
#endif

View File

@@ -1,18 +0,0 @@
#ifndef MIE_MSG_H_
#define MIE_MSG_H_
#include <mie/ir/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;
size_t msg_nr_args;
struct mie_value **msg_args;
};
#endif

View File

@@ -1,13 +0,0 @@
#ifndef MIE_ARITH_H_
#define MIE_ARITH_H_
#include <mie/ir/instr.h>
struct mie_binary_op {
struct mie_instr op_base;
struct mie_type *op_type;
struct mie_value *op_left;
struct mie_value *op_right;
};
#endif

View File

@@ -1,25 +0,0 @@
#ifndef MIE_PHI_H_
#define MIE_PHI_H_
#include <blue/core/queue.h>
#include <mie/ir/instr.h>
#include <mie/misc.h>
struct mie_phi_edge {
b_queue_entry e_entry;
struct mie_block *e_incoming_block;
struct mie_value *e_value;
};
struct mie_phi {
struct mie_instr p_base;
struct mie_type *p_type;
unsigned int p_nr_edges;
struct mie_phi_edge *p_edges;
};
MIE_API struct mie_phi_edge *mie_phi_edge_create(
struct mie_block *incoming_block, struct mie_value *value);
#endif

View File

@@ -1,33 +0,0 @@
#ifndef MIE_PTR_H_
#define MIE_PTR_H_
#include <mie/ir/instr.h>
#include <mie/type.h>
struct mie_getelementptr {
struct mie_instr gep_base;
struct mie_type *gep_container_type;
struct mie_value *gep_container;
struct mie_value *gep_index;
};
struct mie_setelementptr {
struct mie_instr sep_base;
struct mie_type *sep_container_type;
struct mie_value *sep_container;
struct mie_value *sep_index;
};
struct mie_load {
struct mie_instr l_base;
struct mie_type *l_type;
struct mie_value *l_src;
};
struct mie_store {
struct mie_instr s_base;
struct mie_value *s_val;
struct mie_value *s_dest;
};
#endif

View File

@@ -1,16 +0,0 @@
#ifndef MIE_RECORD_H_
#define MIE_RECORD_H_
#define MIE_RECORD(p) ((struct mie_record *)(p))
#include <mie/ir/const.h>
#include <mie/ir/value.h>
struct mie_record {
struct mie_value r_base;
const struct mie_const *r_value;
};
extern struct mie_record *mie_record_create(const struct mie_const *val);
#endif

View File

@@ -1,21 +0,0 @@
#ifndef MIE_SWITCH_H_
#define MIE_SWITCH_H_
#include <mie/ir/const.h>
#include <mie/ir/instr.h>
struct mie_switch_branch {
struct mie_value *b_value;
struct mie_block *b_jump_to;
};
struct mie_switch {
struct mie_instr s_base;
struct mie_value *s_src;
struct mie_block *s_default;
size_t s_nr_branches;
struct mie_switch_branch *s_branches;
};
#endif

View File

@@ -1,60 +0,0 @@
#ifndef MIE_VALUE_H_
#define MIE_VALUE_H_
#include <blue/core/queue.h>
#include <mie/misc.h>
#include <mie/name.h>
#define MIE_VALUE(p) ((struct mie_value *)(p))
struct mie_ctx;
struct mie_value;
enum mie_value_type_id {
MIE_VALUE_NONE = 0,
MIE_VALUE_MODULE,
MIE_VALUE_TYPE,
MIE_VALUE_RECORD,
MIE_VALUE_FUNC,
MIE_VALUE_ARG,
MIE_VALUE_BLOCK,
MIE_VALUE_INSTR,
MIE_VALUE_CONST,
MIE_VALUE_DATA,
};
enum mie_value_flags {
MIE_VALUE_F_NONE = 0x00u,
MIE_VALUE_F_STATIC = 0x01u,
};
struct mie_value_type {
enum mie_value_type_id t_id;
struct mie_type *(*t_get_type)(struct mie_value *, struct mie_ctx *);
void (*t_cleanup)(struct mie_value *);
};
struct mie_value {
struct mie_name v_name;
const struct mie_value_type *v_type;
enum mie_value_flags v_flags;
b_queue_entry v_entry;
};
MIE_API void mie_value_init(struct mie_value *val, enum mie_value_type_id type);
MIE_API void mie_value_destroy(struct mie_value *val);
MIE_API struct mie_type *mie_value_get_type(
struct mie_value *val, struct mie_ctx *ctx);
static inline bool mie_value_is(
const struct mie_value *val, enum mie_value_type_id type_id)
{
if (!val->v_type) {
return false;
}
return val->v_type->t_id == type_id;
}
#endif

View File

@@ -1,17 +0,0 @@
#ifndef MIE_MISC_H_
#define MIE_MISC_H_
#if defined(_MSC_VER) && MIE_STATIC == 0
#ifdef MIE_EXPORT
#define MIE_API extern __declspec(dllexport)
#else
#define MIE_API extern __declspec(dllimport)
#endif
#else
#define MIE_API extern
#endif
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif

View File

@@ -1,55 +0,0 @@
#ifndef MIE_NAME_H_
#define MIE_NAME_H_
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#define MIE_NAME_VALID(p) (((p)->n_str) != NULL)
struct mie_name_map;
enum mie_name_map_flags {
MIE_NAME_MAP_STRICT = 0x01u,
};
enum mie_name_map_entry_type {
MIE_NAME_MAP_E_NONE = 0,
MIE_NAME_MAP_E_NAME,
MIE_NAME_MAP_E_BUCKET,
};
struct mie_name_map_entry {
enum mie_name_map_entry_type e_type;
uint64_t e_hash;
union {
b_queue_entry e_entry;
b_btree_node e_node;
};
};
struct mie_name {
struct mie_name_map_entry n_base;
struct mie_name_map *n_parent;
char *n_str;
};
struct mie_name_bucket {
struct mie_name_map_entry b_base;
b_queue b_names;
};
struct mie_name_map {
b_btree m_entries;
size_t m_next_id;
};
extern struct mie_name_map *mie_name_map_create(void);
extern void mie_name_map_destroy(struct mie_name_map *map);
extern struct mie_name *mie_name_map_put(
struct mie_name_map *map, struct mie_name *entry, const char *hint,
enum mie_name_map_flags flags);
extern void mie_name_destroy(struct mie_name *name);
#endif

View File

@@ -1,55 +0,0 @@
#ifndef MIE_SELECT_BUILDER_H_
#define MIE_SELECT_BUILDER_H_
#include <mie/misc.h>
#include <mie/status.h>
struct mie_ctx;
struct mie_instr;
struct mie_value;
struct mie_select_builder;
struct mie_select_node;
struct mie_select_graph;
struct mie_select_value;
struct mie_target;
MIE_API struct mie_select_builder *mie_select_builder_create(
struct mie_ctx *ctx, const struct mie_target *target);
MIE_API void mie_select_builder_destroy(struct mie_select_builder *builder);
MIE_API struct mie_select_graph *mie_select_builder_get_graph(
struct mie_select_builder *builder);
MIE_API struct mie_ctx *mie_select_builder_get_ctx(
struct mie_select_builder *builder);
MIE_API const struct mie_target *mie_select_builder_get_target(
struct mie_select_builder *builder);
MIE_API struct mie_select_graph *mie_select_builder_finish(
struct mie_select_builder *builder);
MIE_API enum mie_status mie_select_builder_get_const(
struct mie_select_builder *builder, long long value,
struct mie_select_value *out);
MIE_API enum mie_status mie_select_builder_push_instr(
struct mie_select_builder *builder, struct mie_instr *instr);
MIE_API struct mie_select_node *mie_select_builder_find_node_with_ivalue(
struct mie_select_builder *builder, const struct mie_target *target,
unsigned int opcode, long long val);
MIE_API struct mie_select_value *mie_select_builder_get_value(
struct mie_select_builder *builder, struct mie_value *ir_val);
MIE_API enum mie_status mie_select_builder_set_value(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *graph_val);
MIE_API struct mie_select_value *mie_select_builder_get_mem_access(
struct mie_select_builder *builder, struct mie_value *ir_val);
MIE_API enum mie_status mie_select_builder_set_mem_access(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *graph_val);
MIE_API enum mie_status mie_select_builder_collapse_chain_ends(
struct mie_select_builder *builder, struct mie_select_value *out);
#endif

View File

@@ -1,54 +0,0 @@
#ifndef MIE_SELECT_GRAPH_H_
#define MIE_SELECT_GRAPH_H_
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <mie/misc.h>
#include <mie/target/target.h>
struct mie_ctx;
struct mie_type;
struct mie_instr;
struct mie_select_value {
struct mie_select_node *v_node;
unsigned int v_index;
};
struct mie_select_use {
struct mie_select_node *u_user;
struct mie_select_value u_value;
b_queue_entry u_entry;
};
struct mie_select_chain_end {
struct mie_select_value c_value;
b_queue_entry c_entry;
};
struct mie_select_graph {
b_queue g_nodes;
struct mie_select_node *g_root;
struct mie_select_value g_entry;
b_queue g_chain_ends;
size_t g_frame_index;
size_t g_node_id;
};
struct mie_select_use_iterator {
b_queue_entry *it_ptr;
};
MIE_API struct mie_select_graph *mie_select_graph_create(struct mie_ctx *ctx);
MIE_API void mie_select_graph_destroy(struct mie_select_graph *graph);
MIE_API enum mie_status mie_select_graph_get_node(
struct mie_select_graph *graph, const struct mie_target *target,
unsigned int op, struct mie_select_value **operands, size_t nr_operands,
struct mie_type **values, size_t nr_values, struct mie_select_node **out);
MIE_API void mie_select_graph_dump_text(struct mie_select_graph *graph);
MIE_API void mie_select_graph_dump_dot(
struct mie_select_graph *graph, const char *filename);
#endif

View File

@@ -1,104 +0,0 @@
#ifndef MIE_SELECT_NODE_H_
#define MIE_SELECT_NODE_H_
#include <blue/core/queue.h>
#include <mie/status.h>
#include <mie/type.h>
#define MIE_SELECT_NODE_OUTPUT_MAX 4
struct mie_target;
struct mie_value;
struct mie_select_value;
enum mie_select_node_flags {
MIE_SELECT_NODE_F_IVALUE = 0x01u,
MIE_SELECT_NODE_F_PVALUE = 0x02u,
};
struct mie_select_node {
size_t n_id;
unsigned long n_opcode;
enum mie_select_node_flags n_flags;
char *n_description;
/* certain "builtin" parameters that can be used by opcodes */
struct {
struct mie_value *v;
long long i;
void *p;
} n_value;
/* queue entry, links to mie_select_graph.g_nodes */
b_queue_entry n_entry;
/* linked lists of struct mie_select_use,
* listing all the places where this node is being used as an
* operand.
* these pointers point to data in another node's n_operands,
* and the memory belongs to these other nodes, not us.
*/
b_queue n_use;
/* array of struct mie_select_use
* listing all the nodes that are being used as operands by
* this node. other nodes hold pointers to these mie_select_use array
* entries as part of their n_use queue.
*/
struct mie_select_use *n_operands;
size_t n_nr_operands;
/* array of struct mie_type pointers
* listing the types of the values that are produced as outputs by
* this node. the type pointers themselves are owned by a mie_ctx.
*/
struct mie_type **n_results;
size_t n_nr_results;
/* the target system that provides the operation described by n_opcode. */
const struct mie_target *n_target;
};
struct mie_select_node_iterator {
b_queue_entry *it_ptr;
};
static inline struct mie_select_node *mie_select_node_iterator_unbox(
struct mie_select_node_iterator *it)
{
return b_unbox(struct mie_select_node, it->it_ptr, n_entry);
}
MIE_API void mie_select_node_iterator_next(struct mie_select_node_iterator *it);
MIE_API bool mie_select_node_iterator_is_valid(
const struct mie_select_node_iterator *it);
MIE_API struct mie_select_node *mie_select_node_create(
const struct mie_target *target, unsigned int op,
struct mie_type **results, size_t nr_results);
MIE_API void mie_select_node_destroy(struct mie_select_node *node);
MIE_API enum mie_status mie_select_node_set_operands(
struct mie_select_node *node, struct mie_select_value *operands,
size_t nr_operands);
MIE_API enum mie_status mie_select_node_clear_operands(struct mie_select_node *node);
MIE_API void mie_select_node_get_users(
struct mie_select_node *node, struct mie_select_node_iterator *it);
MIE_API void mie_select_node_get_uses(
struct mie_select_node *node, struct mie_select_node_iterator *it);
MIE_API enum mie_status mie_select_node_get_value(
struct mie_select_node *node, struct mie_type *type, size_t index,
struct mie_select_value *out);
MIE_API enum mie_status mie_select_node_set_description(
struct mie_select_node *node, const char *format, ...);
MIE_API struct mie_select_node *mie_select_node_get_glued_node(
struct mie_select_node *node);
MIE_API struct mie_select_node *mie_select_node_get_glued_user(
struct mie_select_node *node);
#endif

View File

@@ -1,33 +0,0 @@
#ifndef MIE_SELECT_OPCODE_H_
#define MIE_SELECT_OPCODE_H_
enum mie_select_opcode {
MIE_SELECT_OP_NONE = 0,
MIE_SELECT_OP_ENTRY,
MIE_SELECT_OP_ROOT,
MIE_SELECT_OP_BLOCK,
MIE_SELECT_OP_CONSTANT,
MIE_SELECT_OP_FRAME_INDEX,
MIE_SELECT_OP_REGISTER,
MIE_SELECT_OP_COPY_FROM_REG,
MIE_SELECT_OP_COPY_TO_REG,
MIE_SELECT_OP_GLOBAL_ADDRESS,
MIE_SELECT_OP_CHAIN_GROUP,
MIE_SELECT_OP_LOAD,
MIE_SELECT_OP_STORE,
MIE_SELECT_OP_ADD,
MIE_SELECT_OP_SUB,
MIE_SELECT_OP_MUL,
MIE_SELECT_OP_DIV,
MIE_SELECT_OP_XOR,
MIE_SELECT_OP_CMP_EQ,
MIE_SELECT_OP_CMP_NEQ,
MIE_SELECT_OP_CMP_LT,
MIE_SELECT_OP_CMP_GT,
MIE_SELECT_OP_CMP_LEQ,
MIE_SELECT_OP_CMP_GEQ,
MIE_SELECT_OP_BR,
MIE_SELECT_OP_BR_COND,
};
#endif

View File

@@ -1,24 +0,0 @@
#ifndef MIE_STATUS_H_
#define MIE_STATUS_H_
#include <mie/misc.h>
#define MIE_ERROR_VENDOR (ivy_error_vendor())
struct b_error_vendor;
enum mie_status {
MIE_SUCCESS = 0,
MIE_ERR_EOF,
MIE_ERR_BAD_SYNTAX,
MIE_ERR_BAD_FORMAT,
MIE_ERR_NOT_SUPPORTED,
MIE_ERR_INVALID_VALUE,
MIE_ERR_INTERNAL_FAILURE,
MIE_ERR_NO_MEMORY,
MIE_ERR_NO_ENTRY,
};
MIE_API const struct b_error_vendor *mie_error_vendor(void);
#endif

View File

@@ -1,36 +0,0 @@
#ifndef MIE_TARGET_SELECT_H_
#define MIE_TARGET_SELECT_H_
#include <mie/misc.h>
#include <mie/status.h>
#include <stddef.h>
struct mie_target;
struct mie_call;
struct mie_msg;
struct mie_select_builder;
struct mie_select_value;
struct mie_target_select_ops {
size_t (*s_node_name)(
const struct mie_target *, unsigned int, char *, size_t);
enum mie_status (*s_lower_call)(
const struct mie_target *, struct mie_select_builder *,
struct mie_call *, struct mie_select_value *);
enum mie_status (*s_lower_msg)(
const struct mie_target *, struct mie_select_builder *,
struct mie_msg *, struct mie_select_value *);
};
MIE_API size_t mie_target_select_node_name(
const struct mie_target *target, unsigned int opcode, char *out,
size_t max);
MIE_API enum mie_status mie_target_select_lower_call(
const struct mie_target *target, struct mie_select_builder *builder,
struct mie_call *call, struct mie_select_value *result);
MIE_API enum mie_status mie_target_select_lower_msg(
const struct mie_target *target, struct mie_select_builder *builder,
struct mie_msg *msg, struct mie_select_value *result);
#endif

View File

@@ -1,14 +0,0 @@
#ifndef MIE_TARGET_TARGET_H_
#define MIE_TARGET_TARGET_H_
#include <mie/misc.h>
#include <mie/target/select.h>
struct mie_target {
const char *t_name;
const struct mie_target_select_ops *t_select;
};
MIE_API const struct mie_target *mie_target_builtin(void);
#endif

View File

@@ -1,41 +0,0 @@
#ifndef MIE_TYPE_H_
#define MIE_TYPE_H_
#define MIE_TYPE(p) ((struct mie_type *)(p))
#include <mie/ir/value.h>
enum mie_type_id {
MIE_TYPE_VOID = 0x00u,
MIE_TYPE_INT = 0x01u,
MIE_TYPE_PTR = 0x02u,
MIE_TYPE_ID = 0x03u,
MIE_TYPE_STR = 0x04u,
MIE_TYPE_ATOM = 0x05u,
MIE_TYPE_CLASS = 0x06u,
MIE_TYPE_ARRAY = 0x08u,
MIE_TYPE_LABEL = 0x09u,
MIE_TYPE_SELECTOR = 0x0Au,
MIE_TYPE_FUNC = 0x0Bu,
MIE_TYPE_GLUE = 0xFEu,
MIE_TYPE_OTHER = 0xFFu,
__MIE_TYPE_COUNT,
};
struct mie_type {
struct mie_value t_base;
enum mie_type_id t_id;
unsigned int t_count;
union {
unsigned int t_width;
b_queue t_vars;
};
};
extern struct mie_type *mie_type_create(void);
MIE_API void mie_type_to_string(const struct mie_type *type, char *out, size_t max);
MIE_API bool mie_type_compare(const struct mie_type *a, const struct mie_type *b);
#endif

View File

@@ -1,30 +0,0 @@
#include <mie/ir/arg.h>
#include <stdlib.h>
#include <string.h>
struct mie_arg *mie_arg_create(struct mie_type *type)
{
struct mie_arg *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->arg_base, MIE_VALUE_ARG);
out->arg_type = type;
return out;
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
struct mie_arg *arg = MIE_ARG(v);
return arg->arg_type;
}
const struct mie_value_type arg_value_type = {
.t_id = MIE_VALUE_ARG,
.t_get_type = get_type,
};

View File

@@ -1,104 +0,0 @@
#include <mie/ctx.h>
#include <mie/ir/block.h>
#include <mie/ir/func.h>
#include <mie/ir/instr.h>
#include <mie/type.h>
#include <stdlib.h>
struct mie_block *mie_block_create(struct mie_func *parent, const char *name)
{
struct mie_block *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->b_base, MIE_VALUE_BLOCK);
struct mie_value *block = MIE_VALUE(out);
if (parent) {
block = mie_func_generate_value_name(parent, block, name);
if (!block) {
free(out);
return NULL;
}
b_queue_push_back(&parent->f_blocks, &block->v_entry);
out->b_parent = parent;
}
return out;
}
bool mie_block_add_instr(struct mie_block *block, struct mie_instr *instr)
{
switch (instr->i_type) {
case MIE_INSTR_PHI:
if (!b_queue_empty(&block->b_instr) || block->b_terminator) {
return false;
}
b_queue_push_back(&block->b_phi, &instr->i_base.v_entry);
return true;
case MIE_INSTR_RET:
case MIE_INSTR_BR:
case MIE_INSTR_SWITCH:
if (block->b_terminator) {
return false;
}
block->b_terminator = instr;
return true;
default:
if (block->b_terminator) {
return false;
}
b_queue_push_back(&block->b_instr, &instr->i_base.v_entry);
return true;
}
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
return mie_ctx_get_type(ctx, MIE_TYPE_LABEL);
}
static void cleanup(struct mie_value *value)
{
struct mie_block *block = MIE_BLOCK(value);
b_queue_entry *entry = b_queue_first(&block->b_phi);
b_queue_entry *next = NULL;
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&block->b_phi, entry);
mie_value_destroy(v);
entry = next;
}
entry = b_queue_first(&block->b_instr);
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&block->b_instr, entry);
mie_value_destroy(v);
entry = next;
}
if (block->b_terminator) {
mie_value_destroy(MIE_VALUE(block->b_terminator));
}
}
const struct mie_value_type block_value_type = {
.t_id = MIE_VALUE_BLOCK,
.t_get_type = get_type,
.t_cleanup = cleanup,
};

View File

@@ -1,834 +0,0 @@
#include <blue/ds/string.h>
#include <mie/ctx.h>
#include <mie/ir/alloca.h>
#include <mie/ir/block.h>
#include <mie/ir/branch.h>
#include <mie/ir/builder.h>
#include <mie/ir/data.h>
#include <mie/ir/func.h>
#include <mie/ir/module.h>
#include <mie/ir/msg.h>
#include <mie/ir/op.h>
#include <mie/ir/phi.h>
#include <mie/ir/ptr.h>
#include <mie/ir/record.h>
#include <mie/type.h>
#include <stdlib.h>
#include <string.h>
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);
}
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;
}
struct mie_record *mie_builder_put_record(
struct mie_builder *builder, struct mie_const *val, const char *name)
{
if (!builder->b_module) {
return NULL;
}
b_queue_entry *entry = b_queue_first(&builder->b_module->m_records);
while (entry) {
struct mie_value *rec = b_unbox(struct mie_value, entry, v_entry);
if (!strcmp(rec->v_name.n_str, name)) {
/* TODO what to do about `val` here? */
return MIE_RECORD(rec);
}
entry = b_queue_next(entry);
}
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);
return rec;
}
struct mie_record *mie_builder_get_record(
struct mie_builder *builder, const char *name)
{
if (!builder->b_module) {
return NULL;
}
b_queue_entry *entry = b_queue_first(&builder->b_module->m_records);
while (entry) {
struct mie_value *rec = b_unbox(struct mie_value, entry, v_entry);
if (!strcmp(rec->v_name.n_str, name)) {
return MIE_RECORD(rec);
}
entry = b_queue_next(entry);
}
return NULL;
}
#if 0
void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data)
{
if (!builder->b_module) {
return;
}
const char *data_name = data->d_base.v_name.n_str;
struct mie_data *v = mie_module_get_data(builder->b_module, data_name);
if (v) {
return;
}
mie_module_put_data(builder->b_module, data);
}
#endif
#if 0
void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type)
{
if (!builder->b_module) {
return;
}
const char *type_name = type->t_base.v_name.n_str;
struct mie_data *v = mie_module_get_data(builder->b_module, type_name);
if (v) {
return;
}
mie_module_put_data(builder->b_module, MIE_VALUE);
}
#endif
void mie_builder_set_insert_point(
struct mie_builder *builder, struct mie_block *block)
{
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, data_ident);
}
return MIE_VALUE(data);
}
struct mie_value *mie_builder_get_string_ptr(
struct mie_builder *builder, const char *s)
{
if (!builder->b_module) {
return NULL;
}
struct mie_data *data = mie_module_get_string_ptr(builder->b_module, s);
if (!data) {
struct mie_type *str
= mie_ctx_get_type(builder->b_ctx, MIE_TYPE_STR);
struct mie_value *value = mie_ctx_get_string(builder->b_ctx, s);
data = mie_data_create_const((struct mie_const *)value);
if (!data) {
return NULL;
}
mie_module_put_data(builder->b_module, data, ".str");
}
return MIE_VALUE(data);
}
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 = val;
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)
{
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, builder->b_ctx);
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(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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, builder->b_ctx);
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);
}
struct mie_value *mie_builder_mul(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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, builder->b_ctx);
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);
}
struct mie_value *mie_builder_div(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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, builder->b_ctx);
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);
}
struct mie_value *mie_builder_load(
struct mie_builder *builder, struct mie_type *type,
struct mie_value *src, const char *name)
{
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)
{
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)
{
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(
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)
{
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(
struct mie_builder *builder, struct mie_value *cond,
struct mie_block *if_true, struct mie_block *if_false)
{
if (!builder->b_current_block) {
return NULL;
}
if (builder->b_current_block->b_terminator) {
return NULL;
}
struct mie_branch_if *br = malloc(sizeof *br);
if (!br) {
return NULL;
}
memset(br, 0x0, sizeof *br);
mie_instr_init(&br->b_base, MIE_INSTR_BR_IF);
br->b_cond = cond;
br->b_true_block = if_true;
br->b_false_block = if_false;
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_msg(
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(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_EQ);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
struct mie_value *mie_builder_cmp_neq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_NEQ);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
struct mie_value *mie_builder_cmp_lt(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_LT);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
struct mie_value *mie_builder_cmp_gt(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_GT);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
struct mie_value *mie_builder_cmp_leq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_LEQ);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
struct mie_value *mie_builder_cmp_geq(
struct mie_builder *builder, struct mie_value *left,
struct mie_value *right, const char *name)
{
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_CMP_GEQ);
sub->op_left = left;
sub->op_right = right;
sub->op_type = mie_ctx_get_int_type(builder->b_ctx, 1);
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);
}
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_value *mie_builder_phi(
struct mie_builder *builder, struct mie_type *type,
struct mie_phi_edge *edges, unsigned int nr_edges, const char *name)
{
struct mie_block *block = builder->b_current_block;
if (!block) {
return NULL;
}
if (block->b_terminator || !b_queue_empty(&block->b_instr)) {
return NULL;
}
struct mie_phi *phi = malloc(sizeof *phi);
if (!phi) {
return NULL;
}
memset(phi, 0x0, sizeof *phi);
mie_instr_init(&phi->p_base, MIE_INSTR_PHI);
phi->p_type = type;
phi->p_nr_edges = nr_edges;
phi->p_edges = calloc(nr_edges, sizeof(struct mie_phi_edge));
if (!phi->p_edges) {
free(phi);
return NULL;
}
memcpy(phi->p_edges, edges, nr_edges * sizeof(struct mie_phi_edge));
if (!mie_block_add_instr(builder->b_current_block, &phi->p_base)) {
free(phi);
free(phi->p_edges);
return NULL;
}
mie_func_generate_value_name(
builder->b_current_block->b_parent, MIE_VALUE(phi), name);
return MIE_VALUE(phi);
}

View File

@@ -1,22 +0,0 @@
#include <mie/ir/const.h>
#include <stdlib.h>
#include <string.h>
void mie_const_init(struct mie_const *c, struct mie_type *type)
{
memset(c, 0x0, sizeof *c);
mie_value_init(&c->c_base, MIE_VALUE_CONST);
c->c_type = type;
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
struct mie_const *c = MIE_CONST(v);
return c->c_type;
}
const struct mie_value_type const_value_type = {
.t_id = MIE_VALUE_CONST,
.t_get_type = get_type,
};

View File

@@ -1,7 +0,0 @@
#include "convert.h"
b_status read_value_from_bitcode(
struct mie_ir_converter *converter, struct mie_value **out)
{
return B_ERR_NOT_SUPPORTED;
}

View File

@@ -1,7 +0,0 @@
#include "convert.h"
b_status write_value_to_bitcode(
struct mie_ir_converter *converter, struct mie_value *value)
{
return B_ERR_NOT_SUPPORTED;
}

View File

@@ -1,217 +0,0 @@
#include "convert.h"
#include <mie/ir/convert.h>
#include <mie/ir/value.h>
#include <stdlib.h>
#include <string.h>
struct mie_ir_converter *mie_ir_converter_create(
struct mie_ctx *ctx, enum mie_ir_format src, enum mie_ir_format dest)
{
if (src == dest) {
return NULL;
}
struct mie_ir_converter *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->c_ctx = ctx;
out->c_src_format = src;
out->c_dest_format = dest;
return out;
}
void mie_ir_converter_destroy(struct mie_ir_converter *converter)
{
free(converter);
}
b_status mie_ir_converter_set_src_value(
struct mie_ir_converter *converter, struct mie_value *value)
{
if (converter->c_src_format != MIE_IR_MEM) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_src_medium = MIE_IR_CONVERTER_MIE_VALUE;
converter->c_src.value = value;
return B_SUCCESS;
}
b_status mie_ir_converter_set_src_bitbuffer(
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer)
{
if (converter->c_src_format != MIE_IR_BITCODE) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_src_medium = MIE_IR_CONVERTER_BITBUFFER;
converter->c_src.bitbuffer = bitbuffer;
return B_SUCCESS;
}
b_status mie_ir_converter_set_src_stringstream(
struct mie_ir_converter *converter, b_stringstream *stringstream)
{
if (converter->c_src_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_src_medium = MIE_IR_CONVERTER_STRINGSTREAM;
converter->c_src.stringstream = stringstream;
return B_SUCCESS;
}
b_status mie_ir_converter_set_src_string(
struct mie_ir_converter *converter, b_string *string)
{
if (converter->c_src_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_src_medium = MIE_IR_CONVERTER_STRING;
converter->c_src.string = string;
return B_SUCCESS;
}
b_status mie_ir_converter_set_src_file(struct mie_ir_converter *converter, FILE *file)
{
if (converter->c_src_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_src_medium = MIE_IR_CONVERTER_FILE;
converter->c_src.file = file;
return B_SUCCESS;
}
b_status mie_ir_converter_set_dest_value(
struct mie_ir_converter *converter, struct mie_value **value)
{
if (converter->c_dest_format != MIE_IR_MEM) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_dest_medium = MIE_IR_CONVERTER_MIE_VALUE;
converter->c_dest.value = value;
return B_SUCCESS;
}
b_status mie_ir_converter_set_dest_bitbuffer(
struct mie_ir_converter *converter, b_bitbuffer *bitbuffer)
{
if (converter->c_dest_format != MIE_IR_BITCODE) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_dest_medium = MIE_IR_CONVERTER_BITBUFFER;
converter->c_dest.bitbuffer = bitbuffer;
return B_SUCCESS;
}
b_status mie_ir_converter_set_dest_stringstream(
struct mie_ir_converter *converter, b_stringstream *stringstream)
{
if (converter->c_dest_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_dest_medium = MIE_IR_CONVERTER_STRINGSTREAM;
converter->c_dest.stringstream = stringstream;
return B_SUCCESS;
}
b_status mie_ir_converter_set_dest_string(
struct mie_ir_converter *converter, b_string *string)
{
if (converter->c_dest_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_dest_medium = MIE_IR_CONVERTER_STRING;
converter->c_dest.string = string;
return B_SUCCESS;
}
b_status mie_ir_converter_set_dest_file(
struct mie_ir_converter *converter, FILE *file)
{
if (converter->c_dest_format != MIE_IR_TEXT) {
return B_ERR_INVALID_ARGUMENT;
}
converter->c_dest_medium = MIE_IR_CONVERTER_FILE;
converter->c_dest.file = file;
return B_SUCCESS;
}
static b_status read_value_from_medium(
struct mie_ir_converter *converter, struct mie_value **value)
{
switch (converter->c_src_format) {
case MIE_IR_MEM:
*value = converter->c_src.value;
return B_SUCCESS;
case MIE_IR_TEXT:
return read_value_from_text(converter, value);
case MIE_IR_BITCODE:
return read_value_from_bitcode(converter, value);
default:
return B_ERR_NOT_SUPPORTED;
}
}
static b_status write_value_to_medium(
struct mie_ir_converter *converter, struct mie_value *value)
{
switch (converter->c_dest_format) {
case MIE_IR_MEM:
*converter->c_dest.value = value;
return B_SUCCESS;
case MIE_IR_TEXT:
return write_value_to_text(converter, value);
case MIE_IR_BITCODE:
return write_value_to_bitcode(converter, value);
default:
return B_ERR_NOT_SUPPORTED;
}
}
b_status mie_ir_converter_process(struct mie_ir_converter *converter)
{
b_status status = B_SUCCESS;
struct mie_value *value = NULL;
status = read_value_from_medium(converter, &value);
if (!B_OK(status)) {
return status;
}
if (!value) {
return B_ERR_BAD_FORMAT;
}
status = write_value_to_medium(converter, value);
if (converter->c_src_format != MIE_IR_MEM) {
mie_value_destroy(value);
}
return status;
}

View File

@@ -1,19 +0,0 @@
#ifndef _MIE_CONVERT_H_
#define _MIE_CONVERT_H_
#include <mie/ir/convert.h>
extern b_status write_char(struct mie_ir_converter *converter, char c);
extern b_status write_string(struct mie_ir_converter *converter, const char *s);
extern b_status read_value_from_text(
struct mie_ir_converter *converter, struct mie_value **out);
extern b_status read_value_from_bitcode(
struct mie_ir_converter *converter, struct mie_value **out);
extern b_status write_value_to_text(
struct mie_ir_converter *converter, struct mie_value *value);
extern b_status write_value_to_bitcode(
struct mie_ir_converter *converter, struct mie_value *value);
#endif

View File

View File

View File

View File

View File

@@ -1,7 +0,0 @@
#include "convert.h"
b_status read_value_from_text(
struct mie_ir_converter *converter, struct mie_value **out)
{
return B_ERR_NOT_SUPPORTED;
}

View File

@@ -1,747 +0,0 @@
#include "convert.h"
#include <blue/ds/hashmap.h>
#include <blue/ds/list.h>
#include <inttypes.h>
#include <mie/ir/alloca.h>
#include <mie/ir/arg.h>
#include <mie/ir/block.h>
#include <mie/ir/branch.h>
#include <mie/ir/const.h>
#include <mie/ir/data.h>
#include <mie/ir/func.h>
#include <mie/ir/instr.h>
#include <mie/ir/module.h>
#include <mie/ir/msg.h>
#include <mie/ir/op.h>
#include <mie/ir/phi.h>
#include <mie/ir/ptr.h>
#include <mie/ir/record.h>
#include <mie/ir/value.h>
#include <mie/type.h>
#include <stdarg.h>
#define F_INCLUDE_TYPE 0x01u
typedef b_status (*write_function)(struct mie_ir_converter *, struct mie_value *);
b_status write_char(struct mie_ir_converter *converter, char c)
{
long result = 0;
char s[] = {c, '\0'};
switch (converter->c_dest_medium) {
case MIE_IR_CONVERTER_STRINGSTREAM:
return b_stream_write_string(
converter->c_dest.stringstream, s, NULL);
case MIE_IR_CONVERTER_STRING:
b_string_append_cstr(converter->c_dest.string, s);
return B_SUCCESS;
case MIE_IR_CONVERTER_FILE:
result = fputc(c, converter->c_dest.file);
return result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS;
default:
return B_ERR_NOT_SUPPORTED;
}
return B_SUCCESS;
}
b_status write_string(struct mie_ir_converter *converter, const char *s)
{
long result = 0;
switch (converter->c_dest_medium) {
case MIE_IR_CONVERTER_STRINGSTREAM:
return b_stream_write_string(
converter->c_dest.stringstream, s, NULL);
case MIE_IR_CONVERTER_STRING:
b_string_append_cstr(converter->c_dest.string, s);
return B_SUCCESS;
case MIE_IR_CONVERTER_FILE:
result = fputs(s, converter->c_dest.file);
return result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS;
default:
return B_ERR_NOT_SUPPORTED;
}
return B_SUCCESS;
}
b_status write_string_f(struct mie_ir_converter *converter, const char *format, ...)
{
long result = 0;
char buf[512];
va_list arg;
va_start(arg, format);
b_status status = B_SUCCESS;
switch (converter->c_dest_medium) {
case MIE_IR_CONVERTER_STRINGSTREAM:
vsnprintf(buf, sizeof buf, format, arg);
status = b_stream_write_string(
converter->c_dest.stringstream, buf, NULL);
break;
case MIE_IR_CONVERTER_STRING:
vsnprintf(buf, sizeof buf, format, arg);
b_string_append_cstr(converter->c_dest.string, buf);
status = B_SUCCESS;
break;
case MIE_IR_CONVERTER_FILE:
result = vfprintf(converter->c_dest.file, format, arg);
status = (result == EOF ? B_ERR_IO_FAILURE : B_SUCCESS);
break;
default:
status = B_ERR_NOT_SUPPORTED;
break;
}
va_end(arg);
return status;
}
static b_status write_operand_const(
struct mie_ir_converter *converter, struct mie_value *value, int flags)
{
struct mie_const *c = MIE_CONST(value);
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);
if (type_name[0] != 0) {
write_char(converter, ' ');
}
}
switch (c->c_type->t_id) {
case MIE_TYPE_INT: {
struct mie_int *v = MIE_INT(c);
write_string_f(converter, "#%" PRId64, v->i_value);
break;
}
case MIE_TYPE_PTR:
case MIE_TYPE_ID:
write_string_f(converter, "%%%s", value->v_name.n_str);
break;
case MIE_TYPE_STR: {
struct mie_string *v = MIE_STRING(c);
write_string_f(converter, "\"%s\"", v->s_value);
break;
}
case MIE_TYPE_ATOM: {
struct mie_atom *v = MIE_ATOM(c);
write_string_f(converter, "\"%s\"", v->a_value);
break;
}
case MIE_TYPE_SELECTOR: {
struct mie_selector *v = MIE_SELECTOR(c);
write_string_f(converter, "@%s", v->sel_value);
break;
}
case MIE_TYPE_CLASS:
write_string_f(converter, "@%s", value->v_name.n_str);
break;
case MIE_TYPE_ARRAY: {
struct mie_array *array = MIE_ARRAY(value);
b_iterator *it = b_list_begin(array->a_values);
write_char(converter, '{');
size_t i = 0;
b_foreach(void *, item, it)
{
if (i > 0) {
write_char(converter, ',');
}
write_string(converter, "\n ");
struct mie_value *child = item;
write_operand_const(converter, child, F_INCLUDE_TYPE);
i++;
}
b_iterator_unref(it);
if (!b_list_empty(array->a_values)) {
write_char(converter, '\n');
}
write_char(converter, '}');
break;
}
default:
break;
}
return B_SUCCESS;
}
static b_status write_operand_instr(
struct mie_ir_converter *converter, struct mie_value *value, int flags)
{
struct mie_instr *instr = MIE_INSTR(value);
if (flags & F_INCLUDE_TYPE) {
char type_name[64];
struct mie_type *type
= mie_value_get_type(value, converter->c_ctx);
mie_type_to_string(type, type_name, sizeof type_name);
write_string_f(converter, "%s ", type_name);
}
write_string_f(converter, "%%%s", value->v_name.n_str);
return B_SUCCESS;
}
static b_status write_operand_block(
struct mie_ir_converter *converter, struct mie_value *value, int flags)
{
struct mie_block *block = MIE_BLOCK(value);
if (flags & F_INCLUDE_TYPE) {
char type_name[64];
struct mie_type *type
= mie_value_get_type(value, converter->c_ctx);
mie_type_to_string(type, type_name, sizeof type_name);
write_string_f(converter, "%s ", type_name);
}
write_string_f(converter, "%%%s", value->v_name.n_str);
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_arg(
struct mie_ir_converter *converter, struct mie_value *value, int flags)
{
struct mie_arg *arg = MIE_ARG(value);
if (flags & F_INCLUDE_TYPE) {
char type_name[64];
mie_type_to_string(arg->arg_type, type_name, sizeof type_name);
write_string_f(converter, "%s ", type_name);
}
write_string_f(converter, "%%%s", value->v_name.n_str);
return B_SUCCESS;
}
static b_status write_operand_func(
struct mie_ir_converter *converter, struct mie_value *value, int flags)
{
struct mie_func *func = MIE_FUNC(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)
{
if (!value) {
write_string(converter, "<NULL VALUE PTR>");
return B_SUCCESS;
}
switch (value->v_type->t_id) {
case MIE_VALUE_NONE:
write_string(converter, "null");
return B_SUCCESS;
case MIE_VALUE_CONST:
return write_operand_const(converter, value, flags);
case MIE_VALUE_INSTR:
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);
case MIE_VALUE_FUNC:
return write_operand_func(converter, value, flags);
case MIE_VALUE_ARG:
return write_operand_arg(converter, value, flags);
default:
write_string_f(converter, "<unknown-value:%d>", value->v_type->t_id);
return B_SUCCESS;
}
}
static b_status write_module(
struct mie_ir_converter *converter, struct mie_value *value)
{
struct mie_module *mod = MIE_MODULE(value);
b_status status = B_SUCCESS;
b_queue_entry *entry = b_queue_first(&mod->m_records);
while (entry) {
struct mie_value *record
= b_unbox(struct mie_value, entry, v_entry);
status = write_value_to_text(converter, record);
if (!B_OK(status)) {
return status;
}
entry = b_queue_next(entry);
}
if (!b_queue_empty(&mod->m_records)) {
write_char(converter, '\n');
}
entry = b_queue_first(&mod->m_types);
while (entry) {
struct mie_value *type = b_unbox(struct mie_value, entry, v_entry);
status = write_value_to_text(converter, type);
if (!B_OK(status)) {
return status;
}
entry = b_queue_next(entry);
}
if (!b_queue_empty(&mod->m_types)) {
write_char(converter, '\n');
}
b_iterator *it = b_iterator_begin(mod->m_data);
b_foreach_ptr(b_hashmap_item, item, it)
{
struct mie_value *data = item->value.value_data;
status = write_value_to_text(converter, data);
if (!B_OK(status)) {
return status;
}
}
b_iterator_unref(it);
if (!b_hashmap_is_empty(mod->m_data)) {
write_char(converter, '\n');
}
unsigned long i = 0;
entry = b_queue_first(&mod->m_func);
while (entry) {
if (i > 0) {
write_char(converter, '\n');
}
struct mie_value *func = b_unbox(struct mie_value, entry, v_entry);
status = write_value_to_text(converter, func);
if (!B_OK(status)) {
return status;
}
i++;
entry = b_queue_next(entry);
}
return B_SUCCESS;
}
static b_status write_type_definition(
struct mie_ir_converter *converter, struct mie_value *value)
{
return B_SUCCESS;
}
static b_status write_record(
struct mie_ir_converter *converter, struct mie_value *value)
{
struct mie_record *rec = MIE_RECORD(value);
write_string_f(converter, "record %s", rec->r_base.v_name.n_str);
if (rec->r_value) {
write_string(converter, " = ");
write_operand_const(
converter, MIE_VALUE(rec->r_value), F_INCLUDE_TYPE);
}
write_char(converter, '\n');
return B_SUCCESS;
}
static b_status write_func_definition(
struct mie_ir_converter *converter, struct mie_value *value)
{
struct mie_func *func = MIE_FUNC(value);
char type_name[32];
mie_type_to_string(func->f_ret, type_name, sizeof type_name);
write_string_f(
converter, "define %s @%s(", type_name, func->f_base.v_name.n_str);
unsigned int i = 0;
struct b_queue_entry *entry = b_queue_first(&func->f_args);
while (entry) {
struct mie_arg *arg = (struct mie_arg *)b_unbox(
struct mie_value, entry, v_entry);
if (i > 0) {
write_string(converter, ", ");
}
mie_type_to_string(func->f_ret, type_name, sizeof type_name);
write_string_f(
converter, "%s %%%s", type_name,
arg->arg_base.v_name.n_str);
i++;
entry = b_queue_next(entry);
}
write_string_f(converter, ")");
switch (func->f_type) {
case MIE_FUNC_STATIC:
write_string_f(converter, " static");
break;
case MIE_FUNC_INSTANCE:
write_string_f(converter, " instance");
break;
case MIE_FUNC_LAMBDA:
write_string_f(converter, " lambda");
break;
default:
break;
}
write_string_f(converter, " {\n");
entry = b_queue_first(&func->f_blocks);
while (entry) {
struct mie_value *block
= b_unbox(struct mie_value, entry, v_entry);
write_value_to_text(converter, block);
entry = b_queue_next(entry);
}
write_string_f(converter, "}\n");
return B_SUCCESS;
}
static b_status write_block_definition(
struct mie_ir_converter *converter, struct mie_value *value)
{
struct mie_block *block = MIE_BLOCK(value);
write_string_f(converter, "%s:\n", block->b_base.v_name.n_str);
b_queue_entry *entry = b_queue_first(&block->b_phi);
while (entry) {
struct mie_value *instr
= b_unbox(struct mie_value, entry, v_entry);
write_value_to_text(converter, instr);
entry = b_queue_next(entry);
}
entry = b_queue_first(&block->b_instr);
while (entry) {
struct mie_value *instr
= b_unbox(struct mie_value, entry, v_entry);
write_value_to_text(converter, instr);
entry = b_queue_next(entry);
}
if (block->b_terminator) {
write_value_to_text(converter, MIE_VALUE(block->b_terminator));
}
return B_SUCCESS;
}
static b_status write_instr(
struct mie_ir_converter *converter, struct mie_value *value)
{
struct mie_instr *instr = MIE_INSTR(value);
write_string_f(converter, "\t");
if (instr->i_base.v_name.n_str) {
write_string_f(converter, "%%%s = ", instr->i_base.v_name.n_str);
}
char type[128];
switch (instr->i_type) {
case MIE_INSTR_RET: {
struct mie_ret *ret = (struct mie_ret *)instr;
write_string(converter, "ret ");
if (!ret->r_val) {
write_string(converter, "void");
break;
}
write_operand(converter, ret->r_val, F_INCLUDE_TYPE);
break;
}
case MIE_INSTR_ADD: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "add %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_SUB: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "sub %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_MUL: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "mul %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_DIV: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "div %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_LOAD: {
struct mie_load *load = (struct mie_load *)instr;
mie_type_to_string(load->l_type, type, sizeof type);
write_string_f(converter, "load %s, ", type);
write_operand(converter, load->l_src, F_INCLUDE_TYPE);
break;
}
case MIE_INSTR_STORE: {
struct mie_store *store = (struct mie_store *)instr;
write_string(converter, "store ");
write_operand(converter, store->s_val, F_INCLUDE_TYPE);
write_string(converter, ", ");
write_operand(converter, store->s_dest, F_INCLUDE_TYPE);
break;
}
case MIE_INSTR_ALLOCA: {
struct mie_alloca *alloca = (struct mie_alloca *)instr;
mie_type_to_string(alloca->a_type, type, sizeof type);
write_string_f(converter, "alloca %s", type);
break;
}
case MIE_INSTR_SWITCH:
write_string(converter, "switch");
break;
case MIE_INSTR_BR: {
struct mie_branch *br = (struct mie_branch *)instr;
write_string(converter, "br ");
write_operand(converter, MIE_VALUE(br->b_dest), F_INCLUDE_TYPE);
break;
}
case MIE_INSTR_BR_IF: {
struct mie_branch_if *br = (struct mie_branch_if *)instr;
write_string(converter, "br ");
write_operand(converter, MIE_VALUE(br->b_cond), F_INCLUDE_TYPE);
write_string(converter, ", ");
write_operand(
converter, MIE_VALUE(br->b_true_block), F_INCLUDE_TYPE);
write_string(converter, ", ");
write_operand(
converter, MIE_VALUE(br->b_false_block), F_INCLUDE_TYPE);
break;
}
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: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp eq %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_CMP_NEQ: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp neq %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_CMP_LT: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp lt %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_CMP_LEQ: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp leq %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_CMP_GT: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp gt %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_CMP_GEQ: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
mie_type_to_string(op->op_type, type, sizeof type);
write_string_f(converter, "cmp geq %s ", type);
write_operand(converter, op->op_left, 0);
write_string(converter, ", ");
write_operand(converter, op->op_right, 0);
break;
}
case MIE_INSTR_GETELEMENTPTR:
write_string(converter, "getelementptr");
break;
case MIE_INSTR_SETELEMENTPTR:
write_string(converter, "setelementptr");
break;
case MIE_INSTR_PHI: {
struct mie_phi *phi = (struct mie_phi *)instr;
mie_type_to_string(phi->p_type, type, sizeof type);
write_string_f(converter, "phi %s ", type);
for (size_t i = 0; i < phi->p_nr_edges; i++) {
if (i > 0) {
write_string(converter, ", ");
}
write_string(converter, "[ ");
write_operand(
converter,
MIE_VALUE(phi->p_edges[i].e_incoming_block), 0);
write_string(converter, ", ");
write_operand(converter, phi->p_edges[i].e_value, 0);
write_string(converter, " ]");
}
break;
}
default:
write_string_f(converter, "<unknown>");
break;
}
write_char(converter, '\n');
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, MIE_VALUE(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,
[MIE_VALUE_RECORD] = write_record,
[MIE_VALUE_FUNC] = write_func_definition,
[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
= sizeof value_writers / sizeof value_writers[0];
b_status write_value_to_text(
struct mie_ir_converter *converter, struct mie_value *value)
{
write_function writer = value_writers[value->v_type->t_id];
return writer(converter, value);
}

View File

@@ -1,52 +0,0 @@
#include <blue/ds/string.h>
#include <mie/ctx.h>
#include <mie/ir/data.h>
#include <mie/type.h>
#include <stdlib.h>
#include <string.h>
struct mie_data *mie_data_create_extern_global(
struct mie_type *type, const char *ident)
{
struct mie_data *data = malloc(sizeof *data);
if (!data) {
return NULL;
}
memset(data, 0x0, sizeof *data);
mie_value_init(&data->d_base, MIE_VALUE_DATA);
data->d_type = MIE_DATA_EXTERN_GLOBAL;
data->d_extern_global.g_type = type;
data->d_base.v_name.n_str = b_strdup(ident);
return data;
}
struct mie_data *mie_data_create_const(struct mie_const *value)
{
struct mie_data *data = malloc(sizeof *data);
if (!data) {
return NULL;
}
memset(data, 0x0, sizeof *data);
mie_value_init(&data->d_base, MIE_VALUE_DATA);
data->d_type = MIE_DATA_CONST;
data->d_const.c_value = value;
return data;
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
return mie_ctx_get_type(ctx, MIE_TYPE_PTR);
}
const struct mie_value_type data_value_type = {
.t_id = MIE_VALUE_DATA,
.t_get_type = get_type,
};

View File

@@ -1,150 +0,0 @@
#include <blue/core/hash.h>
#include <blue/ds/string.h>
#include <mie/ir/arg.h>
#include <mie/ir/block.h>
#include <mie/ir/func.h>
#include <mie/name.h>
#include <stdlib.h>
#include <string.h>
struct mie_func *mie_func_create(enum mie_func_type type, struct mie_type *ret_type)
{
struct mie_func *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->f_base, MIE_VALUE_FUNC);
out->f_type = type;
out->f_ret = ret_type;
out->f_names = mie_name_map_create();
return out;
}
struct mie_value *mie_func_add_arg(
struct mie_func *func, struct mie_type *type, const char *name)
{
struct mie_arg *arg = mie_arg_create(type);
if (!arg) {
return NULL;
}
struct mie_value *v
= mie_func_generate_value_name(func, MIE_VALUE(arg), name);
if (!v) {
mie_value_destroy(MIE_VALUE(arg));
return NULL;
}
b_queue_push_back(&func->f_args, &v->v_entry);
return v;
}
struct mie_block *mie_func_create_block(struct mie_func *func, const char *name)
{
struct mie_block *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->b_base, MIE_VALUE_BLOCK);
struct mie_value *block = MIE_VALUE(out);
block = mie_func_generate_value_name(func, block, name);
if (!block) {
free(out);
return NULL;
}
out->b_parent = func;
return out;
}
void mie_func_insert_block(
struct mie_func *func, struct mie_block *block, struct mie_block *after)
{
if (after) {
b_queue_insert_after(
&func->f_blocks, &block->b_base.v_entry,
&after->b_base.v_entry);
} else {
b_queue_push_back(&func->f_blocks, &block->b_base.v_entry);
}
}
struct mie_value *mie_func_generate_value_name(
struct mie_func *func, struct mie_value *val, const char *hint)
{
struct mie_name *name
= mie_name_map_put(func->f_names, &val->v_name, hint, 0);
return b_unbox(struct mie_value, name, v_name);
}
struct mie_block *mie_func_get_first_block(struct mie_func *func)
{
b_queue_entry *entry = b_queue_first(&func->f_blocks);
if (!entry) {
return NULL;
}
return (struct mie_block *)b_unbox(struct mie_value, entry, v_entry);
}
struct mie_block *mie_func_get_last_block(struct mie_func *func)
{
b_queue_entry *entry = b_queue_last(&func->f_blocks);
if (!entry) {
return NULL;
}
return (struct mie_block *)b_unbox(struct mie_value, entry, v_entry);
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
struct mie_func *f = MIE_FUNC(v);
return f->f_ret;
}
static void cleanup(struct mie_value *value)
{
struct mie_func *func = MIE_FUNC(value);
b_queue_entry *entry = b_queue_first(&func->f_args);
b_queue_entry *next = NULL;
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&func->f_args, entry);
mie_value_destroy(v);
entry = next;
}
entry = b_queue_first(&func->f_blocks);
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&func->f_blocks, entry);
mie_value_destroy(v);
entry = next;
}
mie_name_map_destroy(func->f_names);
}
const struct mie_value_type func_value_type = {
.t_id = MIE_VALUE_FUNC,
.t_get_type = get_type,
.t_cleanup = cleanup,
};

View File

@@ -1,60 +0,0 @@
#include <mie/ctx.h>
#include <mie/ir/instr.h>
#include <mie/ir/msg.h>
#include <mie/ir/op.h>
#include <mie/ir/phi.h>
#include <mie/ir/ptr.h>
void mie_instr_init(struct mie_instr *instr, enum mie_instr_type type)
{
memset(instr, 0x0, sizeof *instr);
mie_value_init(&instr->i_base, MIE_VALUE_INSTR);
instr->i_type = type;
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
struct mie_instr *instr = MIE_INSTR(v);
switch (instr->i_type) {
case MIE_INSTR_RET: {
struct mie_ret *ret = (struct mie_ret *)instr;
return mie_value_get_type(ret->r_val, ctx);
}
case MIE_INSTR_ADD:
case MIE_INSTR_SUB:
case MIE_INSTR_MUL:
case MIE_INSTR_DIV: {
struct mie_binary_op *op = (struct mie_binary_op *)instr;
return op->op_type;
}
case MIE_INSTR_CMP_EQ:
case MIE_INSTR_CMP_NEQ:
case MIE_INSTR_CMP_LT:
case MIE_INSTR_CMP_LEQ:
case MIE_INSTR_CMP_GT:
case MIE_INSTR_CMP_GEQ:
return mie_ctx_get_int_type(ctx, 1);
case MIE_INSTR_LOAD: {
struct mie_load *load = (struct mie_load *)instr;
return load->l_type;
}
case MIE_INSTR_ALLOCA:
return mie_ctx_get_type(ctx, MIE_TYPE_PTR);
case MIE_INSTR_MSG: {
struct mie_msg *msg = (struct mie_msg *)instr;
return msg->msg_ret_type;
}
case MIE_INSTR_PHI: {
struct mie_phi *phi = (struct mie_phi *)instr;
return phi->p_type;
}
default:
return NULL;
}
}
const struct mie_value_type instr_value_type = {
.t_id = MIE_VALUE_INSTR,
.t_get_type = get_type,
};

View File

@@ -1,154 +0,0 @@
#include <blue/ds/hashmap.h>
#include <mie/ir/const.h>
#include <mie/ir/data.h>
#include <mie/ir/func.h>
#include <mie/ir/module.h>
#include <mie/type.h>
#include <stdlib.h>
#include <string.h>
struct mie_module *mie_module_create(void)
{
struct mie_module *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->m_base, MIE_VALUE_MODULE);
out->m_names = mie_name_map_create();
out->m_data = b_hashmap_create(NULL, NULL);
out->m_data_strings = b_hashmap_create(NULL, NULL);
return out;
}
void mie_module_add_function(
struct mie_module *mod, struct mie_func *func, const char *name)
{
struct mie_value *v
= mie_module_generate_value_name(mod, MIE_VALUE(func), name);
if (!v) {
return;
}
b_queue_push_back(&mod->m_func, &v->v_entry);
}
struct mie_data *mie_module_get_string_ptr(struct mie_module *mod, const char *s)
{
b_hashmap_key key = {
.key_data = s,
.key_size = strlen(s),
};
const b_hashmap_value *entry = b_hashmap_get(mod->m_data_strings, &key);
if (entry) {
return entry->value_data;
}
return NULL;
}
struct mie_data *mie_module_get_data(struct mie_module *mod, const char *name)
{
b_hashmap_key key = {
.key_data = name,
.key_size = strlen(name),
};
const b_hashmap_value *entry = b_hashmap_get(mod->m_data, &key);
if (entry) {
return entry->value_data;
}
/* don't search m_data_strings, as it is keyed by the string contents
* rather than the data entry name, and its entries are duplicated in
* m_data anyway */
return NULL;
}
enum b_status mie_module_put_data(
struct mie_module *mod, struct mie_data *data, const char *name)
{
struct mie_value *v
= mie_module_generate_value_name(mod, MIE_VALUE(data), name);
b_hashmap_key key = {
.key_data = v->v_name.n_str,
.key_size = strlen(name),
};
b_hashmap_value value = {
.value_data = data,
.value_size = sizeof *data,
};
b_hashmap_put(mod->m_data, &key, &value);
if (data->d_type != MIE_DATA_CONST) {
return B_SUCCESS;
}
struct mie_const *const_data = data->d_const.c_value;
if (const_data->c_type->t_id == MIE_TYPE_STR) {
struct mie_string *s = MIE_STRING(const_data);
key.key_data = s->s_value;
key.key_size = strlen(key.key_data);
b_hashmap_put(mod->m_data_strings, &key, &value);
}
return B_SUCCESS;
}
struct mie_value *mie_module_generate_value_name(
struct mie_module *mod, struct mie_value *val, const char *hint)
{
struct mie_name *name
= mie_name_map_put(mod->m_names, &val->v_name, hint, 0);
return b_unbox(struct mie_value, name, v_name);
}
static void cleanup(struct mie_value *value)
{
struct mie_module *module = MIE_MODULE(value);
b_queue_entry *entry = b_queue_first(&module->m_records);
b_queue_entry *next = NULL;
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&module->m_records, entry);
mie_value_destroy(v);
entry = next;
}
entry = b_queue_first(&module->m_types);
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&module->m_types, entry);
mie_value_destroy(v);
entry = next;
}
entry = b_queue_first(&module->m_func);
while (entry) {
struct mie_value *v = b_unbox(struct mie_value, entry, v_entry);
next = b_queue_next(entry);
b_queue_delete(&module->m_func, entry);
mie_value_destroy(v);
entry = next;
}
b_hashmap_unref(module->m_data_strings);
b_hashmap_unref(module->m_data);
}
const struct mie_value_type module_value_type = {
.t_id = MIE_VALUE_MODULE,
.t_cleanup = cleanup,
};

View File

@@ -1,19 +0,0 @@
#include <mie/ir/phi.h>
#include <stdlib.h>
#include <string.h>
struct mie_phi_edge *mie_phi_edge_create(
struct mie_block *incoming_block, struct mie_value *value)
{
struct mie_phi_edge *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->e_incoming_block = incoming_block;
out->e_value = value;
return out;
}

View File

@@ -1,29 +0,0 @@
#include <mie/ir/record.h>
#include <stdlib.h>
#include <string.h>
struct mie_record *mie_record_create(const struct mie_const *val)
{
struct mie_record *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
mie_value_init(&out->r_base, MIE_VALUE_RECORD);
out->r_value = val;
return out;
}
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
struct mie_record *r = MIE_RECORD(v);
return r->r_value->c_type;
}
const struct mie_value_type record_value_type = {
.t_id = MIE_VALUE_RECORD,
.t_get_type = get_type,
};

View File

@@ -1,58 +0,0 @@
#include <mie/ir/const.h>
#include <mie/ir/value.h>
#include <stdlib.h>
const struct mie_value_type null_value_type = {
.t_id = MIE_VALUE_NONE,
};
extern const struct mie_value_type module_value_type;
extern const struct mie_value_type record_value_type;
extern const struct mie_value_type func_value_type;
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_value_type,
[MIE_VALUE_MODULE] = &module_value_type,
[MIE_VALUE_RECORD] = &record_value_type,
[MIE_VALUE_FUNC] = &func_value_type,
[MIE_VALUE_ARG] = &arg_value_type,
[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];
void mie_value_init(struct mie_value *val, enum mie_value_type_id type)
{
memset(val, 0x0, sizeof *val);
val->v_type = value_types[type];
}
void mie_value_destroy(struct mie_value *val)
{
if (val->v_type && val->v_type->t_cleanup) {
val->v_type->t_cleanup(val);
}
if (MIE_NAME_VALID(&val->v_name)) {
mie_name_destroy(&val->v_name);
}
free(val);
}
struct mie_type *mie_value_get_type(struct mie_value *val, struct mie_ctx *ctx)
{
if (val->v_type->t_get_type) {
return val->v_type->t_get_type(val, ctx);
}
return NULL;
}

View File

@@ -1,234 +0,0 @@
#include <blue/core/rope.h>
#include <blue/ds/string.h>
#include <mie/name.h>
#include <stdlib.h>
#include <string.h>
B_BTREE_DEFINE_SIMPLE_INSERT(struct mie_name_map_entry, e_node, e_hash, put_entry)
B_BTREE_DEFINE_SIMPLE_GET(
struct mie_name_map_entry, uint64_t, e_node, e_hash, get_entry)
static struct mie_name_bucket *create_bucket(void)
{
struct mie_name_bucket *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->b_base.e_type = MIE_NAME_MAP_E_BUCKET;
return out;
}
static void destroy_bucket(struct mie_name_bucket *bucket)
{
b_queue_entry *entry = b_queue_first(&bucket->b_names);
while (entry) {
b_queue_entry *next = b_queue_next(entry);
b_queue_delete(&bucket->b_names, entry);
entry = next;
}
free(bucket);
}
struct mie_name_map *mie_name_map_create(void)
{
struct mie_name_map *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
return out;
}
void mie_name_map_destroy(struct mie_name_map *map)
{
b_btree_node *node = b_btree_first(&map->m_entries);
while (node) {
struct mie_name_map_entry *entry
= b_unbox(struct mie_name_map_entry, node, e_node);
b_btree_node *next = b_btree_next(node);
b_btree_delete(&map->m_entries, node);
if (entry->e_type == MIE_NAME_MAP_E_BUCKET) {
struct mie_name_bucket *bucket
= (struct mie_name_bucket *)entry;
destroy_bucket(bucket);
}
node = next;
}
free(map);
}
static b_status put_name_in_bucket(
struct mie_name_bucket *bucket, struct mie_name *name)
{
b_queue_entry *entry = b_queue_first(&bucket->b_names);
while (entry) {
struct mie_name *cur = (struct mie_name *)b_unbox(
struct mie_name_map_entry, entry, e_entry);
if (!strcmp(cur->n_str, name->n_str)) {
return B_ERR_NAME_EXISTS;
}
entry = b_queue_next(entry);
}
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
return B_SUCCESS;
}
static b_status put_name(struct mie_name_map *map, struct mie_name *name)
{
struct mie_name_map_entry *entry
= get_entry(&map->m_entries, name->n_base.e_hash);
if (!entry) {
put_entry(&map->m_entries, &name->n_base);
return B_SUCCESS;
}
if (entry->e_type == MIE_NAME_MAP_E_BUCKET) {
struct mie_name_bucket *bucket = (struct mie_name_bucket *)entry;
return put_name_in_bucket(bucket, name);
}
struct mie_name *existing_name = (struct mie_name *)entry;
if (!strcmp(existing_name->n_str, name->n_str)) {
return B_ERR_NAME_EXISTS;
}
struct mie_name_bucket *bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
b_btree_delete(&map->m_entries, &entry->e_node);
entry->e_entry = B_QUEUE_ENTRY_INIT;
bucket->b_base.e_hash = name->n_base.e_hash;
b_queue_push_back(&bucket->b_names, &existing_name->n_base.e_entry);
b_queue_push_back(&bucket->b_names, &name->n_base.e_entry);
put_entry(&map->m_entries, &bucket->b_base);
return B_SUCCESS;
}
struct mie_name *mie_name_map_put(
struct mie_name_map *map, struct mie_name *entry, const char *hint,
enum mie_name_map_flags flags)
{
memset(entry, 0x0, sizeof *entry);
entry->n_base.e_type = MIE_NAME_MAP_E_NAME;
b_rope base = {};
if (hint) {
b_rope_init_cstr_borrowed(&base, hint);
}
char str[256];
if (hint) {
/* first try just the hint on its own */
b_rope_to_cstr(&base, str, sizeof str);
entry->n_str = str;
entry->n_base.e_hash = base.r_v.v_cstr.hash;
b_status status = put_name(map, entry);
if (B_OK(status)) {
entry->n_parent = map;
entry->n_str = b_strdup(str);
return entry;
}
}
if (flags & MIE_NAME_MAP_STRICT) {
/* the caller insists that `hint` be used as the name.
* such a name already exists, so we can't help them */
return NULL;
}
/* that name already exists, use a suffix to make the name unique.
* alternately, no hint was specified, so it's up to us to generate the name */
b_rope dot = B_ROPE_CHAR('.');
b_rope suffix = B_ROPE_UINT(0);
b_rope unique_name;
if (hint) {
const b_rope *parts[] = {&base, &dot, &suffix};
b_rope_join(&unique_name, parts, sizeof parts / sizeof parts[0]);
} else {
b_rope_concat(&unique_name, &base, &suffix);
}
size_t i = 0;
if (!hint || hint[0] == '\0') {
i = map->m_next_id++;
}
for (;; i++) {
suffix.r_v.v_uint = i;
b_rope_to_cstr(&unique_name, str, sizeof str);
entry->n_str = str;
entry->n_base.e_hash = b_hash_cstr(str);
b_status status = put_name(map, entry);
if (B_OK(status)) {
entry->n_parent = map;
entry->n_str = b_strdup(str);
b_rope_destroy(&unique_name);
return entry;
}
}
b_rope_destroy(&unique_name);
return NULL;
}
void mie_name_destroy(struct mie_name *name)
{
struct mie_name_map *parent = name->n_parent;
struct mie_name_map_entry *entry
= get_entry(&parent->m_entries, name->n_base.e_hash);
struct mie_name_bucket *bucket = NULL;
if (!entry) {
return;
}
switch (entry->e_type) {
case MIE_NAME_MAP_E_NAME:
b_btree_delete(&parent->m_entries, &entry->e_node);
break;
case MIE_NAME_MAP_E_BUCKET:
bucket = b_unbox(struct mie_name_bucket, entry, b_base);
b_queue_delete(&bucket->b_names, &name->n_base.e_entry);
break;
default:
abort();
return;
}
name->n_parent = NULL;
if (name->n_str) {
free(name->n_str);
name->n_str = NULL;
}
}

View File

@@ -1,37 +0,0 @@
#include "builder.h"
#include <mie/ctx.h>
#include <mie/ir/alloca.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
static enum mie_status push(
struct mie_select_builder *builder, struct mie_instr *instr)
{
struct mie_alloca *alloca = (struct mie_alloca *)instr;
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
struct mie_type *ptr_type = mie_ctx_get_type(
mie_select_builder_get_ctx(builder), MIE_TYPE_PTR);
struct mie_select_node *frame_index;
enum mie_status status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_FRAME_INDEX, NULL, 0,
&ptr_type, 1, &frame_index);
if (status != MIE_SUCCESS) {
return status;
}
frame_index->n_flags = MIE_SELECT_NODE_F_IVALUE;
frame_index->n_value.i = graph->g_frame_index++;
struct mie_select_value frame_index_value;
mie_select_node_get_value(frame_index, ptr_type, 0, &frame_index_value);
return mie_select_builder_set_value(
builder, MIE_VALUE(instr), &frame_index_value);
}
struct select_instr_type select_alloca = {
.i_push = push,
};

View File

@@ -1,69 +0,0 @@
#include "builder.h"
#include <mie/ir/op.h>
#include <mie/select/graph.h>
#define DEFINE_PUSH_FUNCTION(name, op) \
static enum mie_status push_##name( \
struct mie_select_builder *builder, struct mie_instr *instr) \
{ \
return push_op(op, builder, instr); \
}
#define DEFINE_OP(name) \
struct select_instr_type select_##name = { \
.i_push = push_##name, \
}
static enum mie_status push_op(
unsigned int opcode, struct mie_select_builder *builder,
struct mie_instr *instr)
{
struct mie_binary_op *op = (struct mie_binary_op *)instr;
struct mie_select_value *operands[] = {
mie_select_builder_get_value(builder, op->op_left),
mie_select_builder_get_value(builder, op->op_right),
};
size_t nr_operands = sizeof operands / sizeof operands[0];
struct mie_type *result[] = {
op->op_type,
};
size_t nr_results = sizeof result / sizeof result[0];
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
mie_select_builder_get_graph(builder), mie_target_builtin(),
opcode, operands, nr_operands, result, nr_results, &node);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value value;
mie_select_node_get_value(node, op->op_type, 0, &value);
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &value);
}
DEFINE_PUSH_FUNCTION(add, MIE_SELECT_OP_ADD);
DEFINE_PUSH_FUNCTION(sub, MIE_SELECT_OP_SUB);
DEFINE_PUSH_FUNCTION(mul, MIE_SELECT_OP_MUL);
DEFINE_PUSH_FUNCTION(div, MIE_SELECT_OP_DIV);
DEFINE_PUSH_FUNCTION(cmp_eq, MIE_SELECT_OP_CMP_EQ);
DEFINE_PUSH_FUNCTION(cmp_neq, MIE_SELECT_OP_CMP_NEQ);
DEFINE_PUSH_FUNCTION(cmp_lt, MIE_SELECT_OP_CMP_LT);
DEFINE_PUSH_FUNCTION(cmp_gt, MIE_SELECT_OP_CMP_GT);
DEFINE_PUSH_FUNCTION(cmp_leq, MIE_SELECT_OP_CMP_LEQ);
DEFINE_PUSH_FUNCTION(cmp_geq, MIE_SELECT_OP_CMP_GEQ);
DEFINE_OP(add);
DEFINE_OP(sub);
DEFINE_OP(mul);
DEFINE_OP(div);
DEFINE_OP(cmp_eq);
DEFINE_OP(cmp_neq);
DEFINE_OP(cmp_lt);
DEFINE_OP(cmp_gt);
DEFINE_OP(cmp_leq);
DEFINE_OP(cmp_geq);

View File

@@ -1,171 +0,0 @@
#include "builder.h"
#include <mie/ctx.h>
#include <mie/ir/branch.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
static enum mie_status get_block_node(
struct mie_select_builder *builder, struct mie_block *block,
struct mie_select_value *out)
{
struct mie_select_node *block_node = NULL;
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
struct mie_type *ptr_type = mie_ctx_get_type(
mie_select_builder_get_ctx(builder), MIE_TYPE_PTR);
enum mie_status status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_BLOCK, NULL, 0,
&ptr_type, 1, &block_node);
if (status != MIE_SUCCESS) {
return status;
}
block_node->n_value.v = MIE_VALUE(block);
block_node->n_flags |= MIE_SELECT_NODE_F_PVALUE;
return mie_select_node_get_value(block_node, ptr_type, 0, out);
}
static enum mie_status create_br_cond(
struct mie_select_builder *builder, struct mie_value *cond,
struct mie_select_value *incoming_chain, struct mie_block *dest_block,
struct mie_select_value *out)
{
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
if (!incoming_chain || !incoming_chain->v_node) {
incoming_chain = mie_select_builder_get_mem_access(builder, cond);
}
if (!incoming_chain || !incoming_chain->v_node) {
incoming_chain = &graph->g_entry;
}
struct mie_select_value dest;
enum mie_status status = get_block_node(builder, dest_block, &dest);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value *operands[] = {
incoming_chain,
mie_select_builder_get_value(builder, cond),
&dest,
};
size_t nr_operands = sizeof operands / sizeof operands[0];
struct mie_type *chain_type = mie_ctx_get_type(
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
struct mie_select_node *br_node = NULL;
status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_BR_COND, operands,
nr_operands, &chain_type, 1, &br_node);
if (status != MIE_SUCCESS) {
return status;
}
mie_select_node_get_value(br_node, chain_type, 0, out);
return MIE_SUCCESS;
}
static enum mie_status create_br(
struct mie_select_builder *builder, struct mie_block *dest_block,
struct mie_select_value *incoming_chain, struct mie_select_value *out)
{
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
if (!incoming_chain || !incoming_chain->v_node) {
incoming_chain = &graph->g_entry;
}
struct mie_select_value dest;
enum mie_status status = get_block_node(builder, dest_block, &dest);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value *operands[] = {
incoming_chain,
&dest,
};
size_t nr_operands = sizeof operands / sizeof operands[0];
struct mie_type *chain_type = mie_ctx_get_type(
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
struct mie_select_node *br_node = NULL;
status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_BR, operands,
nr_operands, &chain_type, 1, &br_node);
if (status != MIE_SUCCESS) {
return status;
}
mie_select_node_get_value(br_node, chain_type, 0, out);
return MIE_SUCCESS;
}
static enum mie_status push_br(
struct mie_select_builder *builder, struct mie_instr *instr)
{
struct mie_branch *br = (struct mie_branch *)instr;
struct mie_select_value incoming_chain = {};
enum mie_status status = mie_select_builder_collapse_chain_ends(
builder, &incoming_chain);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value br_result;
status = create_br(builder, br->b_dest, &incoming_chain, &br_result);
if (status != MIE_SUCCESS) {
return status;
}
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &br_result);
}
static enum mie_status push_br_if(
struct mie_select_builder *builder, struct mie_instr *instr)
{
struct mie_branch_if *br = (struct mie_branch_if *)instr;
struct mie_select_value incoming_chain = {};
enum mie_status status = mie_select_builder_collapse_chain_ends(
builder, &incoming_chain);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value br_true_result, br_false_result;
status = create_br_cond(
builder, br->b_cond, &incoming_chain, br->b_true_block,
&br_true_result);
if (status != MIE_SUCCESS) {
return status;
}
status = create_br(
builder, br->b_false_block, &br_true_result, &br_false_result);
if (status != MIE_SUCCESS) {
return status;
}
return mie_select_builder_set_value(
builder, MIE_VALUE(instr), &br_false_result);
}
struct select_instr_type select_br = {
.i_push = push_br,
};
struct select_instr_type select_br_if = {
.i_push = push_br_if,
};

View File

@@ -1,485 +0,0 @@
#include "builder.h"
#include <blue/ds/hashmap.h>
#include <mie/ctx.h>
#include <mie/ir/const.h>
#include <mie/ir/data.h>
#include <mie/ir/instr.h>
#include <mie/select/builder.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
#include <mie/target/target.h>
#include <stdlib.h>
#include <string.h>
struct mie_select_builder {
struct mie_ctx *b_ctx;
struct mie_select_graph *b_graph;
const struct mie_target *b_target;
/* map of mie_instr* to mie_select_value*, defining the graph node that
* corresponds to each value-producing instruction */
b_hashmap *b_nodes;
/* map of mie_instr* to mie_select_value*, defining the graph node that
* last accessed a memory location defined by a particular instruction. */
b_hashmap *b_mem_access;
};
struct mie_select_builder *mie_select_builder_create(
struct mie_ctx *ctx, const struct mie_target *target)
{
struct mie_select_builder *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->b_ctx = ctx;
out->b_target = target;
out->b_graph = mie_select_graph_create(ctx);
if (!out->b_graph) {
free(out);
return NULL;
}
out->b_nodes = b_hashmap_create(NULL, NULL);
if (!out->b_nodes) {
mie_select_graph_destroy(out->b_graph);
free(out);
return NULL;
}
out->b_mem_access = b_hashmap_create(NULL, NULL);
if (!out->b_mem_access) {
b_hashmap_unref(out->b_nodes);
mie_select_graph_destroy(out->b_graph);
free(out);
return NULL;
}
return out;
}
void mie_select_builder_destroy(struct mie_select_builder *builder)
{
if (builder->b_nodes) {
b_hashmap_unref(builder->b_nodes);
}
if (builder->b_mem_access) {
b_hashmap_unref(builder->b_mem_access);
}
if (builder->b_graph) {
mie_select_graph_destroy(builder->b_graph);
}
free(builder);
}
struct mie_select_graph *mie_select_builder_get_graph(
struct mie_select_builder *builder)
{
return builder->b_graph;
}
struct mie_ctx *mie_select_builder_get_ctx(struct mie_select_builder *builder)
{
return builder->b_ctx;
}
const struct mie_target *mie_select_builder_get_target(
struct mie_select_builder *builder)
{
return builder->b_target;
}
struct mie_select_graph *mie_select_builder_finish(struct mie_select_builder *builder)
{
enum mie_status status = MIE_SUCCESS;
struct mie_select_graph *graph = builder->b_graph;
struct mie_select_value *root_operands[] = {
NULL,
};
size_t nr_root_operands = 0;
struct mie_select_value incoming_chain = {};
status = mie_select_builder_collapse_chain_ends(builder, &incoming_chain);
if (status != MIE_SUCCESS) {
return NULL;
}
if (incoming_chain.v_node) {
root_operands[0] = &incoming_chain;
nr_root_operands++;
}
status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_ROOT, root_operands,
nr_root_operands, NULL, 0, &graph->g_root);
if (status != MIE_SUCCESS) {
return NULL;
}
b_hashmap_unref(builder->b_nodes);
builder->b_nodes = b_hashmap_create(NULL, NULL);
b_hashmap_unref(builder->b_mem_access);
builder->b_mem_access = b_hashmap_create(NULL, NULL);
builder->b_graph = mie_select_graph_create(builder->b_ctx);
return graph;
}
enum mie_status mie_select_builder_get_const(
struct mie_select_builder *builder, long long value,
struct mie_select_value *out)
{
const struct mie_target *builtin = mie_target_builtin();
struct mie_type *ctype = mie_ctx_get_int_type(builder->b_ctx, 32);
struct mie_select_node *node = NULL;
b_queue_entry *entry = b_queue_first(&builder->b_graph->g_nodes);
while (entry) {
node = b_unbox(struct mie_select_node, entry, n_entry);
if (node->n_target != builtin) {
goto skip;
}
if (node->n_opcode != MIE_SELECT_OP_CONSTANT) {
goto skip;
}
if (!(node->n_flags & MIE_SELECT_NODE_F_IVALUE)) {
goto skip;
}
if (node->n_value.i != value) {
goto skip;
}
mie_select_node_get_value(node, ctype, 0, out);
return MIE_SUCCESS;
skip:
entry = b_queue_next(entry);
}
enum mie_status status = mie_select_graph_get_node(
builder->b_graph, builtin, MIE_SELECT_OP_CONSTANT, NULL, 0,
&ctype, 1, &node);
if (status != MIE_SUCCESS) {
return status;
}
node->n_flags |= MIE_SELECT_NODE_F_IVALUE;
node->n_value.i = value;
mie_select_node_get_value(node, ctype, 0, out);
return MIE_SUCCESS;
}
enum mie_status mie_select_builder_push_instr(
struct mie_select_builder *builder, struct mie_instr *instr)
{
const struct select_instr_type *i_type
= select_type_for_instr(instr->i_type);
if (!i_type) {
return MIE_ERR_INVALID_VALUE;
}
return i_type->i_push(builder, instr);
}
static enum mie_status get_const_node(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *out)
{
struct mie_const *c = (struct mie_const *)ir_val;
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_CONSTANT,
NULL, 0, &c->c_type, 1, &node);
if (status != MIE_SUCCESS) {
return status;
}
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
node->n_value.v = ir_val;
mie_select_node_get_value(node, c->c_type, 0, out);
return MIE_SUCCESS;
}
static enum mie_status get_data_node(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *out)
{
struct mie_data *data = (struct mie_data *)ir_val;
unsigned int opcode = 0;
struct mie_type *type = NULL;
switch (data->d_type) {
case MIE_DATA_EXTERN_GLOBAL:
opcode = MIE_SELECT_OP_GLOBAL_ADDRESS;
type = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_PTR);
break;
default:
return MIE_ERR_INVALID_VALUE;
}
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
builder->b_graph, mie_target_builtin(), opcode, NULL, 0, &type,
1, &node);
if (status != MIE_SUCCESS) {
return status;
}
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
node->n_value.v = ir_val;
mie_select_node_get_value(node, type, 0, out);
return MIE_SUCCESS;
}
static enum mie_status get_external_value_node(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *out)
{
struct mie_type *type = mie_value_get_type(ir_val, builder->b_ctx);
if (!type) {
return MIE_ERR_INVALID_VALUE;
}
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_REGISTER,
NULL, 0, &type, 1, &node);
if (status != MIE_SUCCESS) {
return status;
}
node->n_flags = MIE_SELECT_NODE_F_PVALUE;
node->n_value.v = ir_val;
mie_select_node_get_value(node, type, 0, out);
return MIE_SUCCESS;
}
struct mie_select_value *mie_select_builder_get_value(
struct mie_select_builder *builder, struct mie_value *ir_val)
{
b_hashmap_key key = {
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
.key_data = ir_val,
.key_size = sizeof(struct mie_value *),
};
const b_hashmap_value *val = b_hashmap_get(builder->b_nodes, &key);
if (val) {
return val->value_data;
}
struct mie_select_value *select_val = malloc(sizeof *select_val);
if (!select_val) {
return NULL;
}
enum mie_status status = MIE_ERR_INVALID_VALUE;
switch (ir_val->v_type->t_id) {
case MIE_VALUE_CONST:
status = get_const_node(builder, ir_val, select_val);
break;
case MIE_VALUE_DATA:
status = get_data_node(builder, ir_val, select_val);
break;
default:
status = get_external_value_node(builder, ir_val, select_val);
break;
}
if (status != MIE_SUCCESS) {
return NULL;
}
key.key_data = ir_val;
key.key_size = sizeof(struct mie_value *);
b_hashmap_value hashmap_val = {
.value_data = select_val,
.value_size = sizeof *select_val,
};
b_hashmap_put(builder->b_nodes, &key, &hashmap_val);
return select_val;
}
enum mie_status mie_select_builder_set_value(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *graph_val)
{
struct mie_select_value *graph_val2 = malloc(sizeof *graph_val2);
if (!graph_val2) {
return MIE_ERR_NO_MEMORY;
}
memcpy(graph_val2, graph_val, sizeof *graph_val);
b_hashmap_key key = {
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
.key_data = ir_val,
.key_size = sizeof(struct mie_value *),
};
b_hashmap_value hashmap_val = {
.value_data = graph_val2,
.value_size = sizeof *graph_val2,
};
b_hashmap_put(builder->b_nodes, &key, &hashmap_val);
return MIE_SUCCESS;
}
struct mie_select_value *mie_select_builder_get_mem_access(
struct mie_select_builder *builder, struct mie_value *ir_val)
{
b_hashmap_key key = {
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
.key_data = ir_val,
.key_size = sizeof(struct mie_value *),
};
const b_hashmap_value *val = b_hashmap_get(builder->b_mem_access, &key);
if (val) {
return val->value_data;
}
return NULL;
}
enum mie_status mie_select_builder_set_mem_access(
struct mie_select_builder *builder, struct mie_value *ir_val,
struct mie_select_value *graph_val)
{
struct mie_select_value *graph_val2 = malloc(sizeof *graph_val2);
if (!graph_val2) {
return MIE_ERR_NO_MEMORY;
}
memcpy(graph_val2, graph_val, sizeof *graph_val);
b_hashmap_key key = {
.key_flags = B_HASHMAP_KEY_F_INTVALUE,
.key_data = ir_val,
.key_size = sizeof(struct mie_value *),
};
b_hashmap_value hashmap_val = {
.value_data = graph_val2,
.value_size = sizeof *graph_val2,
};
b_hashmap_put(builder->b_mem_access, &key, &hashmap_val);
return MIE_SUCCESS;
}
enum mie_status mie_select_builder_collapse_chain_ends(
struct mie_select_builder *builder, struct mie_select_value *out)
{
size_t nr_chains = b_queue_length(&builder->b_graph->g_chain_ends);
b_queue_entry *entry = NULL;
struct mie_select_chain_end *end = NULL;
switch (nr_chains) {
case 0:
memset(out, 0x0, sizeof *out);
return MIE_SUCCESS;
case 1:
entry = b_queue_first(&builder->b_graph->g_chain_ends);
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
memcpy(out, end, sizeof *out);
return MIE_SUCCESS;
default:
break;
}
struct mie_type *chain_type
= mie_ctx_get_type(builder->b_ctx, MIE_TYPE_OTHER);
struct mie_select_value **operands = calloc(nr_chains, sizeof *operands);
if (!operands) {
return MIE_ERR_NO_MEMORY;
}
entry = b_queue_first(&builder->b_graph->g_chain_ends);
size_t i = 0;
while (entry) {
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
operands[i++] = &end->c_value;
entry = b_queue_next(entry);
}
struct mie_select_node *group = NULL;
enum mie_status status = mie_select_graph_get_node(
builder->b_graph, mie_target_builtin(), MIE_SELECT_OP_CHAIN_GROUP,
operands, nr_chains, &chain_type, 1, &group);
free(operands);
if (status != MIE_SUCCESS) {
return status;
}
entry = b_queue_first(&builder->b_graph->g_chain_ends);
while (entry) {
end = b_unbox(struct mie_select_chain_end, entry, c_entry);
b_queue_entry *next = b_queue_next(entry);
b_queue_delete(&builder->b_graph->g_chain_ends, entry);
free(end);
entry = next;
}
struct mie_select_chain_end *group_end = malloc(sizeof *group_end);
if (!group_end) {
return MIE_ERR_NO_MEMORY;
}
memset(group_end, 0x0, sizeof *group_end);
mie_select_node_get_value(group, chain_type, 0, &group_end->c_value);
b_queue_push_back(&builder->b_graph->g_chain_ends, &group_end->c_entry);
*out = group_end->c_value;
return MIE_SUCCESS;
}
struct mie_select_node *mie_select_builder_find_node_with_ivalue(
struct mie_select_builder *builder, const struct mie_target *target,
unsigned int opcode, long long val)
{
b_queue_entry *entry = b_queue_first(&builder->b_graph->g_nodes);
while (entry) {
struct mie_select_node *node
= b_unbox(struct mie_select_node, entry, n_entry);
if (node->n_target == target && node->n_opcode == opcode
&& node->n_value.i == val) {
return node;
}
entry = b_queue_next(entry);
}
return NULL;
}

View File

@@ -1,25 +0,0 @@
#ifndef _SELECT_BUILDER_H_
#define _SELECT_BUILDER_H_
#include <mie/ir/instr.h>
#include <mie/select/builder.h>
#include <mie/select/node.h>
#include <mie/select/opcode.h>
#include <mie/status.h>
struct mie_select_value;
struct mie_select_builder;
struct select_instr_type {
enum mie_status (*i_push)(struct mie_select_builder *, struct mie_instr *);
};
struct select_node_type {
};
extern const struct select_instr_type *select_type_for_instr(
enum mie_instr_type instr);
extern const struct select_node_type *select_type_for_node(
enum mie_select_opcode node);
#endif

View File

@@ -1,292 +0,0 @@
#include <blue/io/file.h>
#include <blue/io/path.h>
#include <inttypes.h>
#include <mie/ir/const.h>
#include <mie/ir/value.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
#include <mie/target/select.h>
#include <stdio.h>
#include <stdlib.h>
static b_status write_operand_const(struct mie_value *value, b_stream *out)
{
struct mie_const *c = MIE_CONST(value);
switch (c->c_type->t_id) {
case MIE_TYPE_INT: {
struct mie_int *v = MIE_INT(c);
b_stream_write_fmt(out, NULL, "%" PRId64, v->i_value);
break;
}
case MIE_TYPE_PTR:
case MIE_TYPE_ID:
b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str);
break;
case MIE_TYPE_STR: {
struct mie_string *v = MIE_STRING(c);
b_stream_write_fmt(out, NULL, "\"%s\"", v->s_value);
break;
}
case MIE_TYPE_ATOM: {
struct mie_atom *v = MIE_ATOM(c);
b_stream_write_fmt(out, NULL, "\"%s\"", v->a_value);
break;
}
case MIE_TYPE_SELECTOR: {
struct mie_selector *v = MIE_SELECTOR(c);
b_stream_write_fmt(out, NULL, "\"%s\"", v->sel_value);
break;
}
case MIE_TYPE_CLASS:
b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str);
break;
default:
break;
}
return B_SUCCESS;
}
static void write_operand(struct mie_value *value, b_stream *out)
{
if (!value) {
b_stream_write_fmt(out, NULL, "null");
return;
}
switch (value->v_type->t_id) {
case MIE_VALUE_CONST:
write_operand_const(value, out);
break;
case MIE_VALUE_INSTR:
case MIE_VALUE_BLOCK:
case MIE_VALUE_ARG:
b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str);
break;
case MIE_VALUE_DATA:
case MIE_VALUE_FUNC:
b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str);
break;
default:
b_stream_write_fmt(
out, NULL, "unknown-value:%d", value->v_type->t_id);
break;
}
}
static void node_dump_text(struct mie_select_node *node)
{
printf("N%zu: ", node->n_id);
char tmp[128];
for (size_t i = 0; i < node->n_nr_results; i++) {
if (i > 0) {
printf(",");
}
if (node->n_results[i]->t_id == MIE_TYPE_OTHER) {
printf("ch");
} else {
mie_type_to_string(node->n_results[i], tmp, sizeof tmp);
printf("%s", tmp);
}
}
if (node->n_nr_results > 0) {
printf(" = ");
}
mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp);
printf("%s", tmp);
if (node->n_description) {
printf(" %s", node->n_description);
}
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
printf("<");
}
if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) {
printf("%lld", node->n_value.i);
}
if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE)
&& (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) {
printf(",");
}
if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) {
write_operand(node->n_value.v, b_stdout);
}
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
printf(">");
}
if (node->n_nr_operands) {
printf("(");
}
for (size_t i = 0; i < node->n_nr_operands; i++) {
if (i > 0) {
printf(", ");
}
const struct mie_select_value *value = &node->n_operands[i].u_value;
printf("N%zu:%u", value->v_node->n_id, value->v_index);
}
if (node->n_nr_operands) {
printf(")");
}
printf("\n");
}
static void node_dump_dot(struct mie_select_node *node, b_stream *out)
{
b_stream_write_fmt(out, NULL, "\tN%zu [label=\"{", node->n_id);
if (node->n_nr_operands > 0) {
b_stream_write_string(out, "{", NULL);
}
for (size_t i = 0; i < node->n_nr_operands; i++) {
if (i > 0) {
b_stream_write_string(out, "|", NULL);
}
b_stream_write_fmt(out, NULL, "<in%zu> %zu", i, i);
}
if (node->n_nr_operands > 0) {
b_stream_write_string(out, "}|", NULL);
}
char tmp[256];
mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp);
b_stream_write_fmt(out, NULL, "<Name> %s", tmp);
if (node->n_description) {
b_stream_write_fmt(out, NULL, " %s", node->n_description);
}
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
b_stream_write_string(out, "\\<", NULL);
}
if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) {
b_stream_write_fmt(out, NULL, "%lld", node->n_value.i);
}
if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE)
&& (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) {
b_stream_write_string(out, ",", NULL);
}
if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) {
write_operand(node->n_value.v, out);
}
if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) {
b_stream_write_string(out, "\\>", NULL);
}
b_stream_write_fmt(out, NULL, "|{N%zu}", node->n_id);
if (node->n_nr_results > 0) {
b_stream_write_string(out, "|{", NULL);
}
for (size_t i = 0; i < node->n_nr_results; i++) {
if (i > 0) {
b_stream_write_string(out, "|", NULL);
}
b_stream_write_fmt(out, NULL, "<out%zu> ", i, i);
if (node->n_results[i]->t_id == MIE_TYPE_OTHER) {
b_stream_write_string(out, "ch", NULL);
} else {
mie_type_to_string(node->n_results[i], tmp, sizeof tmp);
b_stream_write_string(out, tmp, NULL);
}
}
if (node->n_nr_results > 0) {
b_stream_write_string(out, "}", NULL);
}
b_stream_write_string(out, "}\"];\n", NULL);
}
static void node_links_dump_dot(struct mie_select_node *node, b_stream *out)
{
for (size_t i = 0; i < node->n_nr_operands; i++) {
struct mie_select_use *use = &node->n_operands[i];
b_stream_write_fmt(
out, NULL, "\tN%zu:in%zu -> N%zu:out%zu", node->n_id, i,
use->u_value.v_node->n_id, use->u_value.v_index);
if (use->u_value.v_node->n_results[use->u_value.v_index]->t_id
== MIE_TYPE_OTHER) {
b_stream_write_string(
out, "[style=dashed,color=blue]", NULL);
}
b_stream_write_string(out, ";\n", NULL);
}
}
void mie_select_graph_dump_text(struct mie_select_graph *graph)
{
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
while (entry) {
struct mie_select_node *node
= b_unbox(struct mie_select_node, entry, n_entry);
node_dump_text(node);
entry = b_queue_next(entry);
}
}
void mie_select_graph_dump_dot(struct mie_select_graph *graph, const char *filename)
{
FILE *fp = fopen(filename, "w");
b_stream *tmpstream = b_stream_open_fp(fp);
b_stream_write_string(tmpstream, "digraph G {\n", NULL);
b_stream_write_string(tmpstream, "\tnode [shape=Mrecord];\n", NULL);
b_stream_write_string(tmpstream, "\trankdir=\"BT\";\n", NULL);
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
while (entry) {
struct mie_select_node *node
= b_unbox(struct mie_select_node, entry, n_entry);
node_dump_dot(node, tmpstream);
entry = b_queue_next(entry);
}
entry = b_queue_first(&graph->g_nodes);
while (entry) {
struct mie_select_node *node
= b_unbox(struct mie_select_node, entry, n_entry);
node_links_dump_dot(node, tmpstream);
entry = b_queue_next(entry);
}
b_stream_write_string(tmpstream, "}\n", NULL);
b_stream_unref(tmpstream);
char cmd[256];
snprintf(cmd, sizeof cmd, "open %s", filename);
system(cmd);
fclose(fp);
}

View File

@@ -1,147 +0,0 @@
#include <assert.h>
#include <mie/ctx.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
#include <mie/select/opcode.h>
#include <mie/status.h>
#include <mie/target/target.h>
#include <stdlib.h>
#include <string.h>
struct mie_select_graph *mie_select_graph_create(struct mie_ctx *ctx)
{
struct mie_select_graph *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
enum mie_status status = MIE_SUCCESS;
struct mie_select_node *entry;
struct mie_type *entry_values[] = {
mie_ctx_get_type(ctx, MIE_TYPE_OTHER),
mie_ctx_get_type(ctx, MIE_TYPE_GLUE),
};
const size_t nr_entry_values
= sizeof entry_values / sizeof entry_values[0];
status = mie_select_graph_get_node(
out, mie_target_builtin(), MIE_SELECT_OP_ENTRY, NULL, 0,
entry_values, nr_entry_values, &entry);
if (status != MIE_SUCCESS) {
free(out);
return NULL;
}
mie_select_node_get_value(entry, entry_values[0], 0, &out->g_entry);
return out;
}
void mie_select_graph_destroy(struct mie_select_graph *graph)
{
b_queue_entry *entry = b_queue_first(&graph->g_nodes);
while (entry) {
struct mie_select_node *node
= b_unbox(struct mie_select_node, entry, n_entry);
b_queue_entry *next = b_queue_next(entry);
b_queue_delete(&graph->g_nodes, entry);
#if 0
if (node->n_value) {
mie_value_destroy(node->n_value);
}
#endif
free(node);
entry = next;
}
free(graph);
}
static enum mie_status update_chain_ends(
struct mie_select_graph *graph, struct mie_select_value *new_chain)
{
struct mie_select_node *new_node = new_chain->v_node;
b_queue_entry *entry = b_queue_first(&graph->g_chain_ends);
while (entry) {
struct mie_select_chain_end *end
= b_unbox(struct mie_select_chain_end, entry, c_entry);
struct mie_select_node *value_node = end->c_value.v_node;
for (size_t i = 0; i < new_node->n_nr_operands; i++) {
struct mie_select_node *operand_node
= new_node->n_operands[i].u_value.v_node;
if (value_node == operand_node) {
memcpy(&end->c_value, new_chain, sizeof *new_chain);
return MIE_SUCCESS;
}
}
entry = b_queue_next(entry);
}
struct mie_select_chain_end *end = malloc(sizeof *end);
if (!end) {
return MIE_ERR_NO_MEMORY;
}
memset(end, 0x0, sizeof *end);
memcpy(&end->c_value, new_chain, sizeof *new_chain);
b_queue_push_back(&graph->g_chain_ends, &end->c_entry);
return MIE_SUCCESS;
}
enum mie_status mie_select_graph_get_node(
struct mie_select_graph *graph, const struct mie_target *target,
unsigned int op, struct mie_select_value **operands, size_t nr_operands,
struct mie_type **values, size_t nr_values, struct mie_select_node **out)
{
struct mie_select_node *node = mie_select_node_create(
mie_target_builtin(), op, values, nr_values);
if (!node) {
return MIE_ERR_NO_MEMORY;
}
struct mie_select_value *operands2
= calloc(nr_operands, sizeof *operands2);
for (size_t i = 0; i < nr_operands; i++) {
assert(operands[i]);
memcpy(&operands2[i], operands[i], sizeof *operands2);
}
mie_select_node_set_operands(node, operands2, nr_operands);
free(operands2);
node->n_id = graph->g_node_id++;
node->n_target = target;
for (size_t i = 0; i < nr_values; i++) {
if (values[i]->t_id != MIE_TYPE_OTHER) {
continue;
}
struct mie_select_value chain = {
.v_node = node,
.v_index = i,
};
enum mie_status status = update_chain_ends(graph, &chain);
if (status != MIE_SUCCESS) {
return status;
}
}
b_queue_push_back(&graph->g_nodes, &node->n_entry);
*out = node;
return MIE_SUCCESS;
}

View File

@@ -1,45 +0,0 @@
#include "builder.h"
#include <mie/select/opcode.h>
#include <stddef.h>
#define DECLARE_INSTR_TYPE(name) extern struct select_instr_type select_##name
#define INSTR_TYPE_ENTRY(op, name) [MIE_INSTR_##op] = &select_##name
DECLARE_INSTR_TYPE(alloca);
DECLARE_INSTR_TYPE(add);
DECLARE_INSTR_TYPE(sub);
DECLARE_INSTR_TYPE(mul);
DECLARE_INSTR_TYPE(div);
DECLARE_INSTR_TYPE(cmp_eq);
DECLARE_INSTR_TYPE(cmp_neq);
DECLARE_INSTR_TYPE(cmp_lt);
DECLARE_INSTR_TYPE(cmp_gt);
DECLARE_INSTR_TYPE(cmp_leq);
DECLARE_INSTR_TYPE(cmp_geq);
DECLARE_INSTR_TYPE(load);
DECLARE_INSTR_TYPE(store);
DECLARE_INSTR_TYPE(msg);
DECLARE_INSTR_TYPE(br);
DECLARE_INSTR_TYPE(br_if);
static const struct select_instr_type *instr_types[] = {
INSTR_TYPE_ENTRY(ALLOCA, alloca), INSTR_TYPE_ENTRY(LOAD, load),
INSTR_TYPE_ENTRY(STORE, store), INSTR_TYPE_ENTRY(MSG, msg),
INSTR_TYPE_ENTRY(BR, br), INSTR_TYPE_ENTRY(BR_IF, br_if),
INSTR_TYPE_ENTRY(ADD, add), INSTR_TYPE_ENTRY(SUB, sub),
INSTR_TYPE_ENTRY(MUL, mul), INSTR_TYPE_ENTRY(DIV, div),
INSTR_TYPE_ENTRY(CMP_EQ, cmp_eq), INSTR_TYPE_ENTRY(CMP_NEQ, cmp_neq),
INSTR_TYPE_ENTRY(CMP_LT, cmp_lt), INSTR_TYPE_ENTRY(CMP_GT, cmp_gt),
INSTR_TYPE_ENTRY(CMP_LEQ, cmp_leq), INSTR_TYPE_ENTRY(CMP_GEQ, cmp_geq),
};
static const size_t nr_instr_types = sizeof instr_types / sizeof instr_types[0];
const struct select_instr_type *select_type_for_instr(enum mie_instr_type instr)
{
if (instr < 0 || instr >= nr_instr_types) {
return NULL;
}
return instr_types[instr];
}

View File

@@ -1,23 +0,0 @@
#include "builder.h"
#include <mie/ctx.h>
#include <mie/ir/ptr.h>
#include <mie/select/graph.h>
#include <mie/target/select.h>
static enum mie_status push(
struct mie_select_builder *builder, struct mie_instr *instr)
{
const struct mie_target *target = mie_select_builder_get_target(builder);
struct mie_msg *msg = (struct mie_msg *)instr;
struct mie_select_value result;
enum mie_status status
= mie_target_select_lower_msg(target, builder, msg, &result);
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &result);
}
struct select_instr_type select_msg = {
.i_push = push,
};

View File

@@ -1,183 +0,0 @@
#include "builder.h"
#include <blue/core/stringstream.h>
#include <mie/select/graph.h>
#include <mie/select/node.h>
#include <mie/select/opcode.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
static const struct select_node_type *node_types[] = {
};
static const size_t nr_node_types = sizeof node_types / sizeof node_types[0];
const struct select_node_type *select_type_for_node(enum mie_select_opcode node)
{
if (node < 0 || node >= nr_node_types) {
return NULL;
}
return node_types[node];
}
#if 0
void mie_select_node_iterator_next(struct mie_select_node_iterator *it)
{
b_queue_iterator_next(&it->it_base);
}
bool mie_select_node_iterator_is_valid(const struct mie_select_node_iterator *it)
{
return b_queue_iterator_is_valid(&it->it_base);
}
#endif
struct mie_select_node *mie_select_node_create(
const struct mie_target *target, unsigned int op,
struct mie_type **results, size_t nr_results)
{
struct mie_select_node *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->n_target = target;
out->n_opcode = op;
out->n_results = calloc(nr_results, sizeof(struct mie_type *));
if (!out->n_results) {
free(out);
return NULL;
}
out->n_nr_results = nr_results;
memcpy(out->n_results, results, nr_results * sizeof(struct mie_type *));
return out;
}
void mie_select_node_destroy(struct mie_select_node *node)
{
if (node->n_results) {
free(node->n_results);
}
mie_select_node_clear_operands(node);
free(node);
}
enum mie_status mie_select_node_set_operands(
struct mie_select_node *node, struct mie_select_value *operands,
size_t nr_operands)
{
mie_select_node_clear_operands(node);
if (!nr_operands) {
return MIE_SUCCESS;
}
struct mie_select_use *uses = calloc(nr_operands, sizeof *uses);
if (!uses) {
return MIE_ERR_NO_MEMORY;
}
memset(uses, 0x0, sizeof *uses);
for (size_t i = 0; i < nr_operands; i++) {
struct mie_select_node *operand_node = operands[i].v_node;
uses[i].u_user = node;
uses[i].u_value = operands[i];
b_queue_push_back(&operand_node->n_use, &uses[i].u_entry);
}
node->n_operands = uses;
node->n_nr_operands = nr_operands;
return MIE_SUCCESS;
}
enum mie_status mie_select_node_clear_operands(struct mie_select_node *node)
{
b_queue_entry *entry = b_queue_first(&node->n_use);
while (entry) {
struct mie_select_use *use
= b_unbox(struct mie_select_use, entry, u_entry);
if (use->u_value.v_node == node) {
memset(&use->u_value, 0x0, sizeof use->u_value);
}
entry = b_queue_next(entry);
}
if (node->n_operands) {
free(node->n_operands);
}
node->n_operands = NULL;
node->n_nr_operands = 0;
return MIE_SUCCESS;
}
void mie_select_node_get_users(
struct mie_select_node *node, struct mie_select_node_iterator *it)
{
}
void mie_select_node_get_uses(
struct mie_select_node *node, struct mie_select_node_iterator *it)
{
}
enum mie_status mie_select_node_get_value(
struct mie_select_node *node, struct mie_type *type, size_t index,
struct mie_select_value *out)
{
for (size_t i = 0; i < node->n_nr_results; i++) {
if (!mie_type_compare(node->n_results[i], type)) {
continue;
}
if (index > 0) {
index--;
continue;
}
out->v_node = node;
out->v_index = i;
return MIE_SUCCESS;
}
memset(out, 0x0, sizeof *out);
return MIE_ERR_NO_ENTRY;
}
enum mie_status mie_select_node_set_description(
struct mie_select_node *node, const char *format, ...)
{
va_list arg;
va_start(arg, format);
b_stringstream *str = b_stringstream_create();
b_stream_write_vfmt(str, NULL, format, arg);
va_end(arg);
node->n_description = b_stringstream_steal(str);
b_stringstream_unref(str);
return node->n_description ? MIE_SUCCESS : MIE_ERR_NO_MEMORY;
}
struct mie_select_node *mie_select_node_get_glued_node(struct mie_select_node *node)
{
return NULL;
}
struct mie_select_node *mie_select_node_get_glued_user(struct mie_select_node *node)
{
return NULL;
}

View File

@@ -1,2 +0,0 @@
#include <mie/select/node.h>
#include <mie/select/opcode.h>

View File

@@ -1,95 +0,0 @@
#include "builder.h"
#include <mie/ctx.h>
#include <mie/ir/ptr.h>
#include <mie/select/graph.h>
static enum mie_status push_load(
struct mie_select_builder *builder, struct mie_instr *instr)
{
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
struct mie_load *load = (struct mie_load *)instr;
struct mie_type *chain_type = mie_ctx_get_type(
mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER);
struct mie_select_value *chain
= mie_select_builder_get_mem_access(builder, load->l_src);
if (!chain) {
chain = &graph->g_entry;
}
struct mie_select_value *operands[] = {
chain,
mie_select_builder_get_value(builder, load->l_src),
};
size_t nr_operands = sizeof operands / sizeof operands[0];
struct mie_type *result[] = {
load->l_type,
chain_type,
};
size_t nr_results = sizeof result / sizeof result[0];
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_LOAD, operands,
nr_operands, result, nr_results, &node);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value value_result, chain_result;
mie_select_node_get_value(node, load->l_type, 0, &value_result);
mie_select_node_get_value(node, chain_type, 0, &chain_result);
mie_select_builder_set_mem_access(builder, load->l_src, &chain_result);
return mie_select_builder_set_value(
builder, MIE_VALUE(instr), &value_result);
}
static enum mie_status push_store(
struct mie_select_builder *builder, struct mie_instr *instr)
{
struct mie_store *store = (struct mie_store *)instr;
struct mie_select_graph *graph = mie_select_builder_get_graph(builder);
struct mie_select_value *chain
= mie_select_builder_get_mem_access(builder, store->s_dest);
if (!chain) {
chain = &graph->g_entry;
}
struct mie_select_value *operands[] = {
chain,
mie_select_builder_get_value(builder, store->s_val),
mie_select_builder_get_value(builder, store->s_dest),
};
size_t nr_operands = sizeof operands / sizeof operands[0];
struct mie_type *result[] = {
mie_ctx_get_type(mie_select_builder_get_ctx(builder), MIE_TYPE_OTHER),
};
size_t nr_results = sizeof result / sizeof result[0];
struct mie_select_node *node;
enum mie_status status = mie_select_graph_get_node(
graph, mie_target_builtin(), MIE_SELECT_OP_STORE, operands,
nr_operands, result, nr_results, &node);
if (status != MIE_SUCCESS) {
return status;
}
struct mie_select_value value;
mie_select_node_get_value(node, result[0], 0, &value);
mie_select_builder_set_mem_access(builder, store->s_dest, &value);
return mie_select_builder_set_value(builder, MIE_VALUE(instr), &value);
}
struct select_instr_type select_load = {
.i_push = push_load,
};
struct select_instr_type select_store = {
.i_push = push_store,
};

View File

@@ -1,31 +0,0 @@
#include <blue/core/error.h>
#include <errno.h>
#include <mie/status.h>
static const b_error_definition error_defs[] = {
B_ERROR_DEFINITION(MIE_SUCCESS, "SUCCESS", "Success"),
B_ERROR_DEFINITION(MIE_ERR_EOF, "EOF", "Unexpected end of file"),
B_ERROR_DEFINITION(MIE_ERR_BAD_SYNTAX, "BAD_SYNTAX", "Invalid syntax"),
B_ERROR_DEFINITION(MIE_ERR_NO_MEMORY, "NO_MEMORY", "Out of memory"),
B_ERROR_DEFINITION(
MIE_ERR_NOT_SUPPORTED, "NOT_SUPPORTED",
"Operation not supported"),
B_ERROR_DEFINITION(
MIE_ERR_INTERNAL_FAILURE, "INTERNAL_FAILURE",
"Internal failure"),
B_ERROR_DEFINITION(
MIE_ERR_INVALID_VALUE, "INVALID_VALUE", "Invalid value"),
B_ERROR_DEFINITION(MIE_ERR_NO_ENTRY, "NO_ENTRY", "Name does not exist"),
B_ERROR_DEFINITION(MIE_ERR_BAD_FORMAT, "BAD_FORMAT", "Bad format"),
};
static const b_error_vendor error_vendor = {
.v_name = "Mie",
.v_error_definitions = error_defs,
.v_error_definitions_length = sizeof error_defs,
};
const struct b_error_vendor *mie_error_vendor(void)
{
return &error_vendor;
}

View File

@@ -1,92 +0,0 @@
#include <mie/select/opcode.h>
#include <mie/target/select.h>
#include <mie/target/target.h>
#include <stdio.h>
#define NODE_NAME(op, name) \
case MIE_SELECT_OP_##op: \
return snprintf(out, max, name)
static size_t node_name(
const struct mie_target *target, unsigned int opcode, char *out, size_t max)
{
switch (opcode) {
NODE_NAME(ENTRY, "Entry");
NODE_NAME(ROOT, "Root");
NODE_NAME(BLOCK, "Block");
NODE_NAME(CONSTANT, "Constant");
NODE_NAME(FRAME_INDEX, "FrameIndex");
NODE_NAME(REGISTER, "Register");
NODE_NAME(COPY_FROM_REG, "CopyFromReg");
NODE_NAME(COPY_TO_REG, "CopyToReg");
NODE_NAME(GLOBAL_ADDRESS, "GlobalAddress");
NODE_NAME(CHAIN_GROUP, "ChainGroup");
NODE_NAME(LOAD, "Load");
NODE_NAME(STORE, "Store");
NODE_NAME(ADD, "Add");
NODE_NAME(SUB, "Sub");
NODE_NAME(MUL, "Mul");
NODE_NAME(DIV, "Div");
NODE_NAME(CMP_EQ, "Cmp.Eq");
NODE_NAME(CMP_NEQ, "Cmp.Neq");
NODE_NAME(CMP_LT, "Cmp.Lt");
NODE_NAME(CMP_GT, "Cmp.Gt");
NODE_NAME(CMP_LEQ, "Cmp.Leq");
NODE_NAME(CMP_GEQ, "Cmp.Geq");
NODE_NAME(XOR, "Xor");
NODE_NAME(BR, "Branch");
NODE_NAME(BR_COND, "CondBranch");
default:
return snprintf(out, max, "UNKNOWN");
}
return 0;
}
const struct mie_target_select_ops __mie_builtin_select_ops = {
.s_node_name = node_name,
};
size_t mie_target_select_node_name(
const struct mie_target *target, unsigned int opcode, char *out, size_t max)
{
size_t w = snprintf(out, max, "%s::", target->t_name);
if (w < max) {
max -= w;
} else {
max = 0;
}
out += w;
if (target->t_select && target->t_select->s_node_name) {
w += target->t_select->s_node_name(target, opcode, out, max);
} else {
w += snprintf(out, max, "%u", opcode);
}
return w;
}
enum mie_status mie_target_select_lower_call(
const struct mie_target *target, struct mie_select_builder *builder,
struct mie_call *call, struct mie_select_value *result)
{
if (!target->t_select || !target->t_select->s_lower_call) {
return MIE_ERR_NOT_SUPPORTED;
}
return target->t_select->s_lower_call(target, builder, call, result);
}
enum mie_status mie_target_select_lower_msg(
const struct mie_target *target, struct mie_select_builder *builder,
struct mie_msg *msg, struct mie_select_value *result)
{
if (!target->t_select || !target->t_select->s_lower_msg) {
return MIE_ERR_NOT_SUPPORTED;
}
return target->t_select->s_lower_msg(target, builder, msg, result);
}

View File

@@ -1,13 +0,0 @@
#include <mie/target/target.h>
const struct mie_target_select_ops __mie_builtin_select_ops;
static const struct mie_target builtin_target = {
.t_name = "Mie",
.t_select = &__mie_builtin_select_ops,
};
const struct mie_target *mie_target_builtin(void)
{
return &builtin_target;
}

View File

@@ -1,93 +0,0 @@
#include <mie/type.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct mie_type *get_type(struct mie_value *v, struct mie_ctx *ctx)
{
return MIE_TYPE(v);
}
const struct mie_value_type type_value_type = {
.t_id = MIE_VALUE_TYPE,
.t_get_type = get_type,
};
struct mie_type *mie_type_create(void)
{
struct mie_type *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->t_base.v_type = &type_value_type;
return out;
}
void mie_type_to_string(const struct mie_type *type, char *out, size_t max)
{
if (!type) {
snprintf(out, max, "no-type");
return;
}
switch (type->t_id) {
case MIE_TYPE_PTR:
snprintf(out, max, "ptr");
break;
case MIE_TYPE_VOID:
snprintf(out, max, "void");
break;
case MIE_TYPE_INT:
snprintf(out, max, "i%u", type->t_width);
break;
case MIE_TYPE_ID:
snprintf(out, max, "id");
break;
case MIE_TYPE_STR:
snprintf(out, max, "str");
break;
case MIE_TYPE_ATOM:
snprintf(out, max, "atom");
break;
case MIE_TYPE_LABEL:
snprintf(out, max, "label");
break;
case MIE_TYPE_ARRAY:
snprintf(out, max, "array");
break;
case MIE_TYPE_FUNC:
snprintf(out, max, "func");
break;
case MIE_TYPE_GLUE:
snprintf(out, max, "glue");
break;
case MIE_TYPE_SELECTOR:
snprintf(out, max, "");
break;
default:
snprintf(out, max, "unknown-type");
break;
}
}
bool mie_type_compare(const struct mie_type *a, const struct mie_type *b)
{
if (a->t_id != b->t_id) {
return false;
}
if (a->t_count != b->t_count) {
return false;
}
if (a->t_width != b->t_width) {
return false;
}
/* TODO compare complex types */
return true;
}