aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-07-04 17:20:01 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-07-04 17:20:01 -0700
commit6fc9f6c5f6a067475f97cd16cb265332c8b7c6f3 (patch)
tree7f9ae615ec809a45dacd95f8c011e2b2cb56a1ab /src
parentafe6e69e4cda8f5c3a11eed31015a28b1373ff20 (diff)
downloadzig-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.zig153
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 {