Commit a35f156cf6

Jakub Konka <kubkon@jakubkonka.com>
2022-08-31 19:55:39
coff: re-enable default entrypoint for Windows
1 parent 11d14a2
Changed files (7)
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 {
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", .{});
             }
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);
 }
 
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,
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
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
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