mirror of
https://github.com/ziglang/zig.git
synced 2026-02-09 11:03:30 +00:00
wasm linker: flush export section
This commit is contained in:
parent
bf88059591
commit
264a63b000
@ -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);
|
||||
|
||||
@ -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| {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user