708 lines
18 KiB
C
708 lines
18 KiB
C
#include "convert.h"
|
|
|
|
#include <blue/object/hashmap.h>
|
|
#include <blue/object/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/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_stringstream_add(converter->c_dest.stringstream, s);
|
|
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_stringstream_add(converter->c_dest.stringstream, s);
|
|
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_stringstream_add(converter->c_dest.stringstream, buf);
|
|
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_list_iterator it;
|
|
b_list_iterator_begin(array->a_values, &it);
|
|
|
|
write_char(converter, '{');
|
|
while (b_list_iterator_is_valid(&it)) {
|
|
if (it.i > 0) {
|
|
write_char(converter, ',');
|
|
}
|
|
|
|
write_string(converter, "\n ");
|
|
|
|
struct mie_value *child = it.item;
|
|
write_operand_const(converter, child, F_INCLUDE_TYPE);
|
|
|
|
b_list_iterator_next(&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>");
|
|
return B_SUCCESS;
|
|
}
|
|
|
|
switch (value->v_type->t_id) {
|
|
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_iterator it;
|
|
b_queue_foreach (&it, &mod->m_records) {
|
|
struct mie_value *record
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
status = write_value_to_text(converter, record);
|
|
|
|
if (!B_OK(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (!b_queue_empty(&mod->m_records)) {
|
|
write_char(converter, '\n');
|
|
}
|
|
|
|
b_queue_foreach (&it, &mod->m_types) {
|
|
struct mie_value *type
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
status = write_value_to_text(converter, type);
|
|
|
|
if (!B_OK(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (!b_queue_empty(&mod->m_types)) {
|
|
write_char(converter, '\n');
|
|
}
|
|
|
|
b_hashmap_iterator it2;
|
|
b_hashmap_foreach(&it2, mod->m_data)
|
|
{
|
|
struct mie_value *data = it2.value->value_data;
|
|
status = write_value_to_text(converter, data);
|
|
|
|
if (!B_OK(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (!b_hashmap_is_empty(mod->m_data)) {
|
|
write_char(converter, '\n');
|
|
}
|
|
|
|
unsigned long i = 0;
|
|
b_queue_foreach (&it, &mod->m_func) {
|
|
if (i > 0) {
|
|
write_char(converter, '\n');
|
|
}
|
|
|
|
struct mie_value *func
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
status = write_value_to_text(converter, func);
|
|
|
|
if (!B_OK(status)) {
|
|
return status;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
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;
|
|
b_queue_iterator it;
|
|
b_queue_foreach (&it, &func->f_args) {
|
|
struct mie_arg *arg = (struct mie_arg *)b_unbox(
|
|
struct mie_value, it.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++;
|
|
}
|
|
|
|
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");
|
|
|
|
b_queue_foreach (&it, &func->f_blocks) {
|
|
struct mie_value *block
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
write_value_to_text(converter, block);
|
|
}
|
|
|
|
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_iterator it;
|
|
b_queue_foreach (&it, &block->b_phi) {
|
|
struct mie_value *instr
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
write_value_to_text(converter, instr);
|
|
}
|
|
|
|
b_queue_foreach (&it, &block->b_instr) {
|
|
struct mie_value *instr
|
|
= b_unbox(struct mie_value, it.entry, v_entry);
|
|
write_value_to_text(converter, instr);
|
|
}
|
|
|
|
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:
|
|
write_string(converter, "phi");
|
|
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);
|
|
}
|