Skip to content

Commit e657ed4

Browse files
committed
wasm linker: implement hidden visibility
1 parent a9c497c commit e657ed4

File tree

6 files changed

+45
-25
lines changed

6 files changed

+45
-25
lines changed

src/Compilation.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3066,7 +3066,7 @@ pub fn saveState(comp: *Compilation) !void {
30663066
.wasm => {
30673067
const wasm = lf.cast(.wasm).?;
30683068
const is_obj = comp.config.output_mode == .Obj;
3069-
try bufs.ensureUnusedCapacity(83);
3069+
try bufs.ensureUnusedCapacity(85);
30703070
addBuf(&bufs, wasm.string_bytes.items);
30713071
// TODO make it well-defined memory layout
30723072
//addBuf(&bufs, mem.sliceAsBytes(wasm.objects.items));
@@ -3133,6 +3133,8 @@ pub fn saveState(comp: *Compilation) !void {
31333133
addBuf(&bufs, mem.sliceAsBytes(wasm.missing_exports.keys()));
31343134
addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.keys()));
31353135
addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.values()));
3136+
addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.keys()));
3137+
addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.values()));
31363138
addBuf(&bufs, mem.sliceAsBytes(wasm.global_exports.items));
31373139
addBuf(&bufs, mem.sliceAsBytes(wasm.functions.keys()));
31383140
addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.keys()));

src/link/Wasm.zig

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ entry_resolution: FunctionImport.Resolution = .unresolved,
210210

211211
/// Empty when outputting an object.
212212
function_exports: std.AutoArrayHashMapUnmanaged(String, FunctionIndex) = .empty,
213-
/// Tracks the value at the end of prelink.
214-
function_exports_len: u32 = 0,
213+
hidden_function_exports: std.AutoArrayHashMapUnmanaged(String, FunctionIndex) = .empty,
215214
global_exports: std.ArrayListUnmanaged(GlobalExport) = .empty,
216215
/// Tracks the value at the end of prelink.
217216
global_exports_len: u32 = 0,
@@ -360,9 +359,8 @@ pub const FunctionIndex = enum(u32) {
360359
if (wasm.object_function_imports.getPtr(name)) |import| {
361360
return fromResolution(wasm, import.resolution);
362361
}
363-
if (wasm.function_exports.get(name)) |index| {
364-
return index;
365-
}
362+
if (wasm.function_exports.get(name)) |index| return index;
363+
if (wasm.hidden_function_exports.get(name)) |index| return index;
366364
return null;
367365
}
368366

@@ -1919,8 +1917,11 @@ pub const DataSegmentId = enum(u32) {
19191917
const zcu = wasm.base.comp.zcu.?;
19201918
const ip = &zcu.intern_pool;
19211919
const nav = ip.getNav(i.key(wasm).*);
1922-
return nav.getLinkSection().toSlice(ip) orelse
1923-
if (nav.isThreadlocal(ip)) ".tdata" else ".data";
1920+
return nav.getLinkSection().toSlice(ip) orelse switch (category(id, wasm)) {
1921+
.tls => ".tdata",
1922+
.data => ".data",
1923+
.zero => ".bss",
1924+
};
19241925
},
19251926
};
19261927
}
@@ -3110,6 +3111,7 @@ pub fn deinit(wasm: *Wasm) void {
31103111

31113112
wasm.func_types.deinit(gpa);
31123113
wasm.function_exports.deinit(gpa);
3114+
wasm.hidden_function_exports.deinit(gpa);
31133115
wasm.function_imports.deinit(gpa);
31143116
wasm.functions.deinit(gpa);
31153117
wasm.globals.deinit(gpa);
@@ -3417,7 +3419,6 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
34173419
}
34183420
}
34193421
wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
3420-
wasm.function_exports_len = @intCast(wasm.function_exports.entries.len);
34213422

