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(...@@ -809,6 +809,36 @@ pub fn updateDeclExports(
809 if (build_options.skip_non_native and builtin.object_format != .coff) {809 if (build_options.skip_non_native and builtin.object_format != .coff) {
810 @panic("Attempted to compile for object format that was disabled by build configuration");810 @panic("Attempted to compile for object format that was disabled by build configuration");
811 }811 }
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
812 if (build_options.have_llvm) {842 if (build_options.have_llvm) {
813 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports);843 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports);
814 }844 }
...@@ -1114,17 +1144,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -1114,17 +1144,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
1114 try argv.append("-dynamicbase");1144 try argv.append("-dynamicbase");
1115 }1145 }
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
1128 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));1147 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
11291148
1130 if (self.base.options.implib_emit) |emit| {1149 if (self.base.options.implib_emit) |emit| {
...@@ -1186,57 +1205,71 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -1186,57 +1205,71 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
1186 }1205 }
1187 break :blk null;1206 break :blk null;
1188 };1207 };
1208
1189 const Mode = enum { uefi, win32 };1209 const Mode = enum { uefi, win32 };
1190 const mode: Mode = mode: {1210 const mode: Mode = mode: {
1191 if (resolved_subsystem) |subsystem| switch (subsystem) {1211 if (resolved_subsystem) |subsystem| {
1192 .Console => {1212 const subsystem_suffix = ss: {
1193 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{1213 if (self.base.options.major_subsystem_version) |major| {
1194 subsystem_suffix,1214 if (self.base.options.minor_subsystem_version) |minor| {
1195 }));1215 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
1196 break :mode .win32;1216 } else {
1197 },1217 break :ss try allocPrint(arena, ",{d}", .{major});
1198 .EfiApplication => {1218 }
1199 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{1219 }
1200 subsystem_suffix,1220 break :ss "";
1201 }));1221 };
1202 break :mode .uefi;1222
1203 },1223 switch (subsystem) {
1204 .EfiBootServiceDriver => {1224 .Console => {
1205 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{1225 try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
1206 subsystem_suffix,1226 subsystem_suffix,
1207 }));1227 }));
1208 break :mode .uefi;1228 break :mode .win32;
1209 },1229 },
1210 .EfiRom => {1230 .EfiApplication => {
1211 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{1231 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
1212 subsystem_suffix,1232 subsystem_suffix,
1213 }));1233 }));
1214 break :mode .uefi;1234 break :mode .uefi;
1215 },1235 },
1216 .EfiRuntimeDriver => {1236 .EfiBootServiceDriver => {
1217 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{1237 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
1218 subsystem_suffix,1238 subsystem_suffix,
1219 }));1239 }));
1220 break :mode .uefi;1240 break :mode .uefi;
1221 },1241 },
1222 .Native => {1242 .EfiRom => {
1223 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{1243 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
1224 subsystem_suffix,1244 subsystem_suffix,
1225 }));1245 }));
1226 break :mode .win32;1246 break :mode .uefi;
1227 },1247 },
1228 .Posix => {1248 .EfiRuntimeDriver => {
1229 try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{1249 try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
1230 subsystem_suffix,1250 subsystem_suffix,
1231 }));1251 }));
1232 break :mode .win32;1252 break :mode .uefi;
1233 },1253 },
1234 .Windows => {1254 .Native => {
1235 try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{1255 try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
1236 subsystem_suffix,1256 subsystem_suffix,
1237 }));1257 }));
1238 break :mode .win32;1258 break :mode .win32;
1239 },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 }
1240 } else if (target.os.tag == .uefi) {1273 } else if (target.os.tag == .uefi) {
1241 break :mode .uefi;1274 break :mode .uefi;
1242 } else {1275 } else {