authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-28 00:06:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-28 00:06:06-07:00
log91a73a177bc20fa0219dbb6c3cf3dda1c2a465db
tree5f391418951620a1f28e8a8fccddbb8e33aed8f6
parenta9082b4ec51debdbffc20b56e9b37cb82dd04750

stage2: building mingw-w64 and COFF LDD linking

still TODO is the task of creating import .lib files for DLLs on the fly both for -lfoo and for e.g. `extern "kernel32"`

15 files changed, 1506 insertions(+), 156 deletions(-)

BRANCH_TODO+6-4
...@@ -1,14 +1,13 @@...@@ -1,14 +1,13 @@
1 * COFF LLD linking1 * add jobs to build import libs for windows DLLs for explicitly linked libs
2 * mingw-w642 * add jobs to build import libs for windows DLLs for extern "foo" functions used
3 * MachO LLD linking3 * MachO LLD linking
4 * WASM LLD linking4 * WASM LLD linking
5 * audit the CLI options for stage25 * audit the CLI options for stage2
6 * audit the base cache hash6 * audit the base cache hash
7 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.7 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.
8 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]
9 * try building some software with zig cc to make sure it didn't regress
10 * `-ftime-report`8 * `-ftime-report`
11 * -fstack-report print stack size diagnostics\n"9 * -fstack-report print stack size diagnostics\n"
10 * try building some software with zig cc to make sure it didn't regress
1211
13 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API12 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API
14 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API13 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API
...@@ -35,6 +34,7 @@...@@ -35,6 +34,7 @@
35 * integrate target features into building assembly code34 * integrate target features into building assembly code
36 * libc_installation.zig: make it look for msvc only if msvc abi is chosen35 * libc_installation.zig: make it look for msvc only if msvc abi is chosen
37 * switch the default C ABI for windows to be mingw-w6436 * switch the default C ABI for windows to be mingw-w64
37 - make it .obj instead of .o always for coff
38 * change glibc log errors to normal exposed compile errors38 * change glibc log errors to normal exposed compile errors
39 * improve Directory.join to only use 1 allocation in a clean way.39 * improve Directory.join to only use 1 allocation in a clean way.
40 * tracy builds with lc++40 * tracy builds with lc++
...@@ -48,3 +48,5 @@...@@ -48,3 +48,5 @@
48 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)48 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)
49 * submit PR to godbolt and update the CLI options (see changes to test/cli.zig)49 * submit PR to godbolt and update the CLI options (see changes to test/cli.zig)
50 * make proposal about log levels50 * make proposal about log levels
51 * proposal for changing fs Z/W functions to be native paths and have a way to do native path string literals
52 * proposal for block { break x; }
lib/std/zig.zig+1-1
...@@ -93,7 +93,7 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro...@@ -93,7 +93,7 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro
93 };93 };
94 return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });94 return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
95 },95 },
96 .Obj => return std.fmt.allocPrint(allocator, "{}.obj", .{root_name}),96 .Obj => return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, target.abi.oFileExt() }),
97 },97 },
98 .elf => switch (options.output_mode) {98 .elf => switch (options.output_mode) {
99 .Exe => return allocator.dupe(u8, root_name),99 .Exe => return allocator.dupe(u8, root_name),
src/Cache.zig+8
...@@ -76,6 +76,14 @@ pub const HashHelper = struct {...@@ -76,6 +76,14 @@ pub const HashHelper = struct {
76 for (list_of_bytes) |bytes| hh.addBytes(bytes);76 for (list_of_bytes) |bytes| hh.addBytes(bytes);
77 }77 }
7878
79 pub fn addStringSet(hh: *HashHelper, hm: std.StringArrayHashMapUnmanaged(void)) void {
80 const entries = hm.items();
81 hh.add(entries.len);
82 for (entries) |entry| {
83 hh.addBytes(entry.key);
84 }
85 }
86
79 /// Convert the input value into bytes and record it as a dependency of the process being cached.87 /// Convert the input value into bytes and record it as a dependency of the process being cached.
80 pub fn add(hh: *HashHelper, x: anytype) void {88 pub fn add(hh: *HashHelper, x: anytype) void {
81 switch (@TypeOf(x)) {89 switch (@TypeOf(x)) {
src/Compilation.zig+53-15
...@@ -17,6 +17,7 @@ const build_options = @import("build_options");...@@ -17,6 +17,7 @@ const build_options = @import("build_options");
17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18const glibc = @import("glibc.zig");18const glibc = @import("glibc.zig");
19const musl = @import("musl.zig");19const musl = @import("musl.zig");
20const mingw = @import("mingw.zig");
20const libunwind = @import("libunwind.zig");21const libunwind = @import("libunwind.zig");
21const libcxx = @import("libcxx.zig");22const libcxx = @import("libcxx.zig");
22const fatal = @import("main.zig").fatal;23const fatal = @import("main.zig").fatal;
...@@ -59,7 +60,6 @@ verbose_llvm_ir: bool,...@@ -59,7 +60,6 @@ verbose_llvm_ir: bool,
59verbose_cimport: bool,60verbose_cimport: bool,
60verbose_llvm_cpu_features: bool,61verbose_llvm_cpu_features: bool,
61disable_c_depfile: bool,62disable_c_depfile: bool,
62is_test: bool,
63time_report: bool,63time_report: bool,
6464
65c_source_files: []const CSourceFile,65c_source_files: []const CSourceFile,
...@@ -150,8 +150,10 @@ const Job = union(enum) {...@@ -150,8 +150,10 @@ const Job = union(enum) {
150 glibc_crt_file: glibc.CRTFile,150 glibc_crt_file: glibc.CRTFile,
151 /// all of the glibc shared objects151 /// all of the glibc shared objects
152 glibc_shared_objects,152 glibc_shared_objects,
153 /// one of the glibc static objects153 /// one of the musl static objects
154 musl_crt_file: musl.CRTFile,154 musl_crt_file: musl.CRTFile,
155 /// one of the mingw-w64 static objects
156 mingw_crt_file: mingw.CRTFile,
155 /// libunwind.a, usually needed when linking libc157 /// libunwind.a, usually needed when linking libc
156 libunwind: void,158 libunwind: void,
157 libcxx: void,159 libcxx: void,
...@@ -719,6 +721,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -719,6 +721,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
719 fatal("TODO implement support for -femit-h in the self-hosted backend", .{});721 fatal("TODO implement support for -femit-h in the self-hosted backend", .{});
720 }722 }
721723
724 var system_libs: std.StringArrayHashMapUnmanaged(void) = .{};
725 errdefer system_libs.deinit(gpa);
726 try system_libs.ensureCapacity(gpa, options.system_libs.len);
727 for (options.system_libs) |lib_name| {
728 system_libs.putAssumeCapacity(lib_name, {});
729 }
730
722 const bin_file = try link.File.openPath(gpa, .{731 const bin_file = try link.File.openPath(gpa, .{
723 .emit = bin_file_emit,732 .emit = bin_file_emit,
724 .root_name = root_name,733 .root_name = root_name,
...@@ -736,7 +745,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -736,7 +745,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
736 .objects = options.link_objects,745 .objects = options.link_objects,
737 .frameworks = options.frameworks,746 .frameworks = options.frameworks,
738 .framework_dirs = options.framework_dirs,747 .framework_dirs = options.framework_dirs,
739 .system_libs = options.system_libs,748 .system_libs = system_libs,
740 .lib_dirs = options.lib_dirs,749 .lib_dirs = options.lib_dirs,
741 .rpath_list = options.rpath_list,750 .rpath_list = options.rpath_list,
742 .strip = options.strip,751 .strip = options.strip,
...@@ -769,6 +778,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -769,6 +778,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
769 .each_lib_rpath = options.each_lib_rpath orelse false,778 .each_lib_rpath = options.each_lib_rpath orelse false,
770 .disable_lld_caching = options.disable_lld_caching,779 .disable_lld_caching = options.disable_lld_caching,
771 .subsystem = options.subsystem,780 .subsystem = options.subsystem,
781 .is_test = options.is_test,
772 });782 });
773 errdefer bin_file.destroy();783 errdefer bin_file.destroy();
774 comp.* = .{784 comp.* = .{
...@@ -804,7 +814,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -804,7 +814,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
804 .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,814 .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
805 .disable_c_depfile = options.disable_c_depfile,815 .disable_c_depfile = options.disable_c_depfile,
806 .owned_link_dir = owned_link_dir,816 .owned_link_dir = owned_link_dir,
807 .is_test = options.is_test,
808 .color = options.color,817 .color = options.color,
809 .time_report = options.time_report,818 .time_report = options.time_report,
810 .test_filter = options.test_filter,819 .test_filter = options.test_filter,
...@@ -847,8 +856,17 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -847,8 +856,17 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
847 .{ .musl_crt_file = .libc_a },856 .{ .musl_crt_file = .libc_a },
848 });857 });
849 }858 }
850 if (comp.wantBuildMinGWW64FromSource()) {859 if (comp.wantBuildMinGWFromSource()) {
851 @panic("TODO");860 const static_lib_jobs = [_]Job{
861 .{ .mingw_crt_file = .mingw32_lib },
862 .{ .mingw_crt_file = .msvcrt_os_lib },
863 .{ .mingw_crt_file = .mingwex_lib },
864 .{ .mingw_crt_file = .uuid_lib },
865 };
866 const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o };
867 try comp.work_queue.ensureUnusedCapacity(static_lib_jobs.len + 1);
868 comp.work_queue.writeAssumeCapacity(&static_lib_jobs);
869 comp.work_queue.writeItemAssumeCapacity(crt_job);
852 }870 }
853 if (comp.wantBuildLibUnwindFromSource()) {871 if (comp.wantBuildLibUnwindFromSource()) {
854 try comp.work_queue.writeItem(.{ .libunwind = {} });872 try comp.work_queue.writeItem(.{ .libunwind = {} });
...@@ -1209,6 +1227,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {...@@ -1209,6 +1227,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
1209 fatal("unable to build musl CRT file: {}", .{@errorName(err)});1227 fatal("unable to build musl CRT file: {}", .{@errorName(err)});
1210 };1228 };
1211 },1229 },
1230 .mingw_crt_file => |crt_file| {
1231 mingw.buildCRTFile(self, crt_file) catch |err| {
1232 // TODO Expose this as a normal compile error rather than crashing here.
1233 fatal("unable to build mingw-w64 CRT file: {}", .{@errorName(err)});
1234 };
1235 },
1212 .libunwind => {1236 .libunwind => {
1213 libunwind.buildStaticLib(self) catch |err| {1237 libunwind.buildStaticLib(self) catch |err| {
1214 // TODO Expose this as a normal compile error rather than crashing here.1238 // TODO Expose this as a normal compile error rather than crashing here.
...@@ -2087,7 +2111,7 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const...@@ -2087,7 +2111,7 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const
2087pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {2111pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {
2088 if (comp.wantBuildGLibCFromSource() or2112 if (comp.wantBuildGLibCFromSource() or
2089 comp.wantBuildMuslFromSource() or2113 comp.wantBuildMuslFromSource() or
2090 comp.wantBuildMinGWW64FromSource())2114 comp.wantBuildMinGWFromSource())
2091 {2115 {
2092 return comp.crt_files.get(basename).?.full_object_path;2116 return comp.crt_files.get(basename).?.full_object_path;
2093 }2117 }
...@@ -2125,7 +2149,7 @@ fn wantBuildMuslFromSource(comp: Compilation) bool {...@@ -2125,7 +2149,7 @@ fn wantBuildMuslFromSource(comp: Compilation) bool {
2125 return comp.wantBuildLibCFromSource() and comp.getTarget().isMusl();2149 return comp.wantBuildLibCFromSource() and comp.getTarget().isMusl();
2126}2150}
21272151
2128fn wantBuildMinGWW64FromSource(comp: Compilation) bool {2152fn wantBuildMinGWFromSource(comp: Compilation) bool {
2129 return comp.wantBuildLibCFromSource() and comp.getTarget().isMinGW();2153 return comp.wantBuildLibCFromSource() and comp.getTarget().isMinGW();
2130}2154}
21312155
...@@ -2186,7 +2210,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2186,7 +2210,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2186 , .{2210 , .{
2187 @tagName(comp.bin_file.options.output_mode),2211 @tagName(comp.bin_file.options.output_mode),
2188 @tagName(comp.bin_file.options.link_mode),2212 @tagName(comp.bin_file.options.link_mode),
2189 comp.is_test,2213 comp.bin_file.options.is_test,
2190 comp.bin_file.options.single_threaded,2214 comp.bin_file.options.single_threaded,
2191 @tagName(target.abi),2215 @tagName(target.abi),
2192 @tagName(target.cpu.arch),2216 @tagName(target.cpu.arch),
...@@ -2214,7 +2238,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2214,7 +2238,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2214 \\pub const os = Os{{2238 \\pub const os = Os{{
2215 \\ .tag = .{},2239 \\ .tag = .{},
2216 \\ .version_range = .{{2240 \\ .version_range = .{{
2217 ,2241 ,
2218 .{@tagName(target.os.tag)},2242 .{@tagName(target.os.tag)},
2219 );2243 );
22202244
...@@ -2283,7 +2307,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2283,7 +2307,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2283 \\ .max = {s},2307 \\ .max = {s},
2284 \\ }}}},2308 \\ }}}},
2285 \\2309 \\
2286 ,2310 ,
2287 .{ windows.min, windows.max },2311 .{ windows.min, windows.max },
2288 ),2312 ),
2289 }2313 }
...@@ -2311,7 +2335,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2311,7 +2335,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2311 @tagName(comp.bin_file.options.machine_code_model),2335 @tagName(comp.bin_file.options.machine_code_model),
2312 });2336 });
23132337
2314 if (comp.is_test) {2338 if (comp.bin_file.options.is_test) {
2315 try buffer.appendSlice(2339 try buffer.appendSlice(
2316 \\pub var test_functions: []TestFn = undefined; // overwritten later2340 \\pub var test_functions: []TestFn = undefined; // overwritten later
2317 \\2341 \\
...@@ -2384,7 +2408,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR...@@ -2384,7 +2408,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
2384 .basename = bin_basename,2408 .basename = bin_basename,
2385 };2409 };
2386 const optimize_mode: std.builtin.Mode = blk: {2410 const optimize_mode: std.builtin.Mode = blk: {
2387 if (comp.is_test)2411 if (comp.bin_file.options.is_test)
2388 break :blk comp.bin_file.options.optimize_mode;2412 break :blk comp.bin_file.options.optimize_mode;
2389 switch (comp.bin_file.options.optimize_mode) {2413 switch (comp.bin_file.options.optimize_mode) {
2390 .Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast,2414 .Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast,
...@@ -2473,7 +2497,7 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2473,7 +2497,7 @@ fn updateStage1Module(comp: *Compilation) !void {
2473 man.hash.add(target.os.getVersionRange());2497 man.hash.add(target.os.getVersionRange());
2474 man.hash.add(comp.bin_file.options.dll_export_fns);2498 man.hash.add(comp.bin_file.options.dll_export_fns);
2475 man.hash.add(comp.bin_file.options.function_sections);2499 man.hash.add(comp.bin_file.options.function_sections);
2476 man.hash.add(comp.is_test);2500 man.hash.add(comp.bin_file.options.is_test);
2477 man.hash.add(comp.bin_file.options.emit != null);2501 man.hash.add(comp.bin_file.options.emit != null);
2478 man.hash.add(comp.emit_h != null);2502 man.hash.add(comp.emit_h != null);
2479 man.hash.add(comp.emit_asm != null);2503 man.hash.add(comp.emit_asm != null);
...@@ -2537,7 +2561,7 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2537,7 +2561,7 @@ fn updateStage1Module(comp: *Compilation) !void {
2537 zig_lib_dir.ptr,2561 zig_lib_dir.ptr,
2538 zig_lib_dir.len,2562 zig_lib_dir.len,
2539 stage2_target,2563 stage2_target,
2540 comp.is_test,2564 comp.bin_file.options.is_test,
2541 ) orelse return error.OutOfMemory;2565 ) orelse return error.OutOfMemory;
25422566
2543 const emit_bin_path = if (comp.bin_file.options.emit != null) blk: {2567 const emit_bin_path = if (comp.bin_file.options.emit != null) blk: {
...@@ -2609,8 +2633,22 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2609,8 +2633,22 @@ fn updateStage1Module(comp: *Compilation) !void {
2609 .verbose_cimport = comp.verbose_cimport,2633 .verbose_cimport = comp.verbose_cimport,
2610 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,2634 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
2611 .main_progress_node = main_progress_node,2635 .main_progress_node = main_progress_node,
2636 .have_c_main = false,
2637 .have_winmain = false,
2638 .have_wwinmain = false,
2639 .have_winmain_crt_startup = false,
2640 .have_wwinmain_crt_startup = false,
2641 .have_dllmain_crt_startup = false,
2612 };2642 };
2613 stage1_module.build_object();2643 stage1_module.build_object();
2644
2645 mod.have_c_main = stage1_module.have_c_main;
2646 mod.have_winmain = stage1_module.have_winmain;
2647 mod.have_wwinmain = stage1_module.have_wwinmain;
2648 mod.have_winmain_crt_startup = stage1_module.have_winmain_crt_startup;
2649 mod.have_wwinmain_crt_startup = stage1_module.have_wwinmain_crt_startup;
2650 mod.have_dllmain_crt_startup = stage1_module.have_dllmain_crt_startup;
2651
2614 stage1_module.destroy();2652 stage1_module.destroy();
26152653
2616 const digest = man.final();2654 const digest = man.final();
src/Module.zig+8-1
...@@ -75,6 +75,13 @@ global_error_set: std.StringHashMapUnmanaged(u16) = .{},...@@ -75,6 +75,13 @@ global_error_set: std.StringHashMapUnmanaged(u16) = .{},
75/// previous analysis.75/// previous analysis.
76generation: u32 = 0,76generation: u32 = 0,
7777
78have_winmain: bool = false,
79have_wwinmain: bool = false,
80have_winmain_crt_startup: bool = false,
81have_wwinmain_crt_startup: bool = false,
82have_dllmain_crt_startup: bool = false,
83have_c_main: bool = false,
84
78pub const Export = struct {85pub const Export = struct {
79 options: std.builtin.ExportOptions,86 options: std.builtin.ExportOptions,
80 /// Byte offset into the file that contains the export directive.87 /// Byte offset into the file that contains the export directive.
...@@ -2668,7 +2675,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst...@@ -2668,7 +2675,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
2668 const src_info = inst.ty.intInfo(self.getTarget());2675 const src_info = inst.ty.intInfo(self.getTarget());
2669 const dst_info = dest_type.intInfo(self.getTarget());2676 const dst_info = dest_type.intInfo(self.getTarget());
2670 if ((src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) or2677 if ((src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) or
2671 // small enough unsigned ints can get casted to large enough signed ints2678 // small enough unsigned ints can get casted to large enough signed ints
2672 (src_info.signed and !dst_info.signed and dst_info.bits > src_info.bits))2679 (src_info.signed and !dst_info.signed and dst_info.bits > src_info.bits))
2673 {2680 {
2674 const b = try self.requireRuntimeBlock(scope, inst.src);2681 const b = try self.requireRuntimeBlock(scope, inst.src);
src/link.zig+28-27
...@@ -36,7 +36,7 @@ pub const Options = struct {...@@ -36,7 +36,7 @@ pub const Options = struct {
36 root_name: []const u8,36 root_name: []const u8,
37 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.37 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
38 module: ?*Module,38 module: ?*Module,
39 dynamic_linker: ?[]const u8 = null,39 dynamic_linker: ?[]const u8,
40 /// Used for calculating how much space to reserve for symbols in case the binary file40 /// Used for calculating how much space to reserve for symbols in case the binary file
41 /// does not already have a symbol table.41 /// does not already have a symbol table.
42 symbol_count_hint: u64 = 32,42 symbol_count_hint: u64 = 32,
...@@ -44,53 +44,54 @@ pub const Options = struct {...@@ -44,53 +44,54 @@ pub const Options = struct {
44 /// the binary file does not already have such a section.44 /// the binary file does not already have such a section.
45 program_code_size_hint: u64 = 256 * 1024,45 program_code_size_hint: u64 = 256 * 1024,
46 entry_addr: ?u64 = null,46 entry_addr: ?u64 = null,
47 stack_size_override: ?u64 = null,47 stack_size_override: ?u64,
48 /// Set to `true` to omit debug info.48 /// Set to `true` to omit debug info.
49 strip: bool = false,49 strip: bool,
50 /// If this is true then this link code is responsible for outputting an object50 /// If this is true then this link code is responsible for outputting an object
51 /// file and then using LLD to link it together with the link options and other objects.51 /// file and then using LLD to link it together with the link options and other objects.
52 /// Otherwise (depending on `use_llvm`) this link code directly outputs and updates the final binary.52 /// Otherwise (depending on `use_llvm`) this link code directly outputs and updates the final binary.
53 use_lld: bool = false,53 use_lld: bool,
54 /// If this is true then this link code is responsible for making an LLVM IR Module,54 /// If this is true then this link code is responsible for making an LLVM IR Module,
55 /// outputting it to an object file, and then linking that together with link options and55 /// outputting it to an object file, and then linking that together with link options and
56 /// other objects.56 /// other objects.
57 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.57 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
58 use_llvm: bool = false,58 use_llvm: bool,
59 link_libc: bool = false,59 link_libc: bool,
60 link_libcpp: bool = false,60 link_libcpp: bool,
61 function_sections: bool = false,61 function_sections: bool,
62 eh_frame_hdr: bool = false,62 eh_frame_hdr: bool,
63 rdynamic: bool = false,63 rdynamic: bool,
64 z_nodelete: bool = false,64 z_nodelete: bool,
65 z_defs: bool = false,65 z_defs: bool,
66 bind_global_refs_locally: bool,66 bind_global_refs_locally: bool,
67 is_native_os: bool,67 is_native_os: bool,
68 pic: bool,68 pic: bool,
69 valgrind: bool,69 valgrind: bool,
70 stack_check: bool,70 stack_check: bool,
71 single_threaded: bool,71 single_threaded: bool,
72 verbose_link: bool = false,72 verbose_link: bool,
73 dll_export_fns: bool,73 dll_export_fns: bool,
74 error_return_tracing: bool,74 error_return_tracing: bool,
75 is_compiler_rt_or_libc: bool,75 is_compiler_rt_or_libc: bool,
76 each_lib_rpath: bool,76 each_lib_rpath: bool,
77 disable_lld_caching: bool,77 disable_lld_caching: bool,
78 is_test: bool,
78 gc_sections: ?bool = null,79 gc_sections: ?bool = null,
79 allow_shlib_undefined: ?bool = null,80 allow_shlib_undefined: ?bool,
80 subsystem: ?std.Target.SubSystem = null,81 subsystem: ?std.Target.SubSystem,
81 linker_script: ?[]const u8 = null,82 linker_script: ?[]const u8,
82 version_script: ?[]const u8 = null,83 version_script: ?[]const u8,
83 override_soname: ?[]const u8 = null,84 override_soname: ?[]const u8,
84 llvm_cpu_features: ?[*:0]const u8 = null,85 llvm_cpu_features: ?[*:0]const u8,
85 /// Extra args passed directly to LLD. Ignored when not linking with LLD.86 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
86 extra_lld_args: []const []const u8 = &[0][]const u8,87 extra_lld_args: []const []const u8,
8788
88 objects: []const []const u8 = &[0][]const u8{},89 objects: []const []const u8,
89 framework_dirs: []const []const u8 = &[0][]const u8{},90 framework_dirs: []const []const u8,
90 frameworks: []const []const u8 = &[0][]const u8{},91 frameworks: []const []const u8,
91 system_libs: []const []const u8 = &[0][]const u8{},92 system_libs: std.StringArrayHashMapUnmanaged(void),
92 lib_dirs: []const []const u8 = &[0][]const u8{},93 lib_dirs: []const []const u8,
93 rpath_list: []const []const u8 = &[0][]const u8{},94 rpath_list: []const []const u8,
9495
95 version: ?std.builtin.Version,96 version: ?std.builtin.Version,
96 libc_installation: ?*const LibCInstallation,97 libc_installation: ?*const LibCInstallation,
src/link/Coff.zig+497-79
...@@ -5,6 +5,8 @@ const log = std.log.scoped(.link);...@@ -5,6 +5,8 @@ const log = std.log.scoped(.link);
5const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const fs = std.fs;7const fs = std.fs;
8const allocPrint = std.fmt.allocPrint;
9const mem = std.mem;
810
9const trace = @import("../tracy.zig").trace;11const trace = @import("../tracy.zig").trace;
10const Module = @import("../Module.zig");12const Module = @import("../Module.zig");
...@@ -12,6 +14,8 @@ const Compilation = @import("../Compilation.zig");...@@ -12,6 +14,8 @@ const Compilation = @import("../Compilation.zig");
12const codegen = @import("../codegen.zig");14const codegen = @import("../codegen.zig");
13const link = @import("../link.zig");15const link = @import("../link.zig");
14const build_options = @import("build_options");16const build_options = @import("build_options");
17const Cache = @import("../Cache.zig");
18const mingw = @import("../mingw.zig");
1519
16const allocation_padding = 4 / 3;20const allocation_padding = 4 / 3;
17const minimum_text_block_size = 64 * allocation_padding;21const minimum_text_block_size = 64 * allocation_padding;
...@@ -21,7 +25,7 @@ const file_alignment = 512;...@@ -21,7 +25,7 @@ const file_alignment = 512;
21const image_base = 0x400_000;25const image_base = 0x400_000;
22const section_table_size = 2 * 40;26const section_table_size = 2 * 40;
23comptime {27comptime {
24 assert(std.mem.isAligned(image_base, section_alignment));28 assert(mem.isAligned(image_base, section_alignment));
25}29}
2630
27pub const base_tag: link.File.Tag = .coff;31pub const base_tag: link.File.Tag = .coff;
...@@ -155,14 +159,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -155,14 +159,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
155 if (machine == .Unknown) {159 if (machine == .Unknown) {
156 return error.UnsupportedCOFFArchitecture;160 return error.UnsupportedCOFFArchitecture;
157 }161 }
158 std.mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));162 mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
159 index += 2;163 index += 2;
160164
161 // Number of sections (we only use .got, .text)165 // Number of sections (we only use .got, .text)
162 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);166 mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
163 index += 2;167 index += 2;
164 // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)168 // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
165 std.mem.set(u8, hdr_data[index..][0..12], 0);169 mem.set(u8, hdr_data[index..][0..12], 0);
166 index += 12;170 index += 12;
167171
168 const optional_header_size = switch (options.output_mode) {172 const optional_header_size = switch (options.output_mode) {
...@@ -177,8 +181,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -177,8 +181,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
177 const default_offset_table_size = file_alignment;181 const default_offset_table_size = file_alignment;
178 const default_size_of_code = 0;182 const default_size_of_code = 0;
179183
180 self.section_data_offset = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);184 self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
181 const section_data_relative_virtual_address = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);185 const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
182 self.offset_table_virtual_address = image_base + section_data_relative_virtual_address;186 self.offset_table_virtual_address = image_base + section_data_relative_virtual_address;
183 self.offset_table_size = default_offset_table_size;187 self.offset_table_size = default_offset_table_size;
184 self.section_table_offset = section_table_offset;188 self.section_table_offset = section_table_offset;
...@@ -186,9 +190,9 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -186,9 +190,9 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
186 self.text_section_size = default_size_of_code;190 self.text_section_size = default_size_of_code;
187191
188 // Size of file when loaded in memory192 // Size of file when loaded in memory
189 const size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment);193 const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment);
190194
191 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);195 mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
192 index += 2;196 index += 2;
193197
194 // Characteristics198 // Characteristics
...@@ -200,7 +204,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -200,7 +204,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
200 .p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,204 .p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
201 .p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,205 .p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
202 }206 }
203 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);207 mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
204 index += 2;208 index += 2;
205209
206 assert(index == 20);210 assert(index == 20);
...@@ -210,106 +214,106 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -210,106 +214,106 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
210 self.optional_header_offset = coff_file_header_offset + 20;214 self.optional_header_offset = coff_file_header_offset + 20;
211 // Optional header215 // Optional header
212 index = 0;216 index = 0;
213 std.mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {217 mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
214 .p32 => @as(u16, 0x10b),218 .p32 => @as(u16, 0x10b),
215 .p64 => 0x20b,219 .p64 => 0x20b,
216 });220 });
217 index += 2;221 index += 2;
218222
219 // Linker version (u8 + u8)223 // Linker version (u8 + u8)
220 std.mem.set(u8, hdr_data[index..][0..2], 0);224 mem.set(u8, hdr_data[index..][0..2], 0);
221 index += 2;225 index += 2;
222226
223 // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)227 // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
224 std.mem.set(u8, hdr_data[index..][0..20], 0);228 mem.set(u8, hdr_data[index..][0..20], 0);
225 index += 20;229 index += 20;
226230
227 if (self.ptr_width == .p32) {231 if (self.ptr_width == .p32) {
228 // Base of data relative to the image base (UNUSED)232 // Base of data relative to the image base (UNUSED)
229 std.mem.set(u8, hdr_data[index..][0..4], 0);233 mem.set(u8, hdr_data[index..][0..4], 0);
230 index += 4;234 index += 4;
231235
232 // Image base address236 // Image base address
233 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base);237 mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base);
234 index += 4;238 index += 4;
235 } else {239 } else {
236 // Image base address240 // Image base address
237 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base);241 mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base);
238 index += 8;242 index += 8;
239 }243 }
240244
241 // Section alignment245 // Section alignment
242 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);246 mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
243 index += 4;247 index += 4;
244 // File alignment248 // File alignment
245 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);249 mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
246 index += 4;250 index += 4;
247 // Required OS version, 6.0 is vista251 // Required OS version, 6.0 is vista
248 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);252 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
249 index += 2;253 index += 2;
250 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);254 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
251 index += 2;255 index += 2;
252 // Image version256 // Image version
253 std.mem.set(u8, hdr_data[index..][0..4], 0);257 mem.set(u8, hdr_data[index..][0..4], 0);
254 index += 4;258 index += 4;
255 // Required subsystem version, same as OS version259 // Required subsystem version, same as OS version
256 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);260 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
257 index += 2;261 index += 2;
258 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);262 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
259 index += 2;263 index += 2;
260 // Reserved zeroes (u32)264 // Reserved zeroes (u32)
261 std.mem.set(u8, hdr_data[index..][0..4], 0);265 mem.set(u8, hdr_data[index..][0..4], 0);
262 index += 4;266 index += 4;
263 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);267 mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
264 index += 4;268 index += 4;
265 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);269 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
266 index += 4;270 index += 4;
267 // CheckSum (u32)271 // CheckSum (u32)
268 std.mem.set(u8, hdr_data[index..][0..4], 0);272 mem.set(u8, hdr_data[index..][0..4], 0);
269 index += 4;273 index += 4;
270 // Subsystem, TODO: Let users specify the subsystem, always CUI for now274 // Subsystem, TODO: Let users specify the subsystem, always CUI for now
271 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);275 mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
272 index += 2;276 index += 2;
273 // DLL characteristics277 // DLL characteristics
274 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);278 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
275 index += 2;279 index += 2;
276280
277 switch (self.ptr_width) {281 switch (self.ptr_width) {
278 .p32 => {282 .p32 => {
279 // Size of stack reserve + commit283 // Size of stack reserve + commit
280 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);284 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
281 index += 4;285 index += 4;
282 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);286 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
283 index += 4;287 index += 4;
284 // Size of heap reserve + commit288 // Size of heap reserve + commit
285 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);289 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
286 index += 4;290 index += 4;
287 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);291 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
288 index += 4;292 index += 4;
289 },293 },
290 .p64 => {294 .p64 => {
291 // Size of stack reserve + commit295 // Size of stack reserve + commit
292 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);296 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
293 index += 8;297 index += 8;
294 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);298 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
295 index += 8;299 index += 8;
296 // Size of heap reserve + commit300 // Size of heap reserve + commit
297 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);301 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
298 index += 8;302 index += 8;
299 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);303 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
300 index += 8;304 index += 8;
301 },305 },
302 }306 }
303307
304 // Reserved zeroes308 // Reserved zeroes
305 std.mem.set(u8, hdr_data[index..][0..4], 0);309 mem.set(u8, hdr_data[index..][0..4], 0);
306 index += 4;310 index += 4;
307311
308 // Number of data directories312 // Number of data directories
309 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);313 mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
310 index += 4;314 index += 4;
311 // Initialize data directories to zero315 // Initialize data directories to zero
312 std.mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);316 mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
313 index += data_directory_count * 8;317 index += data_directory_count * 8;
314318
315 assert(index == optional_header_size);319 assert(index == optional_header_size);
...@@ -321,52 +325,52 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -321,52 +325,52 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
321 index += 8;325 index += 8;
322 if (options.output_mode == .Exe) {326 if (options.output_mode == .Exe) {
323 // Virtual size (u32)327 // Virtual size (u32)
324 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);328 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
325 index += 4;329 index += 4;
326 // Virtual address (u32)330 // Virtual address (u32)
327 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base);331 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base);
328 index += 4;332 index += 4;
329 } else {333 } else {
330 std.mem.set(u8, hdr_data[index..][0..8], 0);334 mem.set(u8, hdr_data[index..][0..8], 0);
331 index += 8;335 index += 8;
332 }336 }
333 // Size of raw data (u32)337 // Size of raw data (u32)
334 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);338 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
335 index += 4;339 index += 4;
336 // File pointer to the start of the section340 // File pointer to the start of the section
337 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);341 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
338 index += 4;342 index += 4;
339 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)343 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
340 std.mem.set(u8, hdr_data[index..][0..12], 0);344 mem.set(u8, hdr_data[index..][0..12], 0);
341 index += 12;345 index += 12;
342 // Section flags346 // Section flags
343 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);347 mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
344 index += 4;348 index += 4;
345 // Then, the .text section349 // Then, the .text section
346 hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;350 hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
347 index += 8;351 index += 8;
348 if (options.output_mode == .Exe) {352 if (options.output_mode == .Exe) {
349 // Virtual size (u32)353 // Virtual size (u32)
350 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);354 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
351 index += 4;355 index += 4;
352 // Virtual address (u32)356 // Virtual address (u32)
353 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base);357 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base);
354 index += 4;358 index += 4;
355 } else {359 } else {
356 std.mem.set(u8, hdr_data[index..][0..8], 0);360 mem.set(u8, hdr_data[index..][0..8], 0);
357 index += 8;361 index += 8;
358 }362 }
359 // Size of raw data (u32)363 // Size of raw data (u32)
360 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);364 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
361 index += 4;365 index += 4;
362 // File pointer to the start of the section366 // File pointer to the start of the section
363 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);367 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
364 index += 4;368 index += 4;
365 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)369 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
366 std.mem.set(u8, hdr_data[index..][0..12], 0);370 mem.set(u8, hdr_data[index..][0..12], 0);
367 index += 12;371 index += 12;
368 // Section flags372 // Section flags
369 std.mem.writeIntLittle(373 mem.writeIntLittle(
370 u32,374 u32,
371 hdr_data[index..][0..4],375 hdr_data[index..][0..4],
372 std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,376 std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
...@@ -434,7 +438,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a...@@ -434,7 +438,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
434 const free_block = self.text_block_free_list.items[i];438 const free_block = self.text_block_free_list.items[i];
435439
436 const next_block_text_offset = free_block.text_offset + free_block.capacity();440 const next_block_text_offset = free_block.text_offset + free_block.capacity();
437 const new_block_text_offset = std.mem.alignForwardGeneric(u64, free_block.getVAddr(self.*) + free_block.size, alignment) - self.text_section_virtual_address;441 const new_block_text_offset = mem.alignForwardGeneric(u64, free_block.getVAddr(self.*) + free_block.size, alignment) - self.text_section_virtual_address;
438 if (new_block_text_offset < next_block_text_offset and next_block_text_offset - new_block_text_offset >= new_block_min_capacity) {442 if (new_block_text_offset < next_block_text_offset and next_block_text_offset - new_block_text_offset >= new_block_min_capacity) {
439 block_placement = free_block;443 block_placement = free_block;
440444
...@@ -453,7 +457,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a...@@ -453,7 +457,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
453 continue;457 continue;
454 }458 }
455 } else if (self.last_text_block) |last| {459 } else if (self.last_text_block) |last| {
456 const new_block_vaddr = std.mem.alignForwardGeneric(u64, last.getVAddr(self.*) + last.size, alignment);460 const new_block_vaddr = mem.alignForwardGeneric(u64, last.getVAddr(self.*) + last.size, alignment);
457 block_placement = last;461 block_placement = last;
458 break :blk new_block_vaddr;462 break :blk new_block_vaddr;
459 } else {463 } else {
...@@ -463,15 +467,15 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a...@@ -463,15 +467,15 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
463467
464 const expand_text_section = block_placement == null or block_placement.?.next == null;468 const expand_text_section = block_placement == null or block_placement.?.next == null;
465 if (expand_text_section) {469 if (expand_text_section) {
466 const needed_size = @intCast(u32, std.mem.alignForwardGeneric(u64, vaddr + new_block_size - self.text_section_virtual_address, file_alignment));470 const needed_size = @intCast(u32, mem.alignForwardGeneric(u64, vaddr + new_block_size - self.text_section_virtual_address, file_alignment));
467 if (needed_size > self.text_section_size) {471 if (needed_size > self.text_section_size) {
468 const current_text_section_virtual_size = std.mem.alignForwardGeneric(u32, self.text_section_size, section_alignment);472 const current_text_section_virtual_size = mem.alignForwardGeneric(u32, self.text_section_size, section_alignment);
469 const new_text_section_virtual_size = std.mem.alignForwardGeneric(u32, needed_size, section_alignment);473 const new_text_section_virtual_size = mem.alignForwardGeneric(u32, needed_size, section_alignment);
470 if (current_text_section_virtual_size != new_text_section_virtual_size) {474 if (current_text_section_virtual_size != new_text_section_virtual_size) {
471 self.size_of_image_dirty = true;475 self.size_of_image_dirty = true;
472 // Write new virtual size476 // Write new virtual size
473 var buf: [4]u8 = undefined;477 var buf: [4]u8 = undefined;
474 std.mem.writeIntLittle(u32, &buf, new_text_section_virtual_size);478 mem.writeIntLittle(u32, &buf, new_text_section_virtual_size);
475 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 8);479 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 8);
476 }480 }
477481
...@@ -509,7 +513,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a...@@ -509,7 +513,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
509513
510fn growTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {514fn growTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
511 const block_vaddr = text_block.getVAddr(self.*);515 const block_vaddr = text_block.getVAddr(self.*);
512 const align_ok = std.mem.alignBackwardGeneric(u64, block_vaddr, alignment) == block_vaddr;516 const align_ok = mem.alignBackwardGeneric(u64, block_vaddr, alignment) == block_vaddr;
513 const need_realloc = !align_ok or new_block_size > text_block.capacity();517 const need_realloc = !align_ok or new_block_size > text_block.capacity();
514 if (!need_realloc) return @as(u64, block_vaddr);518 if (!need_realloc) return @as(u64, block_vaddr);
515 return self.allocateTextBlock(text_block, new_block_size, alignment);519 return self.allocateTextBlock(text_block, new_block_size, alignment);
...@@ -575,14 +579,14 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -575,14 +579,14 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
575579
576 // Write the new raw size in the .got header580 // Write the new raw size in the .got header
577 var buf: [8]u8 = undefined;581 var buf: [8]u8 = undefined;
578 std.mem.writeIntLittle(u32, buf[0..4], new_raw_size);582 mem.writeIntLittle(u32, buf[0..4], new_raw_size);
579 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 16);583 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 16);
580 // Write the new .text section file offset in the .text section header584 // Write the new .text section file offset in the .text section header
581 std.mem.writeIntLittle(u32, buf[0..4], new_text_section_start);585 mem.writeIntLittle(u32, buf[0..4], new_text_section_start);
582 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 20);586 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 20);
583587
584 const current_virtual_size = std.mem.alignForwardGeneric(u32, self.offset_table_size, section_alignment);588 const current_virtual_size = mem.alignForwardGeneric(u32, self.offset_table_size, section_alignment);
585 const new_virtual_size = std.mem.alignForwardGeneric(u32, new_raw_size, section_alignment);589 const new_virtual_size = mem.alignForwardGeneric(u32, new_raw_size, section_alignment);
586 // If we had to move in the virtual address space, we need to fix the VAs in the offset table, as well as the virtual address of the `.text` section590 // If we had to move in the virtual address space, we need to fix the VAs in the offset table, as well as the virtual address of the `.text` section
587 // and the virutal size of the `.got` section591 // and the virutal size of the `.got` section
588592
...@@ -592,12 +596,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -592,12 +596,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
592 const va_offset = new_virtual_size - current_virtual_size;596 const va_offset = new_virtual_size - current_virtual_size;
593597
594 // Write .got virtual size598 // Write .got virtual size
595 std.mem.writeIntLittle(u32, buf[0..4], new_virtual_size);599 mem.writeIntLittle(u32, buf[0..4], new_virtual_size);
596 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 8);600 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 8);
597601
598 // Write .text new virtual address602 // Write .text new virtual address
599 self.text_section_virtual_address = self.text_section_virtual_address + va_offset;603 self.text_section_virtual_address = self.text_section_virtual_address + va_offset;
600 std.mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base);604 mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base);
601 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12);605 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12);
602606
603 // Fix the VAs in the offset table607 // Fix the VAs in the offset table
...@@ -607,11 +611,11 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -607,11 +611,11 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
607611
608 switch (entry_size) {612 switch (entry_size) {
609 4 => {613 4 => {
610 std.mem.writeInt(u32, buf[0..4], @intCast(u32, va.*), endian);614 mem.writeInt(u32, buf[0..4], @intCast(u32, va.*), endian);
611 try self.base.file.?.pwriteAll(buf[0..4], offset_table_start + idx * entry_size);615 try self.base.file.?.pwriteAll(buf[0..4], offset_table_start + idx * entry_size);
612 },616 },
613 8 => {617 8 => {
614 std.mem.writeInt(u64, &buf, va.*, endian);618 mem.writeInt(u64, &buf, va.*, endian);
615 try self.base.file.?.pwriteAll(&buf, offset_table_start + idx * entry_size);619 try self.base.file.?.pwriteAll(&buf, offset_table_start + idx * entry_size);
616 },620 },
617 else => unreachable,621 else => unreachable,
...@@ -626,12 +630,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -626,12 +630,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
626 switch (entry_size) {630 switch (entry_size) {
627 4 => {631 4 => {
628 var buf: [4]u8 = undefined;632 var buf: [4]u8 = undefined;
629 std.mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);633 mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);
630 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);634 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
631 },635 },
632 8 => {636 8 => {
633 var buf: [8]u8 = undefined;637 var buf: [8]u8 = undefined;
634 std.mem.writeInt(u64, &buf, self.offset_table.items[index], endian);638 mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
635 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);639 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
636 },640 },
637 else => unreachable,641 else => unreachable,
...@@ -664,7 +668,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -664,7 +668,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
664 if (curr_size != 0) {668 if (curr_size != 0) {
665 const capacity = decl.link.coff.capacity();669 const capacity = decl.link.coff.capacity();
666 const need_realloc = code.len > capacity or670 const need_realloc = code.len > capacity or
667 !std.mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);671 !mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
668 if (need_realloc) {672 if (need_realloc) {
669 const curr_vaddr = self.getDeclVAddr(decl);673 const curr_vaddr = self.getDeclVAddr(decl);
670 const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);674 const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);
...@@ -679,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -679,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
679 }683 }
680 } else {684 } else {
681 const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);685 const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);
682 log.debug("allocated text block for {} at 0x{x} (size: {Bi})\n", .{ std.mem.spanZ(decl.name), vaddr, code.len });686 log.debug("allocated text block for {} at 0x{x} (size: {Bi})\n", .{ mem.spanZ(decl.name), vaddr, code.len });
683 errdefer self.freeTextBlock(&decl.link.coff);687 errdefer self.freeTextBlock(&decl.link.coff);
684 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;688 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;
685 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);689 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);
...@@ -702,7 +706,7 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {...@@ -702,7 +706,7 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
702pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {706pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
703 for (exports) |exp| {707 for (exports) |exp| {
704 if (exp.options.section) |section_name| {708 if (exp.options.section) |section_name| {
705 if (!std.mem.eql(u8, section_name, ".text")) {709 if (!mem.eql(u8, section_name, ".text")) {
706 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);710 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
707 module.failed_exports.putAssumeCapacityNoClobber(711 module.failed_exports.putAssumeCapacityNoClobber(
708 exp,712 exp,
...@@ -711,7 +715,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,...@@ -711,7 +715,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
711 continue;715 continue;
712 }716 }
713 }717 }
714 if (std.mem.eql(u8, exp.options.name, "_start")) {718 if (mem.eql(u8, exp.options.name, "_start")) {
715 self.entry_addr = decl.link.coff.getVAddr(self.*) - image_base;719 self.entry_addr = decl.link.coff.getVAddr(self.*) - image_base;
716 } else {720 } else {
717 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);721 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
...@@ -726,8 +730,12 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,...@@ -726,8 +730,12 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
726730
727pub fn flush(self: *Coff, comp: *Compilation) !void {731pub fn flush(self: *Coff, comp: *Compilation) !void {
728 if (build_options.have_llvm and self.base.options.use_lld) {732 if (build_options.have_llvm and self.base.options.use_lld) {
729 return error.CoffLinkingWithLLDUnimplemented;733 return self.linkWithLLD(comp);
730 } else {734 } else {
735 switch (self.base.options.effectiveOutputMode()) {
736 .Exe, .Obj => {},
737 .Lib => return error.TODOImplementWritingLibFiles,
738 }
731 return self.flushModule(comp);739 return self.flushModule(comp);
732 }740 }
733}741}
...@@ -739,16 +747,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {...@@ -739,16 +747,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
739 if (self.text_section_size_dirty) {747 if (self.text_section_size_dirty) {
740 // Write the new raw size in the .text header748 // Write the new raw size in the .text header
741 var buf: [4]u8 = undefined;749 var buf: [4]u8 = undefined;
742 std.mem.writeIntLittle(u32, &buf, self.text_section_size);750 mem.writeIntLittle(u32, &buf, self.text_section_size);
743 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 16);751 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 16);
744 try self.base.file.?.setEndPos(self.section_data_offset + self.offset_table_size + self.text_section_size);752 try self.base.file.?.setEndPos(self.section_data_offset + self.offset_table_size + self.text_section_size);
745 self.text_section_size_dirty = false;753 self.text_section_size_dirty = false;
746 }754 }
747755
748 if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) {756 if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) {
749 const new_size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment);757 const new_size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment);
750 var buf: [4]u8 = undefined;758 var buf: [4]u8 = undefined;
751 std.mem.writeIntLittle(u32, &buf, new_size_of_image);759 mem.writeIntLittle(u32, &buf, new_size_of_image);
752 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56);760 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56);
753 self.size_of_image_dirty = false;761 self.size_of_image_dirty = false;
754 }762 }
...@@ -763,12 +771,422 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {...@@ -763,12 +771,422 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
763 if (self.base.options.output_mode == .Exe) {771 if (self.base.options.output_mode == .Exe) {
764 // Write AddressOfEntryPoint772 // Write AddressOfEntryPoint
765 var buf: [4]u8 = undefined;773 var buf: [4]u8 = undefined;
766 std.mem.writeIntLittle(u32, &buf, self.entry_addr.?);774 mem.writeIntLittle(u32, &buf, self.entry_addr.?);
767 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 16);775 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 16);
768 }776 }
769 }777 }
770}778}
771779
780fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
781 const tracy = trace(@src());
782 defer tracy.end();
783
784 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
785 defer arena_allocator.deinit();
786 const arena = &arena_allocator.allocator;
787
788 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
789
790 // If there is no Zig code to compile, then we should skip flushing the output file because it
791 // will not be part of the linker line anyway.
792 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
793 const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
794 if (use_stage1) {
795 const obj_basename = try std.zig.binNameAlloc(arena, .{
796 .root_name = self.base.options.root_name,
797 .target = self.base.options.target,
798 .output_mode = .Obj,
799 });
800 const o_directory = self.base.options.module.?.zig_cache_artifact_directory;
801 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
802 break :blk full_obj_path;
803 }
804
805 try self.flushModule(comp);
806 const obj_basename = self.base.intermediary_basename.?;
807 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
808 break :blk full_obj_path;
809 } else null;
810
811 const is_lib = self.base.options.output_mode == .Lib;
812 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
813 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
814 const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
815 const target = self.base.options.target;
816
817 // See link/Elf.zig for comments on how this mechanism works.
818 const id_symlink_basename = "lld.id";
819
820 var man: Cache.Manifest = undefined;
821 defer if (!self.base.options.disable_lld_caching) man.deinit();
822
823 var digest: [Cache.hex_digest_len]u8 = undefined;
824
825 if (!self.base.options.disable_lld_caching) {
826 man = comp.cache_parent.obtain();
827 self.base.releaseLock();
828
829 try man.addListOfFiles(self.base.options.objects);
830 for (comp.c_object_table.items()) |entry| {
831 _ = try man.addFile(entry.key.status.success.object_path, null);
832 }
833 try man.addOptionalFile(module_obj_path);
834 man.hash.addOptional(self.base.options.stack_size_override);
835 man.hash.addListOfBytes(self.base.options.extra_lld_args);
836 man.hash.addListOfBytes(self.base.options.lib_dirs);
837 man.hash.add(self.base.options.is_compiler_rt_or_libc);
838 if (self.base.options.link_libc) {
839 man.hash.add(self.base.options.libc_installation != null);
840 if (self.base.options.libc_installation) |libc_installation| {
841 man.hash.addBytes(libc_installation.crt_dir.?);
842 if (target.abi == .msvc) {
843 man.hash.addBytes(libc_installation.msvc_lib_dir.?);
844 man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
845 }
846 }
847 }
848 man.hash.addStringSet(self.base.options.system_libs);
849 man.hash.addOptional(self.base.options.subsystem);
850 man.hash.add(self.base.options.is_test);
851
852 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
853 _ = try man.hit();
854 digest = man.final();
855 var prev_digest_buf: [digest.len]u8 = undefined;
856 const prev_digest: []u8 = directory.handle.readLink(id_symlink_basename, &prev_digest_buf) catch |err| blk: {
857 log.debug("COFF LLD new_digest={} readlink error: {}", .{ digest, @errorName(err) });
858 // Handle this as a cache miss.
859 break :blk prev_digest_buf[0..0];
860 };
861 if (mem.eql(u8, prev_digest, &digest)) {
862 log.debug("COFF LLD digest={} match - skipping invocation", .{digest});
863 // Hot diggity dog! The output binary is already there.
864 self.base.lock = man.toOwnedLock();
865 return;
866 }
867 log.debug("COFF LLD prev_digest={} new_digest={}", .{ prev_digest, digest });
868
869 // We are about to change the output file to be different, so we invalidate the build hash now.
870 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
871 error.FileNotFound => {},
872 else => |e| return e,
873 };
874 }
875
876 const is_obj = self.base.options.output_mode == .Obj;
877
878 // Create an LLD command line and invoke it.
879 var argv = std.ArrayList([]const u8).init(self.base.allocator);
880 defer argv.deinit();
881 // Even though we're calling LLD as a library it thinks the first argument is its own exe name.
882 try argv.append("lld");
883 if (is_obj) {
884 try argv.append("-r");
885 }
886
887 try argv.append("-ERRORLIMIT:0");
888 try argv.append("-NOLOGO");
889 if (!self.base.options.strip) {
890 try argv.append("-DEBUG");
891 }
892 if (self.base.options.output_mode == .Exe) {
893 const stack_size = self.base.options.stack_size_override orelse 16777216;
894 try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size}));
895 }
896
897 if (target.cpu.arch == .i386) {
898 try argv.append("-MACHINE:X86");
899 } else if (target.cpu.arch == .x86_64) {
900 try argv.append("-MACHINE:X64");
901 } else if (target.cpu.arch.isARM()) {
902 if (target.cpu.arch.ptrBitWidth() == 32) {
903 try argv.append("-MACHINE:ARM");
904 } else {
905 try argv.append("-MACHINE:ARM64");
906 }
907 }
908
909 if (is_dyn_lib) {
910 try argv.append("-DLL");
911 }
912
913 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
914 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
915
916 if (self.base.options.link_libc) {
917 if (self.base.options.libc_installation) |libc_installation| {
918 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
919
920 if (target.abi == .msvc) {
921 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
922 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
923 }
924 }
925 }
926
927 for (self.base.options.lib_dirs) |lib_dir| {
928 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
929 }
930
931 try argv.appendSlice(self.base.options.objects);
932
933 for (comp.c_object_table.items()) |entry| {
934 try argv.append(entry.key.status.success.object_path);
935 }
936
937 if (module_obj_path) |p| {
938 try argv.append(p);
939 }
940
941 const resolved_subsystem: ?std.Target.SubSystem = blk: {
942 if (self.base.options.subsystem) |explicit| break :blk explicit;
943 switch (target.os.tag) {
944 .windows => {
945 if (self.base.options.module) |module| {
946 if (module.have_dllmain_crt_startup or is_dyn_lib)
947 break :blk null;
948 if (module.have_c_main or self.base.options.is_test or
949 module.have_winmain_crt_startup or module.have_wwinmain_crt_startup)
950 {
951 break :blk .Console;
952 }
953 if (module.have_winmain or module.have_wwinmain)
954 break :blk .Windows;
955 }
956 },
957 .uefi => break :blk .EfiApplication,
958 else => {},
959 }
960 break :blk null;
961 };
962 const Mode = enum { uefi, win32 };
963 const mode: Mode = mode: {
964 if (resolved_subsystem) |subsystem| switch (subsystem) {
965 .Console => {
966 try argv.append("-SUBSYSTEM:console");
967 break :mode .win32;
968 },
969 .EfiApplication => {
970 try argv.append("-SUBSYSTEM:efi_application");
971 break :mode .uefi;
972 },
973 .EfiBootServiceDriver => {
974 try argv.append("-SUBSYSTEM:efi_boot_service_driver");
975 break :mode .uefi;
976 },
977 .EfiRom => {
978 try argv.append("-SUBSYSTEM:efi_rom");
979 break :mode .uefi;
980 },
981 .EfiRuntimeDriver => {
982 try argv.append("-SUBSYSTEM:efi_runtime_driver");
983 break :mode .uefi;
984 },
985 .Native => {
986 try argv.append("-SUBSYSTEM:native");
987 break :mode .win32;
988 },
989 .Posix => {
990 try argv.append("-SUBSYSTEM:posix");
991 break :mode .win32;
992 },
993 .Windows => {
994 try argv.append("-SUBSYSTEM:windows");
995 break :mode .win32;
996 },
997 } else if (target.os.tag == .uefi) {
998 break :mode .uefi;
999 } else {
1000 break :mode .win32;
1001 }
1002 };
1003
1004 switch (mode) {
1005 .uefi => try argv.appendSlice(&[_][]const u8{
1006 "-BASE:0",
1007 "-ENTRY:EfiMain",
1008 "-OPT:REF",
1009 "-SAFESEH:NO",
1010 "-MERGE:.rdata=.data",
1011 "-ALIGN:32",
1012 "-NODEFAULTLIB",
1013 "-SECTION:.xdata,D",
1014 }),
1015 .win32 => {
1016 if (link_in_crt) {
1017 if (target.abi.isGnu()) {
1018 try argv.append("-lldmingw");
1019
1020 if (target.cpu.arch == .i386) {
1021 try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
1022 } else {
1023 try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
1024 }
1025
1026 if (is_dyn_lib) {
1027 try argv.append(try comp.get_libc_crt_file(arena, "dllcrt2.o"));
1028 } else {
1029 try argv.append(try comp.get_libc_crt_file(arena, "crt2.o"));
1030 }
1031
1032 try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
1033 try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
1034 try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
1035
1036 for (mingw.always_link_libs) |name| {
1037 if (!self.base.options.system_libs.contains(name)) {
1038 const lib_basename = try allocPrint(arena, "{s}.lib", .{name});
1039 try argv.append(try comp.get_libc_crt_file(arena, lib_basename));
1040 }
1041 }
1042 } else {
1043 const lib_str = switch (self.base.options.link_mode) {
1044 .Dynamic => "",
1045 .Static => "lib",
1046 };
1047 const d_str = switch (self.base.options.optimize_mode) {
1048 .Debug => "d",
1049 else => "",
1050 };
1051 switch (self.base.options.link_mode) {
1052 .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})),
1053 .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})),
1054 }
1055
1056 try argv.append(try allocPrint(arena, "{s}vcruntime{s}.lib", .{ lib_str, d_str }));
1057 try argv.append(try allocPrint(arena, "{s}ucrt{s}.lib", .{ lib_str, d_str }));
1058
1059 //Visual C++ 2015 Conformance Changes
1060 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
1061 try argv.append("legacy_stdio_definitions.lib");
1062
1063 // msvcrt depends on kernel32 and ntdll
1064 try argv.append("kernel32.lib");
1065 try argv.append("ntdll.lib");
1066 }
1067 } else {
1068 try argv.append("-NODEFAULTLIB");
1069 if (!is_lib) {
1070 if (self.base.options.module) |module| {
1071 if (module.have_winmain) {
1072 try argv.append("-ENTRY:WinMain");
1073 } else if (module.have_wwinmain) {
1074 try argv.append("-ENTRY:wWinMain");
1075 } else if (module.have_wwinmain_crt_startup) {
1076 try argv.append("-ENTRY:wWinMainCRTStartup");
1077 } else {
1078 try argv.append("-ENTRY:WinMainCRTStartup");
1079 }
1080 } else {
1081 try argv.append("-ENTRY:WinMainCRTStartup");
1082 }
1083 }
1084 }
1085 },
1086 }
1087
1088 if (!is_obj) {
1089 // libc++ dep
1090 if (self.base.options.link_libcpp) {
1091 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
1092 try argv.append(comp.libcxx_static_lib.?.full_object_path);
1093 try argv.append(comp.libunwind_static_lib.?.full_object_path);
1094 }
1095 }
1096
1097 // compiler-rt and libc
1098 if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) {
1099 if (!self.base.options.link_libc) {
1100 try argv.append(comp.libc_static_lib.?.full_object_path);
1101 }
1102 // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
1103 // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
1104 try argv.append(comp.compiler_rt_static_lib.?.full_object_path);
1105 }
1106
1107 for (self.base.options.system_libs.items()) |entry| {
1108 const lib_basename = try allocPrint(arena, "{s}.lib", .{entry.key});
1109 if (comp.crt_files.get(lib_basename)) |crt_file| {
1110 try argv.append(crt_file.full_object_path);
1111 } else {
1112 try argv.append(lib_basename);
1113 }
1114 }
1115
1116 if (self.base.options.verbose_link) {
1117 Compilation.dump_argv(argv.items);
1118 }
1119
1120 const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
1121 new_argv_with_sentinel[argv.items.len] = null;
1122 const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
1123 for (argv.items) |arg, i| {
1124 new_argv[i] = try arena.dupeZ(u8, arg);
1125 }
1126
1127 var stderr_context: LLDContext = .{
1128 .coff = self,
1129 .data = std.ArrayList(u8).init(self.base.allocator),
1130 };
1131 defer stderr_context.data.deinit();
1132 var stdout_context: LLDContext = .{
1133 .coff = self,
1134 .data = std.ArrayList(u8).init(self.base.allocator),
1135 };
1136 defer stdout_context.data.deinit();
1137 const llvm = @import("../llvm.zig");
1138 const ok = llvm.Link(
1139 .COFF,
1140 new_argv.ptr,
1141 new_argv.len,
1142 append_diagnostic,
1143 @ptrToInt(&stdout_context),
1144 @ptrToInt(&stderr_context),
1145 );
1146 if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory;
1147 if (stdout_context.data.items.len != 0) {
1148 std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items});
1149 }
1150 if (!ok) {
1151 // TODO parse this output and surface with the Compilation API rather than
1152 // directly outputting to stderr here.
1153 std.debug.print("{}", .{stderr_context.data.items});
1154 return error.LLDReportedFailure;
1155 }
1156 if (stderr_context.data.items.len != 0) {
1157 std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
1158 }
1159
1160 if (!self.base.options.disable_lld_caching) {
1161 // Update the dangling symlink with the digest. If it fails we can continue; it only
1162 // means that the next invocation will have an unnecessary cache miss.
1163 directory.handle.symLink(&digest, id_symlink_basename, .{}) catch |err| {
1164 std.log.warn("failed to save linking hash digest symlink: {}", .{@errorName(err)});
1165 };
1166 // Again failure here only means an unnecessary cache miss.
1167 man.writeManifest() catch |err| {
1168 std.log.warn("failed to write cache manifest when linking: {}", .{@errorName(err)});
1169 };
1170 // We hang on to this lock so that the output file path can be used without
1171 // other processes clobbering it.
1172 self.base.lock = man.toOwnedLock();
1173 }
1174}
1175
1176const LLDContext = struct {
1177 data: std.ArrayList(u8),
1178 coff: *Coff,
1179 oom: bool = false,
1180};
1181
1182fn append_diagnostic(context: usize, ptr: [*]const u8, len: usize) callconv(.C) void {
1183 const lld_context = @intToPtr(*LLDContext, context);
1184 const msg = ptr[0..len];
1185 lld_context.data.appendSlice(msg) catch |err| switch (err) {
1186 error.OutOfMemory => lld_context.oom = true,
1187 };
1188}
1189
772pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {1190pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
773 return self.text_section_virtual_address + decl.link.coff.text_offset;1191 return self.text_section_virtual_address + decl.link.coff.text_offset;
774}1192}
src/link/Elf.zig+14-11
...@@ -1225,7 +1225,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1225,7 +1225,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1225 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {1225 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
1226 const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;1226 const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
1227 if (use_stage1) {1227 if (use_stage1) {
1228 const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name});1228 const obj_basename = try std.zig.binNameAlloc(arena, .{
1229 .root_name = self.base.options.root_name,
1230 .target = self.base.options.target,
1231 .output_mode = .Obj,
1232 });
1229 const o_directory = self.base.options.module.?.zig_cache_artifact_directory;1233 const o_directory = self.base.options.module.?.zig_cache_artifact_directory;
1230 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});1234 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
1231 break :blk full_obj_path;1235 break :blk full_obj_path;
...@@ -1242,6 +1246,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1242,6 +1246,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1242 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;1246 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
1243 const have_dynamic_linker = self.base.options.link_libc and1247 const have_dynamic_linker = self.base.options.link_libc and
1244 self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;1248 self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;
1249 const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
1250 const target = self.base.options.target;
12451251
1246 // Here we want to determine whether we can save time by not invoking LLD when the1252 // Here we want to determine whether we can save time by not invoking LLD when the
1247 // output is unchanged. None of the linker options or the object files that are being1253 // output is unchanged. None of the linker options or the object files that are being
...@@ -1297,7 +1303,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1297,7 +1303,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1297 man.hash.addOptionalBytes(self.base.options.override_soname);1303 man.hash.addOptionalBytes(self.base.options.override_soname);
1298 man.hash.addOptional(self.base.options.version);1304 man.hash.addOptional(self.base.options.version);
1299 }1305 }
1300 man.hash.addListOfBytes(self.base.options.system_libs);1306 man.hash.addStringSet(self.base.options.system_libs);
1301 man.hash.addOptional(self.base.options.allow_shlib_undefined);1307 man.hash.addOptional(self.base.options.allow_shlib_undefined);
1302 man.hash.add(self.base.options.bind_global_refs_locally);1308 man.hash.add(self.base.options.bind_global_refs_locally);
13031309
...@@ -1326,7 +1332,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1326,7 +1332,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1326 };1332 };
1327 }1333 }
13281334
1329 const target = self.base.options.target;
1330 const is_obj = self.base.options.output_mode == .Obj;1335 const is_obj = self.base.options.output_mode == .Obj;
13311336
1332 // Create an LLD command line and invoke it.1337 // Create an LLD command line and invoke it.
...@@ -1337,7 +1342,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1337,7 +1342,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1337 if (is_obj) {1342 if (is_obj) {
1338 try argv.append("-r");1343 try argv.append("-r");
1339 }1344 }
1340 const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
13411345
1342 try argv.append("-error-limit=0");1346 try argv.append("-error-limit=0");
13431347
...@@ -1440,7 +1444,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1440,7 +1444,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1440 var test_path = std.ArrayList(u8).init(self.base.allocator);1444 var test_path = std.ArrayList(u8).init(self.base.allocator);
1441 defer test_path.deinit();1445 defer test_path.deinit();
1442 for (self.base.options.lib_dirs) |lib_dir_path| {1446 for (self.base.options.lib_dirs) |lib_dir_path| {
1443 for (self.base.options.system_libs) |link_lib| {1447 for (self.base.options.system_libs.items()) |link_lib| {
1444 test_path.shrinkRetainingCapacity(0);1448 test_path.shrinkRetainingCapacity(0);
1445 const sep = fs.path.sep_str;1449 const sep = fs.path.sep_str;
1446 try test_path.writer().print("{}" ++ sep ++ "lib{}.so", .{ lib_dir_path, link_lib });1450 try test_path.writer().print("{}" ++ sep ++ "lib{}.so", .{ lib_dir_path, link_lib });
...@@ -1509,8 +1513,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1509,8 +1513,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1509 }1513 }
15101514
1511 // Shared libraries.1515 // Shared libraries.
1512 try argv.ensureCapacity(argv.items.len + self.base.options.system_libs.len);1516 const system_libs = self.base.options.system_libs.items();
1513 for (self.base.options.system_libs) |link_lib| {1517 try argv.ensureCapacity(argv.items.len + system_libs.len);
1518 for (system_libs) |entry| {
1519 const link_lib = entry.key;
1514 // By this time, we depend on these libs being dynamically linked libraries and not static libraries1520 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
1515 // (the check for that needs to be earlier), but they could be full paths to .so files, in which1521 // (the check for that needs to be earlier), but they could be full paths to .so files, in which
1516 // case we want to avoid prepending "-l".1522 // case we want to avoid prepending "-l".
...@@ -1581,10 +1587,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1581,10 +1587,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1581 }1587 }
15821588
1583 if (self.base.options.verbose_link) {1589 if (self.base.options.verbose_link) {
1584 for (argv.items[0 .. argv.items.len - 1]) |arg| {1590 Compilation.dump_argv(argv.items);
1585 std.debug.print("{} ", .{arg});
1586 }
1587 std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
1588 }1591 }
15891592
1590 // Oh, snapplesauce! We need null terminated argv.1593 // Oh, snapplesauce! We need null terminated argv.
src/mingw.zig created+866
...@@ -0,0 +1,866 @@
1const std = @import("std");
2const Allocator = std.mem.Allocator;
3const mem = std.mem;
4const path = std.fs.path;
5const assert = std.debug.assert;
6
7const target_util = @import("target.zig");
8const Compilation = @import("Compilation.zig");
9const build_options = @import("build_options");
10
11pub const CRTFile = enum {
12 crt2_o,
13 dllcrt2_o,
14 mingw32_lib,
15 msvcrt_os_lib,
16 mingwex_lib,
17 uuid_lib,
18};
19
20pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
21 if (!build_options.have_llvm) {
22 return error.ZigCompilerNotBuiltWithLLVMExtensions;
23 }
24 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
25 defer arena_allocator.deinit();
26 const arena = &arena_allocator.allocator;
27
28 switch (crt_file) {
29 .crt2_o => {
30 var args = std.ArrayList([]const u8).init(arena);
31 try add_cc_args(comp, arena, &args);
32 try args.appendSlice(&[_][]const u8{
33 "-U__CRTDLL__",
34 "-D__MSVCRT__",
35 // Uncomment these 3 things for crtu
36 //"-DUNICODE",
37 //"-D_UNICODE",
38 //"-DWPRFLAG=1",
39 });
40 return comp.build_crt_file("crt2", .Obj, &[1]Compilation.CSourceFile{
41 .{
42 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
43 "libc", "mingw", "crt", "crtexe.c",
44 }),
45 .extra_flags = args.items,
46 },
47 });
48 },
49
50 .dllcrt2_o => {
51 var args = std.ArrayList([]const u8).init(arena);
52 try add_cc_args(comp, arena, &args);
53 try args.appendSlice(&[_][]const u8{
54 "-U__CRTDLL__",
55 "-D__MSVCRT__",
56 });
57 return comp.build_crt_file("dllcrt2", .Obj, &[1]Compilation.CSourceFile{
58 .{
59 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
60 "libc", "mingw", "crt", "crtdll.c",
61 }),
62 .extra_flags = args.items,
63 },
64 });
65 },
66
67 .mingw32_lib => {
68 var c_source_files: [mingw32_lib_deps.len]Compilation.CSourceFile = undefined;
69 for (mingw32_lib_deps) |dep, i| {
70 var args = std.ArrayList([]const u8).init(arena);
71 try args.appendSlice(&[_][]const u8{
72 "-DHAVE_CONFIG_H",
73 "-D_SYSCRT=1",
74 "-DCRTDLL=1",
75
76 "-isystem",
77 try comp.zig_lib_directory.join(arena, &[_][]const u8{
78 "libc", "include", "any-windows-any",
79 }),
80
81 "-isystem",
82 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
83
84 "-std=gnu99",
85 "-D_CRTBLD",
86 "-D_WIN32_WINNT=0x0f00",
87 "-D__MSVCRT_VERSION__=0x700",
88 "-g",
89 "-O2",
90 });
91 c_source_files[i] = .{
92 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
93 "libc", "mingw", "crt", dep,
94 }),
95 .extra_flags = args.items,
96 };
97 }
98 return comp.build_crt_file("mingw32", .Lib, &c_source_files);
99 },
100
101 .msvcrt_os_lib => {
102 const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
103 "-DHAVE_CONFIG_H",
104 "-D__LIBMSVCRT__",
105
106 "-I",
107 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
108
109 "-std=gnu99",
110 "-D_CRTBLD",
111 "-D_WIN32_WINNT=0x0f00",
112 "-D__MSVCRT_VERSION__=0x700",
113
114 "-isystem",
115 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
116
117 "-g",
118 "-O2",
119 });
120 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
121
122 for (msvcrt_common_src) |dep| {
123 (try c_source_files.addOne()).* = .{
124 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", dep }),
125 .extra_flags = extra_flags,
126 };
127 }
128 if (comp.getTarget().cpu.arch == .i386) {
129 for (msvcrt_i386_src) |dep| {
130 (try c_source_files.addOne()).* = .{
131 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
132 "libc", "mingw", dep,
133 }),
134 .extra_flags = extra_flags,
135 };
136 }
137 } else {
138 for (msvcrt_other_src) |dep| {
139 (try c_source_files.addOne()).* = .{
140 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
141 "libc", "mingw", dep,
142 }),
143 .extra_flags = extra_flags,
144 };
145 }
146 }
147 return comp.build_crt_file("msvcrt-os", .Lib, c_source_files.items);
148 },
149
150 .mingwex_lib => {
151 const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
152 "-DHAVE_CONFIG_H",
153
154 "-I",
155 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw" }),
156
157 "-I",
158 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
159
160 "-std=gnu99",
161 "-D_CRTBLD",
162 "-D_WIN32_WINNT=0x0f00",
163 "-D__MSVCRT_VERSION__=0x700",
164 "-g",
165 "-O2",
166
167 "-isystem",
168 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
169 });
170 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
171
172 for (mingwex_generic_src) |dep| {
173 (try c_source_files.addOne()).* = .{
174 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
175 "libc", "mingw", dep,
176 }),
177 .extra_flags = extra_flags,
178 };
179 }
180 const target = comp.getTarget();
181 if (target.cpu.arch == .i386 or target.cpu.arch == .x86_64) {
182 for (mingwex_x86_src) |dep| {
183 (try c_source_files.addOne()).* = .{
184 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
185 "libc", "mingw", dep,
186 }),
187 .extra_flags = extra_flags,
188 };
189 }
190 } else if (target.cpu.arch.isARM()) {
191 if (target.cpu.arch.ptrBitWidth() == 32) {
192 for (mingwex_arm32_src) |dep| {
193 (try c_source_files.addOne()).* = .{
194 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
195 "libc", "mingw", dep,
196 }),
197 .extra_flags = extra_flags,
198 };
199 }
200 } else {
201 for (mingwex_arm64_src) |dep| {
202 (try c_source_files.addOne()).* = .{
203 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
204 "libc", "mingw", dep,
205 }),
206 .extra_flags = extra_flags,
207 };
208 }
209 }
210 } else {
211 unreachable;
212 }
213 return comp.build_crt_file("mingwex", .Lib, c_source_files.items);
214 },
215
216 .uuid_lib => {
217 const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
218 "-DHAVE_CONFIG_H",
219
220 "-I",
221 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw" }),
222
223 "-I",
224 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
225
226 "-std=gnu99",
227 "-D_CRTBLD",
228 "-D_WIN32_WINNT=0x0f00",
229 "-D__MSVCRT_VERSION__=0x700",
230 "-g",
231 "-O2",
232
233 "-isystem",
234 try comp.zig_lib_directory.join(arena, &[_][]const u8{
235 "libc", "include", "any-windows-any",
236 }),
237 });
238 var c_source_files: [uuid_src.len]Compilation.CSourceFile = undefined;
239 for (uuid_src) |dep, i| {
240 c_source_files[i] = .{
241 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
242 "libc", "mingw", "libsrc", dep,
243 }),
244 .extra_flags = extra_flags,
245 };
246 }
247 return comp.build_crt_file("uuid", .Lib, &c_source_files);
248 },
249 }
250}
251
252fn add_cc_args(
253 comp: *Compilation,
254 arena: *Allocator,
255 args: *std.ArrayList([]const u8),
256) error{OutOfMemory}!void {
257 try args.appendSlice(&[_][]const u8{
258 "-DHAVE_CONFIG_H",
259
260 "-I",
261 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
262
263 "-isystem",
264 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
265 });
266
267 const target = comp.getTarget();
268 if (target.cpu.arch.isARM() and target.cpu.arch.ptrBitWidth() == 32) {
269 try args.append("-mfpu=vfp");
270 }
271
272 try args.appendSlice(&[_][]const u8{
273 "-std=gnu11",
274 "-D_CRTBLD",
275 "-D_WIN32_WINNT=0x0f00",
276 "-D__MSVCRT_VERSION__=0x700",
277 });
278}
279
280const mingw32_lib_deps = [_][]const u8{
281 "crt0_c.c",
282 "dll_argv.c",
283 "gccmain.c",
284 "natstart.c",
285 "pseudo-reloc-list.c",
286 "wildcard.c",
287 "charmax.c",
288 "crt0_w.c",
289 "dllargv.c",
290 "gs_support.c",
291 "_newmode.c",
292 "tlssup.c",
293 "xncommod.c",
294 "cinitexe.c",
295 "merr.c",
296 "usermatherr.c",
297 "pesect.c",
298 "udllargc.c",
299 "xthdloc.c",
300 "CRT_fp10.c",
301 "mingw_helpers.c",
302 "pseudo-reloc.c",
303 "udll_argv.c",
304 "xtxtmode.c",
305 "crt_handler.c",
306 "tlsthrd.c",
307 "tlsmthread.c",
308 "tlsmcrt.c",
309 "cxa_atexit.c",
310};
311const msvcrt_common_src = [_][]const u8{
312 "misc" ++ path.sep_str ++ "_create_locale.c",
313 "misc" ++ path.sep_str ++ "_free_locale.c",
314 "misc" ++ path.sep_str ++ "onexit_table.c",
315 "misc" ++ path.sep_str ++ "register_tls_atexit.c",
316 "stdio" ++ path.sep_str ++ "acrt_iob_func.c",
317 "misc" ++ path.sep_str ++ "_configthreadlocale.c",
318 "misc" ++ path.sep_str ++ "_get_current_locale.c",
319 "misc" ++ path.sep_str ++ "invalid_parameter_handler.c",
320 "misc" ++ path.sep_str ++ "output_format.c",
321 "misc" ++ path.sep_str ++ "purecall.c",
322 "secapi" ++ path.sep_str ++ "_access_s.c",
323 "secapi" ++ path.sep_str ++ "_cgets_s.c",
324 "secapi" ++ path.sep_str ++ "_cgetws_s.c",
325 "secapi" ++ path.sep_str ++ "_chsize_s.c",
326 "secapi" ++ path.sep_str ++ "_controlfp_s.c",
327 "secapi" ++ path.sep_str ++ "_cprintf_s.c",
328 "secapi" ++ path.sep_str ++ "_cprintf_s_l.c",
329 "secapi" ++ path.sep_str ++ "_ctime32_s.c",
330 "secapi" ++ path.sep_str ++ "_ctime64_s.c",
331 "secapi" ++ path.sep_str ++ "_cwprintf_s.c",
332 "secapi" ++ path.sep_str ++ "_cwprintf_s_l.c",
333 "secapi" ++ path.sep_str ++ "_gmtime32_s.c",
334 "secapi" ++ path.sep_str ++ "_gmtime64_s.c",
335 "secapi" ++ path.sep_str ++ "_localtime32_s.c",
336 "secapi" ++ path.sep_str ++ "_localtime64_s.c",
337 "secapi" ++ path.sep_str ++ "_mktemp_s.c",
338 "secapi" ++ path.sep_str ++ "_sopen_s.c",
339 "secapi" ++ path.sep_str ++ "_strdate_s.c",
340 "secapi" ++ path.sep_str ++ "_strtime_s.c",
341 "secapi" ++ path.sep_str ++ "_umask_s.c",
342 "secapi" ++ path.sep_str ++ "_vcprintf_s.c",
343 "secapi" ++ path.sep_str ++ "_vcprintf_s_l.c",
344 "secapi" ++ path.sep_str ++ "_vcwprintf_s.c",
345 "secapi" ++ path.sep_str ++ "_vcwprintf_s_l.c",
346 "secapi" ++ path.sep_str ++ "_vscprintf_p.c",
347 "secapi" ++ path.sep_str ++ "_vscwprintf_p.c",
348 "secapi" ++ path.sep_str ++ "_vswprintf_p.c",
349 "secapi" ++ path.sep_str ++ "_waccess_s.c",
350 "secapi" ++ path.sep_str ++ "_wasctime_s.c",
351 "secapi" ++ path.sep_str ++ "_wctime32_s.c",
352 "secapi" ++ path.sep_str ++ "_wctime64_s.c",
353 "secapi" ++ path.sep_str ++ "_wstrtime_s.c",
354 "secapi" ++ path.sep_str ++ "_wmktemp_s.c",
355 "secapi" ++ path.sep_str ++ "_wstrdate_s.c",
356 "secapi" ++ path.sep_str ++ "asctime_s.c",
357 "secapi" ++ path.sep_str ++ "memcpy_s.c",
358 "secapi" ++ path.sep_str ++ "memmove_s.c",
359 "secapi" ++ path.sep_str ++ "rand_s.c",
360 "secapi" ++ path.sep_str ++ "sprintf_s.c",
361 "secapi" ++ path.sep_str ++ "strerror_s.c",
362 "secapi" ++ path.sep_str ++ "vsprintf_s.c",
363 "secapi" ++ path.sep_str ++ "wmemcpy_s.c",
364 "secapi" ++ path.sep_str ++ "wmemmove_s.c",
365 "stdio" ++ path.sep_str ++ "mingw_lock.c",
366};
367const msvcrt_i386_src = [_][]const u8{
368 "misc" ++ path.sep_str ++ "lc_locale_func.c",
369 "misc" ++ path.sep_str ++ "___mb_cur_max_func.c",
370};
371
372const msvcrt_other_src = [_][]const u8{
373 "misc" ++ path.sep_str ++ "__p___argv.c",
374 "misc" ++ path.sep_str ++ "__p__acmdln.c",
375 "misc" ++ path.sep_str ++ "__p__fmode.c",
376 "misc" ++ path.sep_str ++ "__p__wcmdln.c",
377};
378const mingwex_generic_src = [_][]const u8{
379 "complex" ++ path.sep_str ++ "_cabs.c",
380 "complex" ++ path.sep_str ++ "cabs.c",
381 "complex" ++ path.sep_str ++ "cabsf.c",
382 "complex" ++ path.sep_str ++ "cabsl.c",
383 "complex" ++ path.sep_str ++ "cacos.c",
384 "complex" ++ path.sep_str ++ "cacosf.c",
385 "complex" ++ path.sep_str ++ "cacosl.c",
386 "complex" ++ path.sep_str ++ "carg.c",
387 "complex" ++ path.sep_str ++ "cargf.c",
388 "complex" ++ path.sep_str ++ "cargl.c",
389 "complex" ++ path.sep_str ++ "casin.c",
390 "complex" ++ path.sep_str ++ "casinf.c",
391 "complex" ++ path.sep_str ++ "casinl.c",
392 "complex" ++ path.sep_str ++ "catan.c",
393 "complex" ++ path.sep_str ++ "catanf.c",
394 "complex" ++ path.sep_str ++ "catanl.c",
395 "complex" ++ path.sep_str ++ "ccos.c",
396 "complex" ++ path.sep_str ++ "ccosf.c",
397 "complex" ++ path.sep_str ++ "ccosl.c",
398 "complex" ++ path.sep_str ++ "cexp.c",
399 "complex" ++ path.sep_str ++ "cexpf.c",
400 "complex" ++ path.sep_str ++ "cexpl.c",
401 "complex" ++ path.sep_str ++ "cimag.c",
402 "complex" ++ path.sep_str ++ "cimagf.c",
403 "complex" ++ path.sep_str ++ "cimagl.c",
404 "complex" ++ path.sep_str ++ "clog.c",
405 "complex" ++ path.sep_str ++ "clog10.c",
406 "complex" ++ path.sep_str ++ "clog10f.c",
407 "complex" ++ path.sep_str ++ "clog10l.c",
408 "complex" ++ path.sep_str ++ "clogf.c",
409 "complex" ++ path.sep_str ++ "clogl.c",
410 "complex" ++ path.sep_str ++ "conj.c",
411 "complex" ++ path.sep_str ++ "conjf.c",
412 "complex" ++ path.sep_str ++ "conjl.c",
413 "complex" ++ path.sep_str ++ "cpow.c",
414 "complex" ++ path.sep_str ++ "cpowf.c",
415 "complex" ++ path.sep_str ++ "cpowl.c",
416 "complex" ++ path.sep_str ++ "cproj.c",
417 "complex" ++ path.sep_str ++ "cprojf.c",
418 "complex" ++ path.sep_str ++ "cprojl.c",
419 "complex" ++ path.sep_str ++ "creal.c",
420 "complex" ++ path.sep_str ++ "crealf.c",
421 "complex" ++ path.sep_str ++ "creall.c",
422 "complex" ++ path.sep_str ++ "csin.c",
423 "complex" ++ path.sep_str ++ "csinf.c",
424 "complex" ++ path.sep_str ++ "csinl.c",
425 "complex" ++ path.sep_str ++ "csqrt.c",
426 "complex" ++ path.sep_str ++ "csqrtf.c",
427 "complex" ++ path.sep_str ++ "csqrtl.c",
428 "complex" ++ path.sep_str ++ "ctan.c",
429 "complex" ++ path.sep_str ++ "ctanf.c",
430 "complex" ++ path.sep_str ++ "ctanl.c",
431 "crt" ++ path.sep_str ++ "dllentry.c",
432 "crt" ++ path.sep_str ++ "dllmain.c",
433 "gdtoa" ++ path.sep_str ++ "arithchk.c",
434 "gdtoa" ++ path.sep_str ++ "dmisc.c",
435 "gdtoa" ++ path.sep_str ++ "dtoa.c",
436 "gdtoa" ++ path.sep_str ++ "g__fmt.c",
437 "gdtoa" ++ path.sep_str ++ "g_dfmt.c",
438 "gdtoa" ++ path.sep_str ++ "g_ffmt.c",
439 "gdtoa" ++ path.sep_str ++ "g_xfmt.c",
440 "gdtoa" ++ path.sep_str ++ "gdtoa.c",
441 "gdtoa" ++ path.sep_str ++ "gethex.c",
442 "gdtoa" ++ path.sep_str ++ "gmisc.c",
443 "gdtoa" ++ path.sep_str ++ "hd_init.c",
444 "gdtoa" ++ path.sep_str ++ "hexnan.c",
445 "gdtoa" ++ path.sep_str ++ "misc.c",
446 "gdtoa" ++ path.sep_str ++ "qnan.c",
447 "gdtoa" ++ path.sep_str ++ "smisc.c",
448 "gdtoa" ++ path.sep_str ++ "strtodg.c",
449 "gdtoa" ++ path.sep_str ++ "strtodnrp.c",
450 "gdtoa" ++ path.sep_str ++ "strtof.c",
451 "gdtoa" ++ path.sep_str ++ "strtopx.c",
452 "gdtoa" ++ path.sep_str ++ "sum.c",
453 "gdtoa" ++ path.sep_str ++ "ulp.c",
454 "math" ++ path.sep_str ++ "abs64.c",
455 "math" ++ path.sep_str ++ "cbrt.c",
456 "math" ++ path.sep_str ++ "cbrtf.c",
457 "math" ++ path.sep_str ++ "cbrtl.c",
458 "math" ++ path.sep_str ++ "cephes_emath.c",
459 "math" ++ path.sep_str ++ "copysign.c",
460 "math" ++ path.sep_str ++ "copysignf.c",
461 "math" ++ path.sep_str ++ "coshf.c",
462 "math" ++ path.sep_str ++ "coshl.c",
463 "math" ++ path.sep_str ++ "erfl.c",
464 "math" ++ path.sep_str ++ "expf.c",
465 "math" ++ path.sep_str ++ "fabs.c",
466 "math" ++ path.sep_str ++ "fabsf.c",
467 "math" ++ path.sep_str ++ "fabsl.c",
468 "math" ++ path.sep_str ++ "fdim.c",
469 "math" ++ path.sep_str ++ "fdimf.c",
470 "math" ++ path.sep_str ++ "fdiml.c",
471 "math" ++ path.sep_str ++ "fma.c",
472 "math" ++ path.sep_str ++ "fmaf.c",
473 "math" ++ path.sep_str ++ "fmal.c",
474 "math" ++ path.sep_str ++ "fmax.c",
475 "math" ++ path.sep_str ++ "fmaxf.c",
476 "math" ++ path.sep_str ++ "fmaxl.c",
477 "math" ++ path.sep_str ++ "fmin.c",
478 "math" ++ path.sep_str ++ "fminf.c",
479 "math" ++ path.sep_str ++ "fminl.c",
480 "math" ++ path.sep_str ++ "fp_consts.c",
481 "math" ++ path.sep_str ++ "fp_constsf.c",
482 "math" ++ path.sep_str ++ "fp_constsl.c",
483 "math" ++ path.sep_str ++ "fpclassify.c",
484 "math" ++ path.sep_str ++ "fpclassifyf.c",
485 "math" ++ path.sep_str ++ "fpclassifyl.c",
486 "math" ++ path.sep_str ++ "frexpf.c",
487 "math" ++ path.sep_str ++ "hypot.c",
488 "math" ++ path.sep_str ++ "hypotf.c",
489 "math" ++ path.sep_str ++ "hypotl.c",
490 "math" ++ path.sep_str ++ "isnan.c",
491 "math" ++ path.sep_str ++ "isnanf.c",
492 "math" ++ path.sep_str ++ "isnanl.c",
493 "math" ++ path.sep_str ++ "ldexpf.c",
494 "math" ++ path.sep_str ++ "lgamma.c",
495 "math" ++ path.sep_str ++ "lgammaf.c",
496 "math" ++ path.sep_str ++ "lgammal.c",
497 "math" ++ path.sep_str ++ "llrint.c",
498 "math" ++ path.sep_str ++ "llrintf.c",
499 "math" ++ path.sep_str ++ "llrintl.c",
500 "math" ++ path.sep_str ++ "llround.c",
501 "math" ++ path.sep_str ++ "llroundf.c",
502 "math" ++ path.sep_str ++ "llroundl.c",
503 "math" ++ path.sep_str ++ "log10f.c",
504 "math" ++ path.sep_str ++ "logf.c",
505 "math" ++ path.sep_str ++ "lrint.c",
506 "math" ++ path.sep_str ++ "lrintf.c",
507 "math" ++ path.sep_str ++ "lrintl.c",
508 "math" ++ path.sep_str ++ "lround.c",
509 "math" ++ path.sep_str ++ "lroundf.c",
510 "math" ++ path.sep_str ++ "lroundl.c",
511 "math" ++ path.sep_str ++ "modf.c",
512 "math" ++ path.sep_str ++ "modff.c",
513 "math" ++ path.sep_str ++ "modfl.c",
514 "math" ++ path.sep_str ++ "nextafterf.c",
515 "math" ++ path.sep_str ++ "nextafterl.c",
516 "math" ++ path.sep_str ++ "nexttoward.c",
517 "math" ++ path.sep_str ++ "nexttowardf.c",
518 "math" ++ path.sep_str ++ "powf.c",
519 "math" ++ path.sep_str ++ "powi.c",
520 "math" ++ path.sep_str ++ "powif.c",
521 "math" ++ path.sep_str ++ "powil.c",
522 "math" ++ path.sep_str ++ "rint.c",
523 "math" ++ path.sep_str ++ "rintf.c",
524 "math" ++ path.sep_str ++ "rintl.c",
525 "math" ++ path.sep_str ++ "round.c",
526 "math" ++ path.sep_str ++ "roundf.c",
527 "math" ++ path.sep_str ++ "roundl.c",
528 "math" ++ path.sep_str ++ "s_erf.c",
529 "math" ++ path.sep_str ++ "sf_erf.c",
530 "math" ++ path.sep_str ++ "signbit.c",
531 "math" ++ path.sep_str ++ "signbitf.c",
532 "math" ++ path.sep_str ++ "signbitl.c",
533 "math" ++ path.sep_str ++ "signgam.c",
534 "math" ++ path.sep_str ++ "sinhf.c",
535 "math" ++ path.sep_str ++ "sinhl.c",
536 "math" ++ path.sep_str ++ "sqrt.c",
537 "math" ++ path.sep_str ++ "sqrtf.c",
538 "math" ++ path.sep_str ++ "sqrtl.c",
539 "math" ++ path.sep_str ++ "tanhf.c",
540 "math" ++ path.sep_str ++ "tanhl.c",
541 "math" ++ path.sep_str ++ "tgamma.c",
542 "math" ++ path.sep_str ++ "tgammaf.c",
543 "math" ++ path.sep_str ++ "tgammal.c",
544 "math" ++ path.sep_str ++ "truncl.c",
545 "misc" ++ path.sep_str ++ "alarm.c",
546 "misc" ++ path.sep_str ++ "basename.c",
547 "misc" ++ path.sep_str ++ "btowc.c",
548 "misc" ++ path.sep_str ++ "delay-f.c",
549 "misc" ++ path.sep_str ++ "delay-n.c",
550 "misc" ++ path.sep_str ++ "delayimp.c",
551 "misc" ++ path.sep_str ++ "dirent.c",
552 "misc" ++ path.sep_str ++ "dirname.c",
553 "misc" ++ path.sep_str ++ "feclearexcept.c",
554 "misc" ++ path.sep_str ++ "fegetenv.c",
555 "misc" ++ path.sep_str ++ "fegetexceptflag.c",
556 "misc" ++ path.sep_str ++ "fegetround.c",
557 "misc" ++ path.sep_str ++ "feholdexcept.c",
558 "misc" ++ path.sep_str ++ "feraiseexcept.c",
559 "misc" ++ path.sep_str ++ "fesetenv.c",
560 "misc" ++ path.sep_str ++ "fesetexceptflag.c",
561 "misc" ++ path.sep_str ++ "fesetround.c",
562 "misc" ++ path.sep_str ++ "fetestexcept.c",
563 "misc" ++ path.sep_str ++ "feupdateenv.c",
564 "misc" ++ path.sep_str ++ "ftruncate.c",
565 "misc" ++ path.sep_str ++ "ftw.c",
566 "misc" ++ path.sep_str ++ "ftw64.c",
567 "misc" ++ path.sep_str ++ "fwide.c",
568 "misc" ++ path.sep_str ++ "getlogin.c",
569 "misc" ++ path.sep_str ++ "getopt.c",
570 "misc" ++ path.sep_str ++ "gettimeofday.c",
571 "misc" ++ path.sep_str ++ "imaxabs.c",
572 "misc" ++ path.sep_str ++ "imaxdiv.c",
573 "misc" ++ path.sep_str ++ "isblank.c",
574 "misc" ++ path.sep_str ++ "iswblank.c",
575 "misc" ++ path.sep_str ++ "mbrtowc.c",
576 "misc" ++ path.sep_str ++ "mbsinit.c",
577 "misc" ++ path.sep_str ++ "mempcpy.c",
578 "misc" ++ path.sep_str ++ "mingw-aligned-malloc.c",
579 "misc" ++ path.sep_str ++ "mingw-fseek.c",
580 "misc" ++ path.sep_str ++ "mingw_getsp.S",
581 "misc" ++ path.sep_str ++ "mingw_matherr.c",
582 "misc" ++ path.sep_str ++ "mingw_mbwc_convert.c",
583 "misc" ++ path.sep_str ++ "mingw_usleep.c",
584 "misc" ++ path.sep_str ++ "mingw_wcstod.c",
585 "misc" ++ path.sep_str ++ "mingw_wcstof.c",
586 "misc" ++ path.sep_str ++ "mingw_wcstold.c",
587 "misc" ++ path.sep_str ++ "mkstemp.c",
588 "misc" ++ path.sep_str ++ "seterrno.c",
589 "misc" ++ path.sep_str ++ "sleep.c",
590 "misc" ++ path.sep_str ++ "strnlen.c",
591 "misc" ++ path.sep_str ++ "strsafe.c",
592 "misc" ++ path.sep_str ++ "strtoimax.c",
593 "misc" ++ path.sep_str ++ "strtold.c",
594 "misc" ++ path.sep_str ++ "strtoumax.c",
595 "misc" ++ path.sep_str ++ "tdelete.c",
596 "misc" ++ path.sep_str ++ "tfind.c",
597 "misc" ++ path.sep_str ++ "tsearch.c",
598 "misc" ++ path.sep_str ++ "twalk.c",
599 "misc" ++ path.sep_str ++ "uchar_c16rtomb.c",
600 "misc" ++ path.sep_str ++ "uchar_c32rtomb.c",
601 "misc" ++ path.sep_str ++ "uchar_mbrtoc16.c",
602 "misc" ++ path.sep_str ++ "uchar_mbrtoc32.c",
603 "misc" ++ path.sep_str ++ "wassert.c",
604 "misc" ++ path.sep_str ++ "wcrtomb.c",
605 "misc" ++ path.sep_str ++ "wcsnlen.c",
606 "misc" ++ path.sep_str ++ "wcstof.c",
607 "misc" ++ path.sep_str ++ "wcstoimax.c",
608 "misc" ++ path.sep_str ++ "wcstold.c",
609 "misc" ++ path.sep_str ++ "wcstoumax.c",
610 "misc" ++ path.sep_str ++ "wctob.c",
611 "misc" ++ path.sep_str ++ "wctrans.c",
612 "misc" ++ path.sep_str ++ "wctype.c",
613 "misc" ++ path.sep_str ++ "wdirent.c",
614 "misc" ++ path.sep_str ++ "winbs_uint64.c",
615 "misc" ++ path.sep_str ++ "winbs_ulong.c",
616 "misc" ++ path.sep_str ++ "winbs_ushort.c",
617 "misc" ++ path.sep_str ++ "wmemchr.c",
618 "misc" ++ path.sep_str ++ "wmemcmp.c",
619 "misc" ++ path.sep_str ++ "wmemcpy.c",
620 "misc" ++ path.sep_str ++ "wmemmove.c",
621 "misc" ++ path.sep_str ++ "wmempcpy.c",
622 "misc" ++ path.sep_str ++ "wmemset.c",
623 "stdio" ++ path.sep_str ++ "_Exit.c",
624 "stdio" ++ path.sep_str ++ "_findfirst64i32.c",
625 "stdio" ++ path.sep_str ++ "_findnext64i32.c",
626 "stdio" ++ path.sep_str ++ "_fstat.c",
627 "stdio" ++ path.sep_str ++ "_fstat64i32.c",
628 "stdio" ++ path.sep_str ++ "_ftime.c",
629 "stdio" ++ path.sep_str ++ "_getc_nolock.c",
630 "stdio" ++ path.sep_str ++ "_getwc_nolock.c",
631 "stdio" ++ path.sep_str ++ "_putc_nolock.c",
632 "stdio" ++ path.sep_str ++ "_putwc_nolock.c",
633 "stdio" ++ path.sep_str ++ "_stat.c",
634 "stdio" ++ path.sep_str ++ "_stat64i32.c",
635 "stdio" ++ path.sep_str ++ "_wfindfirst64i32.c",
636 "stdio" ++ path.sep_str ++ "_wfindnext64i32.c",
637 "stdio" ++ path.sep_str ++ "_wstat.c",
638 "stdio" ++ path.sep_str ++ "_wstat64i32.c",
639 "stdio" ++ path.sep_str ++ "asprintf.c",
640 "stdio" ++ path.sep_str ++ "atoll.c",
641 "stdio" ++ path.sep_str ++ "fgetpos64.c",
642 "stdio" ++ path.sep_str ++ "fopen64.c",
643 "stdio" ++ path.sep_str ++ "fseeko32.c",
644 "stdio" ++ path.sep_str ++ "fseeko64.c",
645 "stdio" ++ path.sep_str ++ "fsetpos64.c",
646 "stdio" ++ path.sep_str ++ "ftello.c",
647 "stdio" ++ path.sep_str ++ "ftello64.c",
648 "stdio" ++ path.sep_str ++ "ftruncate64.c",
649 "stdio" ++ path.sep_str ++ "lltoa.c",
650 "stdio" ++ path.sep_str ++ "lltow.c",
651 "stdio" ++ path.sep_str ++ "lseek64.c",
652 "stdio" ++ path.sep_str ++ "mingw_asprintf.c",
653 "stdio" ++ path.sep_str ++ "mingw_fprintf.c",
654 "stdio" ++ path.sep_str ++ "mingw_fprintfw.c",
655 "stdio" ++ path.sep_str ++ "mingw_fscanf.c",
656 "stdio" ++ path.sep_str ++ "mingw_fwscanf.c",
657 "stdio" ++ path.sep_str ++ "mingw_pformat.c",
658 "stdio" ++ path.sep_str ++ "mingw_pformatw.c",
659 "stdio" ++ path.sep_str ++ "mingw_printf.c",
660 "stdio" ++ path.sep_str ++ "mingw_printfw.c",
661 "stdio" ++ path.sep_str ++ "mingw_scanf.c",
662 "stdio" ++ path.sep_str ++ "mingw_snprintf.c",
663 "stdio" ++ path.sep_str ++ "mingw_snprintfw.c",
664 "stdio" ++ path.sep_str ++ "mingw_sprintf.c",
665 "stdio" ++ path.sep_str ++ "mingw_sprintfw.c",
666 "stdio" ++ path.sep_str ++ "mingw_sscanf.c",
667 "stdio" ++ path.sep_str ++ "mingw_swscanf.c",
668 "stdio" ++ path.sep_str ++ "mingw_vasprintf.c",
669 "stdio" ++ path.sep_str ++ "mingw_vfprintf.c",
670 "stdio" ++ path.sep_str ++ "mingw_vfprintfw.c",
671 "stdio" ++ path.sep_str ++ "mingw_vfscanf.c",
672 "stdio" ++ path.sep_str ++ "mingw_vprintf.c",
673 "stdio" ++ path.sep_str ++ "mingw_vprintfw.c",
674 "stdio" ++ path.sep_str ++ "mingw_vsnprintf.c",
675 "stdio" ++ path.sep_str ++ "mingw_vsnprintfw.c",
676 "stdio" ++ path.sep_str ++ "mingw_vsprintf.c",
677 "stdio" ++ path.sep_str ++ "mingw_vsprintfw.c",
678 "stdio" ++ path.sep_str ++ "mingw_wscanf.c",
679 "stdio" ++ path.sep_str ++ "mingw_wvfscanf.c",
680 "stdio" ++ path.sep_str ++ "scanf.S",
681 "stdio" ++ path.sep_str ++ "snprintf.c",
682 "stdio" ++ path.sep_str ++ "snwprintf.c",
683 "stdio" ++ path.sep_str ++ "strtof.c",
684 "stdio" ++ path.sep_str ++ "strtok_r.c",
685 "stdio" ++ path.sep_str ++ "truncate.c",
686 "stdio" ++ path.sep_str ++ "ulltoa.c",
687 "stdio" ++ path.sep_str ++ "ulltow.c",
688 "stdio" ++ path.sep_str ++ "vasprintf.c",
689 "stdio" ++ path.sep_str ++ "vfscanf.c",
690 "stdio" ++ path.sep_str ++ "vfscanf2.S",
691 "stdio" ++ path.sep_str ++ "vfwscanf.c",
692 "stdio" ++ path.sep_str ++ "vfwscanf2.S",
693 "stdio" ++ path.sep_str ++ "vscanf.c",
694 "stdio" ++ path.sep_str ++ "vscanf2.S",
695 "stdio" ++ path.sep_str ++ "vsnprintf.c",
696 "stdio" ++ path.sep_str ++ "vsnwprintf.c",
697 "stdio" ++ path.sep_str ++ "vsscanf.c",
698 "stdio" ++ path.sep_str ++ "vsscanf2.S",
699 "stdio" ++ path.sep_str ++ "vswscanf.c",
700 "stdio" ++ path.sep_str ++ "vswscanf2.S",
701 "stdio" ++ path.sep_str ++ "vwscanf.c",
702 "stdio" ++ path.sep_str ++ "vwscanf2.S",
703 "stdio" ++ path.sep_str ++ "wtoll.c",
704};
705
706const mingwex_x86_src = [_][]const u8{
707 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosf.c",
708 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosh.c",
709 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acoshf.c",
710 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acoshl.c",
711 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosl.c",
712 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinf.c",
713 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinh.c",
714 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinhf.c",
715 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinhl.c",
716 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinl.c",
717 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2.c",
718 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2f.c",
719 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2l.c",
720 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanf.c",
721 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanh.c",
722 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanhf.c",
723 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanhl.c",
724 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanl.c",
725 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceilf.S",
726 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceill.S",
727 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceil.S",
728 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "_chgsignl.S",
729 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "copysignl.S",
730 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cos.c",
731 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosf.c",
732 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosl.c",
733 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosl_internal.S",
734 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cossin.c",
735 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2f.S",
736 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2l.S",
737 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2.S",
738 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp.c",
739 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expl.c",
740 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1.c",
741 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1f.c",
742 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1l.c",
743 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floorf.S",
744 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floorl.S",
745 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floor.S",
746 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmod.c",
747 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodf.c",
748 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodl.c",
749 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fucom.c",
750 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogbf.S",
751 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogbl.S",
752 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogb.S",
753 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "internal_logl.S",
754 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexp.c",
755 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexpl.c",
756 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log10l.S",
757 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1pf.S",
758 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1pl.S",
759 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1p.S",
760 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2f.S",
761 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2l.S",
762 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2.S",
763 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logb.c",
764 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logbf.c",
765 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logbl.c",
766 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log.c",
767 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logl.c",
768 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyintf.S",
769 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyintl.S",
770 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyint.S",
771 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "pow.c",
772 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "powl.c",
773 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainderf.S",
774 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainderl.S",
775 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainder.S",
776 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquof.S",
777 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquol.S",
778 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquo.S",
779 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnf.S",
780 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnl.S",
781 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbn.S",
782 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sin.c",
783 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinf.c",
784 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl.c",
785 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl_internal.S",
786 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanf.c",
787 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanl.S",
788 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "truncf.S",
789 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "trunc.S",
790};
791
792const mingwex_arm32_src = [_][]const u8{
793 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "_chgsignl.S",
794 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "exp2.c",
795 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyint.S",
796 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyintf.S",
797 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyintl.S",
798 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "trunc.S",
799 "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "truncf.S",
800};
801
802const mingwex_arm64_src = [_][]const u8{
803 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "_chgsignl.S",
804 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "exp2f.S",
805 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "exp2.S",
806 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyintf.S",
807 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyintl.S",
808 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyint.S",
809 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "truncf.S",
810 "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "trunc.S",
811};
812
813const uuid_src = [_][]const u8{
814 "ativscp-uuid.c",
815 "atsmedia-uuid.c",
816 "bth-uuid.c",
817 "cguid-uuid.c",
818 "comcat-uuid.c",
819 "devguid.c",
820 "docobj-uuid.c",
821 "dxva-uuid.c",
822 "exdisp-uuid.c",
823 "extras-uuid.c",
824 "fwp-uuid.c",
825 "guid_nul.c",
826 "hlguids-uuid.c",
827 "hlink-uuid.c",
828 "mlang-uuid.c",
829 "msctf-uuid.c",
830 "mshtmhst-uuid.c",
831 "mshtml-uuid.c",
832 "msxml-uuid.c",
833 "netcon-uuid.c",
834 "ntddkbd-uuid.c",
835 "ntddmou-uuid.c",
836 "ntddpar-uuid.c",
837 "ntddscsi-uuid.c",
838 "ntddser-uuid.c",
839 "ntddstor-uuid.c",
840 "ntddvdeo-uuid.c",
841 "oaidl-uuid.c",
842 "objidl-uuid.c",
843 "objsafe-uuid.c",
844 "ocidl-uuid.c",
845 "oleacc-uuid.c",
846 "olectlid-uuid.c",
847 "oleidl-uuid.c",
848 "power-uuid.c",
849 "powrprof-uuid.c",
850 "uianimation-uuid.c",
851 "usbcamdi-uuid.c",
852 "usbiodef-uuid.c",
853 "uuid.c",
854 "vds-uuid.c",
855 "virtdisk-uuid.c",
856 "wia-uuid.c",
857};
858
859pub const always_link_libs = [_][]const u8{
860 "advapi32",
861 "kernel32",
862 "msvcrt",
863 "ntdll",
864 "shell32",
865 "user32",
866};
src/musl.zig-3
...@@ -7,9 +7,6 @@ const assert = std.debug.assert;...@@ -7,9 +7,6 @@ const assert = std.debug.assert;
7const target_util = @import("target.zig");7const target_util = @import("target.zig");
8const Compilation = @import("Compilation.zig");8const Compilation = @import("Compilation.zig");
9const build_options = @import("build_options");9const build_options = @import("build_options");
10const trace = @import("tracy.zig").trace;
11const Cache = @import("Cache.zig");
12const Package = @import("Package.zig");
1310
14pub const CRTFile = enum {11pub const CRTFile = enum {
15 crti_o,12 crti_o,
src/stage1.zig+8
...@@ -121,6 +121,14 @@ pub const Module = extern struct {...@@ -121,6 +121,14 @@ pub const Module = extern struct {
121 verbose_cimport: bool,121 verbose_cimport: bool,
122 verbose_llvm_cpu_features: bool,122 verbose_llvm_cpu_features: bool,
123123
124 // Set by stage1
125 have_c_main: bool,
126 have_winmain: bool,
127 have_wwinmain: bool,
128 have_winmain_crt_startup: bool,
129 have_wwinmain_crt_startup: bool,
130 have_dllmain_crt_startup: bool,
131
124 pub fn build_object(mod: *Module) void {132 pub fn build_object(mod: *Module) void {
125 zig_stage1_build_object(mod);133 zig_stage1_build_object(mod);
126 }134 }
src/stage1/all_types.hpp-6
...@@ -2152,12 +2152,6 @@ struct CodeGen {...@@ -2152,12 +2152,6 @@ struct CodeGen {
2152 uint32_t next_unresolved_index;2152 uint32_t next_unresolved_index;
2153 unsigned pointer_size_bytes;2153 unsigned pointer_size_bytes;
2154 bool is_big_endian;2154 bool is_big_endian;
2155 bool have_c_main;
2156 bool have_winmain;
2157 bool have_wwinmain;
2158 bool have_winmain_crt_startup;
2159 bool have_wwinmain_crt_startup;
2160 bool have_dllmain_crt_startup;
2161 bool have_err_ret_tracing;2155 bool have_err_ret_tracing;
2162 bool verbose_tokenize;2156 bool verbose_tokenize;
2163 bool verbose_ast;2157 bool verbose_ast;
src/stage1/analyze.cpp+6-6
...@@ -3496,18 +3496,18 @@ void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLink...@@ -3496,18 +3496,18 @@ void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLink
34963496
3497void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc) {3497void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc) {
3498 if (cc == CallingConventionC && strcmp(symbol_name, "main") == 0 && g->link_libc) {3498 if (cc == CallingConventionC && strcmp(symbol_name, "main") == 0 && g->link_libc) {
3499 g->have_c_main = true;3499 g->stage1.have_c_main = true;
3500 } else if (cc == CallingConventionStdcall && g->zig_target->os == OsWindows) {3500 } else if (cc == CallingConventionStdcall && g->zig_target->os == OsWindows) {
3501 if (strcmp(symbol_name, "WinMain") == 0) {3501 if (strcmp(symbol_name, "WinMain") == 0) {
3502 g->have_winmain = true;3502 g->stage1.have_winmain = true;
3503 } else if (strcmp(symbol_name, "wWinMain") == 0) {3503 } else if (strcmp(symbol_name, "wWinMain") == 0) {
3504 g->have_wwinmain = true;3504 g->stage1.have_wwinmain = true;
3505 } else if (strcmp(symbol_name, "WinMainCRTStartup") == 0) {3505 } else if (strcmp(symbol_name, "WinMainCRTStartup") == 0) {
3506 g->have_winmain_crt_startup = true;3506 g->stage1.have_winmain_crt_startup = true;
3507 } else if (strcmp(symbol_name, "wWinMainCRTStartup") == 0) {3507 } else if (strcmp(symbol_name, "wWinMainCRTStartup") == 0) {
3508 g->have_wwinmain_crt_startup = true;3508 g->stage1.have_wwinmain_crt_startup = true;
3509 } else if (strcmp(symbol_name, "DllMainCRTStartup") == 0) {3509 } else if (strcmp(symbol_name, "DllMainCRTStartup") == 0) {
3510 g->have_dllmain_crt_startup = true;3510 g->stage1.have_dllmain_crt_startup = true;
3511 }3511 }
3512 }3512 }
35133513
src/stage1/codegen.cpp+3-3
...@@ -8666,11 +8666,11 @@ TargetSubsystem detect_subsystem(CodeGen *g) {...@@ -8666,11 +8666,11 @@ TargetSubsystem detect_subsystem(CodeGen *g) {
8666 if (g->subsystem != TargetSubsystemAuto)8666 if (g->subsystem != TargetSubsystemAuto)
8667 return g->subsystem;8667 return g->subsystem;
8668 if (g->zig_target->os == OsWindows) {8668 if (g->zig_target->os == OsWindows) {
8669 if (g->have_dllmain_crt_startup)8669 if (g->stage1.have_dllmain_crt_startup)
8670 return TargetSubsystemAuto;8670 return TargetSubsystemAuto;
8671 if (g->have_c_main || g->is_test_build || g->have_winmain_crt_startup || g->have_wwinmain_crt_startup)8671 if (g->stage1.have_c_main || g->is_test_build || g->stage1.have_winmain_crt_startup || g->stage1.have_wwinmain_crt_startup)
8672 return TargetSubsystemConsole;8672 return TargetSubsystemConsole;
8673 if (g->have_winmain || g->have_wwinmain)8673 if (g->stage1.have_winmain || g->stage1.have_wwinmain)
8674 return TargetSubsystemWindows;8674 return TargetSubsystemWindows;
8675 } else if (g->zig_target->os == OsUefi) {8675 } else if (g->zig_target->os == OsUefi) {
8676 return TargetSubsystemEfiApplication;8676 return TargetSubsystemEfiApplication;
src/stage1/stage1.h+8
...@@ -195,6 +195,14 @@ struct ZigStage1 {...@@ -195,6 +195,14 @@ struct ZigStage1 {
195 bool verbose_llvm_ir;195 bool verbose_llvm_ir;
196 bool verbose_cimport;196 bool verbose_cimport;
197 bool verbose_llvm_cpu_features;197 bool verbose_llvm_cpu_features;
198
199 // Set by stage1
200 bool have_c_main;
201 bool have_winmain;
202 bool have_wwinmain;
203 bool have_winmain_crt_startup;
204 bool have_wwinmain_crt_startup;
205 bool have_dllmain_crt_startup;
198};206};
199207
200ZIG_EXTERN_C void zig_stage1_os_init(void);208ZIG_EXTERN_C void zig_stage1_os_init(void);