From d6e87da47b61ac31fe93a212d4f47eae55fec492 Mon Sep 17 00:00:00 2001 From: Martin Wickham Date: Wed, 1 Sep 2021 14:32:02 -0500 Subject: [PATCH 1/4] Make stage2 start.zig work on Windows --- lib/std/start.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/std/start.zig b/lib/std/start.zig index 057fde62f6a926279bf767014373af10038e1b28..9e561df5ec2f14637c4fe281119589d149341741 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -28,6 +28,8 @@ comptime { if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { @export(main2, .{ .name = "main" }); } + } else if (builtin.stage2_os == .windows) { + @export(wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" }); } else { if (!@hasDecl(root, "_start")) { @export(_start2, .{ .name = "_start" }); @@ -96,6 +98,11 @@ fn callMain2() noreturn { exit2(0); } +fn wWinMainCRTStartup2() callconv(.C) noreturn { + root.main(); + exit2(0); +} + fn exit2(code: usize) noreturn { switch (native_os) { .linux => switch (builtin.stage2_arch) { @@ -148,11 +155,16 @@ fn exit2(code: usize) noreturn { }, else => @compileError("TODO"), }, + .windows => { + ExitProcess(@truncate(u32, code)); + }, else => @compileError("TODO"), } unreachable; } +extern "kernel32" fn ExitProcess(exit_code: u32) callconv(.C) noreturn; + //////////////////////////////////////////////////////////////////////////////// fn _DllMainCRTStartup( -- 2.54.0 From 4782bededa2987f493a6c02a27b0a248d04cb072 Mon Sep 17 00:00:00 2001 From: Martin Wickham Date: Wed, 22 Sep 2021 14:14:03 -0500 Subject: [PATCH 2/4] Remove reference to stage2_os --- lib/std/start.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 9e561df5ec2f14637c4fe281119589d149341741..cd2cf230af10e2d5678869ea380465166ef93d0b 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -28,7 +28,7 @@ comptime { if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { @export(main2, .{ .name = "main" }); } - } else if (builtin.stage2_os == .windows) { + } else if (builtin.os.tag == .windows) { @export(wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" }); } else { if (!@hasDecl(root, "_start")) { -- 2.54.0 From d86678778a6bcc31dc3cb92a286c278de1214c38 Mon Sep 17 00:00:00 2001 From: Martin Wickham Date: Wed, 22 Sep 2021 14:39:02 -0500 Subject: [PATCH 3/4] Fix failing tests and windows link dependencies --- build.zig | 2 ++ test/cases.zig | 2 +- test/stage2/darwin.zig | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index fef9ee786eb231e0e805cdbf6b0e2a7cb593ef5a..11acdec6b5892d7c45b2c884ce1e9f3daf30d86f 100644 --- a/build.zig +++ b/build.zig @@ -115,6 +115,7 @@ pub fn build(b: *Builder) !void { if (target.isWindows() and target.getAbi() == .gnu) { // LTO is currently broken on mingw, this can be removed when it's fixed. exe.want_lto = false; + test_stage2.want_lto = false; } const exe_options = b.addOptions(); @@ -501,6 +502,7 @@ fn addStaticLlvmOptionsToExe( if (exe.target.getOs().tag == .windows) { exe.linkSystemLibrary("version"); exe.linkSystemLibrary("uuid"); + exe.linkSystemLibrary("ole32"); } } diff --git a/test/cases.zig b/test/cases.zig index 33fa5b19e2a30b1e25de2037147a2d949f0222a1..3a8389f7d49606bc9c2a46edd589fe7e5bde3bef 100644 --- a/test/cases.zig +++ b/test/cases.zig @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { var case = ctx.exe("hello world with updates", linux_x64); case.addError("", &[_][]const u8{ - ":95:9: error: struct 'tmp.tmp' has no member named 'main'", + ":97:9: error: struct 'tmp.tmp' has no member named 'main'", }); // Incorrect return type diff --git a/test/stage2/darwin.zig b/test/stage2/darwin.zig index 959313f02172d76ed61b0775934bdd03ff5db47b..90058404d96553e7293a6742ec3af32163c486d1 100644 --- a/test/stage2/darwin.zig +++ b/test/stage2/darwin.zig @@ -14,7 +14,7 @@ pub fn addCases(ctx: *TestContext) !void { { var case = ctx.exe("darwin hello world with updates", target); case.addError("", &[_][]const u8{ - ":95:9: error: struct 'tmp.tmp' has no member named 'main'", + ":97:9: error: struct 'tmp.tmp' has no member named 'main'", }); // Incorrect return type -- 2.54.0 From e03095f167cf0cd8c1424bff0de3c0a7b5f66b18 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 22 Sep 2021 19:00:43 -0700 Subject: [PATCH 4/4] stage2: remove 2 assertions that were too aggressive * `Type.hasCodeGenBits` this function is used to find out if it ever got sent to a linker backend for lowering. In the case that a struct never has its struct fields resolved, this will be false. In such a case, no corresponding `freeDecl` needs to be issued to the linker backend. So instead of asserting the fields of a struct are resolved, this function now returns `false` for this case. * `Module.clearDecl` there was logic that asserted when there is no outdated_decls map, any dependants of a Decl being cleared had to be in the deletion set. However there is a possible scenario where the dependant is not in the deletion set *yet* because there is a Decl which depends on it, about to be deleted. If it were added to an outdated_decls map, it would be subsequently removed from the map when it gets deleted recursively through its dependency being deleted. These issues were uncovered via unrelated changes which are the two commits immediately preceding this one. --- src/Module.zig | 7 ------- src/type.zig | 6 ++---- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index 70c90d9c0168dc87a99202b8300caa5a546f8b36..861648d689584c9ed792a227f213b91513a3fd6c 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3758,13 +3758,6 @@ pub fn clearDecl( dep.removeDependency(decl); if (outdated_decls) |map| { map.putAssumeCapacity(dep, {}); - } else if (std.debug.runtime_safety) { - // If `outdated_decls` is `null`, it means we're being called from - // `Compilation` after `performAllTheWork` and we cannot queue up any - // more work. `dep` must necessarily be another Decl that is no longer - // being referenced, and will be in the `deletion_set`. Otherwise, - // something has gone wrong. - assert(mod.deletion_set.contains(dep)); } } decl.dependants.clearRetainingCapacity(); diff --git a/src/type.zig b/src/type.zig index d4993151dfd8c34edf54a71c31177f8265ca7cf0..f2fe9e4ccb802d7de3960ee266ef5b5b6412c5ac 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1336,6 +1336,8 @@ pub const Type = extern union { } } + /// For structs and unions, if the type does not have their fields resolved + /// this will return `false`. pub fn hasCodeGenBits(self: Type) bool { return switch (self.tag()) { .u1, @@ -1400,14 +1402,10 @@ pub const Type = extern union { => true, .@"struct" => { - // TODO introduce lazy value mechanism const struct_obj = self.castTag(.@"struct").?.data; if (struct_obj.known_has_bits) { return true; } - assert(struct_obj.status == .have_field_types or - struct_obj.status == .layout_wip or - struct_obj.status == .have_layout); for (struct_obj.fields.values()) |value| { if (value.ty.hasCodeGenBits()) return true; -- 2.54.0