x86_64 backend: support returning structs & arrays

This commit is contained in:
Nikita Lisitsa 2026-07-31 13:55:02 +03:00
parent 8d4bc9aa62
commit 16d6ed4174

View file

@ -34,6 +34,11 @@ namespace pslang::jit::linux_x86_64
reg::r9, reg::r9,
}; };
static std::array<reg, 2> integer_ret_reg = {
reg::rax,
reg::rdx,
};
struct small_struct_data struct small_struct_data
{ {
struct octet struct octet
@ -760,7 +765,27 @@ namespace pslang::jit::linux_x86_64
{} {}
else if (struct_type || array_type) 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)) else if (types::is_integer_like_type(*type))
load(*node.value, reg::rax); load(*node.value, reg::rax);
@ -851,7 +876,7 @@ namespace pslang::jit::linux_x86_64
for (std::size_t o : {0, 1}) for (std::size_t o : {0, 1})
{ {
auto & octet = small_struct->octets[o]; auto & octet = small_struct->octets[o];
if (!octet) continue; if (!octet) break;
if (octet->has_integer) if (octet->has_integer)
builder.mov_write(integer_arg_reg[reg_index++], reg::rsp, stack_size - argument_position[i] + 8 * o); builder.mov_write(integer_arg_reg[reg_index++], reg::rsp, stack_size - argument_position[i] + 8 * o);
else if (octet->has_floating_point) 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)}; 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); auto const address = node_address(it);
if (address.base) if (address.base)
builder.mov_read(*address.base, address.offset, reg_dst); builder.mov_read(*address.base, address.offset + offset, reg_dst);
else 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); auto const address = node_address(it);
if (address.base) if (address.base)
builder.mov_write(reg_src, *address.base, address.offset); builder.mov_write(reg_src, *address.base, address.offset + offset);
else 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) if (size != 4 && size != 8)
throw std::runtime_error("Bad type size for load_xmm"); throw std::runtime_error("Bad type size for load_xmm");
@ -960,15 +985,15 @@ namespace pslang::jit::linux_x86_64
if (address.base) if (address.base)
{ {
if (size == 4) 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 else
builder.mov_read_xmm(*address.base, address.offset, reg_dst); builder.mov_read_xmm(*address.base, address.offset + offset, reg_dst);
} }
else else
throw std::runtime_error("RIP-relative XMM read is not supported"); 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) if (size != 4 && size != 8)
throw std::runtime_error("Bad type size for store_xmm"); throw std::runtime_error("Bad type size for store_xmm");
@ -977,9 +1002,9 @@ namespace pslang::jit::linux_x86_64
if (address.base) if (address.base)
{ {
if (size == 4) 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 else
builder.mov_write_xmm(reg_src, *address.base, address.offset); builder.mov_write_xmm(reg_src, *address.base, address.offset + offset);
} }
else else
throw std::runtime_error("RIP-relative XMM write is not supported"); throw std::runtime_error("RIP-relative XMM write is not supported");