mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
stage2 aarch64: add genCall for aarch64 MachO
This commit is contained in:
parent
993eb22a77
commit
a6bc19ea2a
@ -1643,61 +1643,64 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
switch (arch) {
|
||||
.x86_64 => {
|
||||
for (info.args) |mc_arg, arg_i| {
|
||||
const arg = inst.args[arg_i];
|
||||
const arg_mcv = try self.resolveInst(inst.args[arg_i]);
|
||||
// Here we do not use setRegOrMem even though the logic is similar, because
|
||||
// the function call will move the stack pointer, so the offsets are different.
|
||||
switch (mc_arg) {
|
||||
.none => continue,
|
||||
.register => |reg| {
|
||||
try self.genSetReg(arg.src, reg, arg_mcv);
|
||||
// TODO interact with the register allocator to mark the instruction as moved.
|
||||
},
|
||||
.stack_offset => {
|
||||
// Here we need to emit instructions like this:
|
||||
// mov qword ptr [rsp + stack_offset], x
|
||||
return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{});
|
||||
},
|
||||
.ptr_stack_offset => {
|
||||
return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{});
|
||||
},
|
||||
.ptr_embedded_in_code => {
|
||||
return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
|
||||
},
|
||||
.undef => unreachable,
|
||||
.immediate => unreachable,
|
||||
.unreach => unreachable,
|
||||
.dead => unreachable,
|
||||
.embedded_in_code => unreachable,
|
||||
.memory => unreachable,
|
||||
.compare_flags_signed => unreachable,
|
||||
.compare_flags_unsigned => unreachable,
|
||||
}
|
||||
}
|
||||
for (info.args) |mc_arg, arg_i| {
|
||||
const arg = inst.args[arg_i];
|
||||
const arg_mcv = try self.resolveInst(inst.args[arg_i]);
|
||||
// Here we do not use setRegOrMem even though the logic is similar, because
|
||||
// the function call will move the stack pointer, so the offsets are different.
|
||||
switch (mc_arg) {
|
||||
.none => continue,
|
||||
.register => |reg| {
|
||||
try self.genSetReg(arg.src, reg, arg_mcv);
|
||||
// TODO interact with the register allocator to mark the instruction as moved.
|
||||
},
|
||||
.stack_offset => {
|
||||
// Here we need to emit instructions like this:
|
||||
// mov qword ptr [rsp + stack_offset], x
|
||||
return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{});
|
||||
},
|
||||
.ptr_stack_offset => {
|
||||
return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{});
|
||||
},
|
||||
.ptr_embedded_in_code => {
|
||||
return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
|
||||
},
|
||||
.undef => unreachable,
|
||||
.immediate => unreachable,
|
||||
.unreach => unreachable,
|
||||
.dead => unreachable,
|
||||
.embedded_in_code => unreachable,
|
||||
.memory => unreachable,
|
||||
.compare_flags_signed => unreachable,
|
||||
.compare_flags_unsigned => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const func = func_val.func;
|
||||
const got = &macho_file.sections.items[macho_file.got_section_index.?];
|
||||
const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
|
||||
if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const func = func_val.func;
|
||||
const got = &macho_file.sections.items[macho_file.got_section_index.?];
|
||||
const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
|
||||
switch (arch) {
|
||||
.x86_64 => {
|
||||
// Here, we store the got address in %rax, and then call %rax
|
||||
// movabsq [addr], %rax
|
||||
try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
|
||||
// callq *%rax
|
||||
try self.code.ensureCapacity(self.code.items.len + 2);
|
||||
self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
|
||||
},
|
||||
.aarch64 => {
|
||||
try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr });
|
||||
writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
|
||||
},
|
||||
else => unreachable, // unsupported architecture on MachO
|
||||
}
|
||||
},
|
||||
.aarch64 => return self.fail(inst.base.src, "TODO implement codegen for call when linking with MachO for aarch64 arch", .{}),
|
||||
else => unreachable,
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
|
||||
}
|
||||
} else {
|
||||
unreachable;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user