| author | |
| committer | |
| log | c535422423abc0258b03693392bae86560a9cc79 |
| tree | a8eee0bb0e957ca3aac8c491fbcfa0fb55c74dfb |
| parent | f89ef2f7cd1dd4291156e94716df60795a7ee48c |
6 files changed, 45 insertions(+), 25 deletions(-)
src/Compilation.zig+3-1| ... | ... | @@ -3066,7 +3066,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 3066 | 3066 | .wasm => { |
| 3067 | 3067 | const wasm = lf.cast(.wasm).?; |
| 3068 | 3068 | const is_obj = comp.config.output_mode == .Obj; |
| 3069 | try bufs.ensureUnusedCapacity(83); | |
| 3069 | try bufs.ensureUnusedCapacity(85); | |
| 3070 | 3070 | addBuf(&bufs, wasm.string_bytes.items); |
| 3071 | 3071 | // TODO make it well-defined memory layout |
| 3072 | 3072 | //addBuf(&bufs, mem.sliceAsBytes(wasm.objects.items)); |
| ... | ... | @@ -3133,6 +3133,8 @@ pub fn saveState(comp: *Compilation) !void { |
| 3133 | 3133 | addBuf(&bufs, mem.sliceAsBytes(wasm.missing_exports.keys())); |
| 3134 | 3134 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.keys())); |
| 3135 | 3135 | 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())); | |
| 3136 | 3138 | addBuf(&bufs, mem.sliceAsBytes(wasm.global_exports.items)); |
| 3137 | 3139 | addBuf(&bufs, mem.sliceAsBytes(wasm.functions.keys())); |
| 3138 | 3140 | addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.keys())); |
src/link/Wasm.zig+20-10| ... | ... | @@ -210,8 +210,7 @@ entry_resolution: FunctionImport.Resolution = .unresolved, |
| 210 | 210 | |
| 211 | 211 | /// Empty when outputting an object. |
| 212 | 212 | 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, | |
| 215 | 214 | global_exports: std.ArrayListUnmanaged(GlobalExport) = .empty, |
| 216 | 215 | /// Tracks the value at the end of prelink. |
| 217 | 216 | global_exports_len: u32 = 0, |
| ... | ... | @@ -360,9 +359,8 @@ pub const FunctionIndex = enum(u32) { |
| 360 | 359 | if (wasm.object_function_imports.getPtr(name)) |import| { |
| 361 | 360 | return fromResolution(wasm, import.resolution); |
| 362 | 361 | } |
| 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; | |
| 366 | 364 | return null; |
| 367 | 365 | } |
| 368 | 366 | |
| ... | ... | @@ -1919,8 +1917,11 @@ pub const DataSegmentId = enum(u32) { |
| 1919 | 1917 | const zcu = wasm.base.comp.zcu.?; |
| 1920 | 1918 | const ip = &zcu.intern_pool; |
| 1921 | 1919 | 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 | }; | |
| 1924 | 1925 | }, |
| 1925 | 1926 | }; |
| 1926 | 1927 | } |
| ... | ... | @@ -3110,6 +3111,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 3110 | 3111 | |
| 3111 | 3112 | wasm.func_types.deinit(gpa); |
| 3112 | 3113 | wasm.function_exports.deinit(gpa); |
| 3114 | wasm.hidden_function_exports.deinit(gpa); | |
| 3113 | 3115 | wasm.function_imports.deinit(gpa); |
| 3114 | 3116 | wasm.functions.deinit(gpa); |
| 3115 | 3117 | wasm.globals.deinit(gpa); |
| ... | ... | @@ -3417,7 +3419,6 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 3417 | 3419 | } |
| 3418 | 3420 | } |
| 3419 | 3421 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); |
| 3420 | wasm.function_exports_len = @intCast(wasm.function_exports.entries.len); | |
| 3421 | 3422 | |
| 3422 | 3423 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { |
| 3423 | 3424 | if (import.flags.isIncluded(rdynamic)) { |
| ... | ... | @@ -3491,8 +3492,14 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) link.File.FlushError!void { |
| 3491 | 3492 | const function = i.ptr(wasm); |
| 3492 | 3493 | markObject(wasm, function.object_index); |
| 3493 | 3494 | |
| 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 | } | |
| 3496 | 3503 | |
| 3497 | 3504 | try wasm.markRelocations(function.relocations(wasm)); |
| 3498 | 3505 | } |
| ... | ... | @@ -3778,6 +3785,9 @@ pub fn flushModule( |
| 3778 | 3785 | const function_exports_end_zcu: u32 = @intCast(wasm.function_exports.entries.len); |
| 3779 | 3786 | defer wasm.function_exports.shrinkRetainingCapacity(function_exports_end_zcu); |
| 3780 | 3787 | |
| 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 | ||
| 3781 | 3791 | wasm.flush_buffer.clear(); |
| 3782 | 3792 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); |
| 3783 | 3793 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); |
src/link/Wasm/Flush.zig+6-2| ... | ... | @@ -164,10 +164,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 164 | 164 | } |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | for (wasm.nav_exports.keys()) |*nav_export| { | |
| 167 | for (wasm.nav_exports.keys(), wasm.nav_exports.values()) |*nav_export, export_index| { | |
| 168 | 168 | if (ip.isFunctionType(ip.getNav(nav_export.nav_index).typeOf(ip))) { |
| 169 | 169 | 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 | } | |
| 171 | 175 | _ = f.missing_exports.swapRemove(nav_export.name); |
| 172 | 176 | _ = f.function_imports.swapRemove(nav_export.name); |
| 173 | 177 |
test/link/wasm/bss/build.zig+4-8| ... | ... | @@ -47,16 +47,14 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt |
| 47 | 47 | check_lib.checkInHeaders(); |
| 48 | 48 | check_lib.checkExact("Section custom"); |
| 49 | 49 | 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"); | |
| 53 | 51 | // for safe optimization modes `undefined` is stored in data instead of bss. |
| 54 | 52 | if (is_safe) { |
| 55 | check_lib.checkExact("index 1"); | |
| 53 | check_lib.checkExact("index 0"); | |
| 56 | 54 | check_lib.checkExact("name .data"); |
| 57 | 55 | check_lib.checkNotPresent("name .bss"); |
| 58 | 56 | } else { |
| 59 | check_lib.checkExact("index 1"); // bss section always last | |
| 57 | check_lib.checkExact("index 0"); // bss section always last | |
| 60 | 58 | check_lib.checkExact("name .bss"); |
| 61 | 59 | } |
| 62 | 60 | 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 |
| 84 | 82 | check_lib.checkInHeaders(); |
| 85 | 83 | check_lib.checkExact("Section custom"); |
| 86 | 84 | check_lib.checkExact("type data_segment"); |
| 87 | check_lib.checkExact("names 2"); | |
| 85 | check_lib.checkExact("names 1"); | |
| 88 | 86 | check_lib.checkExact("index 0"); |
| 89 | check_lib.checkExact("name .rodata"); | |
| 90 | check_lib.checkExact("index 1"); | |
| 91 | 87 | check_lib.checkExact("name .bss"); |
| 92 | 88 | |
| 93 | 89 | test_step.dependOn(&check_lib.step); |
test/link/wasm/bss/lib.zig+6-2| ... | ... | @@ -1,5 +1,9 @@ |
| 1 | 1 | pub var bss: u32 = undefined; |
| 2 | 2 | |
| 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 }); | |
| 5 | 9 | } |
test/link/wasm/bss/lib2.zig+6-2| ... | ... | @@ -1,5 +1,9 @@ |
| 1 | 1 | pub var bss: u32 = 0; |
| 2 | 2 | |
| 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 }); | |
| 5 | 9 | } |