mie: implement instruction selection graph generation for binary ops and load/store

This commit is contained in:
2025-08-29 15:46:52 +01:00
parent 7fdae9f1e0
commit 9c1e0958b0
19 changed files with 1343 additions and 13 deletions

View File

@@ -2,10 +2,26 @@
#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;
MIE_API struct mie_select_builder *mie_select_builder_create(void);
MIE_API struct mie_select_builder *mie_select_builder_create(struct mie_ctx *ctx);
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 struct mie_select_graph *mie_select_builder_finish(
struct mie_select_builder *builder);
MIE_API enum mie_status mie_select_builder_push_instr(
struct mie_select_builder *builder, struct mie_instr *instr);
#endif

View File

@@ -5,7 +5,9 @@
#include <blue/core/queue.h>
#include <mie/misc.h>
struct mie_select_value;
struct mie_ctx;
struct mie_type;
struct mie_instr;
struct mie_select_value {
struct mie_select_node *v_node;
@@ -15,15 +17,42 @@ struct mie_select_value {
struct mie_select_use {
struct mie_select_node *u_user;
struct mie_select_value u_value;
b_queue u_entry;
b_queue_entry u_entry;
};
struct mie_select_graph {
b_queue g_nodes;
b_queue g_use;
struct mie_select_value g_root;
struct mie_select_value g_entry;
struct mie_select_value g_last_chain;
size_t g_frame_index;
size_t g_node_id;
};
MIE_API struct mie_select_graph *mie_select_graph_create(void);
struct mie_select_use_iterator {
b_queue_iterator it_base;
};
#define mie_select_use_foreach(it, q) b_queue_foreach (&(it)->it_base, q)
static inline struct mie_select_use *mie_select_use_iterator_unbox(
struct mie_select_use_iterator *it)
{
return b_unbox(struct mie_select_use, it->it_base.entry, u_entry);
}
MIE_API void mie_select_use_iterator_next(struct mie_select_use_iterator *it);
MIE_API bool mie_select_use_iterator_is_valid(
const struct mie_select_use_iterator *it);
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, unsigned int op,
struct mie_select_value **operands, size_t nr_operands,
struct mie_type **values, size_t nr_values, struct mie_select_value *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);
#endif

View File

@@ -7,15 +7,86 @@
#define MIE_SELECT_NODE_OUTPUT_MAX 4
struct mie_backend;
struct mie_target;
struct mie_value;
struct mie_select_value;
struct mie_select_node {
unsigned long n_opcode;
struct mie_value *n_value;
b_queue n_entry;
struct mie_backend *n_backend;
const struct mie_type t_outputs[MIE_SELECT_NODE_OUTPUT_MAX];
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;
/* certain "builtin" parameters that can be used by opcodes */
struct mie_value *n_value_p;
long long n_value_i;
/* 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_iterator it_base;
};
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_base.entry, 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 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

View File

@@ -4,10 +4,23 @@
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_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_BR,
MIE_SELECT_OP_BR_COND,
};
#endif

View File

@@ -2,7 +2,11 @@
#define MIE_STATUS_H_
enum mie_status {
MIE_OK = 0,
MIE_SUCCESS = 0,
MIE_ERR_NOT_SUPPORTED,
MIE_ERR_INVALID_VALUE,
MIE_ERR_NO_MEMORY,
MIE_ERR_NO_ENTRY,
};
#endif

View File

@@ -0,0 +1,34 @@
#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_instr;
struct mie_select_builder;
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_instr *);
enum mie_status (*s_lower_msg)(
const struct mie_target *, struct mie_select_builder *,
struct mie_instr *);
};
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_instr *instr);
MIE_API enum mie_status mie_target_select_lower_msg(
const struct mie_target *target, struct mie_select_builder *builder,
struct mie_instr *instr);
#endif

View File

@@ -1,7 +1,14 @@
#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

View File

@@ -35,4 +35,6 @@ struct mie_type {
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);
#endif