authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-30 21:48:05-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
loga4bee3009a45557f788472bd3b396b5528bf0a96
treec55c240958cf69ca00cde3ff00055e7b063c4dbc
parent9ccf500508923c5694904e660b7dfbd563aba68b

wasm linker: implement __wasm_call_ctors


2 files changed, 34 insertions(+), 1 deletions(-)

src/link/Wasm.zig+5
......@@ -378,6 +378,7 @@ pub const OutputFunctionIndex = enum(u32) {
378378 }
379379
380380 pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex {
381 if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @enumFromInt(i);
381382 return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?);
382383 }
383384};
......@@ -3002,6 +3003,10 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
30023003 try markFunctionImport(wasm, name, import, @enumFromInt(i));
30033004 }
30043005 }
3006 // Also treat init functions as roots.
3007 for (wasm.object_init_funcs.items) |init_func| {
3008 try markFunction(wasm, init_func.function_index);
3009 }
30053010 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
30063011 wasm.function_exports_len = @intCast(wasm.function_exports.items.len);
30073012
src/link/Wasm/Flush.zig+29-1
......@@ -679,7 +679,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
679679 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {
680680 .unresolved => unreachable,
681681 .__wasm_apply_global_tls_relocs => @panic("TODO lower __wasm_apply_global_tls_relocs"),
682 .__wasm_call_ctors => @panic("TODO lower __wasm_call_ctors"),
682 .__wasm_call_ctors => {
683 const code_start = try reserveSize(gpa, binary_bytes);
684 defer replaceSize(binary_bytes, code_start);
685 try emitCallCtorsFunction(wasm, binary_bytes);
686 },
683687 .__wasm_init_memory => @panic("TODO lower __wasm_init_memory "),
684688 .__wasm_init_tls => @panic("TODO lower __wasm_init_tls "),
685689 .object_function => |i| {
......@@ -1559,3 +1563,27 @@ fn reloc_leb_table(code: []u8, table: Wasm.TableIndex) void {
15591563fn reloc_leb_type(code: []u8, index: Wasm.FunctionType.Index) void {
15601564 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));
15611565}
1566
1567fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
1568 const gpa = wasm.base.comp.gpa;
1569
1570 try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1);
1571 leb.writeUleb128(binary_bytes.fixedWriter(), @as(u32, 0)) catch unreachable; // no locals
1572
1573 for (wasm.object_init_funcs.items) |init_func| {
1574 const func = init_func.function_index.ptr(wasm);
1575 const ty = func.type_index.ptr(wasm);
1576 const n_returns = ty.returns.slice(wasm).len;
1577
1578 // Call function by its function index
1579 try binary_bytes.ensureUnusedCapacity(gpa, 1 + 5 + n_returns + 1);
1580 const call_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);
1581 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));
1582 leb.writeUleb128(binary_bytes.fixedWriter(), @intFromEnum(call_index)) catch unreachable;
1583
1584 // drop all returned values from the stack as __wasm_call_ctors has no return value
1585 binary_bytes.appendNTimesAssumeCapacity(@intFromEnum(std.wasm.Opcode.drop), n_returns);
1586 }
1587
1588 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); // end function body
1589}