| author | |
| committer | |
| log | 7699b5b997c7a024a6d9558df0ec72d71ef402fe |
| tree | ea996d6252efe24158a802fb50c1a28c3b3d6717 |
| parent | 81f1f72197113a45e827d5c984e219a28aa28083 |
| parent | fff3c1fff4c3ebfcb2bd4f08a43ae7815b5c446b |
| signature |
closes #389116 files changed, 437 insertions(+), 453 deletions(-)
lib/std/builtin.zig+11| ... | @@ -412,6 +412,13 @@ pub const CallOptions = struct { | ... | @@ -412,6 +412,13 @@ pub const CallOptions = struct { |
| 412 | }; | 412 | }; |
| 413 | }; | 413 | }; |
| 414 | 414 | ||
| 415 | /// This function type is used by the Zig language code generation and | ||
| 416 | /// therefore must be kept in sync with the compiler implementation. | ||
| 417 | pub 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 and | 422 | /// 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. |
| 417 | pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn; | 424 | pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn; |
| ... | @@ -424,6 +431,10 @@ pub const panic: PanicFn = if (@hasDecl(root, "panic")) root.panic else default_ | ... | @@ -424,6 +431,10 @@ pub const panic: PanicFn = if (@hasDecl(root, "panic")) root.panic else default_ |
| 424 | /// therefore must be kept in sync with the compiler implementation. | 431 | /// therefore must be kept in sync with the compiler implementation. |
| 425 | pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn { | 432 | pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn { |
| 426 | @setCold(true); | 433 | @setCold(true); |
| 434 | if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) { | ||
| 435 | root.os.panic(msg, error_return_trace); | ||
| 436 | unreachable; | ||
| 437 | } | ||
| 427 | switch (os) { | 438 | switch (os) { |
| 428 | .freestanding => { | 439 | .freestanding => { |
| 429 | while (true) { | 440 | while (true) { |
lib/std/os.zig+12-8| ... | @@ -187,19 +187,23 @@ pub fn abort() noreturn { | ... | @@ -187,19 +187,23 @@ pub fn abort() noreturn { |
| 187 | } | 187 | } |
| 188 | windows.kernel32.ExitProcess(3); | 188 | windows.kernel32.ExitProcess(3); |
| 189 | } | 189 | } |
| 190 | if (builtin.link_libc) { | 190 | if (!builtin.link_libc and builtin.os == .linux) { |
| 191 | system.abort(); | 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); | ||
| 192 | } | 197 | } |
| 193 | if (builtin.os == .uefi) { | 198 | if (builtin.os == .uefi) { |
| 194 | exit(0); // TODO choose appropriate exit code | 199 | exit(0); // TODO choose appropriate exit code |
| 195 | } | 200 | } |
| 201 | if (builtin.os == .wasi) { | ||
| 202 | @breakpoint(); | ||
| 203 | exit(1); | ||
| 204 | } | ||
| 196 | 205 | ||
| 197 | raise(SIGABRT) catch {}; | 206 | system.abort(); |
| 198 | |||
| 199 | // TODO the rest of the implementation of abort() from musl libc here | ||
| 200 | |||
| 201 | raise(SIGKILL) catch {}; | ||
| 202 | exit(127); | ||
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | pub const RaiseError = UnexpectedError; | 209 | pub 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 | ... | @@ -83,7 +83,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn |
| 83 | @setCold(true); | 83 | @setCold(true); |
| 84 | std.debug.panic("{}", msg); | 84 | std.debug.panic("{}", msg); |
| 85 | } | 85 | } |
| 86 | if (builtin.os != .freestanding) { | 86 | if (builtin.os != .freestanding and builtin.os != .other) { |
| 87 | std.os.abort(); | 87 | std.os.abort(); |
| 88 | } | 88 | } |
| 89 | while (true) {} | 89 | 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 | |||
| 3 | const root = @import("root"); | ||
| 4 | const std = @import("std"); | ||
| 5 | const builtin = @import("builtin"); | ||
| 6 | const assert = std.debug.assert; | ||
| 7 | const uefi = std.os.uefi; | ||
| 8 | |||
| 9 | var starting_stack_ptr: [*]usize = undefined; | ||
| 10 | |||
| 11 | const is_wasm = switch (builtin.arch) { | ||
| 12 | .wasm32, .wasm64 => true, | ||
| 13 | else => false, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const is_mips = switch (builtin.arch) { | ||
| 17 | .mips, .mipsel, .mips64, .mips64el => true, | ||
| 18 | else => false, | ||
| 19 | }; | ||
| 20 | |||
| 21 | comptime { | ||
| 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 | |||
| 49 | stdcallcc 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 | |||
| 61 | extern 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 | |||
| 67 | extern 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 | |||
| 90 | nakedcc 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 | |||
| 133 | stdcallcc 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 | ||
| 145 | fn 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 | |||
| 195 | fn 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 | |||
| 204 | extern 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 | ||
| 212 | const 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. | ||
| 216 | inline 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 | |||
| 241 | async 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. | ||
| 250 | fn 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; | ||
| 5 | export var _tls_start: u8 linksection(".tls") = 0; | ||
| 6 | export var _tls_end: u8 linksection(".tls$ZZZ") = 0; | ||
| 7 | export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; | ||
| 8 | export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; | ||
| 9 | |||
| 10 | comptime { | ||
| 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. | ||
| 33 | pub 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 | }; | ||
| 41 | export 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 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const io = std.io; | 2 | const io = std.io; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const test_fn_list = builtin.test_functions; | ||
| 5 | 4 | ||
| 6 | pub fn main() anyerror!void { | 5 | pub 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 | |||
| 3 | const root = @import("root"); | ||
| 4 | const std = @import("std.zig"); | ||
| 5 | const builtin = std.builtin; | ||
| 6 | const assert = std.debug.assert; | ||
| 7 | const uefi = std.os.uefi; | ||
| 8 | |||
| 9 | var starting_stack_ptr: [*]usize = undefined; | ||
| 10 | |||
| 11 | const is_wasm = switch (builtin.arch) { | ||
| 12 | .wasm32, .wasm64 => true, | ||
| 13 | else => false, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const is_mips = switch (builtin.arch) { | ||
| 17 | .mips, .mipsel, .mips64, .mips64el => true, | ||
| 18 | else => false, | ||
| 19 | }; | ||
| 20 | const start_sym_name = if (is_mips) "__start" else "_start"; | ||
| 21 | |||
| 22 | comptime { | ||
| 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 | |||
| 46 | stdcallcc 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 | |||
| 58 | extern 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 | |||
| 64 | extern 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 | |||
| 87 | nakedcc 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 | |||
| 130 | stdcallcc 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 | ||
| 142 | fn 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 | |||
| 192 | fn 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 | |||
| 201 | extern 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 | ||
| 209 | const 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. | ||
| 213 | inline 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 | |||
| 238 | async 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. | ||
| 247 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = std.builtin; | ||
| 3 | |||
| 4 | export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; | ||
| 5 | export var _tls_start: u8 linksection(".tls") = 0; | ||
| 6 | export var _tls_end: u8 linksection(".tls$ZZZ") = 0; | ||
| 7 | export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; | ||
| 8 | export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; | ||
| 9 | |||
| 10 | comptime { | ||
| 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. | ||
| 33 | pub 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 | }; | ||
| 41 | export 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"); | ... | @@ -65,6 +65,13 @@ pub const time = @import("time.zig"); |
| 65 | pub const unicode = @import("unicode.zig"); | 65 | pub const unicode = @import("unicode.zig"); |
| 66 | pub const valgrind = @import("valgrind.zig"); | 66 | pub const valgrind = @import("valgrind.zig"); |
| 67 | pub const zig = @import("zig.zig"); | 67 | pub const zig = @import("zig.zig"); |
| 68 | pub 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. | ||
| 72 | comptime { | ||
| 73 | _ = start; | ||
| 74 | } | ||
| 68 | 75 | ||
| 69 | test "" { | 76 | test "" { |
| 70 | 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; | ||
| 2010 | 2011 | ||
| 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; |
| 3537 | 3537 | ||
| 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; |
| 3541 | 3541 | ||
| 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 | |||
| 9182 | bool 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. | ||
| 9188 | bool 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 | |||
| 9200 | void 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); |
| 277 | ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); | 277 | ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); |
| 278 | bool is_anon_container(ZigType *ty); | 278 | bool is_anon_container(ZigType *ty); |
| 279 | void copy_const_val(ZigValue *dest, ZigValue *src); | ||
| 280 | bool type_has_optional_repr(ZigType *ty); | ||
| 281 | bool is_opt_err_set(ZigType *ty); | ||
| 279 | #endif | 282 | #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) { |
| 8440 | 8440 | ||
| 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 | } |
| 8450 | 8446 | ||
| ... | @@ -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 | } |
| 8537 | 8533 | ||
| 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); |
| 8557 | 8553 | ||
| ... | @@ -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 the | 8666 | // 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); |
| 8674 | 8670 | ||
| 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 | } |
| 9085 | 9081 | ||
| 9086 | static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) { | 9082 | static 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 | |||
| 9103 | static 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 | |||
| 9109 | static void create_test_compile_var_and_add_test_runner(CodeGen *g) { | ||
| 9110 | Error err; | 9083 | Error err; |
| 9111 | 9084 | ||
| 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) { |
| 9166 | 9139 | ||
| 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 | } |
| 9171 | 9143 | ||
| 9172 | static Buf *get_resolved_root_src_path(CodeGen *g) { | 9144 | static Buf *get_resolved_root_src_path(CodeGen *g) { |
| 9173 | // TODO memoize | 9145 | // 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; |
| 9176 | 9148 | ||
| 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); |
| 9179 | 9151 | ||
| 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 | } |
| 9200 | 9172 | ||
| 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); |
| 9203 | 9175 | ||
| 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); |
| 9252 | 9224 | ||
| 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); |
| 10060 | 10024 | ||
| 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 | } |
| 10142 | 10106 | ||
| 10143 | static bool need_llvm_module(CodeGen *g) { | 10107 | static 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 | } |
| 10146 | 10110 | ||
| 10147 | static void resolve_out_paths(CodeGen *g) { | 10111 | static 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); |
| 10390 | 10354 | ||
| 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); | ||
| 10393 | 10356 | ||
| 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 | } |
| 10518 | 10481 | ||
| 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 | } |
| 10525 | 10488 | ||
| 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); |
| 10530 | 10491 |
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); |
| 1217 | 1217 | ||
| 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); |
| 1220 | 1220 | ||
| 1221 | // Poke the functions | 1221 | // 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 |
| 232 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 232 | static 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); |
| 234 | static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); | 234 | static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 235 | static void copy_const_val(ZigValue *dest, ZigValue *src); | ||
| 236 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | 235 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); |
| 237 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | 236 | static 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 | } |
| 720 | 719 | ||
| 721 | static 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 | |||
| 726 | static bool is_tuple(ZigType *type) { | 720 | static 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 | } |
| 11453 | 11447 | ||
| 11454 | // Returns whether the x_optional field of ZigValue is active. | ||
| 11455 | static 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 | |||
| 11467 | static 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 | |||
| 11488 | static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr, | 11448 | static 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) { |
| 623 | 623 | ||
| 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 | } |
| 1271 | 1271 | ||
| 1272 | add_package(g, cur_pkg, g->root_package); | 1272 | add_package(g, cur_pkg, g->main_pkg); |
| 1273 | 1273 | ||
| 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; |