authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-14 20:03:21-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log617eca13eb13936eaaac8252820402e869f3c00f
tree077419799c910d1175e29b0d73d09de2b13b02d5
parentc2a918b7a38fedb71814c295b41751ac1a5ea0f4

wasm-linker: remap function types during flush

this is technically not necessary, and loses value the bigger the output binary is, however it means a smaller output file, so let's do it.

3 files changed, 34 insertions(+), 12 deletions(-)

src/arch/wasm/Emit.zig+2-1
...@@ -187,7 +187,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -187,7 +187,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {
187 });187 });
188 code.appendNTimesAssumeCapacity(0, 5);188 code.appendNTimesAssumeCapacity(0, 5);
189 } else {189 } else {
190 leb.writeUleb128(code.fixedWriter(), @intFromEnum(func_ty_index)) catch unreachable;190 const index: Wasm.Flush.FuncTypeIndex = .fromTypeIndex(func_ty_index, &wasm.flush_buffer);
191 leb.writeUleb128(code.fixedWriter(), @intFromEnum(index)) catch unreachable;
191 }192 }
192 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // table index193 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // table index
193194
src/link/Wasm.zig+1-1
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
12const Wasm = @This();12const Wasm = @This();
13const Archive = @import("Wasm/Archive.zig");13const Archive = @import("Wasm/Archive.zig");
14const Object = @import("Wasm/Object.zig");14const Object = @import("Wasm/Object.zig");
15const Flush = @import("Wasm/Flush.zig");15pub const Flush = @import("Wasm/Flush.zig");
1616
17const builtin = @import("builtin");17const builtin = @import("builtin");
18const native_endian = builtin.cpu.arch.endian();18const native_endian = builtin.cpu.arch.endian();
src/link/Wasm/Flush.zig+31-10
...@@ -36,9 +36,21 @@ data_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.DataImportId) = .empty,...@@ -36,9 +36,21 @@ data_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.DataImportId) = .empty,
3636
37indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, void) = .empty,37indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, void) = .empty,
3838
39/// A subset of the full interned function type list created only during flush.
40func_types: std.AutoArrayHashMapUnmanaged(Wasm.FunctionType.Index, void) = .empty,
41
39/// For debug purposes only.42/// For debug purposes only.
40memory_layout_finished: bool = false,43memory_layout_finished: bool = false,
4144
45/// Index into `func_types`.
46pub const FuncTypeIndex = enum(u32) {
47 _,
48
49 pub fn fromTypeIndex(i: Wasm.FunctionType.Index, f: *const Flush) FuncTypeIndex {
50 return @enumFromInt(f.func_types.getIndex(i).?);
51 }
52};
53
42/// Index into `indirect_function_table`.54/// Index into `indirect_function_table`.
43const IndirectFunctionTableIndex = enum(u32) {55const IndirectFunctionTableIndex = enum(u32) {
44 _,56 _,
...@@ -75,6 +87,7 @@ pub fn clear(f: *Flush) void {...@@ -75,6 +87,7 @@ pub fn clear(f: *Flush) void {
75 f.data_segment_groups.clearRetainingCapacity();87 f.data_segment_groups.clearRetainingCapacity();
76 f.binary_bytes.clearRetainingCapacity();88 f.binary_bytes.clearRetainingCapacity();
77 f.indirect_function_table.clearRetainingCapacity();89 f.indirect_function_table.clearRetainingCapacity();
90 f.func_types.clearRetainingCapacity();
78 f.memory_layout_finished = false;91 f.memory_layout_finished = false;
79}92}
8093
...@@ -87,6 +100,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {...@@ -87,6 +100,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {
87 f.global_imports.deinit(gpa);100 f.global_imports.deinit(gpa);
88 f.data_imports.deinit(gpa);101 f.data_imports.deinit(gpa);
89 f.indirect_function_table.deinit(gpa);102 f.indirect_function_table.deinit(gpa);
103 f.func_types.deinit(gpa);
90 f.* = undefined;104 f.* = undefined;
91}105}
92106
...@@ -510,11 +524,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -510,11 +524,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
510524
511 const binary_writer = binary_bytes.writer(gpa);525 const binary_writer = binary_bytes.writer(gpa);
512526
513 // Type section527 // Type section.
514 if (wasm.func_types.entries.len != 0) {528 for (f.function_imports.values()) |id| {
529 try f.func_types.put(gpa, id.functionType(wasm), {});
530 }
531 for (wasm.functions.keys()) |function| {
532 try f.func_types.put(gpa, function.typeIndex(wasm), {});
533 }
534 if (f.func_types.entries.len != 0) {
515 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);535 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
516 log.debug("Writing type section. Count: ({d})", .{wasm.func_types.entries.len});536 for (f.func_types.keys()) |func_type_index| {
517 for (wasm.func_types.keys()) |func_type| {537 const func_type = func_type_index.ptr(wasm);
518 try leb.writeUleb128(binary_writer, std.wasm.function_type);538 try leb.writeUleb128(binary_writer, std.wasm.function_type);
519 const params = func_type.params.slice(wasm);539 const params = func_type.params.slice(wasm);
520 try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len)));540 try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len)));
...@@ -527,8 +547,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -527,8 +547,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
527 try leb.writeUleb128(binary_writer, @intFromEnum(ret_ty));547 try leb.writeUleb128(binary_writer, @intFromEnum(ret_ty));
528 }548 }
529 }549 }
530550 replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(f.func_types.entries.len));
531 replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(wasm.func_types.entries.len));
532 section_index += 1;551 section_index += 1;
533 }552 }
534553
...@@ -553,7 +572,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -553,7 +572,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
553 try binary_writer.writeAll(name);572 try binary_writer.writeAll(name);
554573
555 try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function));574 try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
556 try leb.writeUleb128(binary_writer, @intFromEnum(id.functionType(wasm)));575 const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f);
576 try leb.writeUleb128(binary_writer, @intFromEnum(type_index));
557 }577 }
558 total_imports += f.function_imports.entries.len;578 total_imports += f.function_imports.entries.len;
559579
...@@ -615,7 +635,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -615,7 +635,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
615 if (wasm.functions.count() != 0) {635 if (wasm.functions.count() != 0) {
616 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);636 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
617 for (wasm.functions.keys()) |function| {637 for (wasm.functions.keys()) |function| {
618 try leb.writeUleb128(binary_writer, @intFromEnum(function.typeIndex(wasm)));638 const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f);
639 try leb.writeUleb128(binary_writer, @intFromEnum(index));
619 }640 }
620641
621 replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count()));642 replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count()));
...@@ -1644,7 +1665,7 @@ fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.Itera...@@ -1644,7 +1665,7 @@ fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.Itera
1644 .table_number_leb => reloc_leb_table(sliced_code, .fromObjectTable(wasm, pointee.table)),1665 .table_number_leb => reloc_leb_table(sliced_code, .fromObjectTable(wasm, pointee.table)),
1645 .table_import_number_leb => reloc_leb_table(sliced_code, .fromSymbolName(wasm, pointee.symbol_name)),1666 .table_import_number_leb => reloc_leb_table(sliced_code, .fromSymbolName(wasm, pointee.symbol_name)),
16461667
1647 .type_index_leb => reloc_leb_type(sliced_code, pointee.type_index),1668 .type_index_leb => reloc_leb_type(sliced_code, .fromTypeIndex(pointee.type_index, &wasm.flush_buffer)),
1648 }1669 }
1649 }1670 }
1650}1671}
...@@ -1733,7 +1754,7 @@ fn reloc_leb_table(code: []u8, table: Wasm.TableIndex) void {...@@ -1733,7 +1754,7 @@ fn reloc_leb_table(code: []u8, table: Wasm.TableIndex) void {
1733 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(table));1754 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(table));
1734}1755}
17351756
1736fn reloc_leb_type(code: []u8, index: Wasm.FunctionType.Index) void {1757fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void {
1737 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));1758 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));
1738}1759}
17391760