diff --git a/asm/CMakeLists.txt b/asm/CMakeLists.txt index d4b7afc..4d216b8 100644 --- a/asm/CMakeLists.txt +++ b/asm/CMakeLists.txt @@ -11,5 +11,5 @@ else () endif () target_include_directories(ivy-asm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/) -target_link_libraries(ivy-asm ivy-common Bluelib::Core Bluelib::Object) -target_compile_definitions(ivy-asm PRIVATE IVY_EXPORT=1 IVY_STATIC=${IVY_STATIC}) \ No newline at end of file +target_link_libraries(ivy-asm ivy-common mie Bluelib::Core Bluelib::Object) +target_compile_definitions(ivy-asm PRIVATE IVY_EXPORT=1 IVY_STATIC=${IVY_STATIC}) diff --git a/asm/include/ivy/asm/mie.h b/asm/include/ivy/asm/mie.h new file mode 100644 index 0000000..990cc59 --- /dev/null +++ b/asm/include/ivy/asm/mie.h @@ -0,0 +1,307 @@ +#ifndef IVY_ASM_MIE_H_ +#define IVY_ASM_MIE_H_ + +#include +#include + +struct mie_target; + +enum ivy_select_opcode { + IVY_SELECT_OP_NONE = IVY_INSTR_NONE, + IVY_SELECT_OP_LDR = IVY_INSTR_LDR, + IVY_SELECT_OP_STR = IVY_INSTR_STR, + IVY_SELECT_OP_PUSH = IVY_INSTR_PUSH, + IVY_SELECT_OP_POP = IVY_INSTR_POP, + IVY_SELECT_OP_MSG = IVY_INSTR_MSG, + IVY_SELECT_OP_ADD = IVY_INSTR_ADD, + IVY_SELECT_OP_SUB = IVY_INSTR_SUB, + IVY_SELECT_OP_MUL = IVY_INSTR_MUL, + IVY_SELECT_OP_DIV = IVY_INSTR_DIV, + IVY_SELECT_OP_C_EQ = IVY_INSTR_C_EQ, + IVY_SELECT_OP_C_NE = IVY_INSTR_C_NE, + IVY_SELECT_OP_C_LT = IVY_INSTR_C_LT, + IVY_SELECT_OP_C_LE = IVY_INSTR_C_LE, + IVY_SELECT_OP_C_GT = IVY_INSTR_C_GT, + IVY_SELECT_OP_C_GE = IVY_INSTR_C_GE, + IVY_SELECT_OP_BR = IVY_INSTR_BR, + IVY_SELECT_OP_BR_T = IVY_INSTR_BR_T, + IVY_SELECT_OP_BR_F = IVY_INSTR_BR_F, + IVY_SELECT_OP_OB_C = IVY_INSTR_OB_C, + IVY_SELECT_OP_OB_E = IVY_INSTR_OB_E, + IVY_SELECT_OP_LAM_C = IVY_INSTR_LAM_C, + IVY_SELECT_OP_IT_G = IVY_INSTR_IT_G, + IVY_SELECT_OP_IT_N = IVY_INSTR_IT_N, + IVY_SELECT_OP_IT_V = IVY_INSTR_IT_V, + IVY_SELECT_OP_STK_A = IVY_INSTR_STK_A, + IVY_SELECT_OP_STK_F = IVY_INSTR_STK_F, + IVY_SELECT_OP_RET = IVY_INSTR_RET, + IVY_SELECT_OP_RET_N = IVY_INSTR_RET_N, + IVY_SELECT_OP_REGISTER, + IVY_SELECT_OP_SELECTOR, +}; + +enum ivy_select_register { + IVY_SELECT_REG_X0, + IVY_SELECT_REG_X1, + IVY_SELECT_REG_X2, + IVY_SELECT_REG_X3, + IVY_SELECT_REG_X4, + IVY_SELECT_REG_X5, + IVY_SELECT_REG_X6, + IVY_SELECT_REG_X7, + IVY_SELECT_REG_X8, + IVY_SELECT_REG_X9, + IVY_SELECT_REG_X10, + IVY_SELECT_REG_X11, + IVY_SELECT_REG_X12, + IVY_SELECT_REG_X13, + IVY_SELECT_REG_X14, + IVY_SELECT_REG_X15, + IVY_SELECT_REG_X16, + IVY_SELECT_REG_X17, + IVY_SELECT_REG_X18, + IVY_SELECT_REG_X19, + IVY_SELECT_REG_X20, + IVY_SELECT_REG_X21, + IVY_SELECT_REG_X22, + IVY_SELECT_REG_X23, + IVY_SELECT_REG_X24, + IVY_SELECT_REG_X25, + IVY_SELECT_REG_X26, + IVY_SELECT_REG_X27, + IVY_SELECT_REG_X28, + IVY_SELECT_REG_X29, + IVY_SELECT_REG_X30, + IVY_SELECT_REG_X31, + IVY_SELECT_REG_X32, + IVY_SELECT_REG_X33, + IVY_SELECT_REG_X34, + IVY_SELECT_REG_X35, + IVY_SELECT_REG_X36, + IVY_SELECT_REG_X37, + IVY_SELECT_REG_X38, + IVY_SELECT_REG_X39, + IVY_SELECT_REG_X40, + IVY_SELECT_REG_X41, + IVY_SELECT_REG_X42, + IVY_SELECT_REG_X43, + IVY_SELECT_REG_X44, + IVY_SELECT_REG_X45, + IVY_SELECT_REG_X46, + IVY_SELECT_REG_X47, + IVY_SELECT_REG_X48, + IVY_SELECT_REG_X49, + IVY_SELECT_REG_X50, + IVY_SELECT_REG_X51, + IVY_SELECT_REG_X52, + IVY_SELECT_REG_X53, + IVY_SELECT_REG_X54, + IVY_SELECT_REG_X55, + IVY_SELECT_REG_X56, + IVY_SELECT_REG_X57, + IVY_SELECT_REG_X58, + IVY_SELECT_REG_X59, + IVY_SELECT_REG_X60, + IVY_SELECT_REG_X61, + IVY_SELECT_REG_X62, + IVY_SELECT_REG_X63, + IVY_SELECT_REG_X64, + IVY_SELECT_REG_X65, + IVY_SELECT_REG_X66, + IVY_SELECT_REG_X67, + IVY_SELECT_REG_X68, + IVY_SELECT_REG_X69, + IVY_SELECT_REG_X70, + IVY_SELECT_REG_X71, + IVY_SELECT_REG_X72, + IVY_SELECT_REG_X73, + IVY_SELECT_REG_X74, + IVY_SELECT_REG_X75, + IVY_SELECT_REG_X76, + IVY_SELECT_REG_X77, + IVY_SELECT_REG_X78, + IVY_SELECT_REG_X79, + IVY_SELECT_REG_X80, + IVY_SELECT_REG_X81, + IVY_SELECT_REG_X82, + IVY_SELECT_REG_X83, + IVY_SELECT_REG_X84, + IVY_SELECT_REG_X85, + IVY_SELECT_REG_X86, + IVY_SELECT_REG_X87, + IVY_SELECT_REG_X88, + IVY_SELECT_REG_X89, + IVY_SELECT_REG_X90, + IVY_SELECT_REG_X91, + IVY_SELECT_REG_X92, + IVY_SELECT_REG_X93, + IVY_SELECT_REG_X94, + IVY_SELECT_REG_X95, + IVY_SELECT_REG_X96, + IVY_SELECT_REG_X97, + IVY_SELECT_REG_X98, + IVY_SELECT_REG_X99, + IVY_SELECT_REG_X100, + IVY_SELECT_REG_X101, + IVY_SELECT_REG_X102, + IVY_SELECT_REG_X103, + IVY_SELECT_REG_X104, + IVY_SELECT_REG_X105, + IVY_SELECT_REG_X106, + IVY_SELECT_REG_X107, + IVY_SELECT_REG_X108, + IVY_SELECT_REG_X109, + IVY_SELECT_REG_X110, + IVY_SELECT_REG_X111, + IVY_SELECT_REG_X112, + IVY_SELECT_REG_X113, + IVY_SELECT_REG_X114, + IVY_SELECT_REG_X115, + IVY_SELECT_REG_X116, + IVY_SELECT_REG_X117, + IVY_SELECT_REG_X118, + IVY_SELECT_REG_X119, + IVY_SELECT_REG_X120, + IVY_SELECT_REG_X121, + IVY_SELECT_REG_X122, + IVY_SELECT_REG_X123, + IVY_SELECT_REG_X124, + IVY_SELECT_REG_X125, + IVY_SELECT_REG_X126, + IVY_SELECT_REG_X127, + IVY_SELECT_REG_X128, + IVY_SELECT_REG_X129, + IVY_SELECT_REG_X130, + IVY_SELECT_REG_X131, + IVY_SELECT_REG_X132, + IVY_SELECT_REG_X133, + IVY_SELECT_REG_X134, + IVY_SELECT_REG_X135, + IVY_SELECT_REG_X136, + IVY_SELECT_REG_X137, + IVY_SELECT_REG_X138, + IVY_SELECT_REG_X139, + IVY_SELECT_REG_X140, + IVY_SELECT_REG_X141, + IVY_SELECT_REG_X142, + IVY_SELECT_REG_X143, + IVY_SELECT_REG_X144, + IVY_SELECT_REG_X145, + IVY_SELECT_REG_X146, + IVY_SELECT_REG_X147, + IVY_SELECT_REG_X148, + IVY_SELECT_REG_X149, + IVY_SELECT_REG_X150, + IVY_SELECT_REG_X151, + IVY_SELECT_REG_X152, + IVY_SELECT_REG_X153, + IVY_SELECT_REG_X154, + IVY_SELECT_REG_X155, + IVY_SELECT_REG_X156, + IVY_SELECT_REG_X157, + IVY_SELECT_REG_X158, + IVY_SELECT_REG_X159, + IVY_SELECT_REG_X160, + IVY_SELECT_REG_X161, + IVY_SELECT_REG_X162, + IVY_SELECT_REG_X163, + IVY_SELECT_REG_X164, + IVY_SELECT_REG_X165, + IVY_SELECT_REG_X166, + IVY_SELECT_REG_X167, + IVY_SELECT_REG_X168, + IVY_SELECT_REG_X169, + IVY_SELECT_REG_X170, + IVY_SELECT_REG_X171, + IVY_SELECT_REG_X172, + IVY_SELECT_REG_X173, + IVY_SELECT_REG_X174, + IVY_SELECT_REG_X175, + IVY_SELECT_REG_X176, + IVY_SELECT_REG_X177, + IVY_SELECT_REG_X178, + IVY_SELECT_REG_X179, + IVY_SELECT_REG_X180, + IVY_SELECT_REG_X181, + IVY_SELECT_REG_X182, + IVY_SELECT_REG_X183, + IVY_SELECT_REG_X184, + IVY_SELECT_REG_X185, + IVY_SELECT_REG_X186, + IVY_SELECT_REG_X187, + IVY_SELECT_REG_X188, + IVY_SELECT_REG_X189, + IVY_SELECT_REG_X190, + IVY_SELECT_REG_X191, + IVY_SELECT_REG_X192, + IVY_SELECT_REG_X193, + IVY_SELECT_REG_X194, + IVY_SELECT_REG_X195, + IVY_SELECT_REG_X196, + IVY_SELECT_REG_X197, + IVY_SELECT_REG_X198, + IVY_SELECT_REG_X199, + IVY_SELECT_REG_X200, + IVY_SELECT_REG_X201, + IVY_SELECT_REG_X202, + IVY_SELECT_REG_X203, + IVY_SELECT_REG_X204, + IVY_SELECT_REG_X205, + IVY_SELECT_REG_X206, + IVY_SELECT_REG_X207, + IVY_SELECT_REG_X208, + IVY_SELECT_REG_X209, + IVY_SELECT_REG_X210, + IVY_SELECT_REG_X211, + IVY_SELECT_REG_X212, + IVY_SELECT_REG_X213, + IVY_SELECT_REG_X214, + IVY_SELECT_REG_X215, + IVY_SELECT_REG_X216, + IVY_SELECT_REG_X217, + IVY_SELECT_REG_X218, + IVY_SELECT_REG_X219, + IVY_SELECT_REG_X220, + IVY_SELECT_REG_X221, + IVY_SELECT_REG_X222, + IVY_SELECT_REG_X223, + IVY_SELECT_REG_X224, + IVY_SELECT_REG_X225, + IVY_SELECT_REG_X226, + IVY_SELECT_REG_X227, + IVY_SELECT_REG_X228, + IVY_SELECT_REG_X229, + IVY_SELECT_REG_X230, + IVY_SELECT_REG_X231, + IVY_SELECT_REG_X232, + IVY_SELECT_REG_X233, + IVY_SELECT_REG_X234, + IVY_SELECT_REG_X235, + IVY_SELECT_REG_X236, + IVY_SELECT_REG_X237, + IVY_SELECT_REG_X238, + IVY_SELECT_REG_X239, + IVY_SELECT_REG_X240, + IVY_SELECT_REG_X241, + IVY_SELECT_REG_X242, + IVY_SELECT_REG_X243, + IVY_SELECT_REG_X244, + IVY_SELECT_REG_X245, + IVY_SELECT_REG_X246, + IVY_SELECT_REG_X247, + IVY_SELECT_REG_X248, + IVY_SELECT_REG_X249, + IVY_SELECT_REG_X250, + IVY_SELECT_REG_X251, + IVY_SELECT_REG_X252, + IVY_SELECT_REG_X253, + IVY_SELECT_REG_X254, + IVY_SELECT_REG_X255, + IVY_SELECT_REG_X256, + IVY_SELECT_REG_SP, + IVY_SELECT_REG_BP, +}; + +IVY_API const struct mie_target *ivy_asm_mie_target(void); + +#endif diff --git a/asm/mie/select.c b/asm/mie/select.c new file mode 100644 index 0000000..3b12c4e --- /dev/null +++ b/asm/mie/select.c @@ -0,0 +1,415 @@ +#include "mie/select/opcode.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NODE_NAME(op) \ + case IVY_SELECT_OP_##op: \ + return snprintf(out, max, #op) + +#define NODE_NAME_(op, name) \ + case IVY_SELECT_OP_##op: \ + return snprintf(out, max, name) + +static size_t node_name( + const struct mie_target *target, unsigned int opcode, char *out, size_t max) +{ + switch (opcode) { + NODE_NAME(LDR); + NODE_NAME(STR); + NODE_NAME(PUSH); + NODE_NAME(POP); + NODE_NAME(MSG); + NODE_NAME(ADD); + NODE_NAME(SUB); + NODE_NAME(MUL); + NODE_NAME(DIV); + NODE_NAME_(C_EQ, "C.EQ"); + NODE_NAME_(C_NE, "C.NE"); + NODE_NAME_(C_LT, "C.LT"); + NODE_NAME_(C_LE, "C.LE"); + NODE_NAME_(C_GT, "C.GT"); + NODE_NAME_(C_GE, "C.GE"); + NODE_NAME(BR); + NODE_NAME_(BR_T, "BR.T"); + NODE_NAME_(BR_F, "BR.F"); + NODE_NAME_(OB_C, "OB.C"); + NODE_NAME_(OB_E, "OB.E"); + NODE_NAME_(LAM_C, "LAM.C"); + NODE_NAME_(IT_G, "IT.G"); + NODE_NAME_(IT_N, "IT.N"); + NODE_NAME_(IT_V, "IT.V"); + NODE_NAME_(STK_A, "STK.A"); + NODE_NAME_(STK_F, "STK.F"); + NODE_NAME(RET); + NODE_NAME_(RET_N, "RET.N"); + NODE_NAME_(REGISTER, "Register"); + NODE_NAME_(SELECTOR, "Selector"); + default: + return snprintf(out, max, "UNKNOWN"); + } + + return 0; +} + +static enum mie_status get_sp_register( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_select_value *out) +{ + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_type *ptr_type = mie_ctx_get_type(ctx, MIE_TYPE_PTR); + + struct mie_select_node *sp_node = mie_select_builder_find_node_with_ivalue( + builder, target, IVY_SELECT_OP_REGISTER, IVY_SELECT_REG_SP); + + if (sp_node) { + mie_select_node_get_value(sp_node, ptr_type, 0, out); + return MIE_SUCCESS; + } + + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + enum mie_status status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_REGISTER, NULL, 0, &ptr_type, 1, + &sp_node); + if (status != MIE_SUCCESS) { + return status; + } + + sp_node->n_value.i = IVY_SELECT_REG_SP; + mie_select_node_set_description(sp_node, "$sp"); + mie_select_node_get_value(sp_node, ptr_type, 0, out); + return MIE_SUCCESS; +} + +static enum mie_status get_selector( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_selector *sel, struct mie_select_value *out) +{ + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_type *ptr_type = mie_ctx_get_type(ctx, MIE_TYPE_PTR); + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + + b_queue *nodes = &graph->g_nodes; + b_queue_iterator it; + b_queue_foreach (&it, nodes) { + struct mie_select_node *node + = b_unbox(struct mie_select_node, it.entry, n_entry); + + if (node->n_target != target) { + continue; + } + + if (node->n_opcode != IVY_SELECT_OP_SELECTOR) { + continue; + } + + if (!node->n_value.v || !mie_value_is_selector(node->n_value.v)) { + continue; + } + + struct mie_selector *sel_node = (struct mie_selector *)node; + if (strcmp(sel->sel_value, sel_node->sel_value) != 0) { + continue; + } + + mie_select_node_get_value(node, ptr_type, 0, out); + return MIE_SUCCESS; + } + + struct mie_select_node *sel_node; + enum mie_status status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_SELECTOR, NULL, 0, &ptr_type, 1, + &sel_node); + if (status != MIE_SUCCESS) { + return status; + } + + sel_node->n_value.v = MIE_VALUE(sel); + mie_select_node_set_description(sel_node, "%s", sel->sel_value); + mie_select_node_get_value(sel_node, ptr_type, 0, out); + + return MIE_SUCCESS; +} + +static enum mie_status load_selector( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_select_value *sel, struct mie_select_value *out) +{ + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_type *id_type = mie_ctx_get_type(ctx, MIE_TYPE_ID); + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + struct mie_select_node *load_sel; + + struct mie_select_value *operands[] = { + &graph->g_entry, + sel, + }; + const size_t nr_operands = sizeof operands / sizeof operands[0]; + + struct mie_type *results[] = { + id_type, + }; + const size_t nr_results = sizeof results / sizeof results[0]; + + enum mie_status status = mie_select_graph_get_node( + graph, mie_target_builtin(), MIE_SELECT_OP_LOAD, operands, + nr_operands, results, nr_results, &load_sel); + if (status != MIE_SUCCESS) { + return status; + } + + mie_select_node_get_value(load_sel, id_type, 0, out); + return MIE_SUCCESS; +} + +static enum mie_status create_stack_alloc( + const struct mie_target *target, struct mie_select_builder *builder, + size_t count, struct mie_select_value *incoming_chain, + struct mie_select_value *out) +{ + struct mie_select_node *alloc; + enum mie_status status; + + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_type *chain = mie_ctx_get_type(ctx, MIE_TYPE_OTHER); + struct mie_type *i32 = mie_ctx_get_int_type(ctx, 32); + + struct mie_select_value count_value; + mie_select_builder_get_const(builder, count, &count_value); + + struct mie_select_value *operands[] = { + &count_value, + incoming_chain, + }; + const size_t nr_operands = sizeof operands / sizeof operands[0]; + + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_STK_A, operands, nr_operands, + &chain, 1, &alloc); + if (status != MIE_SUCCESS) { + return status; + } + + mie_select_node_get_value(alloc, chain, 0, out); + mie_select_node_set_description( + alloc, "(allocate %zu slots on stack)", count); + + return MIE_SUCCESS; +} + +static enum mie_status create_stack_free( + const struct mie_target *target, struct mie_select_builder *builder, + size_t count, struct mie_select_value *incoming_chain, + struct mie_select_value *out) +{ + struct mie_select_node *free_node; + enum mie_status status; + + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_type *chain = mie_ctx_get_type(ctx, MIE_TYPE_OTHER); + struct mie_type *i32 = mie_ctx_get_int_type(ctx, 32); + + struct mie_select_value count_value; + mie_select_builder_get_const(builder, count, &count_value); + + struct mie_select_value *operands[] = { + &count_value, + incoming_chain, + }; + const size_t nr_operands = sizeof operands / sizeof operands[0]; + + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_STK_F, operands, nr_operands, + &chain, 1, &free_node); + if (status != MIE_SUCCESS) { + return status; + } + + mie_select_node_set_description( + free_node, "(free %zu slots on stack)", count); + mie_select_node_get_value(free_node, chain, 0, out); + + return MIE_SUCCESS; +} + +static enum mie_status create_chain_group( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_select_value **incoming_chains, size_t count, + struct mie_select_value *out) +{ + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + struct mie_select_node *group = NULL; + + struct mie_type *chain_type = mie_ctx_get_type(ctx, MIE_TYPE_OTHER); + + enum mie_status status = mie_select_graph_get_node( + graph, mie_target_builtin(), MIE_SELECT_OP_CHAIN_GROUP, + incoming_chains, count, &chain_type, 1, &group); + if (status != MIE_SUCCESS) { + return status; + } + + mie_select_node_get_value(group, chain_type, 0, out); + return MIE_SUCCESS; +} + +static enum mie_status put_param_on_stack( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_select_value *in_chain, struct mie_select_value *param, + size_t offset, struct mie_select_value *out_chain) +{ + struct mie_select_value sp; + struct mie_select_value offset_value; + struct mie_type *chain_type; + + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + + get_sp_register(target, builder, &sp); + mie_select_builder_get_const(builder, offset, &offset_value); + chain_type = mie_ctx_get_type(ctx, MIE_TYPE_OTHER); + + struct mie_select_value *operands[] = { + in_chain, + param, + &sp, + &offset_value, + }; + const size_t nr_operands = sizeof operands / sizeof operands[0]; + + struct mie_select_node *store; + enum mie_status status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_STR, operands, nr_operands, + &chain_type, 1, &store); + + mie_select_node_set_description( + store, "(store N%zu on stack + %zu)", param->v_node->n_id, offset); + mie_select_node_get_value(store, chain_type, 0, out_chain); + return MIE_SUCCESS; +} + +static enum mie_status lower_msg( + const struct mie_target *target, struct mie_select_builder *builder, + struct mie_msg *msg, struct mie_select_value *result) +{ + enum mie_status status = MIE_SUCCESS; + struct mie_select_graph *graph = mie_select_builder_get_graph(builder); + struct mie_ctx *ctx = mie_select_builder_get_ctx(builder); + + struct mie_select_value **param_chains = calloc( + b_max(size_t, 2, msg->msg_nr_args + 1), + sizeof(struct mie_select_value *)); + size_t nr_param_chains = 0; + struct mie_select_value *chain, *recipient, nr_args; + + chain = mie_select_builder_get_mem_access(builder, msg->msg_recipient); + recipient = mie_select_builder_get_value(builder, msg->msg_recipient); + mie_select_builder_get_const(builder, msg->msg_nr_args, &nr_args); + + if (chain) { + param_chains[nr_param_chains++] = chain; + } + + for (size_t i = 0; i < msg->msg_nr_args; i++) { + struct mie_select_value *chain = mie_select_builder_get_mem_access( + builder, msg->msg_args[i]); + if (chain) { + param_chains[nr_param_chains++] = chain; + } + } + + if (nr_param_chains == 0) { + param_chains[nr_param_chains++] = &graph->g_entry; + } + + struct mie_select_value pre_arg_init_chain, post_arg_init_chain; + if (nr_param_chains > 1) { + status = create_chain_group( + target, builder, param_chains, nr_param_chains, + &pre_arg_init_chain); + } else { + pre_arg_init_chain = *param_chains[0]; + } + + struct mie_select_value stack_alloc, stack_free; + status = create_stack_alloc( + target, builder, msg->msg_nr_args, &pre_arg_init_chain, + &stack_alloc); + if (status != MIE_SUCCESS) { + return status; + } + + struct mie_select_value *stack_chains = calloc( + b_max(size_t, 1, msg->msg_nr_args), + sizeof(struct mie_select_value)); + size_t nr_stack_chains = 0; + nr_param_chains = 0; + + for (size_t i = 0; i < msg->msg_nr_args; i++) { + struct mie_select_value *param_value + = mie_select_builder_get_value(builder, msg->msg_args[i]); + status = put_param_on_stack( + target, builder, &stack_alloc, param_value, i, + &stack_chains[nr_stack_chains]); + param_chains[nr_param_chains] = &stack_chains[nr_stack_chains]; + + nr_param_chains++; + nr_stack_chains++; + } + + if (nr_param_chains > 1) { + status = create_chain_group( + target, builder, param_chains, nr_param_chains, + &post_arg_init_chain); + } else { + post_arg_init_chain = *param_chains[0]; + } + + free(param_chains); + free(stack_chains); + + struct mie_select_value sel, load_sel; + get_selector(target, builder, MIE_SELECTOR(msg->msg_selector), &sel); + load_selector(target, builder, &sel, &load_sel); + + struct mie_select_value *msg_params[] = { + &post_arg_init_chain, + recipient, + &load_sel, + &nr_args, + }; + const size_t nr_msg_params = sizeof msg_params / sizeof msg_params[0]; + + struct mie_type *msg_results[] = { + mie_ctx_get_type(ctx, MIE_TYPE_OTHER), + mie_ctx_get_type(ctx, MIE_TYPE_GLUE), + }; + const size_t nr_msg_results = sizeof msg_results / sizeof msg_results[0]; + + struct mie_select_node *msg_node; + status = mie_select_graph_get_node( + graph, target, IVY_SELECT_OP_MSG, msg_params, nr_msg_params, + msg_results, nr_msg_results, &msg_node); + + result->v_node = msg_node; + result->v_index = 0; + + return MIE_SUCCESS; +} + +const struct mie_target_select_ops __ivy_select_ops = { + .s_node_name = node_name, + .s_lower_msg = lower_msg, +}; diff --git a/asm/mie/target.c b/asm/mie/target.c new file mode 100644 index 0000000..c72cb75 --- /dev/null +++ b/asm/mie/target.c @@ -0,0 +1,13 @@ +#include + +extern const struct mie_target_select_ops __ivy_select_ops; + +static const struct mie_target ivy_target = { + .t_name = "Ivy", + .t_select = &__ivy_select_ops, +}; + +const struct mie_target *ivy_asm_mie_target(void) +{ + return &ivy_target; +}