Files
mie/mie/print/op.c

297 lines
7.2 KiB
C

#include <mie/dialect/dialect.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/print/printer.h>
void mie_printer_print_op_arg(
struct mie_printer *printer, const struct mie_op_arg *arg, bool include_type)
{
enum mie_register_flags arg_flags = 0;
const char *arg_name = NULL;
const struct mie_type *arg_type = NULL;
if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) {
if (!arg->arg_value.u_reg) {
arg_flags = 0;
arg_name = "<NULL>";
arg_type = NULL;
} else {
arg_flags = arg->arg_value.u_reg->reg_flags;
arg_name = arg->arg_value.u_reg->reg_name.n_str;
arg_type = arg->arg_value.u_reg->reg_type;
}
} else {
arg_flags = arg->arg_unresolved.reg_flags;
arg_name = arg->arg_unresolved.reg_name;
arg_type = arg->arg_unresolved.reg_type;
}
if (arg_flags & MIE_REGISTER_F_MACHINE) {
b_stream_write_char(printer->p_stream, '$');
} else {
b_stream_write_char(printer->p_stream, '%');
}
b_stream_write_string(printer->p_stream, arg_name, NULL);
if (!include_type || !arg_type) {
return;
}
b_stream_write_string(printer->p_stream, ": ", NULL);
mie_printer_print_type(printer, arg_type);
}
void mie_printer_print_op_successor(
struct mie_printer *printer, const struct mie_op_successor *successor,
bool compact)
{
b_stream_write_char(printer->p_stream, '^');
if (successor->s_flags & MIE_OP_F_SUCCESSOR_RESOLVED) {
b_stream_write_string(
printer->p_stream, successor->s_block->b_name.n_str, NULL);
} else {
b_stream_write_string(
printer->p_stream, successor->s_block_name, NULL);
}
if (MIE_VECTOR_COUNT(successor->s_args) == 0) {
return;
}
if (!compact) {
b_stream_write_char(printer->p_stream, ':');
}
b_stream_write_char(printer->p_stream, '(');
for (size_t i = 0; i < MIE_VECTOR_COUNT(successor->s_args); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_op_arg(printer, &successor->s_args.items[i], true);
}
b_stream_write_char(printer->p_stream, ')');
}
static void print_successor_list(
struct mie_printer *printer, const struct mie_op *op)
{
if (!MIE_VECTOR_COUNT(op->op_successors)) {
return;
}
b_stream_write_string(printer->p_stream, " [ ", NULL);
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_op_successor(
printer, &op->op_successors.items[i], false);
}
b_stream_write_string(printer->p_stream, " ]", NULL);
}
static void print_region_list(struct mie_printer *printer, const struct mie_op *op)
{
if (b_queue_empty(&op->op_regions)) {
return;
}
b_stream_write_string(printer->p_stream, " (", NULL);
struct mie_region *region = mie_op_get_first_region(op);
size_t i = 0;
while (region) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_region(printer, region, 0);
region = mie_op_get_next_region(op, region);
i++;
}
b_stream_write_string(printer->p_stream, ")", NULL);
}
static void print_attribute(
struct mie_printer *printer, const struct mie_attribute_map_iterator *attrib)
{
b_stream_write_fmt(printer->p_stream, NULL, "%s = ", attrib->it_name);
mie_printer_print_attribute(printer, attrib->it_value);
}
static void print_attribute_list(
struct mie_printer *printer, const struct mie_op *op)
{
if (mie_attribute_map_empty(&op->op_attrib)) {
return;
}
b_stream_write_string(printer->p_stream, " { ", NULL);
struct mie_attribute_map_iterator it;
enum mie_status status
= mie_attribute_map_iterator_begin(&it, &op->op_attrib);
size_t i = 0;
while (status == MIE_SUCCESS) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
print_attribute(printer, &it);
status = mie_attribute_map_iterator_move_next(&it);
i++;
}
b_stream_write_string(printer->p_stream, " }", NULL);
}
static void print_type_signature(
struct mie_printer *printer, const struct mie_op *op)
{
const struct mie_type *type = NULL;
b_stream_write_string(printer->p_stream, " : (", NULL);
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
const struct mie_op_arg *arg = &op->op_args.items[i];
if (arg->arg_flags & MIE_OP_F_ARG_RESOLVED) {
type = arg->arg_value.u_reg->reg_type;
} else {
type = arg->arg_unresolved.reg_type;
}
mie_printer_print_type(printer, type);
}
b_stream_write_string(printer->p_stream, ") -> ", NULL);
if (MIE_VECTOR_COUNT(op->op_result) != 1) {
b_stream_write_char(printer->p_stream, '(');
}
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
type = op->op_result.items[i].reg_type;
mie_printer_print_type(printer, type);
}
if (MIE_VECTOR_COUNT(op->op_result) != 1) {
b_stream_write_char(printer->p_stream, ')');
}
}
static void print_generic_op(struct mie_printer *printer, const struct mie_op *op)
{
b_stream_write_char(printer->p_stream, '~');
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
b_stream_write_fmt(
printer->p_stream, NULL, "%s.%s",
op->op_info->op_parent->d_name, op->op_info->op_name);
} else {
b_stream_write_string(printer->p_stream, op->op_name, NULL);
}
b_stream_write_char(printer->p_stream, '(');
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_args); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_op_arg(printer, &op->op_args.items[i], false);
}
b_stream_write_char(printer->p_stream, ')');
print_successor_list(printer, op);
print_region_list(printer, op);
print_attribute_list(printer, op);
print_type_signature(printer, op);
}
void mie_printer_print_op(struct mie_printer *printer, const struct mie_op *op)
{
for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) {
if (i > 0) {
b_stream_write_string(printer->p_stream, ", ", NULL);
}
mie_printer_print_register(printer, &op->op_result.items[i], 0);
}
if (MIE_VECTOR_COUNT(op->op_result) > 0) {
b_stream_write_string(printer->p_stream, " = ", NULL);
}
bool use_generic = !op->op_info || !op->op_info->op_print
|| printer->p_flags & MIE_PRINT_F_GENERIC;
if (use_generic) {
print_generic_op(printer, op);
return;
}
mie_printer_print_op_name(printer, op);
op->op_info->op_print(printer, op);
}
void mie_printer_print_op_name(struct mie_printer *printer, const struct mie_op *op)
{
bool builtin = false;
bool resolved = false;
bool generic = false;
bool abbreviate = false;
if (op->op_flags & MIE_OP_F_OP_RESOLVED) {
resolved = true;
}
if (printer->p_flags & MIE_PRINT_F_ABBREVIATED) {
abbreviate = true;
}
if (printer->p_flags & MIE_PRINT_F_GENERIC) {
generic = true;
b_stream_write_char(printer->p_stream, '~');
} else if (!strcmp(op->op_info->op_parent->d_name, "builtin")) {
builtin = true;
}
if (!resolved) {
b_stream_write_string(printer->p_stream, op->op_name, NULL);
return;
}
if (generic || !builtin || !abbreviate) {
b_stream_write_fmt(
printer->p_stream, NULL, "%s.",
op->op_info->op_parent->d_name);
}
b_stream_write_string(printer->p_stream, op->op_info->op_name, NULL);
return;
}