Compare commits
8 Commits
archive/le
...
79ab1c175b
| Author | SHA1 | Date | |
|---|---|---|---|
| 79ab1c175b | |||
| 0dce84cb7f | |||
| 2e22898fc8 | |||
| 86005451cb | |||
| 21bcbb7edc | |||
| 915cf836f2 | |||
| f9a2cf3b8e | |||
| 6573360656 |
@@ -11,5 +11,5 @@ else ()
|
||||
endif ()
|
||||
|
||||
target_include_directories(mie PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
target_link_libraries(mie Bluelib::Core Bluelib::Ds)
|
||||
target_link_libraries(mie Bluelib::Core Bluelib::Ds Bluelib::Io)
|
||||
target_compile_definitions(mie PRIVATE MIE_EXPORT=1 MIE_STATIC=${MIE_STATIC})
|
||||
|
||||
116
mie/ctx.c
116
mie/ctx.c
@@ -2,21 +2,33 @@
|
||||
#include <blue/ds/list.h>
|
||||
#include <blue/ds/string.h>
|
||||
#include <mie/ctx.h>
|
||||
#include <mie/ir/const.h>
|
||||
#include <mie/dialect/dialect.h>
|
||||
#include <mie/dialect/type.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DIALECT_NS_ID \
|
||||
MIE_ID(0xa1, 0x35, 0x01, 0x1b, 0xe4, 0x71, 0x46, 0x08, 0x92, 0xd4, \
|
||||
0xe6, 0x5a, 0x40, 0xba, 0x7f, 0xee)
|
||||
|
||||
#define TYPE_NS_ID \
|
||||
MIE_ID(0xf5, 0x4e, 0xc5, 0x8c, 0xc0, 0x1e, 0x48, 0x47, 0xb5, 0xf4, \
|
||||
0x7b, 0xb9, 0x6b, 0x47, 0xca, 0x48)
|
||||
|
||||
struct ctx_int_cache_entry {
|
||||
b_btree_node i_node;
|
||||
struct mie_type i_type;
|
||||
// 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;
|
||||
// struct mie_int i_value;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
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(
|
||||
@@ -281,3 +293,101 @@ struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx)
|
||||
|
||||
return MIE_VALUE(array);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct mie_ctx *mie_ctx_create(void)
|
||||
{
|
||||
struct mie_ctx *out = malloc(sizeof *out);
|
||||
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
mie_id dialects_ns = DIALECT_NS_ID;
|
||||
mie_id_map_init(&out->ctx_dialects, &dialects_ns);
|
||||
|
||||
mie_id types_ns = TYPE_NS_ID;
|
||||
mie_id_map_init(&out->ctx_types, &types_ns);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op)
|
||||
{
|
||||
if (op->op_flags & MIE_OP_F_RESOLVED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *dialect_name = NULL, *op_name = NULL;
|
||||
|
||||
char *dot = strchr(op->op_name, '.');
|
||||
if (dot) {
|
||||
*dot = 0;
|
||||
dialect_name = op->op_name;
|
||||
op_name = dot + 1;
|
||||
} else {
|
||||
dialect_name = NULL;
|
||||
op_name = op->op_name;
|
||||
}
|
||||
|
||||
const struct mie_dialect *dialect = mie_ctx_get_dialect(ctx, dialect_name);
|
||||
if (dot) {
|
||||
*dot = '.';
|
||||
}
|
||||
|
||||
/* dialect_name is no longer valid after this point */
|
||||
dialect_name = NULL;
|
||||
|
||||
if (!dialect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct mie_dialect_op *op_info
|
||||
= mie_dialect_get_op(dialect, op_name);
|
||||
if (!op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
op->op_dialect = dialect;
|
||||
op->op_info = op_info;
|
||||
|
||||
free(op->op_name);
|
||||
op->op_name = NULL;
|
||||
|
||||
op->op_flags |= MIE_OP_F_RESOLVED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct mie_dialect *mie_ctx_get_dialect(const struct mie_ctx *ctx, const char *name)
|
||||
{
|
||||
b_rope name_rope = B_ROPE_CSTR(name);
|
||||
mie_id id;
|
||||
mie_id_init_ns(&id, mie_id_map_get_ns(&ctx->ctx_dialects), &name_rope);
|
||||
|
||||
mie_id *target = mie_id_map_get(&ctx->ctx_dialects, &id);
|
||||
return b_unbox(struct mie_dialect, target, d_id);
|
||||
}
|
||||
|
||||
struct mie_dialect_type *mie_ctx_get_dialect_type(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *type_name)
|
||||
{
|
||||
b_rope dialect_name_rope = B_ROPE_CSTR(dialect_name);
|
||||
mie_id id;
|
||||
mie_id_init_ns(
|
||||
&id, mie_id_map_get_ns(&ctx->ctx_dialects), &dialect_name_rope);
|
||||
|
||||
mie_id *target = mie_id_map_get(&ctx->ctx_dialects, &id);
|
||||
struct mie_dialect *dialect = b_unbox(struct mie_dialect, target, d_id);
|
||||
if (!dialect) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b_rope type_name_rope = B_ROPE_CSTR(type_name);
|
||||
mie_id_init_ns(&id, mie_id_map_get_ns(&dialect->d_types), &type_name_rope);
|
||||
target = mie_id_map_get(&dialect->d_types, &id);
|
||||
|
||||
return b_unbox(struct mie_dialect_type, target, ty_id);
|
||||
}
|
||||
|
||||
151
mie/id.c
Normal file
151
mie/id.c
Normal file
@@ -0,0 +1,151 @@
|
||||
#include <blue/core/bstr.h>
|
||||
#include <blue/core/endian.h>
|
||||
#include <blue/core/hash.h>
|
||||
#include <blue/core/random.h>
|
||||
#include <mie/id.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline int id_memcmp(const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
return memcmp(a, b, MIE_ID_NR_BYTES);
|
||||
}
|
||||
|
||||
static mie_id *get_id(const b_btree *tree, mie_id *key)
|
||||
{
|
||||
b_btree_node *cur = tree->b_root;
|
||||
while (cur) {
|
||||
mie_id *cur_node = b_unbox(mie_id, cur, e_node);
|
||||
int cmp = memcmp(
|
||||
key->id_bytes, cur_node->id_bytes, sizeof key->id_bytes);
|
||||
|
||||
if (cmp > 0) {
|
||||
cur = b_btree_right(cur);
|
||||
} else if (cmp < 0) {
|
||||
cur = b_btree_left(cur);
|
||||
} else {
|
||||
return cur_node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void put_id(b_btree *tree, mie_id *node)
|
||||
{
|
||||
if (!tree->b_root) {
|
||||
tree->b_root = &node->e_node;
|
||||
b_btree_insert_fixup(tree, &node->e_node);
|
||||
return;
|
||||
}
|
||||
|
||||
b_btree_node *cur = tree->b_root;
|
||||
while (1) {
|
||||
mie_id *cur_node = b_unbox(mie_id, cur, e_node);
|
||||
b_btree_node *next = NULL;
|
||||
int cmp = memcmp(
|
||||
node->id_bytes, cur_node->id_bytes, sizeof node->id_bytes);
|
||||
|
||||
if (cmp > 0) {
|
||||
next = b_btree_right(cur);
|
||||
|
||||
if (!next) {
|
||||
b_btree_put_right(cur, &node->e_node);
|
||||
break;
|
||||
}
|
||||
} else if (cmp < 0) {
|
||||
next = b_btree_left(cur);
|
||||
|
||||
if (!next) {
|
||||
b_btree_put_left(cur, &node->e_node);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
cur = next;
|
||||
}
|
||||
|
||||
b_btree_insert_fixup(tree, &node->e_node);
|
||||
}
|
||||
|
||||
void mie_id_init(
|
||||
mie_id *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d, uint64_t e)
|
||||
{
|
||||
b_i32 x_a = b_i32_htob(a);
|
||||
b_i16 x_b = b_i16_htob(b);
|
||||
b_i16 x_c = b_i16_htob(c);
|
||||
b_i16 x_d = b_i16_htob(d);
|
||||
b_i64 x_e = b_i64_htob(e);
|
||||
|
||||
memcpy(&out->id_bytes[0], x_a.i_bytes, sizeof x_a.i_bytes);
|
||||
memcpy(&out->id_bytes[4], x_b.i_bytes, sizeof x_b.i_bytes);
|
||||
memcpy(&out->id_bytes[6], x_c.i_bytes, sizeof x_c.i_bytes);
|
||||
memcpy(&out->id_bytes[8], x_d.i_bytes, sizeof x_d.i_bytes);
|
||||
memcpy(&out->id_bytes[10], &x_e.i_bytes[2], sizeof x_e.i_bytes - 2);
|
||||
}
|
||||
|
||||
void mie_id_init_zero(mie_id *out)
|
||||
{
|
||||
memset(out, 0x0, sizeof *out);
|
||||
}
|
||||
|
||||
void mie_id_init_random(mie_id *out)
|
||||
{
|
||||
b_random_ctx *random = b_random_global_ctx();
|
||||
b_random_next_bytes(
|
||||
random, (unsigned char *)out->id_bytes, sizeof out->id_bytes);
|
||||
}
|
||||
|
||||
void mie_id_init_ns(mie_id *out, const mie_id *ns, const b_rope *name)
|
||||
{
|
||||
b_hash_ctx hash;
|
||||
b_hash_ctx_init(&hash, B_HASH_SHA1);
|
||||
|
||||
b_hash_ctx_update(&hash, ns->id_bytes, sizeof ns->id_bytes);
|
||||
b_hash_ctx_update_rope(&hash, name);
|
||||
|
||||
b_hash_ctx_finish(&hash, out->id_bytes, sizeof out->id_bytes);
|
||||
|
||||
out->id_bytes[6] &= 0x0F;
|
||||
out->id_bytes[6] |= 0x50;
|
||||
|
||||
out->id_bytes[8] &= 0x3F;
|
||||
out->id_bytes[8] |= 0x80;
|
||||
}
|
||||
|
||||
void mie_id_to_string(const mie_id *id, char *out, size_t max)
|
||||
{
|
||||
b_bstr str;
|
||||
b_bstr_begin(&str, out, max);
|
||||
for (size_t i = 0; i < sizeof id->id_bytes; i++) {
|
||||
if (i == 4 || i == 6 || i == 8 || i == 10) {
|
||||
b_bstr_write_char(&str, '-');
|
||||
}
|
||||
|
||||
b_bstr_write_fmt(&str, "%02x", id->id_bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void mie_id_map_init(struct mie_id_map *map, const mie_id *ns)
|
||||
{
|
||||
memset(map, 0x0, sizeof *map);
|
||||
|
||||
map->map_ns_id = *ns;
|
||||
}
|
||||
|
||||
const mie_id *mie_id_map_get_ns(const struct mie_id_map *map)
|
||||
{
|
||||
return &map->map_ns_id;
|
||||
}
|
||||
|
||||
void mie_id_map_put(struct mie_id_map *map, mie_id *id, const b_rope *name)
|
||||
{
|
||||
mie_id_init_ns(id, &map->map_ns_id, name);
|
||||
put_id(&map->map_entries, id);
|
||||
}
|
||||
|
||||
mie_id *mie_id_map_get(const struct mie_id_map *map, mie_id *id)
|
||||
{
|
||||
return get_id(&map->map_entries, id);
|
||||
}
|
||||
@@ -3,30 +3,44 @@
|
||||
|
||||
#include <blue/core/btree.h>
|
||||
#include <blue/ds/hashmap.h>
|
||||
#include <mie/type.h>
|
||||
#include <mie/id.h>
|
||||
|
||||
struct mie_op;
|
||||
|
||||
struct mie_ctx {
|
||||
#if 0
|
||||
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;
|
||||
#endif
|
||||
struct mie_id_map ctx_dialects;
|
||||
struct mie_id_map ctx_types;
|
||||
b_btree ctx_int_cache;
|
||||
b_btree ctx_float_cache;
|
||||
b_btree ctx_index_cache;
|
||||
};
|
||||
|
||||
extern struct mie_ctx *mie_ctx_create(void);
|
||||
extern void mie_ctx_destroy(struct mie_ctx *ctx);
|
||||
MIE_API struct mie_ctx *mie_ctx_create(void);
|
||||
MIE_API 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(
|
||||
MIE_API bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op);
|
||||
|
||||
MIE_API struct mie_dialect *mie_ctx_get_dialect(
|
||||
const struct mie_ctx *ctx, const char *name);
|
||||
MIE_API struct mie_dialect_type *mie_ctx_get_dialect_type(
|
||||
const struct mie_ctx *ctx, const char *dialect_name, const char *type_name);
|
||||
|
||||
MIE_API 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(
|
||||
MIE_API struct mie_type *mie_ctx_get_float_type(
|
||||
struct mie_ctx *ctx, unsigned int nr_bits);
|
||||
MIE_API struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx);
|
||||
MIE_API 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);
|
||||
MIE_API struct mie_value *mie_ctx_get_float(
|
||||
struct mie_ctx *ctx, double val, unsigned int nr_bits);
|
||||
MIE_API struct mie_value *mie_ctx_get_index(struct mie_ctx *ctx, size_t val);
|
||||
|
||||
#endif
|
||||
|
||||
60
mie/include/mie/id.h
Normal file
60
mie/include/mie/id.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef MIE_ID_H_
|
||||
#define MIE_ID_H_
|
||||
|
||||
#include <blue/core/btree.h>
|
||||
#include <blue/core/queue.h>
|
||||
#include <blue/core/rope.h>
|
||||
#include <mie/misc.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MIE_ID(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
|
||||
{ \
|
||||
.id_bytes = {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p}, \
|
||||
}
|
||||
#define MIE_ID_ZERO ((mie_id) {0})
|
||||
|
||||
#define MIE_ID_STRING_MAX 37
|
||||
|
||||
#define MIE_ID_NR_BYTES 16
|
||||
#define MIE_ID_NR_WORDS (MIE_ID_NR_BYTES / sizeof(uintptr_t))
|
||||
#define MIE_ID_NR_WORDS_16 (MIE_ID_NR_BYTES / sizeof(uint16_t))
|
||||
#define MIE_ID_NR_WORDS_32 (MIE_ID_NR_BYTES / sizeof(uint32_t))
|
||||
#define MIE_ID_NR_WORDS_64 (MIE_ID_NR_BYTES / sizeof(uint64_t))
|
||||
|
||||
typedef struct mie_id {
|
||||
union {
|
||||
uint8_t id_bytes[MIE_ID_NR_BYTES];
|
||||
uintptr_t id_words[MIE_ID_NR_WORDS];
|
||||
uint16_t id_words_16[MIE_ID_NR_WORDS_16];
|
||||
uint32_t id_words_32[MIE_ID_NR_WORDS_32];
|
||||
uint64_t id_words_64[MIE_ID_NR_WORDS_64];
|
||||
};
|
||||
|
||||
b_btree_node e_node;
|
||||
} mie_id;
|
||||
|
||||
struct mie_id_map {
|
||||
mie_id map_ns_id;
|
||||
b_btree map_entries;
|
||||
};
|
||||
|
||||
MIE_API void mie_id_init(
|
||||
mie_id *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d, uint64_t e);
|
||||
MIE_API void mie_id_init_zero(mie_id *out);
|
||||
MIE_API void mie_id_init_random(mie_id *out);
|
||||
MIE_API void mie_id_init_ns(mie_id *out, const mie_id *ns, const b_rope *name);
|
||||
|
||||
static inline int mie_id_compare(const mie_id *a, const mie_id *b)
|
||||
{
|
||||
return memcmp(a->id_bytes, b->id_bytes, sizeof a->id_bytes);
|
||||
}
|
||||
|
||||
MIE_API void mie_id_to_string(const mie_id *id, char *out, size_t max);
|
||||
|
||||
MIE_API void mie_id_map_init(struct mie_id_map *map, const mie_id *ns);
|
||||
MIE_API const mie_id *mie_id_map_get_ns(const struct mie_id_map *map);
|
||||
MIE_API void mie_id_map_put(struct mie_id_map *map, mie_id *id, const b_rope *name);
|
||||
MIE_API mie_id *mie_id_map_get(const struct mie_id_map *map, mie_id *id);
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,30 +1,21 @@
|
||||
#ifndef MIE_BLOCK_H_
|
||||
#define MIE_BLOCK_H_
|
||||
#ifndef MIE_IR_BLOCK_H_
|
||||
#define MIE_IR_BLOCK_H_
|
||||
|
||||
#define MIE_BLOCK(p) ((struct mie_block *)(p))
|
||||
#include <blue/core/queue.h>
|
||||
#include <mie/misc.h>
|
||||
#include <mie/name.h>
|
||||
#include <mie/vector.h>
|
||||
|
||||
#include <mie/ir/value.h>
|
||||
struct mie_op;
|
||||
struct mie_register;
|
||||
|
||||
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;
|
||||
struct mie_name b_name;
|
||||
|
||||
MIE_VECTOR_DECLARE(struct mie_register, b_params);
|
||||
MIE_VECTOR_DECLARE(struct mie_op, b_ops);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
MIE_API struct mie_op *mie_block_add_op(struct mie_block *block);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,37 +1,21 @@
|
||||
#ifndef MIE_MODULE_H_
|
||||
#define MIE_MODULE_H_
|
||||
#ifndef MIE_IR_MODULE_H_
|
||||
#define MIE_IR_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/misc.h>
|
||||
#include <mie/name.h>
|
||||
#include <mie/vector.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct mie_func;
|
||||
struct mie_op;
|
||||
|
||||
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;
|
||||
MIE_VECTOR_DECLARE(struct mie_op, m_ops);
|
||||
};
|
||||
|
||||
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);
|
||||
MIE_API struct mie_module *mie_module_create(void);
|
||||
MIE_API void mie_module_destroy(struct mie_module *mod);
|
||||
|
||||
extern struct mie_value *mie_module_generate_value_name(
|
||||
struct mie_module *mod, struct mie_value *val, const char *hint);
|
||||
MIE_API struct mie_op *mie_module_add_op(struct mie_module *mod);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -1,13 +1,55 @@
|
||||
#ifndef MIE_ARITH_H_
|
||||
#define MIE_ARITH_H_
|
||||
#ifndef MIE_IR_OP_H_
|
||||
#define MIE_IR_OP_H_
|
||||
|
||||
#include <mie/ir/instr.h>
|
||||
#include "mie/vector.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;
|
||||
#include <mie/misc.h>
|
||||
#include <mie/name.h>
|
||||
|
||||
struct mie_type;
|
||||
|
||||
struct mie_value;
|
||||
struct mie_block;
|
||||
struct mie_region;
|
||||
struct mie_register;
|
||||
|
||||
struct mie_dialect;
|
||||
struct mie_dialect_op;
|
||||
|
||||
enum mie_op_flags {
|
||||
MIE_OP_F_RESOLVED = 0x01u,
|
||||
};
|
||||
|
||||
struct mie_op_successor {
|
||||
struct mie_block *s_block;
|
||||
MIE_VECTOR_DECLARE(struct mie_register *, s_params);
|
||||
};
|
||||
|
||||
struct mie_op_attribute {
|
||||
char *attrib_name;
|
||||
struct mie_value *attrib_value;
|
||||
};
|
||||
|
||||
struct mie_op {
|
||||
enum mie_op_flags op_flags;
|
||||
|
||||
/* these pointers are only valid if the F_RESOLVED flag is set */
|
||||
const struct mie_dialect *op_dialect;
|
||||
const struct mie_dialect_op *op_info;
|
||||
|
||||
/* this pointer is only valid if the F_RESOLVED flag is NOT set */
|
||||
char *op_name;
|
||||
|
||||
MIE_VECTOR_DECLARE(struct mie_region, op_regions);
|
||||
MIE_VECTOR_DECLARE(struct mie_op_successor, op_successors);
|
||||
MIE_VECTOR_DECLARE(struct mie_op_attribute, op_attrib);
|
||||
MIE_VECTOR_DECLARE(struct mie_register *, op_args);
|
||||
MIE_VECTOR_DECLARE(struct mie_register, op_result);
|
||||
};
|
||||
|
||||
MIE_API void mie_op_destroy(struct mie_op *op);
|
||||
|
||||
MIE_API struct mie_region *mie_op_add_region(struct mie_op *op);
|
||||
MIE_API struct mie_op_successor *mie_op_add_successor(struct mie_op *op);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
17
mie/include/mie/ir/region.h
Normal file
17
mie/include/mie/ir/region.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef MIE_IR_REGION_H_
|
||||
#define MIE_IR_REGION_H_
|
||||
|
||||
#include <mie/misc.h>
|
||||
#include <mie/vector.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct mie_block;
|
||||
|
||||
struct mie_region {
|
||||
struct mie_name_map *r_names;
|
||||
MIE_VECTOR_DECLARE(struct mie_block, r_blocks);
|
||||
};
|
||||
|
||||
MIE_API struct mie_block *mie_region_add_block(struct mie_region *region);
|
||||
|
||||
#endif
|
||||
38
mie/include/mie/ir/register.h
Normal file
38
mie/include/mie/ir/register.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MIE_IR_REGISTER_H_
|
||||
#define MIE_IR_REGISTER_H_
|
||||
|
||||
#include <mie/name.h>
|
||||
|
||||
struct mie_target_register;
|
||||
|
||||
enum mie_register_flags {
|
||||
MIE_REGISTER_F_NONE = 0,
|
||||
MIE_REGISTER_F_OP_RESULT = 0x01u,
|
||||
MIE_REGISTER_F_OP_PARAM = 0x02u,
|
||||
MIE_REGISTER_F_BLOCK_PARAM = 0x04u,
|
||||
|
||||
MIE_REGISTER_F_VIRTUAL = 0x10u,
|
||||
MIE_REGISTER_F_MACHINE = 0x20u,
|
||||
};
|
||||
|
||||
struct mie_register {
|
||||
enum mie_register_flags reg_flags;
|
||||
struct mie_name reg_name;
|
||||
/* only valid if F_MACHINE is set. */
|
||||
struct mie_target_register *reg_mach;
|
||||
struct mie_type *reg_value_type;
|
||||
/* if this is an OP_RESULT register, this points to the block within
|
||||
* which this register is defined.
|
||||
* if this is an OP_PARAM register, this pointer is NULL.
|
||||
* if this is a BLOCK_PARAM register, this points to the block for
|
||||
* which this register is a parameter. */
|
||||
struct mie_block *reg_block;
|
||||
/* if this is an OP_RESULT register, this points to the operation
|
||||
* that defines the register.
|
||||
* if this is an OP_PARAM register, this points to the operation
|
||||
* for which this register is a parameter
|
||||
* if this is a BLOCK_PARAM register, this pointer is NULL */
|
||||
struct mie_op *reg_op;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
70
mie/include/mie/macros.h
Normal file
70
mie/include/mie/macros.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef MIE_MACROS_H_
|
||||
#define MIE_MACROS_H_
|
||||
|
||||
#define __MIE_DIALECT_BEGIN(func_prefix, dialect_name) \
|
||||
struct mie_dialect *func_prefix##_dialect_create(struct mie_ctx *ctx) \
|
||||
{ \
|
||||
struct mie_dialect *self = mie_dialect_create(ctx, dialect_name); \
|
||||
if (!self) { \
|
||||
return NULL; \
|
||||
} \
|
||||
struct mie_dialect_op *op = NULL; \
|
||||
struct mie_dialect_type *type = NULL;
|
||||
|
||||
#define __MIE_DIALECT_END() \
|
||||
return self; \
|
||||
}
|
||||
|
||||
#define __MIE_DIALECT_OP_BEGIN(func_prefix, op_name) \
|
||||
struct mie_dialect_op *func_prefix##_op_create(struct mie_dialect *d) \
|
||||
{ \
|
||||
struct mie_dialect_op *op = mie_dialect_op_create(d, op_name); \
|
||||
if (!op) { \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define __MIE_DIALECT_OP_END() \
|
||||
return op; \
|
||||
}
|
||||
|
||||
#define __MIE_DIALECT_TYPE_BEGIN(func_prefix, type_name) \
|
||||
struct mie_dialect_type *func_prefix##_type_create(struct mie_dialect *d) \
|
||||
{ \
|
||||
struct mie_dialect_type *type \
|
||||
= mie_dialect_type_create(d, type_name); \
|
||||
if (!type) { \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define __MIE_DIALECT_TYPE_END() \
|
||||
return type; \
|
||||
}
|
||||
|
||||
#define __MIE_DIALECT_ADD_OP(op_id) \
|
||||
extern struct mie_dialect_op *op_id##_op_create(struct mie_dialect *); \
|
||||
op = op_id##_op_create(self)
|
||||
#define __MIE_DIALECT_ADD_TYPE(type_id) \
|
||||
extern struct mie_dialect_type *type_id##_type_create( \
|
||||
struct mie_dialect *); \
|
||||
type = type_id##_type_create(self)
|
||||
|
||||
#define MIE_DIALECT_BEGIN(c_sym, name) __MIE_DIALECT_BEGIN(c_sym, name)
|
||||
#define MIE_DIALECT_END() __MIE_DIALECT_END()
|
||||
#define MIE_DIALECT_ADD_OP(c_sym) __MIE_DIALECT_ADD_OP(c_sym)
|
||||
#define MIE_DIALECT_ADD_TYPE(c_sym) __MIE_DIALECT_ADD_TYPE(c_sym)
|
||||
|
||||
#define MIE_DIALECT_OP_BEGIN(c_sym, op) __MIE_DIALECT_OP_BEGIN(c_sym, op)
|
||||
#define MIE_DIALECT_OP_END() __MIE_DIALECT_OP_END()
|
||||
#define MIE_DIALECT_OP_PRINT(func) op->op_print = (func)
|
||||
#define MIE_DIALECT_OP_PARSE(func) op->op_parse = (func)
|
||||
|
||||
#define MIE_DIALECT_TYPE_BEGIN(c_sym, type) \
|
||||
__MIE_DIALECT_TYPE_BEGIN(c_sym, type)
|
||||
#define MIE_DIALECT_TYPE_END() __MIE_DIALECT_TYPE_END()
|
||||
#define MIE_DIALECT_TYPE_STRUCT(name) type->ty_data_size = sizeof(name)
|
||||
#define MIE_DIALECT_TYPE_PRINT(func) type->ty_print = (func)
|
||||
#define MIE_DIALECT_TYPE_PARSE(func) type->ty_parse = (func)
|
||||
#define MIE_DIALECT_TYPE_INIT(func) type->ty_init = (func)
|
||||
#define MIE_DIALECT_TYPE_CLEANUP(func) type->ty_cleanup = (func)
|
||||
|
||||
#endif
|
||||
18
mie/include/mie/parse/lex.h
Normal file
18
mie/include/mie/parse/lex.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef MIE_PARSE_LEX_H_
|
||||
#define MIE_PARSE_LEX_H_
|
||||
|
||||
#include <blue/core/stream.h>
|
||||
#include <mie/misc.h>
|
||||
#include <mie/status.h>
|
||||
|
||||
struct mie_lex;
|
||||
struct mie_token;
|
||||
|
||||
MIE_API struct mie_lex *mie_lex_create(b_stream *src);
|
||||
MIE_API void mie_lex_destroy(struct mie_lex *lex);
|
||||
|
||||
MIE_API enum mie_status mie_lex_get_status(const struct mie_lex *lex);
|
||||
MIE_API struct mie_token *mie_lex_peek(struct mie_lex *lex);
|
||||
MIE_API void mie_lex_advance(struct mie_lex *lex);
|
||||
|
||||
#endif
|
||||
111
mie/include/mie/parse/parse.h
Normal file
111
mie/include/mie/parse/parse.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef MIE_PARSE_PARSE_H_
|
||||
#define MIE_PARSE_PARSE_H_
|
||||
|
||||
#include <blue/ds/string.h>
|
||||
#include <mie/misc.h>
|
||||
#include <mie/parse/token.h>
|
||||
#include <mie/status.h>
|
||||
#include <mie/vector.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum mie_unresolved_operand_type {
|
||||
MIE_UNRESOLVED_OPERAND_NONE = 0,
|
||||
MIE_UNRESOLVED_OPERAND_VIRTUAL_REGISTER,
|
||||
MIE_UNRESOLVED_OPERAND_MACHINE_REGISTER,
|
||||
};
|
||||
|
||||
struct mie_parser;
|
||||
struct mie_name_map;
|
||||
struct mie_lex;
|
||||
struct mie_ctx;
|
||||
|
||||
struct mie_type;
|
||||
struct mie_module;
|
||||
struct mie_region;
|
||||
struct mie_op;
|
||||
struct mie_op_attribute;
|
||||
struct mie_op_successor;
|
||||
struct mie_register;
|
||||
|
||||
/* these structs are temporary, and are just here for documentation purposes atm */
|
||||
|
||||
struct mie_argument {
|
||||
};
|
||||
|
||||
struct mie_unresolved_operand {
|
||||
enum mie_unresolved_operand_type op_type;
|
||||
b_string *op_name;
|
||||
};
|
||||
|
||||
MIE_API struct mie_parser *mie_parser_create(
|
||||
struct mie_ctx *ctx, struct mie_lex *lex);
|
||||
MIE_API void mie_parser_destroy(struct mie_parser *ctx);
|
||||
MIE_API enum mie_status mie_parser_get_status(const struct mie_parser *ctx);
|
||||
|
||||
MIE_API struct mie_token *mie_parser_peek(struct mie_parser *ctx);
|
||||
MIE_API enum mie_token_type mie_parser_peek_type(struct mie_parser *ctx);
|
||||
MIE_API enum mie_token_symbol mie_parser_peek_symbol(struct mie_parser *ctx);
|
||||
MIE_API bool mie_parser_advance(struct mie_parser *ctx);
|
||||
|
||||
MIE_API bool mie_parser_check_eof(struct mie_parser *ctx);
|
||||
MIE_API bool mie_parser_check_type(struct mie_parser *ctx, enum mie_token_type type);
|
||||
MIE_API bool mie_parser_check_symbol(
|
||||
struct mie_parser *ctx, enum mie_token_symbol sym);
|
||||
|
||||
MIE_API bool mie_parser_parse_instname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_graphname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_opname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_vregname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_mregname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_blockname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_typename(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_symname(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_string(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_keyword(struct mie_parser *ctx, const char *kw);
|
||||
MIE_API bool mie_parser_parse_symbol(
|
||||
struct mie_parser *ctx, enum mie_token_symbol sym);
|
||||
MIE_API bool mie_parser_parse_assignment_list(
|
||||
struct mie_parser *ctx, struct mie_argument **out_lhs,
|
||||
struct mie_unresolved_operand **out_rhs, size_t *out_count);
|
||||
|
||||
MIE_API bool mie_parser_parse_type(struct mie_parser *ctx, struct mie_type **out);
|
||||
MIE_API bool mie_parser_parse_type_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_type *, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_operand(
|
||||
struct mie_parser *ctx, struct mie_unresolved_operand *out);
|
||||
MIE_API bool mie_parser_parse_operand_list(
|
||||
struct mie_parser *ctx,
|
||||
MIE_VECTOR_PARAM(struct mie_unresolved_operand, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_unknown_keyword(struct mie_parser *ctx, b_string *out);
|
||||
MIE_API bool mie_parser_parse_unknown_symbol(
|
||||
struct mie_parser *ctx, enum mie_token_symbol sym);
|
||||
|
||||
MIE_API bool mie_parser_parse_register(
|
||||
struct mie_parser *ctx, struct mie_name_map *names,
|
||||
struct mie_register *out);
|
||||
MIE_API bool mie_parser_parse_register_list(
|
||||
struct mie_parser *ctx, struct mie_name_map *names,
|
||||
MIE_VECTOR_PARAM(struct mie_register, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_region(
|
||||
struct mie_parser *ctx, struct mie_region *region);
|
||||
MIE_API bool mie_parser_parse_region_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_region, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_attribute(
|
||||
struct mie_parser *ctx, struct mie_op_attribute *attrib);
|
||||
MIE_API bool mie_parser_parse_attribute_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_op_attribute, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_successor(
|
||||
struct mie_parser *ctx, struct mie_op_successor *successor);
|
||||
MIE_API bool mie_parser_parse_successor_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_op_successor, out));
|
||||
|
||||
MIE_API bool mie_parser_parse_module(struct mie_parser *ctx, struct mie_module *mod);
|
||||
MIE_API bool mie_parser_parse_op(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest);
|
||||
|
||||
#endif
|
||||
97
mie/include/mie/parse/token.h
Normal file
97
mie/include/mie/parse/token.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#ifndef MIE_PARSE_TOKEN_H_
|
||||
#define MIE_PARSE_TOKEN_H_
|
||||
|
||||
#include <blue/core/queue.h>
|
||||
#include <mie/misc.h>
|
||||
|
||||
#define MIE_TOKEN_TYPE(tok) ((tok) ? (tok)->tok_type : MIE_TOK_NONE)
|
||||
#define MIE_TOKEN_IS(tok, type) ((tok) && ((tok)->tok_type & (type)) != 0)
|
||||
#define MIE_TOKEN_IS_SYMBOL(tok, sym) \
|
||||
((tok) && (tok)->tok_type == MIE_TOK_SYMBOL && (tok)->tok_sym == (sym))
|
||||
|
||||
enum mie_token_type {
|
||||
MIE_TOK_NONE = 0,
|
||||
MIE_TOK_LINEFEED = 0x0001u,
|
||||
MIE_TOK_INT = 0x0002u,
|
||||
MIE_TOK_DOUBLE = 0x0004u,
|
||||
MIE_TOK_SYMBOL = 0x0008u,
|
||||
MIE_TOK_STRING = 0x0010u,
|
||||
/* single words, not dot-delimited */
|
||||
MIE_TOK_WORD = 0x0020u,
|
||||
/* set of words with at least one dot */
|
||||
MIE_TOK_NAME = 0x0040u,
|
||||
/* word or name, prefixed with an * asterisk */
|
||||
MIE_TOK_INSTNAME = 0x0080u,
|
||||
/* word or name, prefixed with an @ at */
|
||||
MIE_TOK_SYMNAME = 0x0100u,
|
||||
/* word or name, prefixed with a ~ tilde */
|
||||
MIE_TOK_OPNAME = 0x0200u,
|
||||
/* word or name, prefixed with a + plus */
|
||||
MIE_TOK_GRAPHNAME = 0x0400u,
|
||||
/* word or name, prefixed with a % percent */
|
||||
MIE_TOK_VREGNAME = 0x0800u,
|
||||
/* word or name, prefixed with a $ dollar */
|
||||
MIE_TOK_MREGNAME = 0x1000u,
|
||||
/* word or name, prefixed with a ^ caret */
|
||||
MIE_TOK_BLOCKNAME = 0x2000u,
|
||||
/* word or name, prefixed with a # hash */
|
||||
MIE_TOK_TYPENAME = 0x4000u,
|
||||
};
|
||||
|
||||
enum mie_token_value_type {
|
||||
MIE_TOK_V_NONE = 0,
|
||||
MIE_TOK_V_INT,
|
||||
MIE_TOK_V_DOUBLE,
|
||||
MIE_TOK_V_STRING,
|
||||
MIE_TOK_V_SYMBOL,
|
||||
};
|
||||
|
||||
enum mie_token_symbol {
|
||||
MIE_SYM_NONE = 0,
|
||||
MIE_SYM_COLON,
|
||||
MIE_SYM_EQUAL,
|
||||
MIE_SYM_COMMA,
|
||||
MIE_SYM_HYPHEN,
|
||||
MIE_SYM_ASTERISK,
|
||||
MIE_SYM_PLUS,
|
||||
MIE_SYM_PERCENT,
|
||||
MIE_SYM_DOLLAR,
|
||||
MIE_SYM_CARET,
|
||||
MIE_SYM_HASH,
|
||||
MIE_SYM_TILDE,
|
||||
MIE_SYM_ATSIGN,
|
||||
MIE_SYM_LEFT_BRACE,
|
||||
MIE_SYM_RIGHT_BRACE,
|
||||
MIE_SYM_LEFT_BRACKET,
|
||||
MIE_SYM_RIGHT_BRACKET,
|
||||
MIE_SYM_LEFT_PAREN,
|
||||
MIE_SYM_RIGHT_PAREN,
|
||||
MIE_SYM_LEFT_ANGLE,
|
||||
MIE_SYM_RIGHT_ANGLE,
|
||||
MIE_SYM_HYPHEN_RIGHT_ANGLE,
|
||||
MIE_SYM_OTHER,
|
||||
};
|
||||
|
||||
struct mie_token_location {
|
||||
unsigned int c_row, c_col;
|
||||
};
|
||||
|
||||
struct mie_token {
|
||||
struct mie_token_location tok_start, tok_end;
|
||||
enum mie_token_type tok_type;
|
||||
enum mie_token_value_type tok_value_type;
|
||||
b_queue_entry tok_entry;
|
||||
|
||||
union {
|
||||
char *tok_str;
|
||||
enum mie_token_symbol tok_sym;
|
||||
long long tok_int;
|
||||
double tok_double;
|
||||
};
|
||||
};
|
||||
|
||||
MIE_API void mie_token_destroy(struct mie_token *tok);
|
||||
MIE_API const char *mie_token_type_to_string(enum mie_token_type type);
|
||||
MIE_API const char *mie_token_symbol_to_string(enum mie_token_symbol sym);
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
70
mie/include/mie/vector.h
Normal file
70
mie/include/mie/vector.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef MIE_VECTOR_H_
|
||||
#define MIE_VECTOR_H_
|
||||
|
||||
#include <mie/misc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MIE_VECTOR_DEFINE(type, name) \
|
||||
size_t name##_count = 0; \
|
||||
size_t name##_max = 0; \
|
||||
type *name = NULL
|
||||
|
||||
#define MIE_VECTOR_DECLARE(type, name) \
|
||||
size_t name##_count; \
|
||||
size_t name##_max; \
|
||||
type *name
|
||||
|
||||
#define MIE_VECTOR_COUNT(name) name##_count
|
||||
#define MIE_VECTOR_MAX(name) name##_max
|
||||
|
||||
#define MIE_VECTOR_PARAM(type, name) \
|
||||
type **name, size_t *name##_count, size_t *name##_max
|
||||
#define MIE_VECTOR_ARG(name) &(name), &(name##_count), &(name##_max)
|
||||
#define MIE_VECTOR_REF_ARG(name) (name), (name##_count), (name##_max)
|
||||
|
||||
#define mie_vector_push_back(vector, ptr) \
|
||||
__mie_vector_push_back( \
|
||||
(void **)&(vector), ptr, sizeof *ptr, &(vector##_count), \
|
||||
&(vector##_max))
|
||||
#define mie_vector_pop_back(vector) \
|
||||
__mie_vector_pop_back( \
|
||||
(void **)&(vector), sizeof *vector, &(vector##_count), \
|
||||
&(vector##_max))
|
||||
#define mie_vector_emplace_back(vector) \
|
||||
__mie_vector_emplace_back( \
|
||||
(void **)&(vector), sizeof *vector, &(vector##_count), \
|
||||
&(vector##_max))
|
||||
|
||||
#define mie_vector_ref_push_back(vector, ptr) \
|
||||
__mie_vector_push_back( \
|
||||
(void **)(vector), ptr, sizeof *ptr, (vector##_count), \
|
||||
(vector##_max))
|
||||
#define mie_vector_ref_pop_back(vector) \
|
||||
__mie_vector_pop_back( \
|
||||
(void **)(vector), sizeof **vector, (vector##_count), \
|
||||
(vector##_max))
|
||||
#define mie_vector_ref_emplace_back(vector) \
|
||||
__mie_vector_emplace_back( \
|
||||
(void **)(vector), sizeof **vector, (vector##_count), \
|
||||
(vector##_max))
|
||||
|
||||
#define mie_vector_destroy(vector, dtor) \
|
||||
__mie_vector_destroy( \
|
||||
(void **)&(vector), sizeof *vector, &(vector##_count), \
|
||||
&(vector##_max), dtor)
|
||||
#define mie_vector_ref_destroy(vector, dtor) \
|
||||
__mie_vector_destroy( \
|
||||
(void **)(vector), sizeof **vector, (vector##_count), \
|
||||
(vector##_max), dtor)
|
||||
|
||||
MIE_API int __mie_vector_push_back(
|
||||
void **vector, void *item, size_t item_size, size_t *count, size_t *max);
|
||||
MIE_API void __mie_vector_pop_back(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max);
|
||||
MIE_API void *__mie_vector_emplace_back(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max);
|
||||
MIE_API void __mie_vector_destroy(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max,
|
||||
void (*dtor)(void *));
|
||||
|
||||
#endif
|
||||
30
mie/ir/arg.c
30
mie/ir/arg.c
@@ -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,
|
||||
};
|
||||
104
mie/ir/block.c
104
mie/ir/block.c
@@ -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,
|
||||
};
|
||||
834
mie/ir/builder.c
834
mie/ir/builder.c
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
150
mie/ir/func.c
150
mie/ir/func.c
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
154
mie/ir/module.c
154
mie/ir/module.c
@@ -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,
|
||||
};
|
||||
19
mie/ir/phi.c
19
mie/ir/phi.c
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
898
mie/parse/lex.c
Normal file
898
mie/parse/lex.c
Normal file
@@ -0,0 +1,898 @@
|
||||
#include "lex.h"
|
||||
|
||||
#include <blue/core/hash.h>
|
||||
#include <blue/core/misc.h>
|
||||
#include <blue/core/queue.h>
|
||||
#include <blue/ds/dict.h>
|
||||
#include <blue/ds/number.h>
|
||||
#include <blue/ds/string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#define LINEBUF_DEFAULT_CAPACITY 1024
|
||||
|
||||
#define LEX_TOKEN_DEF(i, n) {.id = (i), .name = (n)}
|
||||
|
||||
#define IS_VALID_IDENT_CHAR(c) \
|
||||
(b_wchar_is_alnum(c) || c == '.' || c == '-' || c == '_')
|
||||
#define IS_VALID_IDENT_START_CHAR(c) \
|
||||
(b_wchar_is_alpha(c) || c == '.' || c == '_')
|
||||
#define IS_VALID_REG_START_CHAR(c) (b_wchar_is_alnum(c) || c == '.' || c == '_')
|
||||
|
||||
static struct lex_token_def symbols[] = {
|
||||
LEX_TOKEN_DEF(MIE_SYM_COLON, ":"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_EQUAL, "="),
|
||||
LEX_TOKEN_DEF(MIE_SYM_COMMA, ","),
|
||||
LEX_TOKEN_DEF(MIE_SYM_HYPHEN, "-"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_ASTERISK, "*"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_PLUS, "+"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_PERCENT, "%"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_DOLLAR, "$"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_CARET, "^"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_HASH, "#"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_ATSIGN, "@"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_TILDE, "~"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_LEFT_BRACE, "{"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_RIGHT_BRACE, "}"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_LEFT_BRACKET, "["),
|
||||
LEX_TOKEN_DEF(MIE_SYM_RIGHT_BRACKET, "]"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_LEFT_PAREN, "("),
|
||||
LEX_TOKEN_DEF(MIE_SYM_RIGHT_PAREN, ")"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_LEFT_ANGLE, "<"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_RIGHT_ANGLE, ">"),
|
||||
LEX_TOKEN_DEF(MIE_SYM_HYPHEN_RIGHT_ANGLE, "->"),
|
||||
};
|
||||
static const size_t nr_symbols = sizeof symbols / sizeof symbols[0];
|
||||
|
||||
static struct mie_lex_symbol_node *get_symbol_node(
|
||||
struct mie_lex_symbol_node *node, char c)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_first(&node->s_children);
|
||||
while (entry) {
|
||||
struct mie_lex_symbol_node *child
|
||||
= b_unbox(struct mie_lex_symbol_node, entry, s_entry);
|
||||
if (child->s_char == c) {
|
||||
return child;
|
||||
}
|
||||
|
||||
entry = b_queue_next(entry);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static b_string *get_temp_string(struct mie_lex *lex)
|
||||
{
|
||||
if (!lex->lex_temp) {
|
||||
lex->lex_temp = b_string_create();
|
||||
}
|
||||
|
||||
b_string_clear(lex->lex_temp);
|
||||
return lex->lex_temp;
|
||||
}
|
||||
|
||||
static enum mie_status put_symbol(
|
||||
struct mie_lex_symbol_node *tree, struct lex_token_def *sym)
|
||||
{
|
||||
for (size_t i = 0; sym->name[i]; i++) {
|
||||
char c = sym->name[i];
|
||||
struct mie_lex_symbol_node *child = get_symbol_node(tree, c);
|
||||
if (child) {
|
||||
tree = child;
|
||||
continue;
|
||||
}
|
||||
|
||||
child = malloc(sizeof *child);
|
||||
if (!child) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(child, 0x0, sizeof *child);
|
||||
|
||||
child->s_def = NULL;
|
||||
child->s_char = c;
|
||||
|
||||
b_queue_push_back(&tree->s_children, &child->s_entry);
|
||||
tree = child;
|
||||
}
|
||||
|
||||
tree->s_def = sym;
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static void destroy_symbol_tree(struct mie_lex_symbol_node *tree)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_first(&tree->s_children);
|
||||
while (entry) {
|
||||
struct mie_lex_symbol_node *node
|
||||
= b_unbox(struct mie_lex_symbol_node, entry, s_entry);
|
||||
b_queue_entry *next = b_queue_next(entry);
|
||||
b_queue_delete(&tree->s_children, entry);
|
||||
|
||||
destroy_symbol_tree(node);
|
||||
|
||||
entry = next;
|
||||
}
|
||||
|
||||
free(tree);
|
||||
}
|
||||
|
||||
static struct mie_lex_symbol_node *build_symbol_tree(void)
|
||||
{
|
||||
struct mie_lex_symbol_node *root = malloc(sizeof *root);
|
||||
if (!root) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(root, 0x0, sizeof *root);
|
||||
root->s_def = NULL;
|
||||
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
for (size_t i = 0; i < nr_symbols; i++) {
|
||||
status = put_symbol(root, &symbols[i]);
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
destroy_symbol_tree(root);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
struct mie_lex *mie_lex_create(b_stream *src)
|
||||
{
|
||||
struct mie_lex *lex = malloc(sizeof *lex);
|
||||
if (!lex) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(lex, 0x0, sizeof *lex);
|
||||
|
||||
lex->lex_cursor_row = lex->lex_cursor_col = 1;
|
||||
|
||||
lex->lex_status = MIE_SUCCESS;
|
||||
lex->lex_source = src;
|
||||
lex->lex_linebuf = b_string_create();
|
||||
|
||||
lex->lex_sym_tree = build_symbol_tree();
|
||||
if (!lex->lex_sym_tree) {
|
||||
mie_lex_destroy(lex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lex;
|
||||
}
|
||||
|
||||
void mie_lex_destroy(struct mie_lex *lex)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_first(&lex->lex_queue);
|
||||
|
||||
while (entry) {
|
||||
struct mie_token *tok
|
||||
= b_unbox(struct mie_token, entry, tok_entry);
|
||||
b_queue_entry *next = b_queue_next(entry);
|
||||
b_queue_delete(&lex->lex_queue, entry);
|
||||
|
||||
mie_token_destroy(tok);
|
||||
|
||||
entry = next;
|
||||
}
|
||||
|
||||
if (lex->lex_linebuf) {
|
||||
free(lex->lex_linebuf);
|
||||
}
|
||||
|
||||
if (lex->lex_sym_tree) {
|
||||
destroy_symbol_tree(lex->lex_sym_tree);
|
||||
}
|
||||
|
||||
if (lex->lex_temp) {
|
||||
b_string_unref(lex->lex_temp);
|
||||
}
|
||||
|
||||
free(lex);
|
||||
}
|
||||
|
||||
enum mie_status mie_lex_get_status(const struct mie_lex *lex)
|
||||
{
|
||||
return lex->lex_status;
|
||||
}
|
||||
|
||||
static enum mie_status refill_linebuf(struct mie_lex *lex)
|
||||
{
|
||||
if (!lex->lex_source) {
|
||||
return MIE_ERR_EOF;
|
||||
}
|
||||
|
||||
if (lex->lex_linebuf_ptr) {
|
||||
b_iterator_unref(lex->lex_linebuf_ptr);
|
||||
lex->lex_linebuf_ptr = NULL;
|
||||
}
|
||||
|
||||
b_stringstream *s = b_stringstream_create();
|
||||
|
||||
b_status status = b_stream_read_line_s(lex->lex_source, s);
|
||||
|
||||
if (status == B_ERR_NO_DATA) {
|
||||
return MIE_ERR_EOF;
|
||||
}
|
||||
|
||||
if (!B_OK(status)) {
|
||||
return MIE_ERR_INTERNAL_FAILURE;
|
||||
}
|
||||
|
||||
b_string_replace_all_with_stringstream(lex->lex_linebuf, s);
|
||||
b_stringstream_unref(s);
|
||||
|
||||
lex->lex_linebuf_ptr = b_iterator_begin(lex->lex_linebuf);
|
||||
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static int peek(struct mie_lex *lex)
|
||||
{
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
|
||||
if (!lex->lex_linebuf_ptr || !b_iterator_is_valid(lex->lex_linebuf_ptr)) {
|
||||
status = refill_linebuf(lex);
|
||||
}
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
return -status;
|
||||
}
|
||||
|
||||
if (b_string_get_size(lex->lex_linebuf, B_STRLEN_NORMAL) == 0) {
|
||||
return -MIE_ERR_EOF;
|
||||
}
|
||||
|
||||
b_wchar c = b_iterator_get_value(lex->lex_linebuf_ptr).v_int;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int advance(struct mie_lex *lex)
|
||||
{
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
|
||||
if (!b_iterator_is_valid(lex->lex_linebuf_ptr)) {
|
||||
status = refill_linebuf(lex);
|
||||
}
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
return -status;
|
||||
}
|
||||
|
||||
if (b_string_get_size(lex->lex_linebuf, B_STRLEN_NORMAL) == 0) {
|
||||
return -MIE_ERR_EOF;
|
||||
}
|
||||
|
||||
b_wchar c = b_iterator_get_value(lex->lex_linebuf_ptr).v_int;
|
||||
b_iterator_move_next(lex->lex_linebuf_ptr);
|
||||
|
||||
lex->lex_cursor_col++;
|
||||
if (c == '\n') {
|
||||
lex->lex_cursor_col = 1;
|
||||
lex->lex_cursor_row++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static bool input_available(struct mie_lex *lex)
|
||||
{
|
||||
return lex->lex_linebuf_ptr && b_iterator_is_valid(lex->lex_linebuf_ptr);
|
||||
}
|
||||
|
||||
static bool char_can_begin_symbol(char c)
|
||||
{
|
||||
for (size_t i = 0; i < nr_symbols; i++) {
|
||||
if (symbols[i].name[0] == c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct mie_token *create_token(enum mie_token_type type)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = type;
|
||||
return tok;
|
||||
}
|
||||
|
||||
static void set_token_start(struct mie_lex *lex)
|
||||
{
|
||||
lex->lex_token_start_row = lex->lex_cursor_row;
|
||||
lex->lex_token_start_col = lex->lex_cursor_col;
|
||||
}
|
||||
|
||||
static void set_token_end(struct mie_lex *lex)
|
||||
{
|
||||
lex->lex_token_end_row = lex->lex_cursor_row;
|
||||
lex->lex_token_end_col = lex->lex_cursor_col;
|
||||
}
|
||||
|
||||
static enum mie_status push_token(struct mie_lex *lex, struct mie_token *tok)
|
||||
{
|
||||
tok->tok_start.c_row = lex->lex_token_start_row;
|
||||
tok->tok_start.c_col = lex->lex_token_start_col;
|
||||
tok->tok_end.c_row = lex->lex_token_end_row;
|
||||
tok->tok_end.c_col = lex->lex_token_end_col;
|
||||
|
||||
b_queue_push_back(&lex->lex_queue, &tok->tok_entry);
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mie_status push_linefeed(struct mie_lex *lex)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = MIE_TOK_LINEFEED;
|
||||
tok->tok_value_type = MIE_TOK_V_NONE;
|
||||
return push_token(lex, tok);
|
||||
}
|
||||
|
||||
static enum mie_status push_symbol(struct mie_lex *lex, enum mie_token_symbol sym)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = MIE_TOK_SYMBOL;
|
||||
tok->tok_value_type = MIE_TOK_V_SYMBOL;
|
||||
tok->tok_sym = sym;
|
||||
return push_token(lex, tok);
|
||||
}
|
||||
|
||||
static enum mie_status push_string_token(
|
||||
struct mie_lex *lex, enum mie_token_type type, char *s)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char *ep = NULL;
|
||||
long long v = strtoll(s, &ep, 10);
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = type;
|
||||
|
||||
if (*ep == '\0') {
|
||||
tok->tok_int = v;
|
||||
tok->tok_value_type = MIE_TOK_V_INT;
|
||||
free(s);
|
||||
} else {
|
||||
tok->tok_str = s;
|
||||
tok->tok_value_type = MIE_TOK_V_STRING;
|
||||
}
|
||||
|
||||
return push_token(lex, tok);
|
||||
}
|
||||
|
||||
static enum mie_status push_int(struct mie_lex *lex, unsigned long long v)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = MIE_TOK_INT;
|
||||
tok->tok_value_type = MIE_TOK_V_INT;
|
||||
tok->tok_int = v;
|
||||
return push_token(lex, tok);
|
||||
}
|
||||
|
||||
static enum mie_status push_double(struct mie_lex *lex, double v)
|
||||
{
|
||||
struct mie_token *tok = malloc(sizeof *tok);
|
||||
if (!tok) {
|
||||
return MIE_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(tok, 0x0, sizeof *tok);
|
||||
|
||||
tok->tok_type = MIE_TOK_DOUBLE;
|
||||
tok->tok_value_type = MIE_TOK_V_DOUBLE;
|
||||
tok->tok_double = v;
|
||||
return push_token(lex, tok);
|
||||
}
|
||||
|
||||
static enum mie_status read_line_comment(struct mie_lex *lex)
|
||||
{
|
||||
while (true) {
|
||||
b_wchar c = advance(lex);
|
||||
|
||||
if (c == -MIE_ERR_EOF || c == '\n') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
return -c;
|
||||
}
|
||||
}
|
||||
|
||||
return MIE_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mie_status read_number(struct mie_lex *lex, bool negate)
|
||||
{
|
||||
int token_len = 0;
|
||||
int base = 10;
|
||||
int dots = 0;
|
||||
b_string *str = get_temp_string(lex);
|
||||
|
||||
if (!negate) {
|
||||
set_token_start(lex);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
b_wchar c = peek(lex);
|
||||
if (c == -MIE_ERR_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
return -c;
|
||||
}
|
||||
|
||||
if (c == '_') {
|
||||
token_len++;
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '.') {
|
||||
if (base != 10) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (dots > 0) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
token_len++;
|
||||
dots++;
|
||||
char s[] = {c, 0};
|
||||
b_string_append_cstr(str, s);
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b_wchar_is_space(c) || b_wchar_is_punct(c)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == 'x' && token_len == 1) {
|
||||
base = 16;
|
||||
token_len++;
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == 'b' && token_len == 1) {
|
||||
base = 2;
|
||||
token_len++;
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (base == 2 && c != '0' && c != '1') {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (base == 10 && !isdigit(c)) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (base == 16 && !isxdigit(c)) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
b_string_append_wc(str, c);
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
token_len++;
|
||||
}
|
||||
|
||||
if (token_len == 1 && base == 7) {
|
||||
return push_int(lex, 0);
|
||||
}
|
||||
|
||||
const char *s = b_string_ptr(str);
|
||||
char *ep = NULL;
|
||||
|
||||
/* negative numbers will be lexed as a hyphen followed by a positive
|
||||
* number. */
|
||||
|
||||
if (dots > 0) {
|
||||
double v = strtod(s, &ep);
|
||||
|
||||
if (*ep != '\0') {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (negate) {
|
||||
v *= -1;
|
||||
}
|
||||
|
||||
return push_double(lex, v);
|
||||
} else {
|
||||
unsigned long long v = strtoull(s, &ep, base);
|
||||
|
||||
if (*ep != '\0') {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (negate) {
|
||||
v *= -1;
|
||||
}
|
||||
|
||||
return push_int(lex, v);
|
||||
}
|
||||
}
|
||||
|
||||
static enum mie_status read_ident(struct mie_lex *lex, enum mie_token_type type)
|
||||
{
|
||||
int dots = 0;
|
||||
b_string *str = get_temp_string(lex);
|
||||
b_wchar prev = 0;
|
||||
|
||||
if (type == MIE_TOK_NONE) {
|
||||
set_token_start(lex);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
b_wchar c = peek(lex);
|
||||
|
||||
if ((c == '.' || c == '-') && prev == c) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (c == '.') {
|
||||
dots++;
|
||||
}
|
||||
|
||||
if (!IS_VALID_IDENT_CHAR(c)) {
|
||||
break;
|
||||
}
|
||||
|
||||
prev = c;
|
||||
b_string_append_wc(str, c);
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
}
|
||||
|
||||
if (type == MIE_TOK_NONE) {
|
||||
type = dots > 0 ? MIE_TOK_NAME : MIE_TOK_WORD;
|
||||
}
|
||||
|
||||
char *s = b_string_steal(str);
|
||||
|
||||
switch (type) {
|
||||
case MIE_TOK_INSTNAME:
|
||||
if (dots > 0) {
|
||||
return push_string_token(lex, type, s);
|
||||
} else {
|
||||
push_symbol(lex, MIE_SYM_ASTERISK);
|
||||
return push_string_token(lex, MIE_TOK_WORD, s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return push_string_token(lex, type, s);
|
||||
}
|
||||
}
|
||||
|
||||
static enum mie_status read_string(struct mie_lex *lex)
|
||||
{
|
||||
b_string *str = get_temp_string(lex);
|
||||
|
||||
b_wchar c = peek(lex);
|
||||
bool esc = false;
|
||||
|
||||
if (c != '"') {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
advance(lex);
|
||||
|
||||
while (1) {
|
||||
b_wchar c = peek(lex);
|
||||
|
||||
if (esc) {
|
||||
switch (c) {
|
||||
case '\\':
|
||||
case '"':
|
||||
b_string_append_wc(str, c);
|
||||
break;
|
||||
default:
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
esc = false;
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
esc = true;
|
||||
advance(lex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
advance(lex);
|
||||
break;
|
||||
}
|
||||
|
||||
b_string_append_wc(str, c);
|
||||
advance(lex);
|
||||
}
|
||||
|
||||
char *s = b_string_steal(str);
|
||||
return push_string_token(lex, MIE_TOK_STRING, s);
|
||||
}
|
||||
|
||||
static enum mie_status read_symbol(struct mie_lex *lex)
|
||||
{
|
||||
struct mie_lex_symbol_node *node = lex->lex_sym_tree;
|
||||
set_token_start(lex);
|
||||
b_wchar prev = 0;
|
||||
|
||||
while (true) {
|
||||
b_wchar c = peek(lex);
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct mie_lex_symbol_node *next = get_symbol_node(node, c);
|
||||
if (!next) {
|
||||
prev = c;
|
||||
break;
|
||||
}
|
||||
|
||||
node = next;
|
||||
set_token_end(lex);
|
||||
advance(lex);
|
||||
prev = c;
|
||||
}
|
||||
|
||||
if (!node || node->s_def == NULL) {
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (node->s_def->id == MIE_SYM_HYPHEN && isdigit(prev)) {
|
||||
return read_number(lex, true);
|
||||
}
|
||||
|
||||
if (IS_VALID_IDENT_START_CHAR(prev)) {
|
||||
switch (node->s_def->id) {
|
||||
case MIE_SYM_ASTERISK:
|
||||
return read_ident(lex, MIE_TOK_INSTNAME);
|
||||
case MIE_SYM_PLUS:
|
||||
return read_ident(lex, MIE_TOK_GRAPHNAME);
|
||||
case MIE_SYM_PERCENT:
|
||||
return read_ident(lex, MIE_TOK_VREGNAME);
|
||||
case MIE_SYM_DOLLAR:
|
||||
return read_ident(lex, MIE_TOK_MREGNAME);
|
||||
case MIE_SYM_CARET:
|
||||
return read_ident(lex, MIE_TOK_BLOCKNAME);
|
||||
case MIE_SYM_TILDE:
|
||||
return read_ident(lex, MIE_TOK_OPNAME);
|
||||
case MIE_SYM_HASH:
|
||||
return read_ident(lex, MIE_TOK_TYPENAME);
|
||||
case MIE_SYM_ATSIGN:
|
||||
return read_ident(lex, MIE_TOK_SYMNAME);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_VALID_REG_START_CHAR(prev)) {
|
||||
switch (node->s_def->id) {
|
||||
case MIE_SYM_PERCENT:
|
||||
return read_ident(lex, MIE_TOK_VREGNAME);
|
||||
case MIE_SYM_DOLLAR:
|
||||
return read_ident(lex, MIE_TOK_MREGNAME);
|
||||
case MIE_SYM_ATSIGN:
|
||||
return read_ident(lex, MIE_TOK_SYMNAME);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return push_symbol(lex, node->s_def->id);
|
||||
}
|
||||
|
||||
static void skip_whitespace(struct mie_lex *lex)
|
||||
{
|
||||
b_wchar c = peek(lex);
|
||||
|
||||
while (b_wchar_is_space(c)) {
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool should_skip(b_wchar c, bool skip_linefeeds)
|
||||
{
|
||||
bool skip = b_wchar_is_space(c);
|
||||
|
||||
if (!skip_linefeeds) {
|
||||
skip = (skip && c != '\n');
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
static void skip_ignored_chars(struct mie_lex *lex, bool include_linefeeds)
|
||||
{
|
||||
b_wchar c = peek(lex);
|
||||
|
||||
while (1) {
|
||||
while (should_skip(c, include_linefeeds)) {
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
if (c != ';') {
|
||||
break;
|
||||
}
|
||||
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
|
||||
while (c != '\n') {
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
}
|
||||
}
|
||||
|
||||
static enum mie_status pump_tokens(struct mie_lex *lex)
|
||||
{
|
||||
b_wchar c = peek(lex);
|
||||
|
||||
if (c < 0) {
|
||||
return -c;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (c == ';' || (b_wchar_is_space(c) && c != '\n')) {
|
||||
skip_ignored_chars(lex, false);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
advance(lex);
|
||||
skip_ignored_chars(lex, true);
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
if (c == '\n') {
|
||||
set_token_start(lex);
|
||||
set_token_end(lex);
|
||||
|
||||
while (c == '\n') {
|
||||
advance(lex);
|
||||
|
||||
if (!input_available(lex)) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
return -c;
|
||||
}
|
||||
|
||||
return push_linefeed(lex);
|
||||
}
|
||||
|
||||
while (b_wchar_is_space(c) && c != '\n') {
|
||||
advance(lex);
|
||||
c = peek(lex);
|
||||
}
|
||||
|
||||
if (IS_VALID_IDENT_START_CHAR(c)) {
|
||||
return read_ident(lex, MIE_TOK_NONE);
|
||||
}
|
||||
|
||||
if (char_can_begin_symbol(c)) {
|
||||
return read_symbol(lex);
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
return read_string(lex);
|
||||
}
|
||||
|
||||
if (isdigit(c)) {
|
||||
return read_number(lex, false);
|
||||
}
|
||||
|
||||
return MIE_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
struct mie_token *mie_lex_peek(struct mie_lex *lex)
|
||||
{
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
|
||||
while (b_queue_empty(&lex->lex_queue)) {
|
||||
status = pump_tokens(lex);
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
lex->lex_status = status;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lex->lex_status = status;
|
||||
|
||||
b_queue_entry *entry = b_queue_first(&lex->lex_queue);
|
||||
struct mie_token *tok = b_unbox(struct mie_token, entry, tok_entry);
|
||||
return tok;
|
||||
}
|
||||
|
||||
void mie_lex_advance(struct mie_lex *lex)
|
||||
{
|
||||
enum mie_status status = MIE_SUCCESS;
|
||||
|
||||
while (b_queue_empty(&lex->lex_queue)) {
|
||||
status = pump_tokens(lex);
|
||||
|
||||
if (status != MIE_SUCCESS) {
|
||||
lex->lex_status = status;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
b_queue_entry *entry = b_queue_pop_front(&lex->lex_queue);
|
||||
struct mie_token *tok = b_unbox(struct mie_token, entry, tok_entry);
|
||||
mie_token_destroy(tok);
|
||||
}
|
||||
|
||||
bool mie_lex_tokens_available(struct mie_lex *lex)
|
||||
{
|
||||
if (!b_queue_empty(&lex->lex_queue)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input_available(lex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
45
mie/parse/lex.h
Normal file
45
mie/parse/lex.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _PARSE_LEX_H_
|
||||
#define _PARSE_LEX_H_
|
||||
|
||||
#include <blue/core/queue.h>
|
||||
#include <blue/ds/dict.h>
|
||||
#include <blue/ds/string.h>
|
||||
#include <mie/parse/lex.h>
|
||||
#include <mie/parse/token.h>
|
||||
#include <mie/status.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct mie_lex {
|
||||
struct mie_lex_symbol_node *lex_sym_tree;
|
||||
b_stream *lex_source;
|
||||
enum mie_status lex_status;
|
||||
|
||||
b_queue lex_queue;
|
||||
|
||||
b_string *lex_temp;
|
||||
b_queue lex_state;
|
||||
unsigned int lex_brace_depth;
|
||||
|
||||
unsigned long lex_token_start_row, lex_token_start_col;
|
||||
unsigned long lex_token_end_row, lex_token_end_col;
|
||||
unsigned long lex_cursor_row, lex_cursor_col;
|
||||
|
||||
b_string *lex_linebuf;
|
||||
b_iterator *lex_linebuf_ptr;
|
||||
};
|
||||
|
||||
struct mie_lex_symbol_node {
|
||||
char s_char;
|
||||
struct lex_token_def *s_def;
|
||||
|
||||
b_queue_entry s_entry;
|
||||
b_queue s_children;
|
||||
};
|
||||
|
||||
struct lex_token_def {
|
||||
int id;
|
||||
const char *name;
|
||||
uint64_t name_hash;
|
||||
};
|
||||
|
||||
#endif
|
||||
521
mie/parse/parse.c
Normal file
521
mie/parse/parse.c
Normal file
@@ -0,0 +1,521 @@
|
||||
#include <mie/ir/module.h>
|
||||
#include <mie/ir/op.h>
|
||||
#include <mie/ir/region.h>
|
||||
#include <mie/ir/register.h>
|
||||
#include <mie/parse/lex.h>
|
||||
#include <mie/parse/parse.h>
|
||||
#include <mie/parse/token.h>
|
||||
|
||||
struct mie_parser {
|
||||
struct mie_ctx *p_ctx;
|
||||
struct mie_lex *p_lex;
|
||||
enum mie_status p_status;
|
||||
};
|
||||
|
||||
struct mie_parser *mie_parser_create(struct mie_ctx *ctx, struct mie_lex *lex)
|
||||
{
|
||||
struct mie_parser *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
out->p_ctx = ctx;
|
||||
out->p_lex = lex;
|
||||
out->p_status = MIE_SUCCESS;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void mie_parser_destroy(struct mie_parser *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
enum mie_status mie_parser_get_status(const struct mie_parser *ctx)
|
||||
{
|
||||
return ctx->p_status;
|
||||
}
|
||||
|
||||
struct mie_token *mie_parser_peek(struct mie_parser *ctx)
|
||||
{
|
||||
return mie_lex_peek(ctx->p_lex);
|
||||
}
|
||||
|
||||
enum mie_token_type mie_parser_peek_type(struct mie_parser *ctx)
|
||||
{
|
||||
return MIE_TOKEN_TYPE(mie_lex_peek(ctx->p_lex));
|
||||
}
|
||||
|
||||
enum mie_token_symbol mie_parser_peek_symbol(struct mie_parser *ctx)
|
||||
{
|
||||
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
|
||||
|
||||
if (MIE_TOKEN_TYPE(tok) != MIE_TOK_SYMBOL) {
|
||||
return MIE_SYM_NONE;
|
||||
}
|
||||
|
||||
return tok->tok_sym;
|
||||
}
|
||||
|
||||
bool mie_parser_check_eof(struct mie_parser *ctx)
|
||||
{
|
||||
return mie_lex_peek(ctx->p_lex) == NULL;
|
||||
}
|
||||
|
||||
bool mie_parser_check_type(struct mie_parser *ctx, enum mie_token_type type)
|
||||
{
|
||||
return MIE_TOKEN_IS(mie_lex_peek(ctx->p_lex), type);
|
||||
}
|
||||
|
||||
bool mie_parser_check_symbol(struct mie_parser *ctx, enum mie_token_symbol sym)
|
||||
{
|
||||
return MIE_TOKEN_IS_SYMBOL(mie_lex_peek(ctx->p_lex), sym);
|
||||
}
|
||||
|
||||
bool mie_parser_advance(struct mie_parser *ctx)
|
||||
{
|
||||
mie_lex_advance(ctx->p_lex);
|
||||
return mie_lex_get_status(ctx->p_lex) == MIE_SUCCESS;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_vregname(struct mie_parser *ctx, b_string *out)
|
||||
{
|
||||
if (!mie_parser_check_type(ctx, MIE_TOK_VREGNAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
|
||||
b_string_append_cstr(out, tok->tok_str);
|
||||
mie_lex_advance(ctx->p_lex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_mregname(struct mie_parser *ctx, b_string *out)
|
||||
{
|
||||
if (!mie_parser_check_type(ctx, MIE_TOK_MREGNAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
|
||||
b_string_append_cstr(out, tok->tok_str);
|
||||
mie_lex_advance(ctx->p_lex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_opname(struct mie_parser *ctx, b_string *out)
|
||||
{
|
||||
if (!mie_parser_check_type(ctx, MIE_TOK_OPNAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
|
||||
b_string_append_cstr(out, tok->tok_str);
|
||||
mie_lex_advance(ctx->p_lex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_symbol(struct mie_parser *ctx, enum mie_token_symbol sym)
|
||||
{
|
||||
struct mie_token *tok = mie_lex_peek(ctx->p_lex);
|
||||
if (!MIE_TOKEN_IS_SYMBOL(tok, sym)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mie_lex_advance(ctx->p_lex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_type(struct mie_parser *ctx, struct mie_type **out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_type_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_type *, out))
|
||||
{
|
||||
bool ok = false;
|
||||
struct mie_type **type_slot = NULL;
|
||||
|
||||
type_slot = mie_vector_ref_emplace_back(out);
|
||||
if (!type_slot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_type(ctx, type_slot)) {
|
||||
mie_vector_ref_pop_back(out);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COMMA)) {
|
||||
break;
|
||||
}
|
||||
|
||||
type_slot = mie_vector_ref_emplace_back(out);
|
||||
if (!type_slot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_type(ctx, type_slot)) {
|
||||
mie_vector_ref_pop_back(out);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_operand(
|
||||
struct mie_parser *ctx, struct mie_unresolved_operand *out)
|
||||
{
|
||||
memset(out, 0x0, sizeof *out);
|
||||
out->op_name = b_string_create();
|
||||
if (mie_parser_parse_vregname(ctx, out->op_name)) {
|
||||
out->op_type = MIE_UNRESOLVED_OPERAND_VIRTUAL_REGISTER;
|
||||
} else if (mie_parser_parse_mregname(ctx, out->op_name)) {
|
||||
out->op_type = MIE_UNRESOLVED_OPERAND_MACHINE_REGISTER;
|
||||
} else {
|
||||
b_string_unref(out->op_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_operand_list(
|
||||
struct mie_parser *ctx,
|
||||
MIE_VECTOR_PARAM(struct mie_unresolved_operand, out))
|
||||
{
|
||||
bool ok = false;
|
||||
struct mie_unresolved_operand *operand = NULL;
|
||||
|
||||
struct mie_token *tok = mie_parser_peek(ctx);
|
||||
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
|
||||
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
operand = mie_vector_ref_emplace_back(out);
|
||||
if (!operand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_operand(ctx, operand)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
tok = mie_parser_peek(ctx);
|
||||
|
||||
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
|
||||
break;
|
||||
}
|
||||
|
||||
mie_parser_advance(ctx);
|
||||
tok = mie_parser_peek(ctx);
|
||||
type = MIE_TOKEN_TYPE(tok);
|
||||
|
||||
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
operand = mie_vector_ref_emplace_back(out);
|
||||
if (!operand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_operand(ctx, operand)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_register(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_register *out)
|
||||
{
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
struct mie_token *tok = mie_parser_peek(ctx);
|
||||
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
|
||||
switch (type) {
|
||||
case MIE_TOK_VREGNAME:
|
||||
out->reg_flags |= MIE_REGISTER_F_VIRTUAL;
|
||||
break;
|
||||
case MIE_TOK_MREGNAME:
|
||||
out->reg_flags |= MIE_REGISTER_F_MACHINE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_name_map_put(
|
||||
names, &out->reg_name, tok->tok_str, MIE_NAME_MAP_STRICT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mie_parser_advance(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_register_list(
|
||||
struct mie_parser *ctx, struct mie_name_map *names,
|
||||
MIE_VECTOR_PARAM(struct mie_register, out))
|
||||
{
|
||||
bool ok = false;
|
||||
struct mie_register *reg = NULL;
|
||||
|
||||
struct mie_token *tok = mie_parser_peek(ctx);
|
||||
enum mie_token_type type = MIE_TOKEN_TYPE(tok);
|
||||
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
reg = mie_vector_ref_emplace_back(out);
|
||||
if (!reg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_register(ctx, names, reg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
tok = mie_parser_peek(ctx);
|
||||
|
||||
if (!MIE_TOKEN_IS_SYMBOL(tok, MIE_SYM_COMMA)) {
|
||||
break;
|
||||
}
|
||||
|
||||
mie_parser_advance(ctx);
|
||||
tok = mie_parser_peek(ctx);
|
||||
type = MIE_TOKEN_TYPE(tok);
|
||||
|
||||
if (type != MIE_TOK_VREGNAME && type != MIE_TOK_MREGNAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
reg = mie_vector_ref_emplace_back(out);
|
||||
if (!reg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_register(ctx, names, reg)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_module(struct mie_parser *ctx, struct mie_module *mod)
|
||||
{
|
||||
#define OP_TOKEN_TYPES \
|
||||
(MIE_TOK_NAME | MIE_TOK_OPNAME | MIE_TOK_VREGNAME | MIE_TOK_MREGNAME \
|
||||
| MIE_TOK_GRAPHNAME | MIE_TOK_INSTNAME)
|
||||
while (1) {
|
||||
enum mie_token_type type = mie_parser_peek_type(ctx);
|
||||
bool is_op = (type & OP_TOKEN_TYPES);
|
||||
|
||||
if (!is_op) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct mie_op *op = mie_vector_emplace_back(mod->m_ops);
|
||||
if (!op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_op(ctx, mod->m_names, op)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_region(struct mie_parser *ctx, struct mie_region *region)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_region_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_region, out))
|
||||
{
|
||||
if (!mie_parser_check_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mie_region *region = mie_vector_ref_emplace_back(out);
|
||||
|
||||
if (!mie_parser_parse_region(ctx, region)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COMMA)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mie_parser_check_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct mie_region *region = mie_vector_ref_emplace_back(out);
|
||||
|
||||
if (!mie_parser_parse_region(ctx, region)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_attribute(
|
||||
struct mie_parser *ctx, struct mie_op_attribute *attrib)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_attribute_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_op_attribute, out))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_successor(
|
||||
struct mie_parser *ctx, struct mie_op_successor *successor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_successor_list(
|
||||
struct mie_parser *ctx, MIE_VECTOR_PARAM(struct mie_op_successor, out))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool parse_custom_op(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool parse_generic_op(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
|
||||
{
|
||||
b_string *str = b_string_create();
|
||||
if (!mie_parser_parse_opname(ctx, str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->op_name = b_string_steal(str);
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MIE_VECTOR_DEFINE(struct mie_unresolved_operand, operands);
|
||||
|
||||
if (mie_parser_parse_operand_list(ctx, MIE_VECTOR_ARG(operands))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACKET)) {
|
||||
if (!mie_parser_parse_successor_list(
|
||||
ctx, MIE_VECTOR_ARG(dest->op_successors))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACKET)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_PAREN)) {
|
||||
if (!mie_parser_parse_region_list(
|
||||
ctx, MIE_VECTOR_ARG(dest->op_regions))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_PAREN)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mie_parser_parse_symbol(ctx, MIE_SYM_LEFT_BRACE)) {
|
||||
if (!mie_parser_parse_attribute_list(
|
||||
ctx, MIE_VECTOR_ARG(dest->op_attrib))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_COLON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* parse input type list */
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_HYPHEN_RIGHT_ANGLE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* parse output type list */
|
||||
|
||||
mie_vector_destroy(operands, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_graph_op(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mie_parser_parse_op(
|
||||
struct mie_parser *ctx, struct mie_name_map *names, struct mie_op *dest)
|
||||
{
|
||||
memset(dest, 0x0, sizeof *dest);
|
||||
|
||||
if (mie_parser_check_eof(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mie_parser_check_type(ctx, MIE_TOK_MREGNAME | MIE_TOK_VREGNAME)) {
|
||||
if (!mie_parser_parse_register_list(
|
||||
ctx, names, MIE_VECTOR_ARG(dest->op_result))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mie_parser_parse_symbol(ctx, MIE_SYM_EQUAL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mie_parser_check_type(ctx, MIE_TOK_NAME)) {
|
||||
/* custom-format operation */
|
||||
return parse_custom_op(ctx, names, dest);
|
||||
} else if (mie_parser_check_type(ctx, MIE_TOK_OPNAME)) {
|
||||
/* generic-format operation */
|
||||
return parse_generic_op(ctx, names, dest);
|
||||
} else if (mie_parser_check_type(ctx, MIE_TOK_GRAPHNAME)) {
|
||||
/* graph-node operation */
|
||||
return parse_graph_op(ctx, names, dest);
|
||||
} else {
|
||||
/* not sure what this is */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
72
mie/parse/token.c
Normal file
72
mie/parse/token.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <mie/parse/token.h>
|
||||
|
||||
void mie_token_destroy(struct mie_token *tok)
|
||||
{
|
||||
switch (tok->tok_value_type) {
|
||||
case MIE_TOK_V_STRING:
|
||||
free(tok->tok_str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(tok);
|
||||
}
|
||||
|
||||
#define ENUM_STR(x) \
|
||||
case x: \
|
||||
return #x
|
||||
|
||||
const char *mie_token_type_to_string(enum mie_token_type type)
|
||||
{
|
||||
switch (type) {
|
||||
ENUM_STR(MIE_TOK_NONE);
|
||||
ENUM_STR(MIE_TOK_LINEFEED);
|
||||
ENUM_STR(MIE_TOK_INT);
|
||||
ENUM_STR(MIE_TOK_DOUBLE);
|
||||
ENUM_STR(MIE_TOK_SYMBOL);
|
||||
ENUM_STR(MIE_TOK_WORD);
|
||||
ENUM_STR(MIE_TOK_NAME);
|
||||
ENUM_STR(MIE_TOK_OPNAME);
|
||||
ENUM_STR(MIE_TOK_INSTNAME);
|
||||
ENUM_STR(MIE_TOK_GRAPHNAME);
|
||||
ENUM_STR(MIE_TOK_VREGNAME);
|
||||
ENUM_STR(MIE_TOK_MREGNAME);
|
||||
ENUM_STR(MIE_TOK_BLOCKNAME);
|
||||
ENUM_STR(MIE_TOK_TYPENAME);
|
||||
ENUM_STR(MIE_TOK_SYMNAME);
|
||||
ENUM_STR(MIE_TOK_STRING);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char *mie_token_symbol_to_string(enum mie_token_symbol sym)
|
||||
{
|
||||
switch (sym) {
|
||||
ENUM_STR(MIE_SYM_NONE);
|
||||
ENUM_STR(MIE_SYM_COLON);
|
||||
ENUM_STR(MIE_SYM_EQUAL);
|
||||
ENUM_STR(MIE_SYM_COMMA);
|
||||
ENUM_STR(MIE_SYM_HYPHEN);
|
||||
ENUM_STR(MIE_SYM_ASTERISK);
|
||||
ENUM_STR(MIE_SYM_PLUS);
|
||||
ENUM_STR(MIE_SYM_PERCENT);
|
||||
ENUM_STR(MIE_SYM_DOLLAR);
|
||||
ENUM_STR(MIE_SYM_CARET);
|
||||
ENUM_STR(MIE_SYM_HASH);
|
||||
ENUM_STR(MIE_SYM_ATSIGN);
|
||||
ENUM_STR(MIE_SYM_LEFT_BRACE);
|
||||
ENUM_STR(MIE_SYM_RIGHT_BRACE);
|
||||
ENUM_STR(MIE_SYM_LEFT_BRACKET);
|
||||
ENUM_STR(MIE_SYM_RIGHT_BRACKET);
|
||||
ENUM_STR(MIE_SYM_LEFT_PAREN);
|
||||
ENUM_STR(MIE_SYM_RIGHT_PAREN);
|
||||
ENUM_STR(MIE_SYM_LEFT_ANGLE);
|
||||
ENUM_STR(MIE_SYM_RIGHT_ANGLE);
|
||||
ENUM_STR(MIE_SYM_HYPHEN_RIGHT_ANGLE);
|
||||
ENUM_STR(MIE_SYM_OTHER);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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);
|
||||
171
mie/select/br.c
171
mie/select/br.c
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#include <mie/select/node.h>
|
||||
#include <mie/select/opcode.h>
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
93
mie/type.c
93
mie/type.c
@@ -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;
|
||||
}
|
||||
154
mie/vector.c
Normal file
154
mie/vector.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include <mie/vector.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEFAULT_CAPACITY 4
|
||||
|
||||
struct vector {
|
||||
void *v_buf;
|
||||
size_t v_itemsz;
|
||||
size_t v_count;
|
||||
size_t v_max;
|
||||
};
|
||||
|
||||
static void vector_wrap(
|
||||
struct vector *v, void **vector, size_t item_size, size_t *count,
|
||||
size_t *max)
|
||||
{
|
||||
v->v_buf = *vector;
|
||||
v->v_itemsz = item_size;
|
||||
v->v_count = *count;
|
||||
v->v_max = *max;
|
||||
}
|
||||
|
||||
static void vector_unwrap(
|
||||
struct vector *v, void **vector, size_t item_size, size_t *count,
|
||||
size_t *max)
|
||||
{
|
||||
*vector = v->v_buf;
|
||||
*count = v->v_count;
|
||||
*max = v->v_max;
|
||||
}
|
||||
|
||||
static int vector_reserve(struct vector *v, size_t new_capacity)
|
||||
{
|
||||
if (v->v_max >= new_capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *ptr = realloc(v->v_buf, new_capacity * v->v_itemsz);
|
||||
if (!ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
v->v_buf = ptr;
|
||||
v->v_max = new_capacity;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vector_push_back(struct vector *v, void *item)
|
||||
{
|
||||
int err = vector_reserve(v, v->v_count + 1);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
void *dest = (char *)v->v_buf + (v->v_count * v->v_itemsz);
|
||||
memcpy(dest, item, v->v_itemsz);
|
||||
v->v_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vector_pop_back(struct vector *v)
|
||||
{
|
||||
if (v->v_count > 0) {
|
||||
v->v_count--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *vector_emplace_back(struct vector *v)
|
||||
{
|
||||
int err = vector_reserve(v, v->v_count + 1);
|
||||
if (err != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *dest = (char *)v->v_buf + (v->v_count * v->v_itemsz);
|
||||
memset(dest, 0x0, v->v_itemsz);
|
||||
v->v_count++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void vector_destroy_items(struct vector *v, void (*dtor)(void *))
|
||||
{
|
||||
for (size_t i = 0; i < v->v_count; i++) {
|
||||
void *item = (char *)v->v_buf + (i * v->v_itemsz);
|
||||
dtor(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void vector_destroy(struct vector *v, void (*dtor)(void *))
|
||||
{
|
||||
if (dtor) {
|
||||
vector_destroy_items(v, dtor);
|
||||
}
|
||||
|
||||
if (v->v_buf) {
|
||||
free(v->v_buf);
|
||||
}
|
||||
|
||||
v->v_buf = NULL;
|
||||
v->v_count = 0;
|
||||
v->v_max = 0;
|
||||
}
|
||||
|
||||
int __mie_vector_push_back(
|
||||
void **vector, void *item, size_t item_size, size_t *count, size_t *max)
|
||||
{
|
||||
struct vector v = {};
|
||||
int err = 0;
|
||||
|
||||
vector_wrap(&v, vector, item_size, count, max);
|
||||
err = vector_push_back(&v, item);
|
||||
vector_unwrap(&v, vector, item_size, count, max);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void __mie_vector_pop_back(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max)
|
||||
{
|
||||
struct vector v = {};
|
||||
|
||||
vector_wrap(&v, vector, item_size, count, max);
|
||||
vector_pop_back(&v);
|
||||
vector_unwrap(&v, vector, item_size, count, max);
|
||||
}
|
||||
|
||||
void *__mie_vector_emplace_back(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max)
|
||||
{
|
||||
struct vector v = {};
|
||||
void *p = 0;
|
||||
|
||||
vector_wrap(&v, vector, item_size, count, max);
|
||||
p = vector_emplace_back(&v);
|
||||
vector_unwrap(&v, vector, item_size, count, max);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void __mie_vector_destroy(
|
||||
void **vector, size_t item_size, size_t *count, size_t *max,
|
||||
void (*dtor)(void *))
|
||||
{
|
||||
struct vector v = {};
|
||||
vector_wrap(&v, vector, item_size, count, max);
|
||||
vector_destroy(&v, dtor);
|
||||
vector_unwrap(&v, vector, item_size, count, max);
|
||||
}
|
||||
Reference in New Issue
Block a user