From 16d6ed4174d49ca0c1d070fd9a9922fa2603fc80 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 31 Jul 2026 13:55:02 +0300 Subject: [PATCH] x86_64 backend: support returning structs & arrays --- .../jit/source/arch/linux_x86_64/compiler.cpp | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/libs/jit/source/arch/linux_x86_64/compiler.cpp b/libs/jit/source/arch/linux_x86_64/compiler.cpp index 4053a88..58e5950 100644 --- a/libs/jit/source/arch/linux_x86_64/compiler.cpp +++ b/libs/jit/source/arch/linux_x86_64/compiler.cpp @@ -34,6 +34,11 @@ namespace pslang::jit::linux_x86_64 reg::r9, }; + static std::array integer_ret_reg = { + reg::rax, + reg::rdx, + }; + struct small_struct_data { struct octet @@ -760,7 +765,27 @@ namespace pslang::jit::linux_x86_64 {} else if (struct_type || array_type) { - throw std::runtime_error("Not implemented"); + if (auto small_struct = classify_small_struct(lcontext, type)) + { + auto address = node_address(*node.value); + + std::uint8_t reg_index = 0; + std::uint8_t fp_reg = 0; + for (int o : {0, 1}) + { + auto & octet = small_struct->octets[o]; + if (!octet) break; + + if (octet->has_integer) + load(*node.value, integer_ret_reg[reg_index++], 8 * o); + else if (octet->has_floating_point) + load_xmm(*node.value, (reg)(fp_reg++), 8, 8 * o); + } + } + else + { + copy_memory(node_address(*node.value), {reg::rdi, 0}, size); + } } else if (types::is_integer_like_type(*type)) load(*node.value, reg::rax); @@ -851,7 +876,7 @@ namespace pslang::jit::linux_x86_64 for (std::size_t o : {0, 1}) { auto & octet = small_struct->octets[o]; - if (!octet) continue; + if (!octet) break; if (octet->has_integer) builder.mov_write(integer_arg_reg[reg_index++], reg::rsp, stack_size - argument_position[i] + 8 * o); else if (octet->has_floating_point) @@ -933,25 +958,25 @@ namespace pslang::jit::linux_x86_64 return {.base = reg::rsp, .offset = stack_size - stack_position.at(it)}; } - void load(ir::node_ref it, reg reg_dst) + void load(ir::node_ref it, reg reg_dst, std::int32_t offset = 0) { auto const address = node_address(it); if (address.base) - builder.mov_read(*address.base, address.offset, reg_dst); + builder.mov_read(*address.base, address.offset + offset, reg_dst); else - builder.mov_read_rip_prev(address.offset, reg_dst); + builder.mov_read_rip_prev(address.offset + offset, reg_dst); } - void store(ir::node_ref it, reg reg_src) + void store(ir::node_ref it, reg reg_src, std::int32_t offset = 0) { auto const address = node_address(it); if (address.base) - builder.mov_write(reg_src, *address.base, address.offset); + builder.mov_write(reg_src, *address.base, address.offset + offset); else - builder.mov_write_rip_prev(reg_src, address.offset); + builder.mov_write_rip_prev(reg_src, address.offset + offset); } - void load_xmm(ir::node_ref it, reg reg_dst, std::uint8_t size) + void load_xmm(ir::node_ref it, reg reg_dst, std::uint8_t size, std::int32_t offset = 0) { if (size != 4 && size != 8) throw std::runtime_error("Bad type size for load_xmm"); @@ -960,15 +985,15 @@ namespace pslang::jit::linux_x86_64 if (address.base) { if (size == 4) - builder.mov_read_xmm_32(*address.base, address.offset, reg_dst); + builder.mov_read_xmm_32(*address.base, address.offset + offset, reg_dst); else - builder.mov_read_xmm(*address.base, address.offset, reg_dst); + builder.mov_read_xmm(*address.base, address.offset + offset, reg_dst); } else throw std::runtime_error("RIP-relative XMM read is not supported"); } - void store_xmm(ir::node_ref it, reg reg_src, std::uint8_t size) + void store_xmm(ir::node_ref it, reg reg_src, std::uint8_t size, std::int32_t offset = 0) { if (size != 4 && size != 8) throw std::runtime_error("Bad type size for store_xmm"); @@ -977,9 +1002,9 @@ namespace pslang::jit::linux_x86_64 if (address.base) { if (size == 4) - builder.mov_write_xmm_32(reg_src, *address.base, address.offset); + builder.mov_write_xmm_32(reg_src, *address.base, address.offset + offset); else - builder.mov_write_xmm(reg_src, *address.base, address.offset); + builder.mov_write_xmm(reg_src, *address.base, address.offset + offset); } else throw std::runtime_error("RIP-relative XMM write is not supported");