From a35f156cf60ed3d8095c15c4ab26aee267761a56 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 31 Aug 2022 19:55:39 +0200 Subject: [PATCH] coff: re-enable default entrypoint for Windows --- lib/std/start.zig | 4 +++ src/arch/x86_64/CodeGen.zig | 24 +++++++++++++-- src/link.zig | 2 +- src/link/Coff.zig | 30 +++++++++++++++++-- .../hello_world_with_updates.0.zig | 2 +- .../hello_world_with_updates.0.zig | 2 +- .../hello_world_with_updates.0.zig | 2 +- 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 49094ab02d..9f70cce1ea 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -36,6 +36,10 @@ comptime { if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { @export(main2, .{ .name = "main" }); } + } else if (builtin.os.tag == .windows) { + if (!@hasDecl(root, "wWinMainCRTStartup") and !@hasDecl(root, "mainCRTStartup")) { + @export(wWinMainCRTStartup2, .{ .name = "wWinMainCRTStartup" }); + } } else if (builtin.os.tag == .wasi and @hasDecl(root, "main")) { @export(wasiMain2, .{ .name = "_start" }); } else { diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index e5d47e589a..d7294e9732 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3999,7 +3999,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. .data = undefined, }); } - } else if (self.bin_file.cast(link.File.Coff)) |_| { + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { if (self.air.value(callee)) |func_value| { if (func_value.castTag(.function)) |func_payload| { const func = func_payload.data; @@ -4015,8 +4015,26 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. }), .data = undefined, }); - } else if (func_value.castTag(.extern_fn)) |_| { - return self.fail("TODO implement calling extern functions", .{}); + } else if (func_value.castTag(.extern_fn)) |func_payload| { + const extern_fn = func_payload.data; + const decl_name = mod.declPtr(extern_fn.owner_decl).name; + if (extern_fn.lib_name) |lib_name| { + log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ + decl_name, + lib_name, + }); + } + const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); + _ = try self.addInst(.{ + .tag = .call_extern, + .ops = undefined, + .data = .{ + .relocation = .{ + .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.coff.sym_index, + .sym_index = sym_index, + }, + }, + }); } else { return self.fail("TODO implement calling bitcasted functions", .{}); } diff --git a/src/link.zig b/src/link.zig index a8845a0d57..986f4e81b6 100644 --- a/src/link.zig +++ b/src/link.zig @@ -473,7 +473,7 @@ pub const File = struct { log.debug("getGlobalSymbol '{s}'", .{name}); switch (base.tag) { // zig fmt: off - .coff => unreachable, + .coff => return @fieldParentPtr(Coff, "base", base).getGlobalSymbol(name), .elf => unreachable, .macho => return @fieldParentPtr(MachO, "base", base).getGlobalSymbol(name), .plan9 => unreachable, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index e302571671..bf6a32431c 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -596,7 +596,7 @@ fn allocateSymbol(self: *Coff) !u32 { self.locals.items[index] = .{ .name = [_]u8{0} ** 8, .value = 0, - .section_number = @intToEnum(coff.SectionNumber, 0), + .section_number = .UNDEFINED, .@"type" = .{ .base_type = .NULL, .complex_type = .NULL }, .storage_class = .NULL, .number_of_aux_symbols = 0, @@ -1027,7 +1027,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); } - self.locals.items[sym_index].section_number = @intToEnum(coff.SectionNumber, 0); + self.locals.items[sym_index].section_number = .UNDEFINED; _ = self.atom_by_index_table.remove(sym_index); decl.link.coff.sym_index = 0; } @@ -1268,6 +1268,30 @@ pub fn getDeclVAddr( @panic("TODO getDeclVAddr"); } +pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 { + const gpa = self.base.allocator; + const sym_name = try gpa.dupe(u8, name); + const global_index = @intCast(u32, self.globals.values().len); + _ = global_index; + const gop = try self.globals.getOrPut(gpa, sym_name); + defer if (gop.found_existing) gpa.free(sym_name); + + if (gop.found_existing) { + // TODO audit this: can we ever reference anything from outside the Zig module? + assert(gop.value_ptr.file == null); + return gop.value_ptr.sym_index; + } + + const sym_index = try self.allocateSymbol(); + const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; + const sym = self.getSymbolPtr(sym_loc); + try self.setSymbolName(sym, sym_name); + sym.storage_class = .EXTERNAL; + gop.value_ptr.* = sym_loc; + + return sym_index; +} + pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void { _ = self; _ = module; @@ -1614,7 +1638,7 @@ inline fn getSizeOfImage(self: Coff) u32 { /// Returns symbol location corresponding to the set entrypoint (if any). pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { - const entry_name = self.base.options.entry orelse "_start"; // TODO this is incomplete + const entry_name = self.base.options.entry orelse "wWinMainCRTStartup"; // TODO this is incomplete return self.globals.get(entry_name); } diff --git a/test/cases/aarch64-macos/hello_world_with_updates.0.zig b/test/cases/aarch64-macos/hello_world_with_updates.0.zig index dc65cd8279..0de742bdec 100644 --- a/test/cases/aarch64-macos/hello_world_with_updates.0.zig +++ b/test/cases/aarch64-macos/hello_world_with_updates.0.zig @@ -2,5 +2,5 @@ // output_mode=Exe // target=aarch64-macos // -// :105:9: error: struct 'tmp.tmp' has no member named 'main' +// :107:9: error: struct 'tmp.tmp' has no member named 'main' // :7:1: note: struct declared here diff --git a/test/cases/x86_64-linux/hello_world_with_updates.0.zig b/test/cases/x86_64-linux/hello_world_with_updates.0.zig index 795f4f2991..4816ec1b26 100644 --- a/test/cases/x86_64-linux/hello_world_with_updates.0.zig +++ b/test/cases/x86_64-linux/hello_world_with_updates.0.zig @@ -2,5 +2,5 @@ // output_mode=Exe // target=x86_64-linux // -// :105:9: error: struct 'tmp.tmp' has no member named 'main' +// :107:9: error: struct 'tmp.tmp' has no member named 'main' // :7:1: note: struct declared here diff --git a/test/cases/x86_64-macos/hello_world_with_updates.0.zig b/test/cases/x86_64-macos/hello_world_with_updates.0.zig index 9839371e31..998b2f13eb 100644 --- a/test/cases/x86_64-macos/hello_world_with_updates.0.zig +++ b/test/cases/x86_64-macos/hello_world_with_updates.0.zig @@ -2,5 +2,5 @@ // output_mode=Exe // target=x86_64-macos // -// :105:9: error: struct 'tmp.tmp' has no member named 'main' +// :107:9: error: struct 'tmp.tmp' has no member named 'main' // :7:1: note: struct declared here