diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-07-04 17:20:01 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-07-04 17:20:01 -0700 |
| commit | 6fc9f6c5f6a067475f97cd16cb265332c8b7c6f3 (patch) | |
| tree | 7f9ae615ec809a45dacd95f8c011e2b2cb56a1ab /src | |
| parent | afe6e69e4cda8f5c3a11eed31015a28b1373ff20 (diff) | |
| download | zig-6fc9f6c5f6a067475f97cd16cb265332c8b7c6f3.tar.gz zig-6fc9f6c5f6a067475f97cd16cb265332c8b7c6f3.zip | |
link.Coff: notice special windows symbols
in order to have a better default for subsystem. This brings stage2
behavior on par with stage1.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Coff.zig | 153 |
1 files changed, 93 insertions, 60 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 0e7d7c89ee..1b5ddbbf8b 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -809,6 +809,36 @@ pub fn updateDeclExports( if (build_options.skip_non_native and builtin.object_format != .coff) { @panic("Attempted to compile for object format that was disabled by build configuration"); } + + // Even in the case of LLVM, we need to notice certain exported symbols in order to + // detect the default subsystem. + for (exports) |exp| { + const exported_decl = module.declPtr(exp.exported_decl); + if (exported_decl.getFunction() == null) continue; + const winapi_cc = switch (self.base.options.target.cpu.arch) { + .i386 => std.builtin.CallingConvention.Stdcall, + else => std.builtin.CallingConvention.C, + }; + const decl_cc = exported_decl.ty.fnCallingConvention(); + if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and + self.base.options.link_libc) + { + module.stage1_flags.have_c_main = true; + } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) { + if (mem.eql(u8, exp.options.name, "WinMain")) { + module.stage1_flags.have_winmain = true; + } else if (mem.eql(u8, exp.options.name, "wWinMain")) { + module.stage1_flags.have_wwinmain = true; + } else if (mem.eql(u8, exp.options.name, "WinMainCRTStartup")) { + module.stage1_flags.have_winmain_crt_startup = true; + } else if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) { + module.stage1_flags.have_wwinmain_crt_startup = true; + } else if (mem.eql(u8, exp.options.name, "DllMainCRTStartup")) { + module.stage1_flags.have_dllmain_crt_startup = true; + } + } + } + if (build_options.have_llvm) { if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports); } @@ -1114,17 +1144,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("-dynamicbase"); } - const subsystem_suffix = ss: { - if (self.base.options.major_subsystem_version) |major| { - if (self.base.options.minor_subsystem_version) |minor| { - break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); - } else { - break :ss try allocPrint(arena, ",{d}", .{major}); - } - } - break :ss ""; - }; - try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); if (self.base.options.implib_emit) |emit| { @@ -1186,57 +1205,71 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! } break :blk null; }; + const Mode = enum { uefi, win32 }; const mode: Mode = mode: { - if (resolved_subsystem) |subsystem| switch (subsystem) { - .Console => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{ - subsystem_suffix, - })); - break :mode .win32; - }, - .EfiApplication => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{ - subsystem_suffix, - })); - break :mode .uefi; - }, - .EfiBootServiceDriver => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{ - subsystem_suffix, - })); - break :mode .uefi; - }, - .EfiRom => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{ - subsystem_suffix, - })); - break :mode .uefi; - }, - .EfiRuntimeDriver => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{ - subsystem_suffix, - })); - break :mode .uefi; - }, - .Native => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{ - subsystem_suffix, - })); - break :mode .win32; - }, - .Posix => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{ - subsystem_suffix, - })); - break :mode .win32; - }, - .Windows => { - try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{ - subsystem_suffix, - })); - break :mode .win32; - }, + if (resolved_subsystem) |subsystem| { + const subsystem_suffix = ss: { + if (self.base.options.major_subsystem_version) |major| { + if (self.base.options.minor_subsystem_version) |minor| { + break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); + } else { + break :ss try allocPrint(arena, ",{d}", .{major}); + } + } + break :ss ""; + }; + + switch (subsystem) { + .Console => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{ + subsystem_suffix, + })); + break :mode .win32; + }, + .EfiApplication => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{ + subsystem_suffix, + })); + break :mode .uefi; + }, + .EfiBootServiceDriver => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{ + subsystem_suffix, + })); + break :mode .uefi; + }, + .EfiRom => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{ + subsystem_suffix, + })); + break :mode .uefi; + }, + .EfiRuntimeDriver => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{ + subsystem_suffix, + })); + break :mode .uefi; + }, + .Native => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{ + subsystem_suffix, + })); + break :mode .win32; + }, + .Posix => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{ + subsystem_suffix, + })); + break :mode .win32; + }, + .Windows => { + try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{ + subsystem_suffix, + })); + break :mode .win32; + }, + } } else if (target.os.tag == .uefi) { break :mode .uefi; } else { |
