authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 12:09:39+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 14:34:53+01:00
loga6bc19ea2a2fb99ee7f09dd451b889b6a5d7f388
tree21db839a2cfa74adf67c1cacf05ac59d20a6bbfe
parent993eb22a772323bfeef87cf783672c33b6a2cfa2

stage2 aarch64: add genCall for aarch64 MachO


1 files changed, 50 insertions(+), 47 deletions(-)

src/codegen.zig+50-47
...@@ -1643,61 +1643,64 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1643,61 +1643,64 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1643 else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}),1643 else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}),
1644 }1644 }
1645 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {1645 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
1646 switch (arch) {1646 for (info.args) |mc_arg, arg_i| {
1647 .x86_64 => {1647 const arg = inst.args[arg_i];
1648 for (info.args) |mc_arg, arg_i| {1648 const arg_mcv = try self.resolveInst(inst.args[arg_i]);
1649 const arg = inst.args[arg_i];1649 // Here we do not use setRegOrMem even though the logic is similar, because
1650 const arg_mcv = try self.resolveInst(inst.args[arg_i]);1650 // the function call will move the stack pointer, so the offsets are different.
1651 // Here we do not use setRegOrMem even though the logic is similar, because1651 switch (mc_arg) {
1652 // the function call will move the stack pointer, so the offsets are different.1652 .none => continue,
1653 switch (mc_arg) {1653 .register => |reg| {
1654 .none => continue,1654 try self.genSetReg(arg.src, reg, arg_mcv);
1655 .register => |reg| {1655 // TODO interact with the register allocator to mark the instruction as moved.
1656 try self.genSetReg(arg.src, reg, arg_mcv);1656 },
1657 // TODO interact with the register allocator to mark the instruction as moved.1657 .stack_offset => {
1658 },1658 // Here we need to emit instructions like this:
1659 .stack_offset => {1659 // mov qword ptr [rsp + stack_offset], x
1660 // Here we need to emit instructions like this:1660 return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{});
1661 // mov qword ptr [rsp + stack_offset], x1661 },
1662 return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{});1662 .ptr_stack_offset => {
1663 },1663 return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{});
1664 .ptr_stack_offset => {1664 },
1665 return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{});1665 .ptr_embedded_in_code => {
1666 },1666 return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
1667 .ptr_embedded_in_code => {1667 },
1668 return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});1668 .undef => unreachable,
1669 },1669 .immediate => unreachable,
1670 .undef => unreachable,1670 .unreach => unreachable,
1671 .immediate => unreachable,1671 .dead => unreachable,
1672 .unreach => unreachable,1672 .embedded_in_code => unreachable,
1673 .dead => unreachable,1673 .memory => unreachable,
1674 .embedded_in_code => unreachable,1674 .compare_flags_signed => unreachable,
1675 .memory => unreachable,1675 .compare_flags_unsigned => unreachable,
1676 .compare_flags_signed => unreachable,1676 }
1677 .compare_flags_unsigned => unreachable,1677 }
1678 }
1679 }
16801678
1681 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1679 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1682 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1680 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1683 const func = func_val.func;1681 const func = func_val.func;
1684 const got = &macho_file.sections.items[macho_file.got_section_index.?];1682 const got = &macho_file.sections.items[macho_file.got_section_index.?];
1685 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);1683 const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
1684 switch (arch) {
1685 .x86_64 => {
1686 // Here, we store the got address in %rax, and then call %rax1686 // Here, we store the got address in %rax, and then call %rax
1687 // movabsq [addr], %rax1687 // movabsq [addr], %rax
1688 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });1688 try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
1689 // callq *%rax1689 // callq *%rax
1690 try self.code.ensureCapacity(self.code.items.len + 2);1690 try self.code.ensureCapacity(self.code.items.len + 2);
1691 self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });1691 self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
1692 } else {1692 },
1693 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});1693 .aarch64 => {
1694 }1694 try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr });
1695 } else {1695 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
1696 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});1696 },
1697 else => unreachable, // unsupported architecture on MachO
1697 }1698 }
1698 },1699 } else {
1699 .aarch64 => return self.fail(inst.base.src, "TODO implement codegen for call when linking with MachO for aarch64 arch", .{}),1700 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
1700 else => unreachable,1701 }
1702 } else {
1703 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
1701 }1704 }
1702 } else {1705 } else {
1703 unreachable;1706 unreachable;