authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-12 18:27:17-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-12 18:33:44-05:00
logfff3c1fff4c3ebfcb2bd4f08a43ae7815b5c446b
treeea996d6252efe24158a802fb50c1a28c3b3d6717
parentb37acc4d6870a090c3501d81d3f647bc30220e4b
signature Commit is signed but in an unrecognized format.

un-special-case startup code in the std lib

Previously, the compiler had special logic to determine whether to include the startup code, which was in `std/special/start.zig`. Now, the file is moved to `std/start.zig`, and there is no special logic in the compiler. Instead, the standard library unconditionally imports the `start.zig` file, which then has a `comptime` block that does the logic of determining what, if any, start symbols to export. Instead of `start.zig` being in its own special package, it is just another normal file that is part of the standard library. `std.builtin.TestFn` is now part of the standard library rather than specially generated by the compiler.

15 files changed, 420 insertions(+), 443 deletions(-)

lib/std/builtin.zig+7
...@@ -412,6 +412,13 @@ pub const CallOptions = struct {...@@ -412,6 +412,13 @@ pub const CallOptions = struct {
412 };412 };
413};413};
414414
415/// This function type is used by the Zig language code generation and
416/// therefore must be kept in sync with the compiler implementation.
417pub const TestFn = struct {
418 name: []const u8,
419 func: fn()anyerror!void,
420};
421
415/// This function type is used by the Zig language code generation and422/// This function type is used by the Zig language code generation and
416/// therefore must be kept in sync with the compiler implementation.423/// therefore must be kept in sync with the compiler implementation.
417pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;424pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;
lib/std/special.zig deleted-1
...@@ -1 +0,0 @@
1pub const start = @import("special/start.zig");
lib/std/special/start.zig deleted-283
...@@ -1,283 +0,0 @@
1// This file is included in the compilation unit when exporting an executable.
2
3const root = @import("root");
4const std = @import("std");
5const builtin = @import("builtin");
6const assert = std.debug.assert;
7const uefi = std.os.uefi;
8
9var starting_stack_ptr: [*]usize = undefined;
10
11const is_wasm = switch (builtin.arch) {
12 .wasm32, .wasm64 => true,
13 else => false,
14};
15
16const is_mips = switch (builtin.arch) {
17 .mips, .mipsel, .mips64, .mips64el => true,
18 else => false,
19};
20const start_sym_name = if (is_mips) "__start" else "_start";
21
22comptime {
23 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
24 if (builtin.os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {
25 @export("_DllMainCRTStartup", _DllMainCRTStartup, .Strong);
26 }
27 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
28 if (builtin.link_libc and @hasDecl(root, "main")) {
29 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
30 @export("main", main, .Weak);
31 }
32 } else if (builtin.os == .windows) {
33 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) {
34 @export("WinMainCRTStartup", WinMainCRTStartup, .Strong);
35 }
36 } else if (builtin.os == .uefi) {
37 if (!@hasDecl(root, "EfiMain")) @export("EfiMain", EfiMain, .Strong);
38 } else if (is_wasm and builtin.os == .freestanding) {
39 if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, wasm_freestanding_start, .Strong);
40 } else if (builtin.os != .other and builtin.os != .freestanding) {
41 if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, _start, .Strong);
42 }
43 }
44}
45
46stdcallcc fn _DllMainCRTStartup(
47 hinstDLL: std.os.windows.HINSTANCE,
48 fdwReason: std.os.windows.DWORD,
49 lpReserved: std.os.windows.LPVOID,
50) std.os.windows.BOOL {
51 if (@hasDecl(root, "DllMain")) {
52 return root.DllMain(hinstDLL, fdwReason, lpReserved);
53 }
54
55 return std.os.windows.TRUE;
56}
57
58extern fn wasm_freestanding_start() void {
59 // This is marked inline because for some reason LLVM in release mode fails to inline it,
60 // and we want fewer call frames in stack traces.
61 _ = @call(.{ .modifier = .always_inline }, callMain, .{});
62}
63
64extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
65 const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'";
66 uefi.handle = handle;
67 uefi.system_table = system_table;
68
69 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
70 .NoReturn => {
71 root.main();
72 },
73 .Void => {
74 root.main();
75 return 0;
76 },
77 .Int => |info| {
78 if (info.bits != @typeInfo(usize).Int.bits) {
79 @compileError(bad_efi_main_ret);
80 }
81 return root.main();
82 },
83 else => @compileError(bad_efi_main_ret),
84 }
85}
86
87nakedcc fn _start() noreturn {
88 if (builtin.os == builtin.Os.wasi) {
89 // This is marked inline because for some reason LLVM in release mode fails to inline it,
90 // and we want fewer call frames in stack traces.
91 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
92 }
93
94 switch (builtin.arch) {
95 .x86_64 => {
96 starting_stack_ptr = asm (""
97 : [argc] "={rsp}" (-> [*]usize)
98 );
99 },
100 .i386 => {
101 starting_stack_ptr = asm (""
102 : [argc] "={esp}" (-> [*]usize)
103 );
104 },
105 .aarch64, .aarch64_be, .arm => {
106 starting_stack_ptr = asm ("mov %[argc], sp"
107 : [argc] "=r" (-> [*]usize)
108 );
109 },
110 .riscv64 => {
111 starting_stack_ptr = asm ("mv %[argc], sp"
112 : [argc] "=r" (-> [*]usize)
113 );
114 },
115 .mipsel => {
116 // Need noat here because LLVM is free to pick any register
117 starting_stack_ptr = asm (
118 \\ .set noat
119 \\ move %[argc], $sp
120 : [argc] "=r" (-> [*]usize)
121 );
122 },
123 else => @compileError("unsupported arch"),
124 }
125 // If LLVM inlines stack variables into _start, they will overwrite
126 // the command line argument data.
127 @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
128}
129
130stdcallcc fn WinMainCRTStartup() noreturn {
131 @setAlignStack(16);
132 if (!builtin.single_threaded) {
133 _ = @import("start_windows_tls.zig");
134 }
135
136 std.debug.maybeEnableSegfaultHandler();
137
138 std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain());
139}
140
141// TODO https://github.com/ziglang/zig/issues/265
142fn posixCallMainAndExit() noreturn {
143 if (builtin.os == builtin.Os.freebsd) {
144 @setAlignStack(16);
145 }
146 const argc = starting_stack_ptr[0];
147 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
148
149 const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
150 var envp_count: usize = 0;
151 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
152 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
153
154 if (builtin.os == .linux) {
155 // Find the beginning of the auxiliary vector
156 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
157 std.os.linux.elf_aux_maybe = auxv;
158 // Initialize the TLS area
159 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
160
161 if (std.os.linux.tls.tls_image) |tls_img| {
162 const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
163 const tp = std.os.linux.tls.copyTLS(tls_addr);
164 std.os.linux.tls.setThreadPointer(tp);
165 }
166
167 // TODO This is disabled because what should we do when linking libc and this code
168 // does not execute? And also it's causing a test failure in stack traces in release modes.
169
170 //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further
171 //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down
172 //// the stack and requires "probing". So here we allocate our own stack.
173 //const wanted_stack_size = gnu_stack_phdr.p_memsz;
174 //assert(wanted_stack_size % std.mem.page_size == 0);
175 //// Allocate an extra page as the guard page.
176 //const total_size = wanted_stack_size + std.mem.page_size;
177 //const new_stack = std.os.mmap(
178 // null,
179 // total_size,
180 // std.os.PROT_READ | std.os.PROT_WRITE,
181 // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS,
182 // -1,
183 // 0,
184 //) catch @panic("out of memory");
185 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
186 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
187 }
188
189 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
190}
191
192fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
193 std.os.argv = argv[0..argc];
194 std.os.environ = envp;
195
196 std.debug.maybeEnableSegfaultHandler();
197
198 return initEventLoopAndCallMain();
199}
200
201extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
202 var env_count: usize = 0;
203 while (c_envp[env_count] != null) : (env_count += 1) {}
204 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
205 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
206}
207
208// General error message for a malformed return type
209const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
210
211// This is marked inline because for some reason LLVM in release mode fails to inline it,
212// and we want fewer call frames in stack traces.
213inline fn initEventLoopAndCallMain() u8 {
214 if (std.event.Loop.instance) |loop| {
215 if (!@hasDecl(root, "event_loop")) {
216 loop.init() catch |err| {
217 std.debug.warn("error: {}\n", .{@errorName(err)});
218 if (@errorReturnTrace()) |trace| {
219 std.debug.dumpStackTrace(trace.*);
220 }
221 return 1;
222 };
223 defer loop.deinit();
224
225 var result: u8 = undefined;
226 var frame: @Frame(callMainAsync) = undefined;
227 _ = @asyncCall(&frame, &result, callMainAsync, loop);
228 loop.run();
229 return result;
230 }
231 }
232
233 // This is marked inline because for some reason LLVM in release mode fails to inline it,
234 // and we want fewer call frames in stack traces.
235 return @call(.{ .modifier = .always_inline }, callMain, .{});
236}
237
238async fn callMainAsync(loop: *std.event.Loop) u8 {
239 // This prevents the event loop from terminating at least until main() has returned.
240 loop.beginOneEvent();
241 defer loop.finishOneEvent();
242 return callMain();
243}
244
245// This is not marked inline because it is called with @asyncCall when
246// there is an event loop.
247pub fn callMain() u8 {
248 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
249 .NoReturn => {
250 root.main();
251 },
252 .Void => {
253 root.main();
254 return 0;
255 },
256 .Int => |info| {
257 if (info.bits != 8) {
258 @compileError(bad_main_ret);
259 }
260 return root.main();
261 },
262 .ErrorUnion => {
263 const result = root.main() catch |err| {
264 std.debug.warn("error: {}\n", .{@errorName(err)});
265 if (@errorReturnTrace()) |trace| {
266 std.debug.dumpStackTrace(trace.*);
267 }
268 return 1;
269 };
270 switch (@typeInfo(@TypeOf(result))) {
271 .Void => return 0,
272 .Int => |info| {
273 if (info.bits != 8) {
274 @compileError(bad_main_ret);
275 }
276 return result;
277 },
278 else => @compileError(bad_main_ret),
279 }
280 },
281 else => @compileError(bad_main_ret),
282 }
283}
lib/std/special/start_windows_tls.zig deleted-48
...@@ -1,48 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
5export var _tls_start: u8 linksection(".tls") = 0;
6export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
7export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
8export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
9
10comptime {
11 if (builtin.arch == .i386) {
12 // The __tls_array is the offset of the ThreadLocalStoragePointer field
13 // in the TEB block whose base address held in the %fs segment.
14 asm (
15 \\ .global __tls_array
16 \\ __tls_array = 0x2C
17 );
18 }
19}
20
21// TODO this is how I would like it to be expressed
22// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
23// why they do that.
24//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY {
25// .StartAddressOfRawData = @ptrToInt(&_tls_start),
26// .EndAddressOfRawData = @ptrToInt(&_tls_end),
27// .AddressOfIndex = @ptrToInt(&_tls_index),
28// .AddressOfCallBacks = @ptrToInt(__xl_a),
29// .SizeOfZeroFill = 0,
30// .Characteristics = 0,
31//};
32// This is the workaround because we can't do @ptrToInt at comptime like that.
33pub const IMAGE_TLS_DIRECTORY = extern struct {
34 StartAddressOfRawData: *c_void,
35 EndAddressOfRawData: *c_void,
36 AddressOfIndex: *c_void,
37 AddressOfCallBacks: *c_void,
38 SizeOfZeroFill: u32,
39 Characteristics: u32,
40};
41export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
42 .StartAddressOfRawData = &_tls_start,
43 .EndAddressOfRawData = &_tls_end,
44 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,
46 .SizeOfZeroFill = 0,
47 .Characteristics = 0,
48};
lib/std/special/test_runner.zig+4-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const std = @import("std");1const std = @import("std");
2const io = std.io;2const io = std.io;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const test_fn_list = builtin.test_functions;
54
6pub fn main() anyerror!void {5pub fn main() anyerror!void {
6 const test_fn_list = builtin.test_functions;
7 var ok_count: usize = 0;7 var ok_count: usize = 0;
8 var skip_count: usize = 0;8 var skip_count: usize = 0;
9 var progress = std.Progress{};9 var progress = std.Progress{};
...@@ -16,7 +16,9 @@ pub fn main() anyerror!void {...@@ -16,7 +16,9 @@ pub fn main() anyerror!void {
16 var test_node = root_node.start(test_fn.name, null);16 var test_node = root_node.start(test_fn.name, null);
17 test_node.activate();17 test_node.activate();
18 progress.refresh();18 progress.refresh();
19 if (progress.terminal == null) std.debug.warn("{}/{} {}...", .{ i + 1, test_fn_list.len, test_fn.name });19 if (progress.terminal == null) {
20 std.debug.warn("{}/{} {}...", .{ i + 1, test_fn_list.len, test_fn.name });
21 }
20 if (test_fn.func()) |_| {22 if (test_fn.func()) |_| {
21 ok_count += 1;23 ok_count += 1;
22 test_node.end();24 test_node.end();
lib/std/start.zig created+283
...@@ -0,0 +1,283 @@
1// This file is included in the compilation unit when exporting an executable.
2
3const root = @import("root");
4const std = @import("std.zig");
5const builtin = std.builtin;
6const assert = std.debug.assert;
7const uefi = std.os.uefi;
8
9var starting_stack_ptr: [*]usize = undefined;
10
11const is_wasm = switch (builtin.arch) {
12 .wasm32, .wasm64 => true,
13 else => false,
14};
15
16const is_mips = switch (builtin.arch) {
17 .mips, .mipsel, .mips64, .mips64el => true,
18 else => false,
19};
20const start_sym_name = if (is_mips) "__start" else "_start";
21
22comptime {
23 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
24 if (builtin.os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {
25 @export("_DllMainCRTStartup", _DllMainCRTStartup, .Strong);
26 }
27 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
28 if (builtin.link_libc and @hasDecl(root, "main")) {
29 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
30 @export("main", main, .Weak);
31 }
32 } else if (builtin.os == .windows) {
33 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) {
34 @export("WinMainCRTStartup", WinMainCRTStartup, .Strong);
35 }
36 } else if (builtin.os == .uefi) {
37 if (!@hasDecl(root, "EfiMain")) @export("EfiMain", EfiMain, .Strong);
38 } else if (is_wasm and builtin.os == .freestanding) {
39 if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, wasm_freestanding_start, .Strong);
40 } else if (builtin.os != .other and builtin.os != .freestanding) {
41 if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, _start, .Strong);
42 }
43 }
44}
45
46stdcallcc fn _DllMainCRTStartup(
47 hinstDLL: std.os.windows.HINSTANCE,
48 fdwReason: std.os.windows.DWORD,
49 lpReserved: std.os.windows.LPVOID,
50) std.os.windows.BOOL {
51 if (@hasDecl(root, "DllMain")) {
52 return root.DllMain(hinstDLL, fdwReason, lpReserved);
53 }
54
55 return std.os.windows.TRUE;
56}
57
58extern fn wasm_freestanding_start() void {
59 // This is marked inline because for some reason LLVM in release mode fails to inline it,
60 // and we want fewer call frames in stack traces.
61 _ = @call(.{ .modifier = .always_inline }, callMain, .{});
62}
63
64extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
65 const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'";
66 uefi.handle = handle;
67 uefi.system_table = system_table;
68
69 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
70 .NoReturn => {
71 root.main();
72 },
73 .Void => {
74 root.main();
75 return 0;
76 },
77 .Int => |info| {
78 if (info.bits != @typeInfo(usize).Int.bits) {
79 @compileError(bad_efi_main_ret);
80 }
81 return root.main();
82 },
83 else => @compileError(bad_efi_main_ret),
84 }
85}
86
87nakedcc fn _start() noreturn {
88 if (builtin.os == builtin.Os.wasi) {
89 // This is marked inline because for some reason LLVM in release mode fails to inline it,
90 // and we want fewer call frames in stack traces.
91 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
92 }
93
94 switch (builtin.arch) {
95 .x86_64 => {
96 starting_stack_ptr = asm (""
97 : [argc] "={rsp}" (-> [*]usize)
98 );
99 },
100 .i386 => {
101 starting_stack_ptr = asm (""
102 : [argc] "={esp}" (-> [*]usize)
103 );
104 },
105 .aarch64, .aarch64_be, .arm => {
106 starting_stack_ptr = asm ("mov %[argc], sp"
107 : [argc] "=r" (-> [*]usize)
108 );
109 },
110 .riscv64 => {
111 starting_stack_ptr = asm ("mv %[argc], sp"
112 : [argc] "=r" (-> [*]usize)
113 );
114 },
115 .mipsel => {
116 // Need noat here because LLVM is free to pick any register
117 starting_stack_ptr = asm (
118 \\ .set noat
119 \\ move %[argc], $sp
120 : [argc] "=r" (-> [*]usize)
121 );
122 },
123 else => @compileError("unsupported arch"),
124 }
125 // If LLVM inlines stack variables into _start, they will overwrite
126 // the command line argument data.
127 @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
128}
129
130stdcallcc fn WinMainCRTStartup() noreturn {
131 @setAlignStack(16);
132 if (!builtin.single_threaded) {
133 _ = @import("start_windows_tls.zig");
134 }
135
136 std.debug.maybeEnableSegfaultHandler();
137
138 std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain());
139}
140
141// TODO https://github.com/ziglang/zig/issues/265
142fn posixCallMainAndExit() noreturn {
143 if (builtin.os == builtin.Os.freebsd) {
144 @setAlignStack(16);
145 }
146 const argc = starting_stack_ptr[0];
147 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
148
149 const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
150 var envp_count: usize = 0;
151 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
152 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
153
154 if (builtin.os == .linux) {
155 // Find the beginning of the auxiliary vector
156 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
157 std.os.linux.elf_aux_maybe = auxv;
158 // Initialize the TLS area
159 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
160
161 if (std.os.linux.tls.tls_image) |tls_img| {
162 const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
163 const tp = std.os.linux.tls.copyTLS(tls_addr);
164 std.os.linux.tls.setThreadPointer(tp);
165 }
166
167 // TODO This is disabled because what should we do when linking libc and this code
168 // does not execute? And also it's causing a test failure in stack traces in release modes.
169
170 //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further
171 //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down
172 //// the stack and requires "probing". So here we allocate our own stack.
173 //const wanted_stack_size = gnu_stack_phdr.p_memsz;
174 //assert(wanted_stack_size % std.mem.page_size == 0);
175 //// Allocate an extra page as the guard page.
176 //const total_size = wanted_stack_size + std.mem.page_size;
177 //const new_stack = std.os.mmap(
178 // null,
179 // total_size,
180 // std.os.PROT_READ | std.os.PROT_WRITE,
181 // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS,
182 // -1,
183 // 0,
184 //) catch @panic("out of memory");
185 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
186 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
187 }
188
189 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
190}
191
192fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
193 std.os.argv = argv[0..argc];
194 std.os.environ = envp;
195
196 std.debug.maybeEnableSegfaultHandler();
197
198 return initEventLoopAndCallMain();
199}
200
201extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
202 var env_count: usize = 0;
203 while (c_envp[env_count] != null) : (env_count += 1) {}
204 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
205 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
206}
207
208// General error message for a malformed return type
209const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
210
211// This is marked inline because for some reason LLVM in release mode fails to inline it,
212// and we want fewer call frames in stack traces.
213inline fn initEventLoopAndCallMain() u8 {
214 if (std.event.Loop.instance) |loop| {
215 if (!@hasDecl(root, "event_loop")) {
216 loop.init() catch |err| {
217 std.debug.warn("error: {}\n", .{@errorName(err)});
218 if (@errorReturnTrace()) |trace| {
219 std.debug.dumpStackTrace(trace.*);
220 }
221 return 1;
222 };
223 defer loop.deinit();
224
225 var result: u8 = undefined;
226 var frame: @Frame(callMainAsync) = undefined;
227 _ = @asyncCall(&frame, &result, callMainAsync, loop);
228 loop.run();
229 return result;
230 }
231 }
232
233 // This is marked inline because for some reason LLVM in release mode fails to inline it,
234 // and we want fewer call frames in stack traces.
235 return @call(.{ .modifier = .always_inline }, callMain, .{});
236}
237
238async fn callMainAsync(loop: *std.event.Loop) u8 {
239 // This prevents the event loop from terminating at least until main() has returned.
240 loop.beginOneEvent();
241 defer loop.finishOneEvent();
242 return callMain();
243}
244
245// This is not marked inline because it is called with @asyncCall when
246// there is an event loop.
247pub fn callMain() u8 {
248 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
249 .NoReturn => {
250 root.main();
251 },
252 .Void => {
253 root.main();
254 return 0;
255 },
256 .Int => |info| {
257 if (info.bits != 8) {
258 @compileError(bad_main_ret);
259 }
260 return root.main();
261 },
262 .ErrorUnion => {
263 const result = root.main() catch |err| {
264 std.debug.warn("error: {}\n", .{@errorName(err)});
265 if (@errorReturnTrace()) |trace| {
266 std.debug.dumpStackTrace(trace.*);
267 }
268 return 1;
269 };
270 switch (@typeInfo(@TypeOf(result))) {
271 .Void => return 0,
272 .Int => |info| {
273 if (info.bits != 8) {
274 @compileError(bad_main_ret);
275 }
276 return result;
277 },
278 else => @compileError(bad_main_ret),
279 }
280 },
281 else => @compileError(bad_main_ret),
282 }
283}
lib/std/start_windows_tls.zig created+48
...@@ -0,0 +1,48 @@
1const std = @import("std");
2const builtin = std.builtin;
3
4export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
5export var _tls_start: u8 linksection(".tls") = 0;
6export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
7export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
8export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
9
10comptime {
11 if (builtin.arch == .i386) {
12 // The __tls_array is the offset of the ThreadLocalStoragePointer field
13 // in the TEB block whose base address held in the %fs segment.
14 asm (
15 \\ .global __tls_array
16 \\ __tls_array = 0x2C
17 );
18 }
19}
20
21// TODO this is how I would like it to be expressed
22// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
23// why they do that.
24//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY {
25// .StartAddressOfRawData = @ptrToInt(&_tls_start),
26// .EndAddressOfRawData = @ptrToInt(&_tls_end),
27// .AddressOfIndex = @ptrToInt(&_tls_index),
28// .AddressOfCallBacks = @ptrToInt(__xl_a),
29// .SizeOfZeroFill = 0,
30// .Characteristics = 0,
31//};
32// This is the workaround because we can't do @ptrToInt at comptime like that.
33pub const IMAGE_TLS_DIRECTORY = extern struct {
34 StartAddressOfRawData: *c_void,
35 EndAddressOfRawData: *c_void,
36 AddressOfIndex: *c_void,
37 AddressOfCallBacks: *c_void,
38 SizeOfZeroFill: u32,
39 Characteristics: u32,
40};
41export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
42 .StartAddressOfRawData = &_tls_start,
43 .EndAddressOfRawData = &_tls_end,
44 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,
46 .SizeOfZeroFill = 0,
47 .Characteristics = 0,
48};
lib/std/std.zig+7-1
...@@ -65,7 +65,13 @@ pub const time = @import("time.zig");...@@ -65,7 +65,13 @@ pub const time = @import("time.zig");
65pub const unicode = @import("unicode.zig");65pub const unicode = @import("unicode.zig");
66pub const valgrind = @import("valgrind.zig");66pub const valgrind = @import("valgrind.zig");
67pub const zig = @import("zig.zig");67pub const zig = @import("zig.zig");
68pub const special = @import("special.zig");68pub const start = @import("start.zig");
69
70// This forces the start.zig file to be imported, and the comptime logic inside that
71// file decides whether to export any appropriate start symbols.
72comptime {
73 _ = start;
74}
6975
70test "" {76test "" {
71 meta.refAllDecls(@This());77 meta.refAllDecls(@This());
src/all_types.hpp+2-2
...@@ -2003,10 +2003,11 @@ struct CodeGen {...@@ -2003,10 +2003,11 @@ struct CodeGen {
2003 ZigPackage *std_package;2003 ZigPackage *std_package;
2004 ZigPackage *test_runner_package;2004 ZigPackage *test_runner_package;
2005 ZigPackage *compile_var_package;2005 ZigPackage *compile_var_package;
2006 ZigPackage *root_pkg; // @import("root")
2007 ZigPackage *main_pkg; // usually same as root_pkg, except for `zig test`
2006 ZigType *compile_var_import;2008 ZigType *compile_var_import;
2007 ZigType *root_import;2009 ZigType *root_import;
2008 ZigType *start_import;2010 ZigType *start_import;
2009 ZigType *test_runner_import;
20102011
2011 struct {2012 struct {
2012 ZigType *entry_bool;2013 ZigType *entry_bool;
...@@ -2179,7 +2180,6 @@ struct CodeGen {...@@ -2179,7 +2180,6 @@ struct CodeGen {
2179 Buf *root_out_name;2180 Buf *root_out_name;
2180 Buf *test_filter;2181 Buf *test_filter;
2181 Buf *test_name_prefix;2182 Buf *test_name_prefix;
2182 ZigPackage *root_package;
2183 Buf *zig_lib_dir;2183 Buf *zig_lib_dir;
2184 Buf *zig_std_dir;2184 Buf *zig_std_dir;
2185 Buf *dynamic_linker_path;2185 Buf *dynamic_linker_path;
src/analyze.cpp+41-2
...@@ -3536,7 +3536,7 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope...@@ -3536,7 +3536,7 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope
3536 return;3536 return;
35373537
3538 ZigType *import = get_scope_import(&decls_scope->base);3538 ZigType *import = get_scope_import(&decls_scope->base);
3539 if (import->data.structure.root_struct->package != g->root_package)3539 if (import->data.structure.root_struct->package != g->main_pkg)
3540 return;3540 return;
35413541
3542 Buf *decl_name_buf = node->data.test_decl.name;3542 Buf *decl_name_buf = node->data.test_decl.name;
...@@ -3577,7 +3577,7 @@ void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) {...@@ -3577,7 +3577,7 @@ void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) {
3577 resolve_top_level_decl(g, tld, tld->source_node, false);3577 resolve_top_level_decl(g, tld, tld->source_node, false);
3578 assert(tld->id == TldIdVar);3578 assert(tld->id == TldIdVar);
3579 TldVar *tld_var = (TldVar *)tld;3579 TldVar *tld_var = (TldVar *)tld;
3580 tld_var->var->const_value = value;3580 copy_const_val(tld_var->var->const_value, value);
3581 tld_var->var->var_type = value->type;3581 tld_var->var->var_type = value->type;
3582 tld_var->var->align_bytes = get_abi_alignment(g, value->type);3582 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
3583}3583}
...@@ -9178,3 +9178,42 @@ bool is_anon_container(ZigType *ty) {...@@ -9178,3 +9178,42 @@ bool is_anon_container(ZigType *ty) {
9178 ty->data.structure.special == StructSpecialInferredTuple ||9178 ty->data.structure.special == StructSpecialInferredTuple ||
9179 ty->data.structure.special == StructSpecialInferredStruct);9179 ty->data.structure.special == StructSpecialInferredStruct);
9180}9180}
9181
9182bool is_opt_err_set(ZigType *ty) {
9183 return ty->id == ZigTypeIdErrorSet ||
9184 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
9185}
9186
9187// Returns whether the x_optional field of ZigValue is active.
9188bool type_has_optional_repr(ZigType *ty) {
9189 if (ty->id != ZigTypeIdOptional) {
9190 return false;
9191 } else if (get_codegen_ptr_type(ty) != nullptr) {
9192 return false;
9193 } else if (is_opt_err_set(ty)) {
9194 return false;
9195 } else {
9196 return true;
9197 }
9198}
9199
9200void copy_const_val(ZigValue *dest, ZigValue *src) {
9201 memcpy(dest, src, sizeof(ZigValue));
9202 if (src->special != ConstValSpecialStatic)
9203 return;
9204 dest->parent.id = ConstParentIdNone;
9205 if (dest->type->id == ZigTypeIdStruct) {
9206 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
9207 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
9208 copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
9209 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
9210 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
9211 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
9212 }
9213 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
9214 dest->data.x_optional = create_const_vals(1);
9215 copy_const_val(dest->data.x_optional, src->data.x_optional);
9216 dest->data.x_optional->parent.id = ConstParentIdOptionalPayload;
9217 dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest;
9218 }
9219}
src/analyze.hpp+3
...@@ -276,4 +276,7 @@ Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_targe...@@ -276,4 +276,7 @@ Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_targe
276 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);276 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
277ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);277ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
278bool is_anon_container(ZigType *ty);278bool is_anon_container(ZigType *ty);
279void copy_const_val(ZigValue *dest, ZigValue *src);
280bool type_has_optional_repr(ZigType *ty);
281bool is_opt_err_set(ZigType *ty);
279#endif282#endif
src/codegen.cpp+22-61
...@@ -8440,11 +8440,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -8440,11 +8440,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
84408440
8441 if (g->is_test_build) {8441 if (g->is_test_build) {
8442 buf_appendf(contents,8442 buf_appendf(contents,
8443 "const TestFn = struct {\n"8443 "pub var test_functions: []TestFn = undefined; // overwritten later\n"
8444 "name: []const u8,\n"
8445 "func: fn()anyerror!void,\n"
8446 "};\n"
8447 "pub const test_functions = {}; // overwritten later\n"
8448 );8444 );
8449 }8445 }
84508446
...@@ -8535,23 +8531,23 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -8535,23 +8531,23 @@ static Error define_builtin_compile_vars(CodeGen *g) {
8535 }8531 }
8536 }8532 }
85378533
8538 assert(g->root_package);8534 assert(g->main_pkg);
8539 assert(g->std_package);8535 assert(g->std_package);
8540 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename, "builtin");8536 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename, "builtin");
8541 g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package);
8542 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8543 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8544 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
8545 ZigPackage *root_pkg;
8546 if (g->is_test_build) {8537 if (g->is_test_build) {
8547 if (g->test_runner_package == nullptr) {8538 if (g->test_runner_package == nullptr) {
8548 g->test_runner_package = create_test_runner_pkg(g);8539 g->test_runner_package = create_test_runner_pkg(g);
8549 }8540 }
8550 root_pkg = g->test_runner_package;8541 g->root_pkg = g->test_runner_package;
8551 } else {8542 } else {
8552 root_pkg = g->root_package;8543 g->root_pkg = g->main_pkg;
8553 }8544 }
8554 g->std_package->package_table.put(buf_create_from_str("root"), root_pkg);8545 g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package);
8546 g->main_pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8547 g->main_pkg->package_table.put(buf_create_from_str("root"), g->root_pkg);
8548 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8549 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
8550 g->std_package->package_table.put(buf_create_from_str("root"), g->root_pkg);
8555 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,8551 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
8556 SourceKindPkgMain);8552 SourceKindPkgMain);
85578553
...@@ -8670,7 +8666,7 @@ static void init(CodeGen *g) {...@@ -8670,7 +8666,7 @@ static void init(CodeGen *g) {
8670 // no longer reference DW_AT_comp_dir, for the purpose of being able to support the8666 // no longer reference DW_AT_comp_dir, for the purpose of being able to support the
8671 // common practice of stripping all but the line number sections from an executable.8667 // common practice of stripping all but the line number sections from an executable.
8672 const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." :8668 const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." :
8673 buf_ptr(&g->root_package->root_src_dir);8669 buf_ptr(&g->main_pkg->root_src_dir);
86748670
8675 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),8671 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),
8676 compile_unit_dir);8672 compile_unit_dir);
...@@ -9083,30 +9079,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us...@@ -9083,30 +9079,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
9083 }9079 }
9084}9080}
90859081
9086static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {9082static void update_test_functions_builtin_decl(CodeGen *g) {
9087 Buf *code_basename = buf_create_from_str(basename);
9088 Buf path_to_code_src = BUF_INIT;
9089 os_path_join(g->zig_std_special_dir, code_basename, &path_to_code_src);
9090
9091 Buf *resolve_paths[] = {&path_to_code_src};
9092 Buf *resolved_path = buf_alloc();
9093 *resolved_path = os_path_resolve(resolve_paths, 1);
9094 Buf *import_code = buf_alloc();
9095 Error err;
9096 if ((err = file_fetch(g, resolved_path, import_code))) {
9097 zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
9098 }
9099
9100 return add_source_file(g, package, resolved_path, import_code, SourceKindPkgMain);
9101}
9102
9103static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
9104 ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "start.zig", "std.special");
9105 package->package_table.put(buf_create_from_str("root"), pkg_with_main);
9106 return package;
9107}
9108
9109static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
9110 Error err;9083 Error err;
91119084
9112 assert(g->is_test_build);9085 assert(g->is_test_build);
...@@ -9166,16 +9139,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -9166,16 +9139,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
91669139
9167 update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice);9140 update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice);
9168 assert(g->test_runner_package != nullptr);9141 assert(g->test_runner_package != nullptr);
9169 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");
9170}9142}
91719143
9172static Buf *get_resolved_root_src_path(CodeGen *g) {9144static Buf *get_resolved_root_src_path(CodeGen *g) {
9173 // TODO memoize9145 // TODO memoize
9174 if (buf_len(&g->root_package->root_src_path) == 0)9146 if (buf_len(&g->main_pkg->root_src_path) == 0)
9175 return nullptr;9147 return nullptr;
91769148
9177 Buf rel_full_path = BUF_INIT;9149 Buf rel_full_path = BUF_INIT;
9178 os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, &rel_full_path);9150 os_path_join(&g->main_pkg->root_src_dir, &g->main_pkg->root_src_path, &rel_full_path);
91799151
9180 Buf *resolved_path = buf_alloc();9152 Buf *resolved_path = buf_alloc();
9181 Buf *resolve_paths[] = {&rel_full_path};9153 Buf *resolve_paths[] = {&rel_full_path};
...@@ -9198,7 +9170,7 @@ static void gen_root_source(CodeGen *g) {...@@ -9198,7 +9170,7 @@ static void gen_root_source(CodeGen *g) {
9198 exit(1);9170 exit(1);
9199 }9171 }
92009172
9201 ZigType *root_import_alias = add_source_file(g, g->root_package, resolved_path, source_code, SourceKindRoot);9173 ZigType *root_import_alias = add_source_file(g, g->main_pkg, resolved_path, source_code, SourceKindRoot);
9202 assert(root_import_alias == g->root_import);9174 assert(root_import_alias == g->root_import);
92039175
9204 assert(g->root_out_name);9176 assert(g->root_out_name);
...@@ -9250,16 +9222,8 @@ static void gen_root_source(CodeGen *g) {...@@ -9250,16 +9222,8 @@ static void gen_root_source(CodeGen *g) {
9250 }9222 }
9251 report_errors_and_maybe_exit(g);9223 report_errors_and_maybe_exit(g);
92529224
9253 if (!g->is_test_build) {
9254 g->start_import = add_special_code(g, create_start_pkg(g, g->root_package), "start.zig");
9255 }
9256 if (!g->error_during_imports) {
9257 semantic_analyze(g);
9258 }
9259 if (g->is_test_build) {9225 if (g->is_test_build) {
9260 create_test_compile_var_and_add_test_runner(g);9226 update_test_functions_builtin_decl(g);
9261 g->start_import = add_special_code(g, create_start_pkg(g, g->test_runner_package), "start.zig");
9262
9263 if (!g->error_during_imports) {9227 if (!g->error_during_imports) {
9264 semantic_analyze(g);9228 semantic_analyze(g);
9265 }9229 }
...@@ -10058,7 +10022,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10058,7 +10022,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10058 CacheHash *ch = &g->cache_hash;10022 CacheHash *ch = &g->cache_hash;
10059 cache_init(ch, manifest_dir);10023 cache_init(ch, manifest_dir);
1006010024
10061 add_cache_pkg(g, ch, g->root_package);10025 add_cache_pkg(g, ch, g->main_pkg);
10062 if (g->linker_script != nullptr) {10026 if (g->linker_script != nullptr) {
10063 cache_file(ch, buf_create_from_str(g->linker_script));10027 cache_file(ch, buf_create_from_str(g->linker_script));
10064 }10028 }
...@@ -10141,7 +10105,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10141,7 +10105,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10141}10105}
1014210106
10143static bool need_llvm_module(CodeGen *g) {10107static bool need_llvm_module(CodeGen *g) {
10144 return buf_len(&g->root_package->root_src_path) != 0;10108 return buf_len(&g->main_pkg->root_src_path) != 0;
10145}10109}
1014610110
10147static void resolve_out_paths(CodeGen *g) {10111static void resolve_out_paths(CodeGen *g) {
...@@ -10388,8 +10352,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c...@@ -10388,8 +10352,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
10388 assert(g->compile_var_package != nullptr);10352 assert(g->compile_var_package != nullptr);
10389 pkg->package_table.put(buf_create_from_str("std"), g->std_package);10353 pkg->package_table.put(buf_create_from_str("std"), g->std_package);
1039010354
10391 ZigPackage *main_pkg = g->is_test_build ? g->test_runner_package : g->root_package;10355 pkg->package_table.put(buf_create_from_str("root"), g->root_pkg);
10392 pkg->package_table.put(buf_create_from_str("root"), main_pkg);
1039310356
10394 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);10357 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
10395 }10358 }
...@@ -10516,15 +10479,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget...@@ -10516,15 +10479,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
10516 buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1);10479 buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1);
10517 }10480 }
1051810481
10519 g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), "");10482 g->main_pkg = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), "");
10520 g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std");10483 g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std");
10521 g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);10484 g->main_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
10522 } else {10485 } else {
10523 g->root_package = new_package(".", "", "");10486 g->main_pkg = new_package(".", "", "");
10524 }10487 }
1052510488
10526 g->root_package->package_table.put(buf_create_from_str("root"), g->root_package);
10527
10528 g->zig_std_special_dir = buf_alloc();10489 g->zig_std_special_dir = buf_alloc();
10529 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);10490 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
1053010491
src/dump_analysis.cpp+1-1
...@@ -1216,7 +1216,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const...@@ -1216,7 +1216,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
1216 jw_end_object(jw);1216 jw_end_object(jw);
12171217
1218 jw_object_field(jw, "rootPkg");1218 jw_object_field(jw, "rootPkg");
1219 anal_dump_pkg_ref(&ctx, g->root_package);1219 anal_dump_pkg_ref(&ctx, g->main_pkg);
12201220
1221 // Poke the functions1221 // Poke the functions
1222 for (size_t i = 0; i < g->fn_defs.length; i += 1) {1222 for (size_t i = 0; i < g->fn_defs.length; i += 1) {
src/ir.cpp-40
...@@ -232,7 +232,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -232,7 +232,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
232static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,232static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
233 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);233 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
234static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);234static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
235static void copy_const_val(ZigValue *dest, ZigValue *src);
236static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);235static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
237static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,236static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
238 ZigType *ptr_type);237 ZigType *ptr_type);
...@@ -718,11 +717,6 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {...@@ -718,11 +717,6 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
718 return result;717 return result;
719}718}
720719
721static bool is_opt_err_set(ZigType *ty) {
722 return ty->id == ZigTypeIdErrorSet ||
723 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
724}
725
726static bool is_tuple(ZigType *type) {720static bool is_tuple(ZigType *type) {
727 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple;721 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple;
728}722}
...@@ -11451,40 +11445,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -11451,40 +11445,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
11451 }11445 }
11452}11446}
1145311447
11454// Returns whether the x_optional field of ZigValue is active.
11455static bool type_has_optional_repr(ZigType *ty) {
11456 if (ty->id != ZigTypeIdOptional) {
11457 return false;
11458 } else if (get_codegen_ptr_type(ty) != nullptr) {
11459 return false;
11460 } else if (is_opt_err_set(ty)) {
11461 return false;
11462 } else {
11463 return true;
11464 }
11465}
11466
11467static void copy_const_val(ZigValue *dest, ZigValue *src) {
11468 memcpy(dest, src, sizeof(ZigValue));
11469 if (src->special != ConstValSpecialStatic)
11470 return;
11471 dest->parent.id = ConstParentIdNone;
11472 if (dest->type->id == ZigTypeIdStruct) {
11473 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
11474 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
11475 copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
11476 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
11477 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
11478 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
11479 }
11480 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
11481 dest->data.x_optional = create_const_vals(1);
11482 copy_const_val(dest->data.x_optional, src->data.x_optional);
11483 dest->data.x_optional->parent.id = ConstParentIdOptionalPayload;
11484 dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest;
11485 }
11486}
11487
11488static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,11448static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,
11489 CastOp cast_op,11449 CastOp cast_op,
11490 ZigValue *other_val, ZigType *other_type,11450 ZigValue *other_val, ZigType *other_type,
src/main.cpp+2-2
...@@ -623,7 +623,7 @@ int main(int argc, char **argv) {...@@ -623,7 +623,7 @@ int main(int argc, char **argv) {
623623
624 ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),624 ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
625 buf_ptr(&build_file_basename), "std.special");625 buf_ptr(&build_file_basename), "std.special");
626 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);626 g->main_pkg->package_table.put(buf_create_from_str("@build"), build_pkg);
627 g->enable_cache = get_cache_opt(enable_cache, true);627 g->enable_cache = get_cache_opt(enable_cache, true);
628 codegen_build_and_link(g);628 codegen_build_and_link(g);
629 if (root_progress_node != nullptr) {629 if (root_progress_node != nullptr) {
...@@ -1269,7 +1269,7 @@ int main(int argc, char **argv) {...@@ -1269,7 +1269,7 @@ int main(int argc, char **argv) {
1269 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));1269 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
1270 }1270 }
12711271
1272 add_package(g, cur_pkg, g->root_package);1272 add_package(g, cur_pkg, g->main_pkg);
12731273
1274 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {1274 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
1275 g->c_source_files = c_source_files;1275 g->c_source_files = c_source_files;