| author | |
| committer | |
| log | 91c3206b45074821749f52043937bf6ed6d9a105 |
| tree | 5d6d674d146e4189bc22865bed42dea0f9ada320 |
| parent | b521510cd4e68407226dd95c9e87cc97ca5a0796 |
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.5 files changed, 40 insertions(+), 15 deletions(-)
src/arch/aarch64/CodeGen.zig+3| ... | ... | @@ -2393,6 +2393,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 2393 | 2393 | }, |
| 2394 | 2394 | .Int => { |
| 2395 | 2395 | const info = typed_value.ty.intInfo(self.target.*); |
| 2396 | if (info.bits <= ptr_bits and info.signedness == .signed) { | |
| 2397 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; | |
| 2398 | } | |
| 2396 | 2399 | if (info.bits > ptr_bits or info.signedness == .signed) { |
| 2397 | 2400 | return self.fail("TODO const int bigger than ptr and signed int", .{}); |
| 2398 | 2401 | } |
src/arch/aarch64/bits.zig+13-3| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const DW = std.dwarf; |
| 3 | 4 | const assert = std.debug.assert; |
| 4 | 5 | const testing = std.testing; |
| ... | ... | @@ -58,10 +59,19 @@ pub const Register = enum(u6) { |
| 58 | 59 | |
| 59 | 60 | // zig fmt: on |
| 60 | 61 | |
| 61 | pub const callee_preserved_regs = [_]Register{ | |
| 62 | .x19, .x20, .x21, .x22, .x23, | |
| 63 | .x24, .x25, .x26, .x27, .x28, | |
| 62 | const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct { | |
| 63 | pub const callee_preserved_regs = [_]Register{ | |
| 64 | .x20, .x21, .x22, .x23, | |
| 65 | .x24, .x25, .x26, .x27, | |
| 66 | .x28, | |
| 67 | }; | |
| 68 | } else struct { | |
| 69 | pub const callee_preserved_regs = [_]Register{ | |
| 70 | .x19, .x20, .x21, .x22, .x23, | |
| 71 | .x24, .x25, .x26, .x27, .x28, | |
| 72 | }; | |
| 64 | 73 | }; |
| 74 | pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_regs; | |
| 65 | 75 | |
| 66 | 76 | pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; |
| 67 | 77 | pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; |
src/arch/x86_64/CodeGen.zig+3| ... | ... | @@ -3178,6 +3178,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3178 | 3178 | }, |
| 3179 | 3179 | .Int => { |
| 3180 | 3180 | const info = typed_value.ty.intInfo(self.target.*); |
| 3181 | if (info.bits <= ptr_bits and info.signedness == .signed) { | |
| 3182 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; | |
| 3183 | } | |
| 3181 | 3184 | if (info.bits > ptr_bits or info.signedness == .signed) { |
| 3182 | 3185 | return self.fail("TODO const int bigger than ptr and signed int", .{}); |
| 3183 | 3186 | } |
src/link/MachO.zig+1| ... | ... | @@ -3285,6 +3285,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3285 | 3285 | .seg = self.data_const_segment_cmd_index.?, |
| 3286 | 3286 | .sect = self.got_section_index.?, |
| 3287 | 3287 | }).? + 1); |
| 3288 | got_atom.dirty = true; | |
| 3288 | 3289 | } |
| 3289 | 3290 | |
| 3290 | 3291 | symbol.n_value = vaddr; |
test/stage2/darwin.zig+20-12| ... | ... | @@ -45,18 +45,32 @@ pub fn addCases(ctx: *TestContext) !void { |
| 45 | 45 | "Hello, World!\n", |
| 46 | 46 | ); |
| 47 | 47 | |
| 48 | // Now using start.zig without an explicit extern exit fn | |
| 49 | case.addCompareOutput( | |
| 50 | \\extern fn write(usize, usize, usize) usize; | |
| 51 | \\ | |
| 52 | \\pub fn main() void { | |
| 53 | \\ print(); | |
| 54 | \\} | |
| 55 | \\ | |
| 56 | \\fn print() void { | |
| 57 | \\ const msg = @ptrToInt("Hello, World!\n"); | |
| 58 | \\ const len = 14; | |
| 59 | \\ _ = write(1, msg, len); | |
| 60 | \\} | |
| 61 | , | |
| 62 | "Hello, World!\n", | |
| 63 | ); | |
| 64 | ||
| 48 | 65 | // Print it 4 times and force growth and realloc. |
| 49 | 66 | case.addCompareOutput( |
| 50 | 67 | \\extern fn write(usize, usize, usize) usize; |
| 51 | \\extern fn exit(usize) noreturn; | |
| 52 | 68 | \\ |
| 53 | \\pub export fn main() noreturn { | |
| 69 | \\pub fn main() void { | |
| 54 | 70 | \\ print(); |
| 55 | 71 | \\ print(); |
| 56 | 72 | \\ print(); |
| 57 | 73 | \\ print(); |
| 58 | \\ | |
| 59 | \\ exit(0); | |
| 60 | 74 | \\} |
| 61 | 75 | \\ |
| 62 | 76 | \\fn print() void { |
| ... | ... | @@ -75,12 +89,9 @@ pub fn addCases(ctx: *TestContext) !void { |
| 75 | 89 | // Print it once, and change the message. |
| 76 | 90 | case.addCompareOutput( |
| 77 | 91 | \\extern fn write(usize, usize, usize) usize; |
| 78 | \\extern fn exit(usize) noreturn; | |
| 79 | 92 | \\ |
| 80 | \\pub export fn main() noreturn { | |
| 93 | \\pub fn main() void { | |
| 81 | 94 | \\ print(); |
| 82 | \\ | |
| 83 | \\ exit(0); | |
| 84 | 95 | \\} |
| 85 | 96 | \\ |
| 86 | 97 | \\fn print() void { |
| ... | ... | @@ -95,13 +106,10 @@ pub fn addCases(ctx: *TestContext) !void { |
| 95 | 106 | // Now we print it twice. |
| 96 | 107 | case.addCompareOutput( |
| 97 | 108 | \\extern fn write(usize, usize, usize) usize; |
| 98 | \\extern fn exit(usize) noreturn; | |
| 99 | 109 | \\ |
| 100 | \\pub export fn main() noreturn { | |
| 110 | \\pub fn main() void { | |
| 101 | 111 | \\ print(); |
| 102 | 112 | \\ print(); |
| 103 | \\ | |
| 104 | \\ exit(0); | |
| 105 | 113 | \\} |
| 106 | 114 | \\ |
| 107 | 115 | \\fn print() void { |