authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-04 17:20:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-04 17:20:01-07:00
log6fc9f6c5f6a067475f97cd16cb265332c8b7c6f3
tree7f9ae615ec809a45dacd95f8c011e2b2cb56a1ab
parentafe6e69e4cda8f5c3a11eed31015a28b1373ff20

link.Coff: notice special windows symbols

in order to have a better default for subsystem. This brings stage2 behavior on par with stage1.

1 files changed, 93 insertions(+), 60 deletions(-)

src/link/Coff.zig+93-60
......@@ -809,6 +809,36 @@ pub fn updateDeclExports(
809809 if (build_options.skip_non_native and builtin.object_format != .coff) {
810810 @panic("Attempted to compile for object format that was disabled by build configuration");
811811 }
812
813 // Even in the case of LLVM, we need to notice certain exported symbols in order to
814 // detect the default subsystem.
815 for (exports) |exp| {
816 const exported_decl = module.declPtr(exp.exported_decl);
817 if (exported_decl.getFunction() == null) continue;
818 const winapi_cc = switch (self.base.options.target.cpu.arch) {
819 .i386 => std.builtin.CallingConvention.Stdcall,
820 else => std.builtin.CallingConvention.C,
821 };
822 const decl_cc = exported_decl.ty.fnCallingConvention();
823 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and
824 self.base.options.link_libc)
825 {
826 module.stage1_flags.have_c_main = true;
827 } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) {
828 if (mem.eql(u8, exp.options.name, "WinMain")) {
829 module.stage1_flags.have_winmain = true;
830 } else if (mem.eql(u8, exp.options.name, "wWinMain")) {
831 module.stage1_flags.have_wwinmain = true;
832 } else if (mem.eql(u8, exp.options.name, "WinMainCRTStartup")) {
833 module.stage1_flags.have_winmain_crt_startup = true;
834 } else if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) {
835 module.stage1_flags.have_wwinmain_crt_startup = true;
836 } else if (mem.eql(u8, exp.options.name, "DllMainCRTStartup")) {
837 module.stage1_flags.have_dllmain_crt_startup = true;
838 }
839 }
840 }
841
812842 if (build_options.have_llvm) {
813843 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports);
814844 }
......@@ -1114,17 +1144,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
11141144 try argv.append("-dynamicbase");
11151145 }
11161146
1117 const subsystem_suffix = ss: {
1118 if (self.base.options.major_subsystem_version) |major| {
1119 if (self.base.options.minor_subsystem_version) |minor| {
1120 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
1121 } else {
1122 break :ss try allocPrint(arena, ",{d}", .{major});
1123 }
1124 }
1125 break :ss "";
1126 };
1127
11281147 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
11291148
11301149 if (self.base.options.implib_emit) |emit| {
......@@ -1186,57 +1205,71 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
11861205 }
11871206 break :blk null;
11881207 };
1208
11891209 const Mode = enum { uefi, win32 };
11901210 const mode: Mode = mode: {
1191 if (resolved_subsystem) |subsystem| switch (subsystem) {
1192 .Console => {
1193 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
1194 subsystem_suffix,
1195 }));
1196 break :mode .win32;
1197 },
1198 .EfiApplication => {
1199 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
1200 subsystem_suffix,
1201 }));
1202 break :mode .uefi;
1203 },
1204 .EfiBootServiceDriver => {
1205 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
1206 subsystem_suffix,
1207 }));
1208 break :mode .uefi;
1209 },
1210 .EfiRom => {
1211 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
1212 subsystem_suffix,
1213 }));
1214 break :mode .uefi;
1215 },
1216 .EfiRuntimeDriver => {
1217 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
1218 subsystem_suffix,
1219 }));
1220 break :mode .uefi;
1221 },
1222 .Native => {
1223 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
1224 subsystem_suffix,
1225 }));
1226 break :mode .win32;
1227 },
1228 .Posix => {
1229 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
1230 subsystem_suffix,
1231 }));
1232 break :mode .win32;
1233 },
1234 .Windows => {
1235 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
1236 subsystem_suffix,
1237 }));
1238 break :mode .win32;
1239 },
1211 if (resolved_subsystem) |subsystem| {
1212 const subsystem_suffix = ss: {
1213 if (self.base.options.major_subsystem_version) |major| {
1214 if (self.base.options.minor_subsystem_version) |minor| {
1215 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
1216 } else {
1217 break :ss try allocPrint(arena, ",{d}", .{major});
1218 }
1219 }
1220 break :ss "";
1221 };
1222
1223 switch (subsystem) {
1224 .Console => {
1225 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
1226 subsystem_suffix,
1227 }));
1228 break :mode .win32;
1229 },
1230 .EfiApplication => {
1231 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
1232 subsystem_suffix,
1233 }));
1234 break :mode .uefi;
1235 },
1236 .EfiBootServiceDriver => {
1237 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
1238 subsystem_suffix,
1239 }));
1240 break :mode .uefi;
1241 },
1242 .EfiRom => {
1243 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
1244 subsystem_suffix,
1245 }));
1246 break :mode .uefi;
1247 },
1248 .EfiRuntimeDriver => {
1249 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
1250 subsystem_suffix,
1251 }));
1252 break :mode .uefi;
1253 },
1254 .Native => {
1255 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
1256 subsystem_suffix,
1257 }));
1258 break :mode .win32;
1259 },
1260 .Posix => {
1261 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
1262 subsystem_suffix,
1263 }));
1264 break :mode .win32;
1265 },
1266 .Windows => {
1267 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
1268 subsystem_suffix,
1269 }));
1270 break :mode .win32;
1271 },
1272 }
12401273 } else if (target.os.tag == .uefi) {
12411274 break :mode .uefi;
12421275 } else {