| ... | @@ -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 | } |
| 1116 | | 1146 | |
| 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})); |
| 1129 | | 1148 | |
| 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 { |