x86_64 backend: support returning structs & arrays
This commit is contained in:
parent
866af8d21c
commit
4c583c8b3b
1 changed files with 39 additions and 14 deletions
|
|
@ -34,6 +34,11 @@ namespace pslang::jit::linux_x86_64
|
|||
reg::r9,
|
||||
};
|
||||
|
||||
static std::array<reg, 2> 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");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue