Commit 264a63b000
src/link/Wasm/Flush.zig
@@ -79,14 +79,20 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
for (wasm.nav_exports.keys()) |*nav_export| {
if (ip.isFunctionType(ip.getNav(nav_export.nav_index).typeOf(ip))) {
- try wasm.function_exports.append(gpa, Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?);
+ try wasm.function_exports.append(gpa, .{
+ .name = nav_export.name,
+ .function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?,
+ });
_ = f.missing_exports.swapRemove(nav_export.name);
_ = wasm.function_imports.swapRemove(nav_export.name);
if (nav_export.name.toOptional() == entry_name)
wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index);
} else {
- try wasm.global_exports.append(gpa, Wasm.GlobalIndex.fromIpNav(wasm, nav_export.nav_index).?);
+ try wasm.global_exports.append(gpa, .{
+ .name = nav_export.name,
+ .global_index = Wasm.GlobalIndex.fromIpNav(wasm, nav_export.nav_index).?,
+ });
_ = f.missing_exports.swapRemove(nav_export.name);
_ = wasm.global_imports.swapRemove(nav_export.name);
}
@@ -437,8 +443,12 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
}
total_imports += wasm.global_imports.entries.len;
- replaceVecSectionHeader(binary_bytes, header_offset, .import, @intCast(total_imports));
- section_index += 1;
+ if (total_imports > 0) {
+ replaceVecSectionHeader(binary_bytes, header_offset, .import, @intCast(total_imports));
+ section_index += 1;
+ } else {
+ binary_bytes.shrinkRetainingCapacity(header_offset);
+ }
}
// Function section
@@ -474,7 +484,8 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
}
// Global section (used to emit stack pointer)
- if (wasm.globals.entries.len > 0) {
+ const globals_len: u32 = @intCast(wasm.globals.entries.len);
+ if (globals_len > 0) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
for (wasm.globals.keys()) |global_resolution| {
@@ -498,32 +509,50 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
}
}
- replaceVecSectionHeader(binary_bytes, header_offset, .global, @intCast(wasm.globals.entries.len));
+ replaceVecSectionHeader(binary_bytes, header_offset, .global, globals_len);
section_index += 1;
}
// Export section
- if (wasm.exports.items.len != 0 or export_memory) {
+ {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
+ var exports_len: usize = 0;
- for (wasm.exports.items) |exp| {
+ for (wasm.function_exports.items) |exp| {
const name = exp.name.slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
- try binary_writer.writeAll(name);
- try leb.writeUleb128(binary_writer, @intFromEnum(exp.kind));
- try leb.writeUleb128(binary_writer, exp.index);
+ try binary_bytes.appendSlice(gpa, name);
+ try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.function));
+ try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.function_imports.entries.len + @intFromEnum(exp.function_index))));
}
+ exports_len += wasm.function_exports.items.len;
+
+ // No table exports.
if (export_memory) {
- try leb.writeUleb128(binary_writer, @as(u32, @intCast("memory".len)));
- try binary_writer.writeAll("memory");
- try binary_writer.writeByte(std.wasm.externalKind(.memory));
+ const name = "memory";
+ try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
+ try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory));
try leb.writeUleb128(binary_writer, @as(u32, 0));
+ exports_len += 1;
}
- const n_items: u32 = @intCast(wasm.exports.items.len + @intFromBool(export_memory));
- replaceVecSectionHeader(binary_bytes, header_offset, .@"export", n_items);
- section_index += 1;
+ for (wasm.global_exports.items) |exp| {
+ const name = exp.name.slice(wasm);
+ try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
+ try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.global));
+ try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.global_imports.entries.len + @intFromEnum(exp.global_index))));
+ }
+ exports_len += wasm.global_exports.items.len;
+
+ if (exports_len > 0) {
+ replaceVecSectionHeader(binary_bytes, header_offset, .@"export", @intCast(exports_len));
+ section_index += 1;
+ } else {
+ binary_bytes.shrinkRetainingCapacity(header_offset);
+ }
}
if (Wasm.FunctionIndex.fromResolution(wasm.entry_resolution)) |entry_index| {
src/link/Wasm.zig
@@ -187,10 +187,10 @@ missing_exports_init: []String = &.{},
entry_resolution: FunctionImport.Resolution = .unresolved,
/// Empty when outputting an object.
-function_exports: std.ArrayListUnmanaged(FunctionIndex) = .empty,
+function_exports: std.ArrayListUnmanaged(FunctionExport) = .empty,
/// Tracks the value at the end of prelink.
function_exports_len: u32 = 0,
-global_exports: std.ArrayListUnmanaged(GlobalIndex) = .empty,
+global_exports: std.ArrayListUnmanaged(GlobalExport) = .empty,
/// Tracks the value at the end of prelink.
global_exports_len: u32 = 0,
@@ -262,16 +262,30 @@ pub const ObjectIndex = enum(u32) {
}
};
-/// Index into `functions`.
+/// Index into `Wasm.functions`.
pub const FunctionIndex = enum(u32) {
_,
+ pub fn ptr(index: FunctionIndex, wasm: *const Wasm) *FunctionImport.Resolution {
+ return &wasm.functions.keys()[@intFromEnum(index)];
+ }
+
pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?FunctionIndex {
const i = wasm.functions.getIndex(.fromIpNav(wasm, nav_index)) orelse return null;
return @enumFromInt(i);
}
};
+pub const FunctionExport = extern struct {
+ name: String,
+ function_index: FunctionIndex,
+};
+
+pub const GlobalExport = extern struct {
+ name: String,
+ global_index: GlobalIndex,
+};
+
/// 0. Index into `function_imports`
/// 1. Index into `functions`.
///
@@ -2232,8 +2246,10 @@ fn markFunction(
} else {
const gop = wasm.functions.getOrPutAssumeCapacity(import.resolution);
- if (!is_obj and import.flags.isExported(rdynamic))
- try wasm.function_exports.append(gpa, @enumFromInt(gop.index));
+ if (!is_obj and import.flags.isExported(rdynamic)) try wasm.function_exports.append(gpa, .{
+ .name = name,
+ .function_index = @enumFromInt(gop.index),
+ });
for (try wasm.functionResolutionRelocSlice(import.resolution)) |reloc|
try wasm.markReloc(reloc);
@@ -2282,8 +2298,10 @@ fn markGlobal(
} else {
const gop = wasm.globals.getOrPutAssumeCapacity(import.resolution);
- if (!is_obj and import.flags.isExported(rdynamic))
- try wasm.global_exports.append(gpa, @enumFromInt(gop.index));
+ if (!is_obj and import.flags.isExported(rdynamic)) try wasm.global_exports.append(gpa, .{
+ .name = name,
+ .global_index = @enumFromInt(gop.index),
+ });
for (try wasm.globalResolutionRelocSlice(import.resolution)) |reloc|
try wasm.markReloc(reloc);