From 26a49162e602ff110faf87a87047d0ce8103bb73 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 10 Mar 2026 19:12:14 +0000 Subject: [PATCH] toolchain: replace ifc interface compiler with xpcg xpcg is used to generate xpc interfaces --- toolchain/CMakeLists.txt | 2 +- toolchain/ifc/CMakeLists.txt | 7 - toolchain/xpcg/CMakeLists.txt | 7 + toolchain/{ifc => xpcg}/backend.h | 4 +- .../{ifc => xpcg}/backend/c-mpc/backend.c | 1054 ++++------------- toolchain/{ifc => xpcg}/ctx.c | 8 + toolchain/{ifc => xpcg}/ctx.h | 4 +- toolchain/{ifc => xpcg}/file-span.h | 4 +- toolchain/{ifc => xpcg}/interface.c | 5 +- toolchain/{ifc => xpcg}/interface.h | 8 +- toolchain/{ifc => xpcg}/lex.c | 5 +- toolchain/{ifc => xpcg}/lex.h | 4 +- toolchain/{ifc => xpcg}/line-source.c | 0 toolchain/{ifc => xpcg}/line-source.h | 0 toolchain/{ifc => xpcg}/main.c | 11 +- toolchain/{ifc => xpcg}/msg.c | 3 +- toolchain/{ifc => xpcg}/msg.h | 9 +- toolchain/{ifc => xpcg}/parse.c | 138 ++- toolchain/{ifc => xpcg}/parse.h | 4 +- toolchain/{ifc => xpcg}/status.h | 4 +- toolchain/{ifc => xpcg}/token.c | 3 +- toolchain/{ifc => xpcg}/token.h | 9 +- toolchain/{ifc => xpcg}/type.c | 6 + toolchain/{ifc => xpcg}/type.h | 6 +- 24 files changed, 427 insertions(+), 878 deletions(-) delete mode 100644 toolchain/ifc/CMakeLists.txt create mode 100644 toolchain/xpcg/CMakeLists.txt rename toolchain/{ifc => xpcg}/backend.h (79%) rename toolchain/{ifc => xpcg}/backend/c-mpc/backend.c (52%) rename toolchain/{ifc => xpcg}/ctx.c (84%) rename toolchain/{ifc => xpcg}/ctx.h (89%) rename toolchain/{ifc => xpcg}/file-span.h (69%) rename toolchain/{ifc => xpcg}/interface.c (91%) rename toolchain/{ifc => xpcg}/interface.h (82%) rename toolchain/{ifc => xpcg}/lex.c (98%) rename toolchain/{ifc => xpcg}/lex.h (96%) rename toolchain/{ifc => xpcg}/line-source.c (100%) rename toolchain/{ifc => xpcg}/line-source.h (100%) rename toolchain/{ifc => xpcg}/main.c (94%) rename toolchain/{ifc => xpcg}/msg.c (95%) rename toolchain/{ifc => xpcg}/msg.h (83%) rename toolchain/{ifc => xpcg}/parse.c (64%) rename toolchain/{ifc => xpcg}/parse.h (78%) rename toolchain/{ifc => xpcg}/status.h (84%) rename toolchain/{ifc => xpcg}/token.c (96%) rename toolchain/{ifc => xpcg}/token.h (93%) rename toolchain/{ifc => xpcg}/type.c (74%) rename toolchain/{ifc => xpcg}/type.h (72%) diff --git a/toolchain/CMakeLists.txt b/toolchain/CMakeLists.txt index 6fcd468..3318416 100644 --- a/toolchain/CMakeLists.txt +++ b/toolchain/CMakeLists.txt @@ -14,4 +14,4 @@ add_subdirectory( ../kernel/tools ${CMAKE_CURRENT_BINARY_DIR}/kernel-tools) -add_subdirectory(ifc) +add_subdirectory(xpcg) diff --git a/toolchain/ifc/CMakeLists.txt b/toolchain/ifc/CMakeLists.txt deleted file mode 100644 index 400f265..0000000 --- a/toolchain/ifc/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB sources - *.c *.h - backend/c-mpc/*.c backend/c-mpc/*.h) - -add_executable(ifc ${sources}) - -target_link_libraries(ifc Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io) diff --git a/toolchain/xpcg/CMakeLists.txt b/toolchain/xpcg/CMakeLists.txt new file mode 100644 index 0000000..3e0d24e --- /dev/null +++ b/toolchain/xpcg/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB sources + *.c *.h + backend/c-mpc/*.c backend/c-mpc/*.h) + +add_executable(xpcg ${sources}) + +target_link_libraries(xpcg Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io) diff --git a/toolchain/ifc/backend.h b/toolchain/xpcg/backend.h similarity index 79% rename from toolchain/ifc/backend.h rename to toolchain/xpcg/backend.h index 6bf8a1b..ac22ed1 100644 --- a/toolchain/ifc/backend.h +++ b/toolchain/xpcg/backend.h @@ -1,5 +1,5 @@ -#ifndef IFC_BACKEND_H_ -#define IFC_BACKEND_H_ +#ifndef XPCG_BACKEND_H_ +#define XPCG_BACKEND_H_ struct interface_definition; diff --git a/toolchain/ifc/backend/c-mpc/backend.c b/toolchain/xpcg/backend/c-mpc/backend.c similarity index 52% rename from toolchain/ifc/backend/c-mpc/backend.c rename to toolchain/xpcg/backend/c-mpc/backend.c index 09a9daa..f8626f4 100644 --- a/toolchain/ifc/backend/c-mpc/backend.c +++ b/toolchain/xpcg/backend/c-mpc/backend.c @@ -73,167 +73,6 @@ static int emit_header_guard_end( return 0; } -static int emit_header_lib_impl(struct emit_ctx *ctx) -{ - emit(ctx, "kern_status_t msg_recv_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nstruct msg_endpoint *out_sender,\nstruct " - "msg_header *out_hdr,\nkern_msg_handle_t *out_handles,\nsize_t " - "out_handles_max)\n"); - emit_unindent(ctx); - emit(ctx, "{\n"); - emit_indent(ctx); - - /* clang-format off */ - emit(ctx, - "kern_iovec_t iov = IOVEC(out_hdr, sizeof *out_hdr);\n" - "kern_msg_t msg = { .msg_data = &iov, .msg_data_count = 1, " - ".msg_handles = out_handles, .msg_handles_count = out_handles_max };\n" - "kern_status_t status = msg_recv(channel, &msg);\n" - "if (status != KERN_OK) return status;\n" - "if (out_hdr->hdr_magic != MSG_MAGIC) return KERN_INVALID_ARGUMENT;\n" - "out_sender->e_task = msg.msg_sender;\n" - "out_sender->e_port = msg.msg_endpoint;\n" - "out_sender->e_msg = msg.msg_id;\n" - "return KERN_OK;\n"); - /* clang-format on */ - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - emit(ctx, "kern_status_t msg_read_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nconst struct msg_endpoint *sender,\n" - "struct msg_header *out_hdr)\n"); - emit_unindent(ctx); - emit(ctx, "{\n"); - emit_indent(ctx); - - /* clang-format off */ - emit(ctx, - "kern_iovec_t iov = IOVEC(out_hdr, sizeof *out_hdr);\n" - "size_t r = 0;\n" - "kern_status_t status = msg_read(channel, sender->e_msg, 0, &iov, 1, &r);\n" - "if (status != KERN_OK) return status;\n" - "if (r != sizeof *out_hdr) return KERN_INVALID_ARGUMENT;\n" - "if (out_hdr->hdr_magic != MSG_MAGIC) return KERN_INVALID_ARGUMENT;\n" - "return KERN_OK;\n"); - /* clang-format on */ - - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - emit(ctx, "kern_status_t msg_reply_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nconst struct msg_endpoint *sender,\n" - "const struct msg_header *msg_data,\nuint16_t status)\n"); - emit_unindent(ctx); - emit(ctx, "{\n"); - emit_indent(ctx); - - /* clang-format off */ - emit(ctx, - "struct msg_header resp_data = {\n"); - emit_indent(ctx); - emit(ctx, - ".hdr_magic = MSG_MAGIC,\n.hdr_status = status,\n"); - emit_unindent(ctx); - emit(ctx, "};\n"); - emit(ctx, - "if (msg_data) {\n"); - emit_indent(ctx); - emit(ctx, - "resp_data.hdr_protocol = msg_data->hdr_protocol;\n" - "resp_data.hdr_func = msg_data->hdr_func;\n"); - emit_unindent(ctx); - emit(ctx, "}\n"); - - emit(ctx, - "kern_iovec_t iov = IOVEC(&resp_data, sizeof resp_data);\n" - "kern_msg_t reply = { .msg_data = &iov, .msg_data_count = 1 };\n" - "return msg_reply(channel, sender->e_msg, &reply);\n"); - /* clang-format on */ - - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - return 0; -} - -static int emit_header_lib_definitions(struct emit_ctx *ctx) -{ - emit(ctx, "#if !defined(MSG_STRINGBUF_SIZE)\n"); - emit(ctx, "#define MSG_STRINGBUF_SIZE 256\n"); - emit(ctx, "#endif\n\n"); - - emit(ctx, "#if !defined(MSG_LIB_DEFINED)\n"); - emit(ctx, "#define MSG_LIB_DEFINED\n\n"); - - emit(ctx, "#define MSG_MAGIC 0x9AB07D10U\n\n"); - - emit(ctx, "struct msg_endpoint {\n"); - emit_indent(ctx); - - emit(ctx, "tid_t e_task;\n"); - emit(ctx, "koid_t e_port;\n"); - emit(ctx, "msgid_t e_msg;\n"); - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - - emit(ctx, "struct msg_header {\n"); - emit_indent(ctx); - - emit(ctx, "uint32_t hdr_magic;\n"); - emit(ctx, "uint32_t hdr_protocol;\n"); - emit(ctx, "uint16_t hdr_func;\n"); - emit(ctx, "uint16_t hdr_status;\n"); - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - - emit(ctx, "struct msg_string {\n"); - emit_indent(ctx); - - emit(ctx, "char *str_buf;\n"); - emit(ctx, "size_t str_len;\n"); - emit(ctx, "size_t str_max;\n"); - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - - emit(ctx, "extern kern_status_t msg_recv_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nstruct msg_endpoint *out_sender,\nstruct " - "msg_header *out_hdr,\nkern_msg_handle_t *out_handles,\nsize_t " - "out_handles_max);\n"); - emit_unindent(ctx); - - emit(ctx, "extern kern_status_t msg_read_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nconst struct msg_endpoint *sender,\n" - "struct msg_header *out_hdr);\n"); - emit_unindent(ctx); - - emit(ctx, "extern kern_status_t msg_reply_generic(\n"); - emit_indent(ctx); - emit(ctx, - "kern_handle_t channel,\nconst struct msg_endpoint *sender,\n" - "const struct msg_header *msg_data, uint16_t status);\n"); - emit_unindent(ctx); - - emit(ctx, "#if defined(MSG_IMPLEMENTATION)\n\n"); - emit_header_lib_impl(ctx); - emit(ctx, "#endif\n\n"); - - emit(ctx, "#endif\n\n"); - return 0; -} - static size_t get_msg_handle_params(const struct msg_definition *msg) { size_t count = 0; @@ -278,10 +117,10 @@ static int emit_interface_id_macros( b_string_append_cstr(iface_define_name, iface->if_name); b_string_toupper(iface_define_name); - uint32_t protocol_id = b_hash_cstr(iface->if_name) & 0xFFFFFFFF; + uint32_t protocol_id = iface->if_id; emit(ctx, - "/* %s protocol ID */\n#define PROTOCOL_%s 0x%08xU\n\n", + "/* %s protocol ID */\n#define INTERFACE_%s 0x%08xU\n\n", iface->if_name, b_string_ptr(iface_define_name), protocol_id); @@ -300,7 +139,7 @@ static int emit_interface_id_macros( msg->msg_name); emit(ctx, "/* %s message ID */\n", b_string_ptr(msg_name)); - uint16_t msg_id = b_hash_cstr(b_string_ptr(msg_name)) & 0xFFFF; + uint16_t msg_id = msg->msg_id; b_string_clear(msg_name); b_string_append_cstrf( @@ -334,7 +173,11 @@ static int emit_msg_struct_member( case TYPE_HANDLE: emit(ctx, "kern_handle_t %s;\n", param->p_name); break; + case TYPE_SIZE: + emit(ctx, "uint64_t %s;\n", param->p_name); + break; case TYPE_STRING: + case TYPE_BUFFER: emit(ctx, "uint16_t %s_offset;\n", param->p_name); emit(ctx, "uint16_t %s_len;\n", param->p_name); break; @@ -361,12 +204,19 @@ static int emit_msg_struct_params( while (entry) { const struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); - if (param->p_type->ty_id != TYPE_STRING) { - entry = b_queue_next(entry); - continue; - } - emit(ctx, "uint16_t %s_max;\n", param->p_name); + switch (param->p_type->ty_id) { + case TYPE_STRING: + emit(ctx, "uint16_t %s_offset;\n", param->p_name); + emit(ctx, "uint16_t %s_max;\n", param->p_name); + break; + case TYPE_BUFFER: + emit(ctx, "uint16_t %s_offset;\n", param->p_name); + emit(ctx, "uint32_t %s_max;\n", param->p_name); + break; + default: + break; + } entry = b_queue_next(entry); } @@ -396,10 +246,10 @@ static int emit_interface_msg_struct( { b_string *tmp = b_string_create(); - emit(ctx, "struct msg_%s_%s {\n", iface->if_name, msg->msg_name); + emit(ctx, "struct %s_%s_msg {\n", iface->if_name, msg->msg_name); emit_indent(ctx); - emit(ctx, "struct msg_header msg_header;\n"); + emit(ctx, "xpc_msg_header_t msg_header;\n"); emit(ctx, "union {\n"); emit_indent(ctx); @@ -460,22 +310,21 @@ static int emit_interface_msg_function_send_impl( b_string_toupper(msg_ucase); emit(ctx, - "struct msg_%s_%s msg_data = {0};\n", + "struct %s_%s_msg msg_data = {0};\n", iface->if_name, msg->msg_name); - emit(ctx, "msg_data.msg_header.hdr_magic = MSG_MAGIC;\n"); emit(ctx, - "msg_data.msg_header.hdr_protocol = PROTOCOL_%s;\n", - b_string_ptr(iface_ucase)); - emit(ctx, - "msg_data.msg_header.hdr_func = MSG_%s_%s;\n\n", + "xpc_msg_header_init(&msg_data.msg_header, INTERFACE_%s, " + "MSG_%s_%s);\n", + b_string_ptr(iface_ucase), b_string_ptr(iface_ucase), b_string_ptr(msg_ucase)); b_string_unref(iface_ucase); b_string_unref(msg_ucase); - emit(ctx, "uint16_t offset = sizeof msg_data;\n\n"); + emit(ctx, "uint32_t in_offset = sizeof msg_data;\n\n"); + emit(ctx, "uint32_t out_offset = sizeof msg_data;\n\n"); size_t nr_req_handles = 0; size_t nr_resp_handles = 0; @@ -486,6 +335,7 @@ static int emit_interface_msg_function_send_impl( = b_unbox(struct msg_parameter, entry, p_entry); switch (param->p_type->ty_id) { case TYPE_INT: + case TYPE_SIZE: emit(ctx, "msg_data.msg_request.%s = %s;\n\n", param->p_name, @@ -500,14 +350,26 @@ static int emit_interface_msg_function_send_impl( break; case TYPE_STRING: emit(ctx, - "msg_data.msg_request.%s_offset = offset;\n", + "msg_data.msg_request.%s_offset = in_offset;\n", param->p_name); emit(ctx, "msg_data.msg_request.%s_len = strlen(%s);\n", param->p_name, param->p_name); emit(ctx, - "offset += msg_data.msg_request.%s_len;\n", + "in_offset += msg_data.msg_request.%s_len;\n", + param->p_name); + break; + case TYPE_BUFFER: + emit(ctx, + "msg_data.msg_request.%s_offset = offset;\n", + param->p_name); + emit(ctx, + "msg_data.msg_request.%s_len = %s_len;\n", + param->p_name, + param->p_name); + emit(ctx, + "in_offset += msg_data.msg_request.%s_len;\n", param->p_name); break; default: @@ -523,10 +385,16 @@ static int emit_interface_msg_function_send_impl( = b_unbox(struct msg_parameter, entry, p_entry); switch (param->p_type->ty_id) { case TYPE_STRING: + case TYPE_BUFFER: emit(ctx, - "msg_data.msg_request.%s_max = out_%s->str_max;\n", + "msg_data.msg_request.%s_offset = out_offset;\n", param->p_name, param->p_name); + emit(ctx, + "msg_data.msg_request.%s_max = out_%s_max;\n", + param->p_name, + param->p_name); + emit(ctx, "out_offset += out_%s_max;\n", param->p_name); break; case TYPE_HANDLE: nr_resp_handles++; @@ -547,17 +415,20 @@ static int emit_interface_msg_function_send_impl( while (entry) { struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); - if (param->p_type->ty_id != TYPE_STRING) { - entry = b_queue_next(entry); - continue; + + switch (param->p_type->ty_id) { + case TYPE_STRING: + case TYPE_BUFFER: + emit(ctx, + "IOVEC(%s, msg_data.msg_request.%s_len),\n", + param->p_name, + param->p_name); + nr_req_iov++; + break; + default: + break; } - emit(ctx, - "IOVEC(%s, msg_data.msg_request.%s_len),\n", - param->p_name, - param->p_name); - - nr_req_iov++; entry = b_queue_next(entry); } @@ -579,17 +450,20 @@ static int emit_interface_msg_function_send_impl( while (entry) { struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); - if (param->p_type->ty_id != TYPE_STRING) { - entry = b_queue_next(entry); - continue; + + switch (param->p_type->ty_id) { + case TYPE_STRING: + case TYPE_BUFFER: + emit(ctx, + "IOVEC(out_%s, out_%s_max),\n", + param->p_name, + param->p_name); + nr_resp_iov++; + break; + default: + break; } - emit(ctx, - "IOVEC(out_%s->str_buf, out_%s->str_max),\n", - param->p_name, - param->p_name); - - nr_resp_iov++; entry = b_queue_next(entry); } @@ -608,7 +482,7 @@ static int emit_interface_msg_function_send_impl( if (nr_req_handles) { emit(ctx, - ".msg_handles = req_handles,\n.msg_handles_count = %zu.", + ".msg_handles = req_handles,\n.msg_handles_count = %zu,", nr_req_handles); } @@ -642,22 +516,6 @@ static int emit_interface_msg_function_send_impl( struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); switch (param->p_type->ty_id) { - case TYPE_STRING: - emit(ctx, - "out_%s->str_len = " - "msg_data.msg_response.%s_len;\n", - param->p_name, - param->p_name); - emit(ctx, - "out_%s->str_buf[out_%s->str_len < " - "out_%s->str_max ? out_%s->str_len : " - "(out_%s->str_max - 1)] = '\\0';\n", - param->p_name, - param->p_name, - param->p_name, - param->p_name, - param->p_name); - break; case TYPE_HANDLE: emit(ctx, "*out_%s = ", param->p_name); emit(ctx, @@ -671,6 +529,9 @@ static int emit_interface_msg_function_send_impl( param->p_name); emit(ctx, ": KERN_HANDLE_INVALID;\n"); break; + case TYPE_BUFFER: + case TYPE_STRING: + break; default: emit(ctx, "*out_%s = msg_data.msg_response.%s;\n", @@ -686,239 +547,6 @@ static int emit_interface_msg_function_send_impl( return 0; } -static int emit_interface_msg_function_recv_impl( - struct emit_ctx *ctx, - const struct interface_definition *iface, - const struct msg_definition *msg) -{ - emit(ctx, - "struct msg_%s_%s msg_data;\n", - iface->if_name, - msg->msg_name); - emit(ctx, "kern_iovec_t iov = IOVEC(&msg_data, sizeof msg_data);\n"); - emit(ctx, "size_t r = 0;\n\n"); - - emit(ctx, - "kern_status_t status = msg_read(channel, sender->e_msg, 0, &iov, " - "1, &r);\n"); - - emit(ctx, "if (status != KERN_OK) return status;\n"); - emit(ctx, - "if (r != sizeof msg_data) return KERN_INVALID_ARGUMENT;\n\n"); - - b_queue_entry *entry = b_queue_first(&msg->msg_params); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - switch (param->p_type->ty_id) { - case TYPE_INT: - emit(ctx, - "*out_%s = msg_data.msg_request.%s;\n", - param->p_name, - param->p_name); - break; - case TYPE_HANDLE: - emit(ctx, "*out_%s = ", param->p_name); - emit(ctx, - "msg_data.msg_request.%s < nr_handles ", - param->p_name); - emit(ctx, - "? handles[msg_data.msg_request.%s].hnd_value ", - param->p_name); - emit(ctx, ": KERN_HANDLE_INVALID;\n", param->p_name); - break; - case TYPE_STRING: - emit(ctx, - "out_%s->str_len = msg_data.msg_request.%s_len;\n", - param->p_name, - param->p_name); - - emit(ctx, - "if (out_%s->str_max > 1) {\n", - param->p_name); - emit_indent(ctx); - - emit(ctx, - "iov.io_base = (virt_addr_t)out_%s->str_buf;\n", - param->p_name); - emit(ctx, - "iov.io_len = out_%s->str_max - 1;\n", - param->p_name); - emit(ctx, - "if (iov.io_len > out_%s->str_len) iov.io_len " - "= out_%s->str_len;\n", - param->p_name, - param->p_name); - - emit(ctx, "status = msg_read(\n"); - emit_indent(ctx); - emit(ctx, "channel,\n"); - emit(ctx, "sender->e_msg,\n"); - emit(ctx, - "msg_data.msg_request.%s_offset,\n", - param->p_name); - emit(ctx, "&iov,\n"); - emit(ctx, "1,\n"); - emit(ctx, "&r);\n"); - emit_unindent(ctx); - - emit(ctx, "if (status != KERN_OK) return status;\n\n"); - emit(ctx, - "if (r != iov.io_len) return " - "KERN_INVALID_ARGUMENT;\n\n"); - emit(ctx, - "out_%s->str_buf[iov.io_len] = '\\0';\n", - param->p_name); - - emit_unindent(ctx); - emit(ctx, "} else if (out_%s->str_max > 0) {\n"); - emit_indent(ctx); - emit(ctx, - "out_%s->str_buf[0] = '\\0';\n", - param->p_name); - emit_unindent(ctx); - emit(ctx, "}\n\n"); - break; - default: - break; - } - - entry = b_queue_next(entry); - } - - emit(ctx, "return status;\n"); - return 0; -} - -static int emit_interface_msg_function_reply_impl( - struct emit_ctx *ctx, - const struct interface_definition *iface, - const struct msg_definition *msg) -{ - b_string *iface_ucase = b_string_create_from_cstr(iface->if_name); - b_string_toupper(iface_ucase); - b_string *msg_ucase = b_string_create_from_cstr(msg->msg_name); - b_string_toupper(msg_ucase); - - emit(ctx, - "struct msg_%s_%s msg_data = {0};\n", - iface->if_name, - msg->msg_name); - emit(ctx, "msg_data.msg_header.hdr_magic = MSG_MAGIC;\n"); - emit(ctx, - "msg_data.msg_header.hdr_protocol = PROTOCOL_%s;\n", - b_string_ptr(iface_ucase)); - emit(ctx, - "msg_data.msg_header.hdr_func = MSG_%s_%s;\n\n", - b_string_ptr(iface_ucase), - b_string_ptr(msg_ucase)); - - b_string_unref(iface_ucase); - b_string_unref(msg_ucase); - - size_t handle_index = 0; - - b_queue_entry *entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - switch (param->p_type->ty_id) { - case TYPE_INT: - emit(ctx, - "msg_data.msg_response.%s = %s;\n\n", - param->p_name, - param->p_name); - break; - case TYPE_HANDLE: - emit(ctx, - "msg_data.msg_response.%s = %zu;\n\n", - param->p_name, - handle_index); - handle_index++; - break; - case TYPE_STRING: - emit(ctx, - "msg_data.msg_response.%s_len = strlen(%s);\n", - param->p_name, - param->p_name); - break; - default: - break; - } - - entry = b_queue_next(entry); - } - - emit(ctx, "\nkern_iovec_t iov[] = {\n"); - emit_indent(ctx); - emit(ctx, "IOVEC(&msg_data, sizeof msg_data),\n"); - size_t nr_iov = 1; - - entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - switch (param->p_type->ty_id) { - case TYPE_STRING: - emit(ctx, - "IOVEC(%s, msg_data.msg_response.%s_len),\n", - param->p_name, - param->p_name); - nr_iov++; - break; - default: - break; - } - - entry = b_queue_next(entry); - } - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - - if (handle_index) { - emit(ctx, "kern_msg_handle_t handles[] = {\n"); - emit_indent(ctx); - entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - switch (param->p_type->ty_id) { - case TYPE_HANDLE: - emit(ctx, - "{ .hnd_value = %s, .hnd_mode = " - "KERN_MSG_HANDLE_MOVE, },\n", - param->p_name); - break; - default: - break; - } - - entry = b_queue_next(entry); - } - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - } - - emit(ctx, "kern_msg_t reply = {\n"); - emit_indent(ctx); - emit(ctx, ".msg_data = iov,\n.msg_data_count = %zu,\n", nr_iov); - - if (handle_index) { - emit(ctx, - ".msg_handles = handles,\n.msg_handles_count = %zu,\n", - handle_index); - } - - emit_unindent(ctx); - emit(ctx, "};\n\n"); - - emit(ctx, "return msg_reply(channel, sender->e_msg, &reply);\n"); - - return 0; -} - static int emit_interface_msg_function_send( struct emit_ctx *ctx, const struct interface_definition *iface, @@ -947,9 +575,17 @@ static int emit_interface_msg_function_send( case TYPE_HANDLE: emit(ctx, "kern_handle_t %s", param->p_name); break; + case TYPE_SIZE: + emit(ctx, "size_t %s", param->p_name); + break; case TYPE_STRING: emit(ctx, "const char *%s", param->p_name); break; + case TYPE_BUFFER: + emit(ctx, + "const void *%s, size_t %s_len", + param->p_name, + param->p_name); default: break; } @@ -965,11 +601,23 @@ static int emit_interface_msg_function_send( case TYPE_INT: emit(ctx, "int *out_%s", param->p_name); break; + case TYPE_SIZE: + emit(ctx, "size_t *out_%s", param->p_name); + break; case TYPE_HANDLE: emit(ctx, "kern_handle_t *out_%s", param->p_name); break; case TYPE_STRING: - emit(ctx, "struct msg_string *out_%s", param->p_name); + emit(ctx, + "char *out_%s,\nsize_t out_%s_max", + param->p_name, + param->p_name); + break; + case TYPE_BUFFER: + emit(ctx, + "void *out_%s,\nsize_t out_%s_max", + param->p_name, + param->p_name); break; default: break; @@ -996,191 +644,62 @@ static int emit_interface_msg_function_send( return 0; } -static int emit_interface_msg_function_recv( - struct emit_ctx *ctx, - const struct interface_definition *iface, - const struct msg_definition *msg, - bool prototype_only) -{ - if (prototype_only) { - emit(ctx, "extern "); - } - - emit(ctx, "kern_status_t %s_%s_recv(\n", iface->if_name, msg->msg_name); - - emit_indent(ctx); - - emit(ctx, - "kern_handle_t channel,\nconst struct msg_endpoint *sender,\n" - "kern_msg_handle_t *handles,\nsize_t nr_handles"); - - b_queue_entry *entry = b_queue_first(&msg->msg_params); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n"); - switch (param->p_type->ty_id) { - case TYPE_INT: - emit(ctx, "int *out_%s", param->p_name); - break; - case TYPE_HANDLE: - emit(ctx, "kern_handle_t *out_%s", param->p_name); - break; - case TYPE_STRING: - emit(ctx, "struct msg_string *out_%s", param->p_name); - break; - default: - break; - } - entry = b_queue_next(entry); - } - - emit(ctx, ")"); - emit_unindent(ctx); - - if (prototype_only) { - emit(ctx, ";\n"); - return 0; - } - - emit(ctx, "\n{\n"); - emit_indent(ctx); - - emit_interface_msg_function_recv_impl(ctx, iface, msg); - - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - return 0; -} - -static int emit_interface_msg_function_reply( - struct emit_ctx *ctx, - const struct interface_definition *iface, - const struct msg_definition *msg, - bool prototype_only) -{ - if (prototype_only) { - emit(ctx, "extern "); - } - - emit(ctx, - "kern_status_t %s_%s_reply(\n", - iface->if_name, - msg->msg_name); - - emit_indent(ctx); - - emit(ctx, "kern_handle_t channel,\nconst struct msg_endpoint *sender"); - - b_queue_entry *entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n"); - switch (param->p_type->ty_id) { - case TYPE_INT: - emit(ctx, "int %s", param->p_name); - break; - case TYPE_HANDLE: - emit(ctx, "kern_handle_t %s", param->p_name); - break; - case TYPE_STRING: - emit(ctx, "const char *%s", param->p_name); - break; - default: - break; - } - entry = b_queue_next(entry); - } - - emit(ctx, ")"); - emit_unindent(ctx); - - if (prototype_only) { - emit(ctx, ";\n"); - return 0; - } - - emit(ctx, "\n{\n"); - emit_indent(ctx); - - emit_interface_msg_function_reply_impl(ctx, iface, msg); - - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - return 0; -} - -static int emit_interface_msg_functions( - struct emit_ctx *ctx, - const struct interface_definition *iface, - const struct msg_definition *msg, - bool prototype_only) -{ - emit_interface_msg_function_send(ctx, iface, msg, prototype_only); - emit_interface_msg_function_recv(ctx, iface, msg, prototype_only); - emit_interface_msg_function_reply(ctx, iface, msg, prototype_only); - return 0; -} - -static int emit_string_destructor_list( - struct emit_ctx *ctx, - b_queue_entry *param_entry) -{ - while (param_entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, param_entry, p_entry); - - if (param->p_type->ty_id == TYPE_STRING) { - emit(ctx, "free(%s.str_buf);\n", param->p_name); - } - - param_entry = b_queue_prev(param_entry); - } - - return 0; -} - static int emit_interface_dispatcher_impl_msg( struct emit_ctx *ctx, const struct interface_definition *iface, const struct msg_definition *msg) { +#define MSG_STRUCT_NAME "__data" +#define MSG_STRUCT_OFFSET_NAME "__data_offset" emit(ctx, - "if (!vtable->%s) return msg_reply_generic(channel, sender, msg, " + "if (!vtable->%s) return xpc_msg_reply_error(msg, " "KERN_UNIMPLEMENTED);\n", msg->msg_name); + emit(ctx, + "struct %s_%s_msg " MSG_STRUCT_NAME " = {0};\n", + iface->if_name, + msg->msg_name); + emit(ctx, + "status = xpc_msg_read(msg, 0, &" MSG_STRUCT_NAME + ", sizeof " MSG_STRUCT_NAME ");\n"); + b_queue_entry *entry = b_queue_first(&msg->msg_params); while (entry) { struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); switch (param->p_type->ty_id) { case TYPE_INT: - emit(ctx, "int %s;\n", param->p_name); + emit(ctx, + "int %s = " MSG_STRUCT_NAME ".msg_request.%s;\n", + param->p_name, + param->p_name); + break; + case TYPE_SIZE: + emit(ctx, + "size_t %s = " MSG_STRUCT_NAME + ".msg_request.%s;\n", + param->p_name, + param->p_name); break; case TYPE_STRING: emit(ctx, - "struct msg_string %s = {0};\n", - param->p_name); - emit_indent_zero(ctx); - emit(ctx, "#if defined(MSG_NO_MALLOC)\n"); - emit_unindent(ctx); - emit(ctx, - "char %s_buf[MSG_STRINGBUF_SIZE];\n", - param->p_name); - emit(ctx, - "%s.str_buf = %s_buf;\n", + "xpc_string_t %s = " + "XPC_STRING_IN(msg, " MSG_STRUCT_NAME + ".msg_request.%s_offset, " MSG_STRUCT_NAME + ".msg_request.%s_len);\n", + param->p_name, param->p_name, param->p_name); + break; + case TYPE_BUFFER: emit(ctx, - "%s.str_max = MSG_STRINGBUF_SIZE;\n", + "xpc_string_t %s = " + "XPC_BUFFER_IN(msg, " MSG_STRUCT_NAME + ".msg_request.%s_offset, " MSG_STRUCT_NAME + ".msg_request.%s_len);\n", + param->p_name, + param->p_name, param->p_name); - - emit_indent_zero(ctx); - emit(ctx, "#endif\n"); - emit_unindent(ctx); break; default: break; @@ -1195,32 +714,35 @@ static int emit_interface_dispatcher_impl_msg( = b_unbox(struct msg_parameter, entry, p_entry); switch (param->p_type->ty_id) { case TYPE_INT: - emit(ctx, "int %s;\n", param->p_name); + emit(ctx, "int %s = 0;\n", param->p_name); + break; + case TYPE_SIZE: + emit(ctx, "size_t %s = 0;\n", param->p_name); break; case TYPE_HANDLE: - emit(ctx, "kern_handle_t %s;\n", param->p_name); + emit(ctx, + "kern_handle_t %s = KERN_HANDLE_INVALID;\n", + param->p_name); break; case TYPE_STRING: emit(ctx, - "struct msg_string %s = {0};\n", - param->p_name); - emit_indent_zero(ctx); - emit(ctx, "#if defined(MSG_NO_MALLOC)\n"); - emit_unindent(ctx); - emit(ctx, - "char %s_buf[MSG_STRINGBUF_SIZE];\n", - param->p_name); - emit(ctx, - "%s.str_buf = %s_buf;\n", + "xpc_string_t %s = " + "XPC_STRING_OUT(msg, " MSG_STRUCT_NAME + ".msg_request.%s_offset, " MSG_STRUCT_NAME + ".msg_request.%s_max);\n", + param->p_name, param->p_name, param->p_name); + break; + case TYPE_BUFFER: emit(ctx, - "%s.str_max = MSG_STRINGBUF_SIZE;\n", + "xpc_buffer_t %s = " + "XPC_BUFFER_OUT(msg, " MSG_STRUCT_NAME + ".msg_request.%s_offset, " MSG_STRUCT_NAME + ".msg_request.%s_max);\n", + param->p_name, + param->p_name, param->p_name); - - emit_indent_zero(ctx); - emit(ctx, "#endif\n"); - emit_unindent(ctx); break; default: break; @@ -1229,165 +751,61 @@ static int emit_interface_dispatcher_impl_msg( entry = b_queue_next(entry); } - emit(ctx, "status = %s_%s_recv(\n", iface->if_name, msg->msg_name); - emit_indent(ctx); - emit(ctx, "channel,\nsender,\nhandles,\nnr_handles"); - entry = b_queue_first(&msg->msg_params); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n&%s", param->p_name); - - entry = b_queue_next(entry); - } - - emit(ctx, ");\n"); - emit_unindent(ctx); - - emit(ctx, "if (status != KERN_OK) {\n"); - emit_indent(ctx); - emit(ctx, "msg_reply_generic(channel, sender, msg, status);\n"); - emit(ctx, "return status;\n"); - emit_unindent(ctx); - emit(ctx, "}\n"); - - emit_indent_zero(ctx); - emit(ctx, "#if !defined(MSG_NO_MALLOC)\n"); - emit_unindent(ctx); - - entry = b_queue_first(&msg->msg_params); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - switch (param->p_type->ty_id) { - case TYPE_STRING: - emit(ctx, - "%s.str_max = %s.str_len + 1;\n", - param->p_name, - param->p_name); - emit(ctx, - "%s.str_buf = malloc(%s.str_max);\n", - param->p_name, - param->p_name); - - emit(ctx, "if (!%s.str_buf) {\n", param->p_name); - emit_indent(ctx); - emit_string_destructor_list(ctx, b_queue_prev(entry)); - emit(ctx, "return KERN_NO_MEMORY;\n"); - emit_unindent(ctx); - emit(ctx, "}\n", param->p_name); - break; - default: - break; - } - - entry = b_queue_next(entry); - } - - emit(ctx, "status = %s_%s_recv(\n", iface->if_name, msg->msg_name); - emit_indent(ctx); - emit(ctx, "channel,\nsender,\nhandles,\nnr_handles"); - entry = b_queue_first(&msg->msg_params); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n&%s", param->p_name); - - entry = b_queue_next(entry); - } - emit(ctx, ");\n"); - emit_unindent(ctx); - - emit(ctx, "if (status != KERN_OK) {\n"); - emit_indent(ctx); - emit_string_destructor_list(ctx, b_queue_last(&msg->msg_params)); - emit(ctx, "msg_reply_generic(channel, sender, msg, status);\n"); - emit(ctx, "return status;\n"); - emit_unindent(ctx); - emit(ctx, "}\n"); - - emit_indent_zero(ctx); - emit(ctx, "#endif\n"); - emit_unindent(ctx); - emit(ctx, "status = vtable->%s(\n", msg->msg_name); emit_indent(ctx); - emit(ctx, "sender"); - - size_t i = 0; + emit(ctx, "ctx,\n&msg->msg_sender"); entry = b_queue_first(&msg->msg_params); while (entry) { struct msg_parameter *param = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n"); switch (param->p_type->ty_id) { - case TYPE_INT: - case TYPE_HANDLE: - emit(ctx, "%s", param->p_name); - break; case TYPE_STRING: - emit(ctx, "%s.str_buf", param->p_name); + case TYPE_BUFFER: + emit(ctx, ",\n&%s", param->p_name); break; default: - break; - } - - i++; - entry = b_queue_next(entry); - } - - entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - emit(ctx, ",\n"); - - emit(ctx, "&%s", param->p_name); - - i++; - entry = b_queue_next(entry); - } - - if (i > 0) { - emit(ctx, ",\n"); - } - - emit(ctx, "arg"); - - emit(ctx, ");\n"); - emit_unindent(ctx); - - emit_indent_zero(ctx); - emit(ctx, "#if !defined(MSG_NO_MALLOC)\n"); - emit_unindent(ctx); - emit_string_destructor_list(ctx, b_queue_last(&msg->msg_params)); - emit_indent_zero(ctx); - emit(ctx, "#endif\n"); - emit_unindent(ctx); - - emit(ctx, "if (status != KERN_OK) {\n"); - emit_indent(ctx); - emit(ctx, "msg_reply_generic(channel, sender, msg, status);\n"); - emit(ctx, "return status;\n"); - emit_unindent(ctx); - emit(ctx, "}\n\n"); - - emit(ctx, "status = %s_%s_reply(\n", iface->if_name, msg->msg_name); - emit_indent(ctx); - emit(ctx, "channel,\nsender"); - entry = b_queue_first(&msg->msg_results); - while (entry) { - struct msg_parameter *param - = b_unbox(struct msg_parameter, entry, p_entry); - - switch (param->p_type->ty_id) { - case TYPE_INT: - case TYPE_HANDLE: emit(ctx, ",\n%s", param->p_name); break; - case TYPE_STRING: - emit(ctx, ",\n%s.str_buf", param->p_name); + } + + entry = b_queue_next(entry); + } + entry = b_queue_first(&msg->msg_results); + while (entry) { + struct msg_parameter *param + = b_unbox(struct msg_parameter, entry, p_entry); + emit(ctx, ",\n&%s", param->p_name); + + entry = b_queue_next(entry); + } + + emit(ctx, ",\narg);\n"); + emit_unindent(ctx); + + emit(ctx, + "if (status != KERN_OK) return xpc_msg_reply_error(msg, " + "status);\n"); + + emit(ctx, MSG_STRUCT_NAME ".msg_header.hdr_status = 0;\n"); + size_t handle_index = 0; + entry = b_queue_first(&msg->msg_results); + while (entry) { + struct msg_parameter *param + = b_unbox(struct msg_parameter, entry, p_entry); + switch (param->p_type->ty_id) { + case TYPE_INT: + emit(ctx, + MSG_STRUCT_NAME ".msg_response.%s = %s;\n", + param->p_name, + param->p_name); + break; + case TYPE_HANDLE: + emit(ctx, + MSG_STRUCT_NAME ".msg_response.%s = %zu;\n", + param->p_name, + handle_index); + handle_index++; break; default: break; @@ -1396,10 +814,34 @@ static int emit_interface_dispatcher_impl_msg( entry = b_queue_next(entry); } - emit(ctx, ");\n"); - emit_unindent(ctx); + emit(ctx, + "kern_iovec_t iov = IOVEC(&" MSG_STRUCT_NAME + ", sizeof " MSG_STRUCT_NAME ");\n"); - emit(ctx, "if (status != KERN_OK) return status;\n"); + emit(ctx, "kern_msg_handle_t out_handles[] = {\n"); + emit_indent(ctx); + entry = b_queue_first(&msg->msg_results); + while (entry) { + struct msg_parameter *param + = b_unbox(struct msg_parameter, entry, p_entry); + switch (param->p_type->ty_id) { + case TYPE_HANDLE: + emit(ctx, + "MSG_HANDLE(KERN_MSG_HANDLE_MOVE, %s),\n", + param->p_name); + break; + default: + break; + } + + entry = b_queue_next(entry); + } + emit_unindent(ctx); + emit(ctx, "};\n"); + + emit(ctx, + "status = xpc_msg_reply(msg, &iov, 1, out_handles, sizeof " + "out_handles / sizeof out_handles[0]);\n"); return 0; } @@ -1413,12 +855,12 @@ static int emit_interface_dispatcher_impl( b_string *msg_ucase = b_string_create(); emit(ctx, - "if (msg->hdr_protocol != PROTOCOL_%s) return " + "if (msg->msg_header.hdr_interface != INTERFACE_%s) return " "KERN_INVALID_ARGUMENT;\n\n", b_string_ptr(iface_ucase)); emit(ctx, "kern_status_t status = KERN_OK;\n"); - emit(ctx, "switch (msg->hdr_func) {\n"); + emit(ctx, "switch (msg->msg_header.hdr_func) {\n"); b_queue_entry *entry = b_queue_first(&iface->if_msg); while (entry) { @@ -1464,13 +906,10 @@ static int emit_interface_dispatcher( emit(ctx, "kern_status_t %s_dispatch(\n", iface->if_name); emit_indent(ctx); - emit(ctx, "kern_handle_t channel,\n"); + emit(ctx, "xpc_context_t *ctx,\n"); + emit(ctx, "const xpc_msg_t *msg,\n"); emit(ctx, "const struct %s_vtable *vtable,\n", iface->if_name); - emit(ctx, "const struct msg_endpoint *sender,\n"); - emit(ctx, "const struct msg_header *msg,\n"); - emit(ctx, "kern_msg_handle_t *handles,\n"); - emit(ctx, "size_t nr_handles,\n\n"); - emit(ctx, "void *arg)\n\n"); + emit(ctx, "void *arg)"); emit_unindent(ctx); if (prototype_only) { @@ -1499,7 +938,11 @@ static int emit_interface_functions( const struct msg_definition *msg = b_unbox(struct msg_definition, entry, msg_entry); - emit_interface_msg_functions(ctx, iface, msg, prototype_only); + emit_interface_msg_function_send( + ctx, + iface, + msg, + prototype_only); entry = b_queue_next(entry); } @@ -1514,10 +957,10 @@ static int emit_interface_vtable_entry( const struct interface_definition *iface, const struct msg_definition *msg) { - emit(ctx, - "kern_status_t(*%s)(\nconst struct msg_endpoint *sender\n", - msg->msg_name); + emit(ctx, "kern_status_t(*%s)(\n", msg->msg_name); emit_indent(ctx); + emit(ctx, "xpc_context_t *ctx,\n"); + emit(ctx, "const xpc_endpoint_t *sender"); size_t i = 0; b_queue_entry *entry = b_queue_first(&msg->msg_params); @@ -1530,11 +973,17 @@ static int emit_interface_vtable_entry( case TYPE_INT: emit(ctx, "int %s", param->p_name); break; + case TYPE_SIZE: + emit(ctx, "size_t %s", param->p_name); + break; + case TYPE_BUFFER: + emit(ctx, "const xpc_buffer_t *%s", param->p_name); + break; case TYPE_HANDLE: emit(ctx, "kern_handle_t %s", param->p_name); break; case TYPE_STRING: - emit(ctx, "const char *%s", param->p_name); + emit(ctx, "const xpc_string_t *%s", param->p_name); break; default: break; @@ -1558,7 +1007,13 @@ static int emit_interface_vtable_entry( emit(ctx, "kern_handle_t *out_%s", param->p_name); break; case TYPE_STRING: - emit(ctx, "struct msg_string *out_%s", param->p_name); + emit(ctx, "xpc_string_t *out_%s", param->p_name); + break; + case TYPE_SIZE: + emit(ctx, "size_t *out_%s", param->p_name); + break; + case TYPE_BUFFER: + emit(ctx, "xpc_buffer_t *out_%s", param->p_name); break; default: break; @@ -1572,7 +1027,7 @@ static int emit_interface_vtable_entry( emit(ctx, ",\n"); } - emit(ctx, "void *arg"); + emit(ctx, "void *"); emit(ctx, ");\n", msg->msg_name); emit_unindent(ctx); @@ -1610,14 +1065,15 @@ static int emit_header( emit_include(ctx, "stdint.h", true); emit_include(ctx, "stddef.h", true); emit_include(ctx, "string.h", true); - emit(ctx, "#if !defined(MSG_NO_MALLOC)\n"); - emit_include(ctx, "stdlib.h", true); - emit(ctx, "#endif\n"); + emit_include(ctx, "xpc/endpoint.h", true); + emit_include(ctx, "xpc/msg.h", true); + emit_include(ctx, "xpc/string.h", true); + emit_include(ctx, "xpc/buffer.h", true); + emit_include(ctx, "xpc/context.h", true); emit_include(ctx, "mango/msg.h", true); emit_include(ctx, "mango/types.h", true); emit(ctx, "\n"); - emit_header_lib_definitions(ctx); emit_interface_id_macros(ctx, iface); emit_interface_vtable(ctx, iface); emit_interface_msg_structs(ctx, iface); diff --git a/toolchain/ifc/ctx.c b/toolchain/xpcg/ctx.c similarity index 84% rename from toolchain/ifc/ctx.c rename to toolchain/xpcg/ctx.c index a397bb6..d347f96 100644 --- a/toolchain/ifc/ctx.c +++ b/toolchain/xpcg/ctx.c @@ -43,6 +43,14 @@ const struct type *ctx_get_type(struct ctx *ctx, const char *name) return ctx_get_builtin_type(ctx, TYPE_HANDLE); } + if (!strcmp(name, "size")) { + return ctx_get_builtin_type(ctx, TYPE_SIZE); + } + + if (!strcmp(name, "buffer")) { + return ctx_get_builtin_type(ctx, TYPE_BUFFER); + } + return NULL; } diff --git a/toolchain/ifc/ctx.h b/toolchain/xpcg/ctx.h similarity index 89% rename from toolchain/ifc/ctx.h rename to toolchain/xpcg/ctx.h index 2eee056..dbc478c 100644 --- a/toolchain/ifc/ctx.h +++ b/toolchain/xpcg/ctx.h @@ -1,5 +1,5 @@ -#ifndef IFC_CTX_H_ -#define IFC_CTX_H_ +#ifndef XPCG_CTX_H_ +#define XPCG_CTX_H_ #include "type.h" diff --git a/toolchain/ifc/file-span.h b/toolchain/xpcg/file-span.h similarity index 69% rename from toolchain/ifc/file-span.h rename to toolchain/xpcg/file-span.h index 95d060d..9f18ac4 100644 --- a/toolchain/ifc/file-span.h +++ b/toolchain/xpcg/file-span.h @@ -1,5 +1,5 @@ -#ifndef IFC_FILE_SPAN_H_ -#define IFC_FILE_SPAN_H_ +#ifndef XPCG_FILE_SPAN_H_ +#define XPCG_FILE_SPAN_H_ struct file_cell { unsigned int c_row, c_col; diff --git a/toolchain/ifc/interface.c b/toolchain/xpcg/interface.c similarity index 91% rename from toolchain/ifc/interface.c rename to toolchain/xpcg/interface.c index c715e05..8db9cc3 100644 --- a/toolchain/ifc/interface.c +++ b/toolchain/xpcg/interface.c @@ -6,7 +6,9 @@ #include #include -struct interface_definition *interface_definition_create(const char *name) +struct interface_definition *interface_definition_create( + const char *name, + long long id) { struct interface_definition *out = malloc(sizeof *out); if (!out) { @@ -16,6 +18,7 @@ struct interface_definition *interface_definition_create(const char *name) memset(out, 0x0, sizeof *out); out->if_name = b_strdup(name); + out->if_id = id; return out; } diff --git a/toolchain/ifc/interface.h b/toolchain/xpcg/interface.h similarity index 82% rename from toolchain/ifc/interface.h rename to toolchain/xpcg/interface.h index 7ebc8df..8692a94 100644 --- a/toolchain/ifc/interface.h +++ b/toolchain/xpcg/interface.h @@ -1,5 +1,5 @@ -#ifndef IFC_INTERFACE_H_ -#define IFC_INTERFACE_H_ +#ifndef XPCG_INTERFACE_H_ +#define XPCG_INTERFACE_H_ #include @@ -7,11 +7,13 @@ struct msg_definition; struct interface_definition { char *if_name; + long long if_id; b_queue if_msg; }; extern struct interface_definition *interface_definition_create( - const char *name); + const char *name, + long long id); extern void interface_definition_destroy(struct interface_definition *iface); extern bool interface_definition_has_msg( diff --git a/toolchain/ifc/lex.c b/toolchain/xpcg/lex.c similarity index 98% rename from toolchain/ifc/lex.c rename to toolchain/xpcg/lex.c index 6e3f0ec..fb781cf 100644 --- a/toolchain/ifc/lex.c +++ b/toolchain/xpcg/lex.c @@ -29,18 +29,21 @@ static struct lex_token_def symbols[] = { LEX_TOKEN_DEF(SYM_COMMA, ","), LEX_TOKEN_DEF(SYM_HYPHEN, "-"), + LEX_TOKEN_DEF(SYM_LEFT_BRACKET, "["), + LEX_TOKEN_DEF(SYM_RIGHT_BRACKET, "]"), LEX_TOKEN_DEF(SYM_LEFT_BRACE, "{"), LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"), LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("), LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"), LEX_TOKEN_DEF(SYM_SEMICOLON, ";"), + LEX_TOKEN_DEF(SYM_COLON, ":"), LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"), }; static const size_t nr_symbols = sizeof symbols / sizeof symbols[0]; static struct lex_token_def keywords[] = { LEX_TOKEN_DEF(KW_INTERFACE, "interface"), - LEX_TOKEN_DEF(KW_MSG, "msg"), + LEX_TOKEN_DEF(KW_FUNC, "func"), }; static const size_t nr_keywords = sizeof keywords / sizeof keywords[0]; diff --git a/toolchain/ifc/lex.h b/toolchain/xpcg/lex.h similarity index 96% rename from toolchain/ifc/lex.h rename to toolchain/xpcg/lex.h index 47e325d..7a0ad82 100644 --- a/toolchain/ifc/lex.h +++ b/toolchain/xpcg/lex.h @@ -1,5 +1,5 @@ -#ifndef IFC_LEX_H_ -#define IFC_LEX_H_ +#ifndef XPCG_LEX_H_ +#define XPCG_LEX_H_ #include "status.h" #include "token.h" diff --git a/toolchain/ifc/line-source.c b/toolchain/xpcg/line-source.c similarity index 100% rename from toolchain/ifc/line-source.c rename to toolchain/xpcg/line-source.c diff --git a/toolchain/ifc/line-source.h b/toolchain/xpcg/line-source.h similarity index 100% rename from toolchain/ifc/line-source.h rename to toolchain/xpcg/line-source.h diff --git a/toolchain/ifc/main.c b/toolchain/xpcg/main.c similarity index 94% rename from toolchain/ifc/main.c rename to toolchain/xpcg/main.c index 60c5bb9..461fa8d 100644 --- a/toolchain/ifc/main.c +++ b/toolchain/xpcg/main.c @@ -64,7 +64,10 @@ static void print_interface(struct interface_definition *iface) } } -static int ifc(const b_command *self, const b_arglist *opt, const b_array *args) +static int xpcg( + const b_command *self, + const b_arglist *opt, + const b_array *args) { const char *path = NULL; b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_SRCPATH, 0, &path); @@ -132,10 +135,10 @@ static int ifc(const b_command *self, const b_arglist *opt, const b_array *args) B_COMMAND(CMD_ID, B_COMMAND_INVALID_ID) { - B_COMMAND_NAME("ifc"); - B_COMMAND_DESC("interface definition compiler."); + B_COMMAND_NAME("xpcg"); + B_COMMAND_DESC("xpc interface generator."); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); - B_COMMAND_FUNCTION(ifc); + B_COMMAND_FUNCTION(xpcg); B_COMMAND_HELP_OPTION(); B_COMMAND_ARG(ARG_SRCPATH) diff --git a/toolchain/ifc/msg.c b/toolchain/xpcg/msg.c similarity index 95% rename from toolchain/ifc/msg.c rename to toolchain/xpcg/msg.c index 822d607..3366a75 100644 --- a/toolchain/ifc/msg.c +++ b/toolchain/xpcg/msg.c @@ -4,7 +4,7 @@ #include #include -struct msg_definition *msg_definition_create(const char *name) +struct msg_definition *msg_definition_create(const char *name, long long id) { struct msg_definition *out = malloc(sizeof *out); if (!out) { @@ -14,6 +14,7 @@ struct msg_definition *msg_definition_create(const char *name) memset(out, 0x0, sizeof *out); out->msg_name = b_strdup(name); + out->msg_id = id; return out; } diff --git a/toolchain/ifc/msg.h b/toolchain/xpcg/msg.h similarity index 83% rename from toolchain/ifc/msg.h rename to toolchain/xpcg/msg.h index 9c8c067..a33d2c5 100644 --- a/toolchain/ifc/msg.h +++ b/toolchain/xpcg/msg.h @@ -1,5 +1,5 @@ -#ifndef IFC_MSG_H_ -#define IFC_MSG_H_ +#ifndef XPCG_MSG_H_ +#define XPCG_MSG_H_ #include @@ -13,13 +13,16 @@ struct msg_parameter { struct msg_definition { char *msg_name; + long long msg_id; b_queue_entry msg_entry; b_queue msg_params; b_queue msg_results; }; -extern struct msg_definition *msg_definition_create(const char *name); +extern struct msg_definition *msg_definition_create( + const char *name, + long long id); extern void msg_definition_destroy(struct msg_definition *msg); extern bool msg_definition_has_param( diff --git a/toolchain/ifc/parse.c b/toolchain/xpcg/parse.c similarity index 64% rename from toolchain/ifc/parse.c rename to toolchain/xpcg/parse.c index d187d0e..825a782 100644 --- a/toolchain/ifc/parse.c +++ b/toolchain/xpcg/parse.c @@ -48,26 +48,55 @@ static bool parse_word(struct lex *lex, char **out) return true; } +static bool parse_int(struct lex *lex, long long *out) +{ + struct token *tok = lex_peek(lex); + if (!tok || tok->tok_type != TOK_INT) { + return false; + } + + *out = tok->tok_int; + lex_advance(lex); + return true; +} + struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) { struct msg_definition *msg = NULL; - if (!parse_keyword(lex, KW_MSG)) { - report_error("expected `msg` keyword\n"); + if (!parse_keyword(lex, KW_FUNC)) { + report_error("expected `func` keyword\n"); goto fail; } char *msg_name = NULL; if (!parse_word(lex, &msg_name)) { - report_error("expected message identifier\n"); + report_error("expected function identifier\n"); goto fail; } - msg = msg_definition_create(msg_name); + long long msg_id = 0; + if (!parse_symbol(lex, SYM_LEFT_BRACKET)) { + report_error("expected `[` after function identifier\n"); + goto fail; + } + + if (!parse_int(lex, &msg_id)) { + report_error("expected function id number after `[`\n"); + goto fail; + } + + if (!parse_symbol(lex, SYM_RIGHT_BRACKET)) { + report_error("expected `]` after function id number\n"); + goto fail; + } + + msg = msg_definition_create(msg_name, msg_id); free(msg_name); if (!parse_symbol(lex, SYM_LEFT_PAREN)) { - report_error("expected `(` after message identifier\n"); + report_error( + "expected `(` after function id number specifier\n"); goto fail; } @@ -79,14 +108,31 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) } if (i > 0 && !parse_symbol(lex, SYM_COMMA)) { - report_error("expected `,` after message parameter\n"); + report_error( + "expected `,` after function " + "parameter\n"); + ok = false; + break; + } + + char *param_name; + if (!parse_word(lex, ¶m_name)) { + report_error("expected function parameter name\n"); + ok = false; + break; + } + + if (!parse_symbol(lex, SYM_COLON)) { + report_error( + "expected `:` after function parameter " + "name\n"); ok = false; break; } char *type_name; if (!parse_word(lex, &type_name)) { - report_error("expected message parameter type\n"); + report_error("expected function parameter type\n"); ok = false; break; } @@ -94,7 +140,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) const struct type *type = ctx_get_type(ctx, type_name); if (!type) { report_error( - "message parameter has unknown type " + "function parameter has unknown type " "'%s'\n", type_name); free(type_name); @@ -104,19 +150,13 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) free(type_name); - char *param_name; - if (!parse_word(lex, ¶m_name)) { - report_error("expected message parameter name\n"); - ok = false; - break; - } - bool duplicate = msg_definition_has_param(msg, param_name) || msg_definition_has_result(msg, param_name); if (duplicate) { free(param_name); report_error( - "message has multiple parameters/results with " + "function has multiple " + "parameters/results with " "name '%s'\n", param_name); ok = false; @@ -133,12 +173,14 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) } if (!parse_symbol(lex, SYM_HYPHEN_RIGHT_ANGLE)) { - report_error("expected `->` after message parameter list\n"); + report_error( + "expected `->` after function parameter " + "list\n"); goto fail; } if (!parse_symbol(lex, SYM_LEFT_PAREN)) { - report_error("expected `(` for message results list\n"); + report_error("expected `(` for function results list\n"); goto fail; } @@ -150,14 +192,30 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) if (i > 0 && !parse_symbol(lex, SYM_COMMA)) { report_error( - "expected `,` or `)` after message result\n"); + "expected `,` or `)` after function " + "result\n"); + ok = false; + break; + } + + char *result_name; + if (!parse_word(lex, &result_name)) { + report_error("expected function parameter name\n"); + ok = false; + break; + } + + if (!parse_symbol(lex, SYM_COLON)) { + report_error( + "expected `:` after function result " + "name\n"); ok = false; break; } char *type_name; if (!parse_word(lex, &type_name)) { - report_error("expected message result type\n"); + report_error("expected function result type\n"); ok = false; break; } @@ -165,7 +223,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) const struct type *type = ctx_get_type(ctx, type_name); if (!type) { report_error( - "message result has unknown type " + "function result has unknown type " "'%s'\n", type_name); free(type_name); @@ -174,18 +232,12 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) } free(type_name); - char *result_name; - if (!parse_word(lex, &result_name)) { - report_error("expected message parameter name\n"); - ok = false; - break; - } - bool duplicate = msg_definition_has_param(msg, result_name) || msg_definition_has_result(msg, result_name); if (duplicate) { report_error( - "message has multiple parameters/results with " + "function has multiple " + "parameters/results with " "name '%s'\n", result_name); free(result_name); @@ -199,7 +251,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) } if (!parse_symbol(lex, SYM_SEMICOLON)) { - report_error("expected `;` after message definition\n"); + report_error("expected `;` after function definition\n"); goto fail; } @@ -226,29 +278,35 @@ struct interface_definition *parse_interface_definition( char *if_name = NULL; if (!parse_word(lex, &if_name)) { - report_error("expected interface identifier"); + report_error("expected interface name"); goto fail; } - iface = interface_definition_create(if_name); + long long if_id = 0; + if (!parse_int(lex, &if_id)) { + report_error("expected interface id number"); + goto fail; + } + + if (!parse_symbol(lex, SYM_SEMICOLON)) { + report_error("expected `;` after interface definition"); + goto fail; + } + + iface = interface_definition_create(if_name, if_id); free(if_name); if (!iface) { goto fail; } - if (!parse_symbol(lex, SYM_LEFT_BRACE)) { - report_error("expected `{` after interface identifier"); - goto fail; - } - bool ok = true; while (ok) { - if (parse_symbol(lex, SYM_RIGHT_BRACE)) { + if (!lex_peek(lex) && lex_get_status(lex) == ERR_EOF) { break; } - if (peek_keyword(lex, KW_MSG)) { + if (peek_keyword(lex, KW_FUNC)) { struct msg_definition *msg = parse_msg_definition(ctx, lex); if (!msg) { @@ -268,7 +326,7 @@ struct interface_definition *parse_interface_definition( continue; } - report_error("expected `}` or message definition\n"); + report_error("expected eof or function definition\n"); ok = false; break; } diff --git a/toolchain/ifc/parse.h b/toolchain/xpcg/parse.h similarity index 78% rename from toolchain/ifc/parse.h rename to toolchain/xpcg/parse.h index 57c6065..51b5cfd 100644 --- a/toolchain/ifc/parse.h +++ b/toolchain/xpcg/parse.h @@ -1,5 +1,5 @@ -#ifndef IFC_PARSE_H_ -#define IFC_PARSE_H_ +#ifndef XPCG_PARSE_H_ +#define XPCG_PARSE_H_ struct ctx; struct lex; diff --git a/toolchain/ifc/status.h b/toolchain/xpcg/status.h similarity index 84% rename from toolchain/ifc/status.h rename to toolchain/xpcg/status.h index da6c732..d58fa95 100644 --- a/toolchain/ifc/status.h +++ b/toolchain/xpcg/status.h @@ -1,5 +1,5 @@ -#ifndef IFC_STATUS_H_ -#define IFC_STATUS_H_ +#ifndef XPCG_STATUS_H_ +#define XPCG_STATUS_H_ enum status { SUCCESS = 0, diff --git a/toolchain/ifc/token.c b/toolchain/xpcg/token.c similarity index 96% rename from toolchain/ifc/token.c rename to toolchain/xpcg/token.c index 5460ca5..4bc401d 100644 --- a/toolchain/ifc/token.c +++ b/toolchain/xpcg/token.c @@ -40,6 +40,7 @@ const char *token_symbol_to_string(enum token_symbol sym) ENUM_STR(SYM_NONE); ENUM_STR(SYM_COMMA); ENUM_STR(SYM_SEMICOLON); + ENUM_STR(SYM_COLON); ENUM_STR(SYM_HYPHEN); ENUM_STR(SYM_LEFT_BRACE); ENUM_STR(SYM_RIGHT_BRACE); @@ -56,7 +57,7 @@ const char *token_keyword_to_string(enum token_keyword kw) switch (kw) { ENUM_STR(KW_NONE); ENUM_STR(KW_INTERFACE); - ENUM_STR(KW_MSG); + ENUM_STR(KW_FUNC); default: return ""; } diff --git a/toolchain/ifc/token.h b/toolchain/xpcg/token.h similarity index 93% rename from toolchain/ifc/token.h rename to toolchain/xpcg/token.h index 4c47f2e..3a661fd 100644 --- a/toolchain/ifc/token.h +++ b/toolchain/xpcg/token.h @@ -1,5 +1,5 @@ -#ifndef IFC_TOKEN_H_ -#define IFC_TOKEN_H_ +#ifndef XPCG_TOKEN_H_ +#define XPCG_TOKEN_H_ #include "file-span.h" @@ -34,6 +34,9 @@ enum token_symbol { SYM_COMMA = __TOK_UBOUND, SYM_HYPHEN, SYM_SEMICOLON, + SYM_COLON, + SYM_LEFT_BRACKET, + SYM_RIGHT_BRACKET, SYM_LEFT_BRACE, SYM_RIGHT_BRACE, SYM_LEFT_PAREN, @@ -45,7 +48,7 @@ enum token_symbol { enum token_keyword { KW_NONE = 0, KW_INTERFACE = __SYM_UBOUND, - KW_MSG, + KW_FUNC, }; struct token { diff --git a/toolchain/ifc/type.c b/toolchain/xpcg/type.c similarity index 74% rename from toolchain/ifc/type.c rename to toolchain/xpcg/type.c index 761b038..e502185 100644 --- a/toolchain/ifc/type.c +++ b/toolchain/xpcg/type.c @@ -11,6 +11,12 @@ void type_print(const struct type *ty) case TYPE_STRING: printf("string"); break; + case TYPE_SIZE: + printf("size"); + break; + case TYPE_BUFFER: + printf("buffer"); + break; case TYPE_HANDLE: printf("handle"); break; diff --git a/toolchain/ifc/type.h b/toolchain/xpcg/type.h similarity index 72% rename from toolchain/ifc/type.h rename to toolchain/xpcg/type.h index 593897a..f36d4ac 100644 --- a/toolchain/ifc/type.h +++ b/toolchain/xpcg/type.h @@ -1,10 +1,12 @@ -#ifndef IFC_TYPE_H_ -#define IFC_TYPE_H_ +#ifndef XPCG_TYPE_H_ +#define XPCG_TYPE_H_ enum type_id { TYPE_NONE, TYPE_INT, + TYPE_SIZE, TYPE_STRING, + TYPE_BUFFER, TYPE_HANDLE, TYPE_OTHER, };