| ... | ... | @@ -17,6 +17,8 @@ const target_util = @import("../target.zig"); |
| 17 | 17 | const Type = @import("../Type.zig"); |
| 18 | 18 | const Value = @import("../Value.zig"); |
| 19 | 19 | const Zcu = @import("../Zcu.zig"); |
| 20 | const ModuleDefinition = @import("../libs/mingw/def.zig").ModuleDefinition; |
| 21 | const implib = @import("../libs/mingw/implib.zig"); |
| 20 | 22 | |
| 21 | 23 | base: link.File, |
| 22 | 24 | mf: MappedFile, |
| ... | ... | @@ -287,6 +289,7 @@ pub const ExportTable = struct { |
| 287 | 289 | pending_sort: bool = false, |
| 288 | 290 | |
| 289 | 291 | pub const Entry = struct { |
| 292 | si: Symbol.Index, |
| 290 | 293 | name_index: u32, |
| 291 | 294 | name_len: u32, |
| 292 | 295 | export_address_table_ri: Reloc.Index, |
| ... | ... | @@ -1888,6 +1891,81 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void { |
| 1888 | 1891 | }; |
| 1889 | 1892 | } |
| 1890 | 1893 | |
| 1894 | fn flushImplib( |
| 1895 | coff: *Coff, |
| 1896 | implib_file: []const u8, |
| 1897 | ) !void { |
| 1898 | // Emitting implibs is only valid for images |
| 1899 | assert(coff.export_table.ni != .none); |
| 1900 | |
| 1901 | const comp = coff.base.comp; |
| 1902 | const gpa = comp.gpa; |
| 1903 | const io = comp.io; |
| 1904 | |
| 1905 | const image_name = std.mem.sliceTo( |
| 1906 | coff.export_table.ni.slice(&coff.mf)[@sizeOf(std.coff.ExportDirectoryTable)..], |
| 1907 | 0, |
| 1908 | ); |
| 1909 | const machine_type = coff.targetLoad(&coff.headerPtr().machine); |
| 1910 | const members = members: { |
| 1911 | const def_arena: std.heap.ArenaAllocator = .init(gpa); |
| 1912 | var def: ModuleDefinition = .{ |
| 1913 | .name = image_name, |
| 1914 | .arena = def_arena, |
| 1915 | .type = .mingw, |
| 1916 | }; |
| 1917 | defer def.deinit(); |
| 1918 | |
| 1919 | try def.exports.ensureUnusedCapacity( |
| 1920 | def.arena.allocator(), |
| 1921 | coff.export_table.entries.count(), |
| 1922 | ); |
| 1923 | |
| 1924 | const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf); |
| 1925 | for (coff.export_table.entries.values(), 0..) |entry, ord| { |
| 1926 | const name = name_table_slice[entry.name_index..][0..entry.name_len]; |
| 1927 | const section_number = entry.si.get(coff).section_number; |
| 1928 | const import_type: std.coff.ImportType = switch (section_number.symbol(coff)) { |
| 1929 | .data, .rdata => .DATA, |
| 1930 | .text => .CODE, |
| 1931 | else => return comp.link_diags.fail( |
| 1932 | "unsupported section for export '{s}': {s}", |
| 1933 | .{ name, &section_number.header(coff).name }, |
| 1934 | ), |
| 1935 | }; |
| 1936 | |
| 1937 | def.exports.appendAssumeCapacity(.{ |
| 1938 | .name = name, |
| 1939 | .mangled_symbol_name = null, |
| 1940 | .ext_name = null, |
| 1941 | .import_name = null, |
| 1942 | .export_as = null, |
| 1943 | .no_name = false, |
| 1944 | .ordinal = @intCast(ord), |
| 1945 | .type = import_type, |
| 1946 | .private = false, |
| 1947 | }); |
| 1948 | } |
| 1949 | |
| 1950 | def.fixupForImportLibraryGeneration(machine_type); |
| 1951 | break :members try implib.getMembers(gpa, def, machine_type); |
| 1952 | }; |
| 1953 | defer members.deinit(); |
| 1954 | |
| 1955 | const lib_sub_path = try std.fs.path.join(gpa, &.{ |
| 1956 | std.fs.path.dirname(coff.base.emit.sub_path) orelse "", |
| 1957 | implib_file, |
| 1958 | }); |
| 1959 | defer gpa.free(lib_sub_path); |
| 1960 | |
| 1961 | const lib_final_file = try coff.base.emit.root_dir.handle.createFile(io, lib_sub_path, .{ .truncate = true }); |
| 1962 | defer lib_final_file.close(io); |
| 1963 | var buffer: [1024]u8 = undefined; |
| 1964 | var file_writer = lib_final_file.writer(io, &buffer); |
| 1965 | try implib.writeCoffArchive(gpa, &file_writer.interface, members); |
| 1966 | try file_writer.interface.flush(); |
| 1967 | } |
| 1968 | |
| 1891 | 1969 | pub fn flush( |
| 1892 | 1970 | coff: *Coff, |
| 1893 | 1971 | arena: std.mem.Allocator, |
| ... | ... | @@ -1898,11 +1976,18 @@ pub fn flush( |
| 1898 | 1976 | _ = prog_node; |
| 1899 | 1977 | while (try coff.idle(tid)) {} |
| 1900 | 1978 | |
| 1901 | | // hack for stage2_x86_64 + coff |
| 1902 | 1979 | const comp = coff.base.comp; |
| 1980 | |
| 1981 | // Implib generation should instead be done via building a MappedFile progressively |
| 1982 | if (comp.emit_implib) |implib_file| |
| 1983 | coff.flushImplib(implib_file) catch |err| |
| 1984 | return comp.link_diags.fail("flushing implib '{s}' failed: {t}", .{ implib_file, err }); |
| 1985 | |
| 1986 | // hack for stage2_x86_64 + coff |
| 1903 | 1987 | if (comp.compiler_rt_dyn_lib) |crt_file| { |
| 1904 | 1988 | const gpa = comp.gpa; |
| 1905 | 1989 | const io = comp.io; |
| 1990 | |
| 1906 | 1991 | const compiler_rt_sub_path = try std.fs.path.join(gpa, &.{ |
| 1907 | 1992 | std.fs.path.dirname(coff.base.emit.sub_path) orelse "", |
| 1908 | 1993 | std.fs.path.basename(crt_file.full_object_path.sub_path), |
| ... | ... | @@ -2670,6 +2755,7 @@ fn updateExportsInner( |
| 2670 | 2755 | ); |
| 2671 | 2756 | |
| 2672 | 2757 | gop.value_ptr.* = .{ |
| 2758 | .si = export_si, |
| 2673 | 2759 | .name_index = @intCast(name_index), |
| 2674 | 2760 | .name_len = @intCast(name.len), |
| 2675 | 2761 | .export_address_table_ri = @enumFromInt(coff.relocs.items.len), |
| ... | ... | @@ -2683,6 +2769,7 @@ fn updateExportsInner( |
| 2683 | 2769 | .{ .AMD64 = .ADDR32NB }, |
| 2684 | 2770 | ); |
| 2685 | 2771 | } else { |
| 2772 | gop.value_ptr.si = export_si; |
| 2686 | 2773 | const reloc = gop.value_ptr.*.export_address_table_ri.get(coff); |
| 2687 | 2774 | reloc.target = export_si; |
| 2688 | 2775 | export_si.applyTargetRelocs(coff); |