mie: select: implement branch operation processing
This commit is contained in:
171
mie/select/br.c
Normal file
171
mie/select/br.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
#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,
|
||||||
|
};
|
||||||
@@ -20,10 +20,13 @@ DECLARE_INSTR_TYPE(cmp_geq);
|
|||||||
DECLARE_INSTR_TYPE(load);
|
DECLARE_INSTR_TYPE(load);
|
||||||
DECLARE_INSTR_TYPE(store);
|
DECLARE_INSTR_TYPE(store);
|
||||||
DECLARE_INSTR_TYPE(msg);
|
DECLARE_INSTR_TYPE(msg);
|
||||||
|
DECLARE_INSTR_TYPE(br);
|
||||||
|
DECLARE_INSTR_TYPE(br_if);
|
||||||
|
|
||||||
static const struct select_instr_type *instr_types[] = {
|
static const struct select_instr_type *instr_types[] = {
|
||||||
INSTR_TYPE_ENTRY(ALLOCA, alloca), INSTR_TYPE_ENTRY(LOAD, load),
|
INSTR_TYPE_ENTRY(ALLOCA, alloca), INSTR_TYPE_ENTRY(LOAD, load),
|
||||||
INSTR_TYPE_ENTRY(STORE, store), INSTR_TYPE_ENTRY(MSG, msg),
|
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(ADD, add), INSTR_TYPE_ENTRY(SUB, sub),
|
||||||
INSTR_TYPE_ENTRY(MUL, mul), INSTR_TYPE_ENTRY(DIV, div),
|
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_EQ, cmp_eq), INSTR_TYPE_ENTRY(CMP_NEQ, cmp_neq),
|
||||||
|
|||||||
Reference in New Issue
Block a user