#include #include #include #include #include #include #include #include #include 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; }