34223423
for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| {
34233424
if (import.flags.isIncluded(rdynamic)) {
@@ -3491,8 +3492,14 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) link.File.FlushError!void {
34913492
const function = i.ptr(wasm);
34923493
markObject(wasm, function.object_index);
34933494

3494-
if (!is_obj and function.flags.isExported(rdynamic))
3495-
try wasm.function_exports.put(gpa, function.name.unwrap().?, @enumFromInt(gop.index));
3495+
if (!is_obj and function.flags.isExported(rdynamic)) {
3496+
const symbol_name = function.name.unwrap().?;
3497+
if (function.flags.visibility_hidden) {
3498+
try wasm.hidden_function_exports.put(gpa, symbol_name, @enumFromInt(gop.index));
3499+
} else {
3500+
try wasm.function_exports.put(gpa, symbol_name, @enumFromInt(gop.index));
3501+
}
3502+
}
34963503

34973504
try wasm.markRelocations(function.relocations(wasm));
34983505
}
@@ -3778,6 +3785,9 @@ pub fn flushModule(
37783785
const function_exports_end_zcu: u32 = @intCast(wasm.function_exports.entries.len);
37793786
defer wasm.function_exports.shrinkRetainingCapacity(function_exports_end_zcu);
37803787

3788+
const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len);
3789+
defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu);
3790+
37813791
wasm.flush_buffer.clear();
37823792
try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{});
37833793
try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values());

src/link/Wasm/Flush.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
164164
}
165165
}
166166

167-
for (wasm.nav_exports.keys()) |*nav_export| {
167+
for (wasm.nav_exports.keys(), wasm.nav_exports.values()) |*nav_export, export_index| {
168168
if (ip.isFunctionType(ip.getNav(nav_export.nav_index).typeOf(ip))) {
169169
log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });
170-
try wasm.function_exports.put(gpa, nav_export.name, Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?);
170+
const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;
171+
switch (export_index.ptr(zcu).opts.visibility) {
172+
.default, .protected => try wasm.function_exports.put(gpa, nav_export.name, function_index),
173+
.hidden => try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index),
174+
}
171175
_ = f.missing_exports.swapRemove(nav_export.name);
172176
_ = f.function_imports.swapRemove(nav_export.name);
173177

test/link/wasm/bss/build.zig

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,14 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt
4747
check_lib.checkInHeaders();
4848
check_lib.checkExact("Section custom");
4949
check_lib.checkExact("type data_segment");
50-
check_lib.checkExact("names 2");
51-
check_lib.checkExact("index 0");
52-
check_lib.checkExact("name .rodata");
50+
check_lib.checkExact("names 1");
5351
// for safe optimization modes `undefined` is stored in data instead of bss.
5452
if (is_safe) {
55-
check_lib.checkExact("index 1");
53+
check_lib.checkExact("index 0");
5654
check_lib.checkExact("name .data");
5755
check_lib.checkNotPresent("name .bss");
5856
} else {
59-
check_lib.checkExact("index 1"); // bss section always last
57+
check_lib.checkExact("index 0"); // bss section always last
6058
check_lib.checkExact("name .bss");
6159
}
6260
test_step.dependOn(&check_lib.step);
@@ -84,10 +82,8 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt
8482
check_lib.checkInHeaders();
8583
check_lib.checkExact("Section custom");
8684
check_lib.checkExact("type data_segment");
87-
check_lib.checkExact("names 2");
85+
check_lib.checkExact("names 1");
8886
check_lib.checkExact("index 0");
89-
check_lib.checkExact("name .rodata");
90-
check_lib.checkExact("index 1");
9187
check_lib.checkExact("name .bss");
9288

9389
test_step.dependOn(&check_lib.step);

test/link/wasm/bss/lib.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
pub var bss: u32 = undefined;
22

3-
export fn foo() void {
4-
_ = bss;
3+
fn foo() callconv(.c) u32 {
4+
return bss;
5+
}
6+
7+
comptime {
8+
@export(&foo, .{ .name = "foo", .visibility = .hidden });
59
}

test/link/wasm/bss/lib2.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
pub var bss: u32 = 0;
22

3-
export fn foo() void {
4-
_ = bss;
3+
fn foo() callconv(.c) u32 {
4+
return bss;
5+
}
6+
7+
comptime {
8+
@export(&foo, .{ .name = "foo", .visibility = .hidden });
59
}

0 commit comments

Comments
 (0)