Commit a35f156cf6
Changed files (7)
lib
std
src
test
cases
aarch64-macos
x86_64-linux
x86_64-macos
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