diff --git a/src/codegen.zig b/src/codegen.zig index eea87d70f1..53d065d26c 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -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;