authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-12 18:56:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-12 18:56:39-05:00
log7699b5b997c7a024a6d9558df0ec72d71ef402fe
treeea996d6252efe24158a802fb50c1a28c3b3d6717
parent81f1f72197113a45e827d5c984e219a28aa28083
parentfff3c1fff4c3ebfcb2bd4f08a43ae7815b5c446b
signature Commit is signed but in an unrecognized format.

Merge branch 'Xe-expose-callMain'

closes #3891

16 files changed, 437 insertions(+), 453 deletions(-)

lib/std/builtin.zig+11
......@@ -412,6 +412,13 @@ pub const CallOptions = struct {
412412 };
413413};
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
415422/// This function type is used by the Zig language code generation and
416423/// therefore must be kept in sync with the compiler implementation.
417424pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;
......@@ -424,6 +431,10 @@ pub const panic: PanicFn = if (@hasDecl(root, "panic")) root.panic else default_
424431/// therefore must be kept in sync with the compiler implementation.
425432pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn {
426433 @setCold(true);
434 if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) {
435 root.os.panic(msg, error_return_trace);
436 unreachable;
437 }
427438 switch (os) {
428439 .freestanding => {
429440 while (true) {
lib/std/os.zig+12-8
......@@ -187,19 +187,23 @@ pub fn abort() noreturn {
187187 }
188188 windows.kernel32.ExitProcess(3);
189189 }
190 if (builtin.link_libc) {
191 system.abort();
190 if (!builtin.link_libc and builtin.os == .linux) {
191 raise(SIGABRT) catch {};
192
193 // TODO the rest of the implementation of abort() from musl libc here
194
195 raise(SIGKILL) catch {};
196 exit(127);
192197 }
193198 if (builtin.os == .uefi) {
194199 exit(0); // TODO choose appropriate exit code
195200 }
201 if (builtin.os == .wasi) {
202 @breakpoint();
203 exit(1);
204 }
196205
197 raise(SIGABRT) catch {};
198
199 // TODO the rest of the implementation of abort() from musl libc here
200
201 raise(SIGKILL) catch {};
202 exit(127);
206 system.abort();
203207}
204208
205209pub const RaiseError = UnexpectedError;
lib/std/special/c.zig+1-1
......@@ -83,7 +83,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
8383 @setCold(true);
8484 std.debug.panic("{}", msg);
8585 }
86 if (builtin.os != .freestanding) {
86 if (builtin.os != .freestanding and builtin.os != .other) {
8787 std.os.abort();
8888 }
8989 while (true) {}
lib/std/special/start.zig deleted-286
......@@ -1,286 +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};
20
21comptime {
22 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
23 if (builtin.os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {
24 @export("_DllMainCRTStartup", _DllMainCRTStartup, .Strong);
25 }
26 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
27 if (builtin.link_libc and @hasDecl(root, "main")) {
28 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
29 @export("main", main, .Weak);
30 }
31 } else if (builtin.os == .windows) {
32 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) {
33 @export("WinMainCRTStartup", WinMainCRTStartup, .Strong);
34 }
35 } else if (builtin.os == .uefi) {
36 if (!@hasDecl(root, "EfiMain")) @export("EfiMain", EfiMain, .Strong);
37 } else if (builtin.os != .freestanding) {
38 if (is_mips) {
39 if (!@hasDecl(root, "__start")) @export("__start", _start, .Strong);
40 } else {
41 if (!@hasDecl(root, "_start")) @export("_start", _start, .Strong);
42 }
43 } else if (is_wasm) {
44 if (!@hasDecl(root, "_start")) @export("_start", wasm_freestanding_start, .Strong);
45 }
46 }
47}
48
49stdcallcc fn _DllMainCRTStartup(
50 hinstDLL: std.os.windows.HINSTANCE,
51 fdwReason: std.os.windows.DWORD,
52 lpReserved: std.os.windows.LPVOID,
53) std.os.windows.BOOL {
54 if (@hasDecl(root, "DllMain")) {
55 return root.DllMain(hinstDLL, fdwReason, lpReserved);
56 }
57
58 return std.os.windows.TRUE;
59}
60
61extern fn wasm_freestanding_start() void {
62 // This is marked inline because for some reason LLVM in release mode fails to inline it,
63 // and we want fewer call frames in stack traces.
64 _ = @call(.{ .modifier = .always_inline }, callMain, .{});
65}
66
67extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
68 const bad_efi_main_ret = "expected return type of main to be 'void', 'noreturn', or 'usize'";
69 uefi.handle = handle;
70 uefi.system_table = system_table;
71
72 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
73 .NoReturn => {
74 root.main();
75 },
76 .Void => {
77 root.main();
78 return 0;
79 },
80 .Int => |info| {
81 if (info.bits != @typeInfo(usize).Int.bits) {
82 @compileError(bad_efi_main_ret);
83 }
84 return root.main();
85 },
86 else => @compileError(bad_efi_main_ret),
87 }
88}
89
90nakedcc fn _start() noreturn {
91 if (builtin.os == builtin.Os.wasi) {
92 // This is marked inline because for some reason LLVM in release mode fails to inline it,
93 // and we want fewer call frames in stack traces.
94 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
95 }
96
97 switch (builtin.arch) {
98 .x86_64 => {
99 starting_stack_ptr = asm (""
100 : [argc] "={rsp}" (-> [*]usize)
101 );
102 },
103 .i386 => {
104 starting_stack_ptr = asm (""
105 : [argc] "={esp}" (-> [*]usize)
106 );
107 },
108 .aarch64, .aarch64_be, .arm => {
109 starting_stack_ptr = asm ("mov %[argc], sp"
110 : [argc] "=r" (-> [*]usize)
111 );
112 },
113 .riscv64 => {
114 starting_stack_ptr = asm ("mv %[argc], sp"
115 : [argc] "=r" (-> [*]usize)
116 );
117 },
118 .mipsel => {
119 // Need noat here because LLVM is free to pick any register
120 starting_stack_ptr = asm (
121 \\ .set noat
122 \\ move %[argc], $sp
123 : [argc] "=r" (-> [*]usize)
124 );
125 },
126 else => @compileError("unsupported arch"),
127 }
128 // If LLVM inlines stack variables into _start, they will overwrite
129 // the command line argument data.
130 @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
131}
132
133stdcallcc fn WinMainCRTStartup() noreturn {
134 @setAlignStack(16);
135 if (!builtin.single_threaded) {
136 _ = @import("start_windows_tls.zig");
137 }
138
139 std.debug.maybeEnableSegfaultHandler();
140
141 std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain());
142}
143
144// TODO https://github.com/ziglang/zig/issues/265
145fn posixCallMainAndExit() noreturn {
146 if (builtin.os == builtin.Os.freebsd) {
147 @setAlignStack(16);
148 }
149 const argc = starting_stack_ptr[0];
150 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
151
152 const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
153 var envp_count: usize = 0;
154 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
155 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
156
157 if (builtin.os == .linux) {
158 // Find the beginning of the auxiliary vector
159 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
160 std.os.linux.elf_aux_maybe = auxv;
161 // Initialize the TLS area
162 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
163
164 if (std.os.linux.tls.tls_image) |tls_img| {
165 const tls_addr = std.os.linux.tls.allocateTLS(tls_img.alloc_size);
166 const tp = std.os.linux.tls.copyTLS(tls_addr);
167 std.os.linux.tls.setThreadPointer(tp);
168 }
169
170 // TODO This is disabled because what should we do when linking libc and this code
171 // does not execute? And also it's causing a test failure in stack traces in release modes.
172
173 //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further
174 //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down
175 //// the stack and requires "probing". So here we allocate our own stack.
176 //const wanted_stack_size = gnu_stack_phdr.p_memsz;
177 //assert(wanted_stack_size % std.mem.page_size == 0);
178 //// Allocate an extra page as the guard page.
179 //const total_size = wanted_stack_size + std.mem.page_size;
180 //const new_stack = std.os.mmap(
181 // null,
182 // total_size,
183 // std.os.PROT_READ | std.os.PROT_WRITE,
184 // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS,
185 // -1,
186 // 0,
187 //) catch @panic("out of memory");
188 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
189 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
190 }
191
192 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
193}
194
195fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
196 std.os.argv = argv[0..argc];
197 std.os.environ = envp;
198
199 std.debug.maybeEnableSegfaultHandler();
200
201 return initEventLoopAndCallMain();
202}
203
204extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
205 var env_count: usize = 0;
206 while (c_envp[env_count] != null) : (env_count += 1) {}
207 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
208 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
209}
210
211// General error message for a malformed return type
212const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
213
214// This is marked inline because for some reason LLVM in release mode fails to inline it,
215// and we want fewer call frames in stack traces.
216inline fn initEventLoopAndCallMain() u8 {
217 if (std.event.Loop.instance) |loop| {
218 if (!@hasDecl(root, "event_loop")) {
219 loop.init() catch |err| {
220 std.debug.warn("error: {}\n", .{@errorName(err)});
221 if (@errorReturnTrace()) |trace| {
222 std.debug.dumpStackTrace(trace.*);
223 }
224 return 1;
225 };
226 defer loop.deinit();
227
228 var result: u8 = undefined;
229 var frame: @Frame(callMainAsync) = undefined;
230 _ = @asyncCall(&frame, &result, callMainAsync, loop);
231 loop.run();
232 return result;
233 }
234 }
235
236 // This is marked inline because for some reason LLVM in release mode fails to inline it,
237 // and we want fewer call frames in stack traces.
238 return @call(.{ .modifier = .always_inline }, callMain, .{});
239}
240
241async fn callMainAsync(loop: *std.event.Loop) u8 {
242 // This prevents the event loop from terminating at least until main() has returned.
243 loop.beginOneEvent();
244 defer loop.finishOneEvent();
245 return callMain();
246}
247
248// This is not marked inline because it is called with @asyncCall when
249// there is an event loop.
250fn callMain() u8 {
251 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {
252 .NoReturn => {
253 root.main();
254 },
255 .Void => {
256 root.main();
257 return 0;
258 },
259 .Int => |info| {
260 if (info.bits != 8) {
261 @compileError(bad_main_ret);
262 }
263 return root.main();
264 },
265 .ErrorUnion => {
266 const result = root.main() catch |err| {
267 std.debug.warn("error: {}\n", .{@errorName(err)});
268 if (@errorReturnTrace()) |trace| {
269 std.debug.dumpStackTrace(trace.*);
270 }
271 return 1;
272 };
273 switch (@typeInfo(@TypeOf(result))) {
274 .Void => return 0,
275 .Int => |info| {
276 if (info.bits != 8) {
277 @compileError(bad_main_ret);
278 }
279 return result;
280 },
281 else => @compileError(bad_main_ret),
282 }
283 },
284 else => @compileError(bad_main_ret),
285 }
286}
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 @@
11const std = @import("std");
22const io = std.io;
33const builtin = @import("builtin");
4const test_fn_list = builtin.test_functions;
54
65pub fn main() anyerror!void {
6 const test_fn_list = builtin.test_functions;
77 var ok_count: usize = 0;
88 var skip_count: usize = 0;
99 var progress = std.Progress{};
......@@ -16,7 +16,9 @@ pub fn main() anyerror!void {
1616 var test_node = root_node.start(test_fn.name, null);
1717 test_node.activate();
1818 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 }
2022 if (test_fn.func()) |_| {
2123 ok_count += 1;
2224 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
......@@ -65,6 +65,13 @@ pub const time = @import("time.zig");
6565pub const unicode = @import("unicode.zig");
6666pub const valgrind = @import("valgrind.zig");
6767pub const zig = @import("zig.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}
6875
6976test "" {
7077 meta.refAllDecls(@This());
src/all_types.hpp+2-2
......@@ -2003,10 +2003,11 @@ struct CodeGen {
20032003 ZigPackage *std_package;
20042004 ZigPackage *test_runner_package;
20052005 ZigPackage *compile_var_package;
2006 ZigPackage *root_pkg; // @import("root")
2007 ZigPackage *main_pkg; // usually same as root_pkg, except for `zig test`
20062008 ZigType *compile_var_import;
20072009 ZigType *root_import;
20082010 ZigType *start_import;
2009 ZigType *test_runner_import;
20102011
20112012 struct {
20122013 ZigType *entry_bool;
......@@ -2179,7 +2180,6 @@ struct CodeGen {
21792180 Buf *root_out_name;
21802181 Buf *test_filter;
21812182 Buf *test_name_prefix;
2182 ZigPackage *root_package;
21832183 Buf *zig_lib_dir;
21842184 Buf *zig_std_dir;
21852185 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
35363536 return;
35373537
35383538 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)
35403540 return;
35413541
35423542 Buf *decl_name_buf = node->data.test_decl.name;
......@@ -3577,7 +3577,7 @@ void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) {
35773577 resolve_top_level_decl(g, tld, tld->source_node, false);
35783578 assert(tld->id == TldIdVar);
35793579 TldVar *tld_var = (TldVar *)tld;
3580 tld_var->var->const_value = value;
3580 copy_const_val(tld_var->var->const_value, value);
35813581 tld_var->var->var_type = value->type;
35823582 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
35833583}
......@@ -9178,3 +9178,42 @@ bool is_anon_container(ZigType *ty) {
91789178 ty->data.structure.special == StructSpecialInferredTuple ||
91799179 ty->data.structure.special == StructSpecialInferredStruct);
91809180}
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
276276 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
277277ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
278278bool 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);
279282#endif
src/codegen.cpp+22-61
......@@ -8440,11 +8440,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
84408440
84418441 if (g->is_test_build) {
84428442 buf_appendf(contents,
8443 "const TestFn = struct {\n"
8444 "name: []const u8,\n"
8445 "func: fn()anyerror!void,\n"
8446 "};\n"
8447 "pub const test_functions = {}; // overwritten later\n"
8443 "pub var test_functions: []TestFn = undefined; // overwritten later\n"
84488444 );
84498445 }
84508446
......@@ -8535,23 +8531,23 @@ static Error define_builtin_compile_vars(CodeGen *g) {
85358531 }
85368532 }
85378533
8538 assert(g->root_package);
8534 assert(g->main_pkg);
85398535 assert(g->std_package);
85408536 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;
85468537 if (g->is_test_build) {
85478538 if (g->test_runner_package == nullptr) {
85488539 g->test_runner_package = create_test_runner_pkg(g);
85498540 }
8550 root_pkg = g->test_runner_package;
8541 g->root_pkg = g->test_runner_package;
85518542 } else {
8552 root_pkg = g->root_package;
8543 g->root_pkg = g->main_pkg;
85538544 }
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);
85558551 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
85568552 SourceKindPkgMain);
85578553
......@@ -8670,7 +8666,7 @@ static void init(CodeGen *g) {
86708666 // no longer reference DW_AT_comp_dir, for the purpose of being able to support the
86718667 // common practice of stripping all but the line number sections from an executable.
86728668 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
86758671 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),
86768672 compile_unit_dir);
......@@ -9083,30 +9079,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
90839079 }
90849080}
90859081
9086static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {
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) {
9082static void update_test_functions_builtin_decl(CodeGen *g) {
91109083 Error err;
91119084
91129085 assert(g->is_test_build);
......@@ -9166,16 +9139,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
91669139
91679140 update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice);
91689141 assert(g->test_runner_package != nullptr);
9169 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");
91709142}
91719143
91729144static Buf *get_resolved_root_src_path(CodeGen *g) {
91739145 // TODO memoize
9174 if (buf_len(&g->root_package->root_src_path) == 0)
9146 if (buf_len(&g->main_pkg->root_src_path) == 0)
91759147 return nullptr;
91769148
91779149 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
91809152 Buf *resolved_path = buf_alloc();
91819153 Buf *resolve_paths[] = {&rel_full_path};
......@@ -9198,7 +9170,7 @@ static void gen_root_source(CodeGen *g) {
91989170 exit(1);
91999171 }
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);
92029174 assert(root_import_alias == g->root_import);
92039175
92049176 assert(g->root_out_name);
......@@ -9250,16 +9222,8 @@ static void gen_root_source(CodeGen *g) {
92509222 }
92519223 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 }
92599225 if (g->is_test_build) {
9260 create_test_compile_var_and_add_test_runner(g);
9261 g->start_import = add_special_code(g, create_start_pkg(g, g->test_runner_package), "start.zig");
9262
9226 update_test_functions_builtin_decl(g);
92639227 if (!g->error_during_imports) {
92649228 semantic_analyze(g);
92659229 }
......@@ -10058,7 +10022,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1005810022 CacheHash *ch = &g->cache_hash;
1005910023 cache_init(ch, manifest_dir);
1006010024
10061 add_cache_pkg(g, ch, g->root_package);
10025 add_cache_pkg(g, ch, g->main_pkg);
1006210026 if (g->linker_script != nullptr) {
1006310027 cache_file(ch, buf_create_from_str(g->linker_script));
1006410028 }
......@@ -10141,7 +10105,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1014110105}
1014210106
1014310107static 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;
1014510109}
1014610110
1014710111static void resolve_out_paths(CodeGen *g) {
......@@ -10388,8 +10352,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
1038810352 assert(g->compile_var_package != nullptr);
1038910353 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;
10392 pkg->package_table.put(buf_create_from_str("root"), main_pkg);
10355 pkg->package_table.put(buf_create_from_str("root"), g->root_pkg);
1039310356
1039410357 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
1039510358 }
......@@ -10516,15 +10479,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
1051610479 buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1);
1051710480 }
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), "");
1052010483 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);
1052210485 } else {
10523 g->root_package = new_package(".", "", "");
10486 g->main_pkg = new_package(".", "", "");
1052410487 }
1052510488
10526 g->root_package->package_table.put(buf_create_from_str("root"), g->root_package);
10527
1052810489 g->zig_std_special_dir = buf_alloc();
1052910490 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
12161216 jw_end_object(jw);
12171217
12181218 jw_object_field(jw, "rootPkg");
1219 anal_dump_pkg_ref(&ctx, g->root_package);
1219 anal_dump_pkg_ref(&ctx, g->main_pkg);
12201220
12211221 // Poke the functions
12221222 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
232232static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
233233 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
234234static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
235static void copy_const_val(ZigValue *dest, ZigValue *src);
236235static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
237236static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
238237 ZigType *ptr_type);
......@@ -718,11 +717,6 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
718717 return result;
719718}
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
726720static bool is_tuple(ZigType *type) {
727721 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple;
728722}
......@@ -11451,40 +11445,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1145111445 }
1145211446}
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
1148811448static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,
1148911449 CastOp cast_op,
1149011450 ZigValue *other_val, ZigType *other_type,
src/main.cpp+2-2
......@@ -623,7 +623,7 @@ int main(int argc, char **argv) {
623623
624624 ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
625625 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);
627627 g->enable_cache = get_cache_opt(enable_cache, true);
628628 codegen_build_and_link(g);
629629 if (root_progress_node != nullptr) {
......@@ -1269,7 +1269,7 @@ int main(int argc, char **argv) {
12691269 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
12701270 }
12711271
1272 add_package(g, cur_pkg, g->root_package);
1272 add_package(g, cur_pkg, g->main_pkg);
12731273
12741274 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
12751275 g->c_source_files = c_source_files;