Commit 91c3206b45

Jakub Konka <kubkon@jakubkonka.com>
2021-11-09 16:56:36
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.
1 parent b521510
Changed files (5)
src
test
stage2
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 };
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", .{});
             }
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", .{});
             }
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;
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 {