From 91c3206b45074821749f52043937bf6ed6d9a105 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 9 Nov 2021 16:56:36 +0100 Subject: [PATCH] macho: use start.zig for macOS entrypoint This effectively allows us to compile ```zig pub fn main() void {} ``` which then calls into `std.start`. Changes required to make this happen: * handle signed int to immediate in x86_64 and aarch64 codegen * ensure that on arm64 macOS, `.x19` is a caller-preserved register - I'm not sure about that one at all and would like to brainstorm it with anyone interested and especially Joachim. * finally, fix a bug in the linker - mark new got entry as dirty upon atom growth. --- src/arch/aarch64/CodeGen.zig | 3 +++ src/arch/aarch64/bits.zig | 16 +++++++++++++--- src/arch/x86_64/CodeGen.zig | 3 +++ src/link/MachO.zig | 1 + test/stage2/darwin.zig | 32 ++++++++++++++++++++------------ 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index a763651825..d3c72fe1b1 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -2393,6 +2393,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { }, .Int => { const info = typed_value.ty.intInfo(self.target.*); + if (info.bits <= ptr_bits and info.signedness == .signed) { + return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; + } if (info.bits > ptr_bits or info.signedness == .signed) { return self.fail("TODO const int bigger than ptr and signed int", .{}); } diff --git a/src/arch/aarch64/bits.zig b/src/arch/aarch64/bits.zig index dfda04da85..f751170818 100644 --- a/src/arch/aarch64/bits.zig +++ b/src/arch/aarch64/bits.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const builtin = @import("builtin"); const DW = std.dwarf; const assert = std.debug.assert; const testing = std.testing; @@ -58,10 +59,19 @@ pub const Register = enum(u6) { // zig fmt: on -pub const callee_preserved_regs = [_]Register{ - .x19, .x20, .x21, .x22, .x23, - .x24, .x25, .x26, .x27, .x28, +const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct { + pub const callee_preserved_regs = [_]Register{ + .x20, .x21, .x22, .x23, + .x24, .x25, .x26, .x27, + .x28, + }; +} else struct { + pub const callee_preserved_regs = [_]Register{ + .x19, .x20, .x21, .x22, .x23, + .x24, .x25, .x26, .x27, .x28, + }; }; +pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_regs; pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index b590937110..d0405c5a00 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3178,6 +3178,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { }, .Int => { const info = typed_value.ty.intInfo(self.target.*); + if (info.bits <= ptr_bits and info.signedness == .signed) { + return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; + } if (info.bits > ptr_bits or info.signedness == .signed) { return self.fail("TODO const int bigger than ptr and signed int", .{}); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 9c3dc36def..d4ddf80094 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3285,6 +3285,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 .seg = self.data_const_segment_cmd_index.?, .sect = self.got_section_index.?, }).? + 1); + got_atom.dirty = true; } symbol.n_value = vaddr; diff --git a/test/stage2/darwin.zig b/test/stage2/darwin.zig index 84334828bd..ab4f3923ae 100644 --- a/test/stage2/darwin.zig +++ b/test/stage2/darwin.zig @@ -45,18 +45,32 @@ pub fn addCases(ctx: *TestContext) !void { "Hello, World!\n", ); + // Now using start.zig without an explicit extern exit fn + case.addCompareOutput( + \\extern fn write(usize, usize, usize) usize; + \\ + \\pub fn main() void { + \\ print(); + \\} + \\ + \\fn print() void { + \\ const msg = @ptrToInt("Hello, World!\n"); + \\ const len = 14; + \\ _ = write(1, msg, len); + \\} + , + "Hello, World!\n", + ); + // Print it 4 times and force growth and realloc. case.addCompareOutput( \\extern fn write(usize, usize, usize) usize; - \\extern fn exit(usize) noreturn; \\ - \\pub export fn main() noreturn { + \\pub fn main() void { \\ print(); \\ print(); \\ print(); \\ print(); - \\ - \\ exit(0); \\} \\ \\fn print() void { @@ -75,12 +89,9 @@ pub fn addCases(ctx: *TestContext) !void { // Print it once, and change the message. case.addCompareOutput( \\extern fn write(usize, usize, usize) usize; - \\extern fn exit(usize) noreturn; \\ - \\pub export fn main() noreturn { + \\pub fn main() void { \\ print(); - \\ - \\ exit(0); \\} \\ \\fn print() void { @@ -95,13 +106,10 @@ pub fn addCases(ctx: *TestContext) !void { // Now we print it twice. case.addCompareOutput( \\extern fn write(usize, usize, usize) usize; - \\extern fn exit(usize) noreturn; \\ - \\pub export fn main() noreturn { + \\pub fn main() void { \\ print(); \\ print(); - \\ - \\ exit(0); \\} \\ \\fn print() void {