| author | |
| committer | |
| log | 196ba706a05046b2209529744d2df47215819691 |
| tree | 38939524afabc97b9c56bf8f393bc7bc1990e437 |
| parent | 5ba5a2c133be5e06083f088aa875ff18658fbf8c |
| signature |
Certain symbols were left unmarked, meaning they would not be emit into
the final binary incorrectly. We now mark the synthetic symbols to ensure
they are emit as they are already created under the circumstance they're
needed for. This also re-enables disabled tests that were left disabled
in a previous merge conflict.
Lastly, this adds the shared-memory test to the test harnass as it was
previously forgotten and therefore regressed.8 files changed, 117 insertions(+), 95 deletions(-)
src/link/Wasm.zig+38-17| ... | @@ -11,6 +11,7 @@ const leb = std.leb; | ... | @@ -11,6 +11,7 @@ const leb = std.leb; |
| 11 | const link = @import("../link.zig"); | 11 | const link = @import("../link.zig"); |
| 12 | const lldMain = @import("../main.zig").lldMain; | 12 | const lldMain = @import("../main.zig").lldMain; |
| 13 | const log = std.log.scoped(.link); | 13 | const log = std.log.scoped(.link); |
| 14 | const gc_log = std.log.scoped(.gc); | ||
| 14 | const mem = std.mem; | 15 | const mem = std.mem; |
| 15 | const trace = @import("../tracy.zig").trace; | 16 | const trace = @import("../tracy.zig").trace; |
| 16 | const types = @import("Wasm/types.zig"); | 17 | const types = @import("Wasm/types.zig"); |
| ... | @@ -525,6 +526,7 @@ pub fn createEmpty( | ... | @@ -525,6 +526,7 @@ pub fn createEmpty( |
| 525 | const symbol = loc.getSymbol(wasm); | 526 | const symbol = loc.getSymbol(wasm); |
| 526 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 527 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 527 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); | 528 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); |
| 529 | symbol.mark(); | ||
| 528 | try wasm.wasm_globals.append(gpa, .{ | 530 | try wasm.wasm_globals.append(gpa, .{ |
| 529 | .global_type = .{ .valtype = .i32, .mutable = true }, | 531 | .global_type = .{ .valtype = .i32, .mutable = true }, |
| 530 | .init = .{ .i32_const = undefined }, | 532 | .init = .{ .i32_const = undefined }, |
| ... | @@ -535,6 +537,7 @@ pub fn createEmpty( | ... | @@ -535,6 +537,7 @@ pub fn createEmpty( |
| 535 | const symbol = loc.getSymbol(wasm); | 537 | const symbol = loc.getSymbol(wasm); |
| 536 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 538 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 537 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); | 539 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); |
| 540 | symbol.mark(); | ||
| 538 | try wasm.wasm_globals.append(gpa, .{ | 541 | try wasm.wasm_globals.append(gpa, .{ |
| 539 | .global_type = .{ .valtype = .i32, .mutable = false }, | 542 | .global_type = .{ .valtype = .i32, .mutable = false }, |
| 540 | .init = .{ .i32_const = undefined }, | 543 | .init = .{ .i32_const = undefined }, |
| ... | @@ -545,6 +548,7 @@ pub fn createEmpty( | ... | @@ -545,6 +548,7 @@ pub fn createEmpty( |
| 545 | const symbol = loc.getSymbol(wasm); | 548 | const symbol = loc.getSymbol(wasm); |
| 546 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 549 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 547 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); | 550 | symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); |
| 551 | symbol.mark(); | ||
| 548 | try wasm.wasm_globals.append(gpa, .{ | 552 | try wasm.wasm_globals.append(gpa, .{ |
| 549 | .global_type = .{ .valtype = .i32, .mutable = false }, | 553 | .global_type = .{ .valtype = .i32, .mutable = false }, |
| 550 | .init = .{ .i32_const = undefined }, | 554 | .init = .{ .i32_const = undefined }, |
| ... | @@ -968,6 +972,8 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { | ... | @@ -968,6 +972,8 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { |
| 968 | if (!wasm.hasPassiveInitializationSegments()) { | 972 | if (!wasm.hasPassiveInitializationSegments()) { |
| 969 | return; | 973 | return; |
| 970 | } | 974 | } |
| 975 | const sym_loc = try wasm.createSyntheticSymbol("__wasm_init_memory", .function); | ||
| 976 | sym_loc.getSymbol(wasm).mark(); | ||
| 971 | 977 | ||
| 972 | const flag_address: u32 = if (shared_memory) address: { | 978 | const flag_address: u32 = if (shared_memory) address: { |
| 973 | // when we have passive initialization segments and shared memory | 979 | // when we have passive initialization segments and shared memory |
| ... | @@ -1130,7 +1136,8 @@ fn setupTLSRelocationsFunction(wasm: *Wasm) !void { | ... | @@ -1130,7 +1136,8 @@ fn setupTLSRelocationsFunction(wasm: *Wasm) !void { |
| 1130 | return; | 1136 | return; |
| 1131 | } | 1137 | } |
| 1132 | 1138 | ||
| 1133 | // const loc = try wasm.createSyntheticSymbol("__wasm_apply_global_tls_relocs"); | 1139 | const loc = try wasm.createSyntheticSymbol("__wasm_apply_global_tls_relocs", .function); |
| 1140 | loc.getSymbol(wasm).mark(); | ||
| 1134 | var function_body = std.ArrayList(u8).init(gpa); | 1141 | var function_body = std.ArrayList(u8).init(gpa); |
| 1135 | defer function_body.deinit(); | 1142 | defer function_body.deinit(); |
| 1136 | const writer = function_body.writer(); | 1143 | const writer = function_body.writer(); |
| ... | @@ -1833,8 +1840,7 @@ fn createSyntheticFunction( | ... | @@ -1833,8 +1840,7 @@ fn createSyntheticFunction( |
| 1833 | function_body: *std.ArrayList(u8), | 1840 | function_body: *std.ArrayList(u8), |
| 1834 | ) !void { | 1841 | ) !void { |
| 1835 | const gpa = wasm.base.comp.gpa; | 1842 | const gpa = wasm.base.comp.gpa; |
| 1836 | const loc = wasm.findGlobalSymbol(symbol_name) orelse | 1843 | const loc = wasm.findGlobalSymbol(symbol_name).?; // forgot to create symbol? |
| 1837 | try wasm.createSyntheticSymbol(symbol_name, .function); | ||
| 1838 | const symbol = loc.getSymbol(wasm); | 1844 | const symbol = loc.getSymbol(wasm); |
| 1839 | if (symbol.isDead()) { | 1845 | if (symbol.isDead()) { |
| 1840 | return; | 1846 | return; |
| ... | @@ -1884,6 +1890,9 @@ fn initializeTLSFunction(wasm: *Wasm) !void { | ... | @@ -1884,6 +1890,9 @@ fn initializeTLSFunction(wasm: *Wasm) !void { |
| 1884 | 1890 | ||
| 1885 | if (!shared_memory) return; | 1891 | if (!shared_memory) return; |
| 1886 | 1892 | ||
| 1893 | // ensure function is marked as we must emit it | ||
| 1894 | wasm.findGlobalSymbol("__wasm_init_tls").?.getSymbol(wasm).mark(); | ||
| 1895 | |||
| 1887 | var function_body = std.ArrayList(u8).init(gpa); | 1896 | var function_body = std.ArrayList(u8).init(gpa); |
| 1888 | defer function_body.deinit(); | 1897 | defer function_body.deinit(); |
| 1889 | const writer = function_body.writer(); | 1898 | const writer = function_body.writer(); |
| ... | @@ -1932,6 +1941,7 @@ fn initializeTLSFunction(wasm: *Wasm) !void { | ... | @@ -1932,6 +1941,7 @@ fn initializeTLSFunction(wasm: *Wasm) !void { |
| 1932 | if (wasm.findGlobalSymbol("__wasm_apply_global_tls_relocs")) |loc| { | 1941 | if (wasm.findGlobalSymbol("__wasm_apply_global_tls_relocs")) |loc| { |
| 1933 | try writer.writeByte(std.wasm.opcode(.call)); | 1942 | try writer.writeByte(std.wasm.opcode(.call)); |
| 1934 | try leb.writeULEB128(writer, loc.getSymbol(wasm).index); | 1943 | try leb.writeULEB128(writer, loc.getSymbol(wasm).index); |
| 1944 | loc.getSymbol(wasm).mark(); | ||
| 1935 | } | 1945 | } |
| 1936 | 1946 | ||
| 1937 | try writer.writeByte(std.wasm.opcode(.end)); | 1947 | try writer.writeByte(std.wasm.opcode(.end)); |
| ... | @@ -2039,14 +2049,19 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -2039,14 +2049,19 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2039 | // We found an alias to the same function, discard this symbol in favor of | 2049 | // We found an alias to the same function, discard this symbol in favor of |
| 2040 | // the original symbol and point the discard function to it. This ensures | 2050 | // the original symbol and point the discard function to it. This ensures |
| 2041 | // we only emit a single function, instead of duplicates. | 2051 | // we only emit a single function, instead of duplicates. |
| 2042 | symbol.unmark(); | 2052 | // we favor keeping the global over a local. |
| 2043 | try wasm.discarded.putNoClobber( | 2053 | const original_loc: SymbolLoc = .{ .file = gop.key_ptr.file, .index = gop.value_ptr.sym_index }; |
| 2044 | gpa, | 2054 | const original_sym = original_loc.getSymbol(wasm); |
| 2045 | sym_loc, | 2055 | if (original_sym.isLocal() and symbol.isGlobal()) { |
| 2046 | .{ .file = gop.key_ptr.*.file, .index = gop.value_ptr.*.sym_index }, | 2056 | original_sym.unmark(); |
| 2047 | ); | 2057 | try wasm.discarded.put(gpa, original_loc, sym_loc); |
| 2048 | try removed_duplicates.append(sym_loc); | 2058 | try removed_duplicates.append(original_loc); |
| 2049 | continue; | 2059 | } else { |
| 2060 | symbol.unmark(); | ||
| 2061 | try wasm.discarded.putNoClobber(gpa, sym_loc, original_loc); | ||
| 2062 | try removed_duplicates.append(sym_loc); | ||
| 2063 | continue; | ||
| 2064 | } | ||
| 2050 | } | 2065 | } |
| 2051 | gop.value_ptr.* = .{ .func = obj_file.function(sym_loc.index), .sym_index = sym_loc.index }; | 2066 | gop.value_ptr.* = .{ .func = obj_file.function(sym_loc.index), .sym_index = sym_loc.index }; |
| 2052 | symbol.index = @as(u32, @intCast(gop.index)) + wasm.imported_functions_count; | 2067 | symbol.index = @as(u32, @intCast(gop.index)) + wasm.imported_functions_count; |
| ... | @@ -2073,6 +2088,7 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -2073,6 +2088,7 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2073 | // For any removed duplicates, remove them from the resolved symbols list | 2088 | // For any removed duplicates, remove them from the resolved symbols list |
| 2074 | for (removed_duplicates.items) |sym_loc| { | 2089 | for (removed_duplicates.items) |sym_loc| { |
| 2075 | assert(wasm.resolved_symbols.swapRemove(sym_loc)); | 2090 | assert(wasm.resolved_symbols.swapRemove(sym_loc)); |
| 2091 | gc_log.debug("Removed duplicate for function '{s}'", .{sym_loc.getName(wasm)}); | ||
| 2076 | } | 2092 | } |
| 2077 | 2093 | ||
| 2078 | log.debug("Merged ({d}) functions", .{wasm.functions.count()}); | 2094 | log.debug("Merged ({d}) functions", .{wasm.functions.count()}); |
| ... | @@ -2119,12 +2135,7 @@ fn mergeTypes(wasm: *Wasm) !void { | ... | @@ -2119,12 +2135,7 @@ fn mergeTypes(wasm: *Wasm) !void { |
| 2119 | log.debug("Completed merging and deduplicating types. Total count: ({d})", .{wasm.func_types.items.len}); | 2135 | log.debug("Completed merging and deduplicating types. Total count: ({d})", .{wasm.func_types.items.len}); |
| 2120 | } | 2136 | } |
| 2121 | 2137 | ||
| 2122 | fn setupExports(wasm: *Wasm) !void { | 2138 | fn checkExportNames(wasm: *Wasm) !void { |
| 2123 | const comp = wasm.base.comp; | ||
| 2124 | const gpa = comp.gpa; | ||
| 2125 | if (comp.config.output_mode == .Obj) return; | ||
| 2126 | log.debug("Building exports from symbols", .{}); | ||
| 2127 | |||
| 2128 | const force_exp_names = wasm.export_symbol_names; | 2139 | const force_exp_names = wasm.export_symbol_names; |
| 2129 | if (force_exp_names.len > 0) { | 2140 | if (force_exp_names.len > 0) { |
| 2130 | var failed_exports = false; | 2141 | var failed_exports = false; |
| ... | @@ -2144,6 +2155,13 @@ fn setupExports(wasm: *Wasm) !void { | ... | @@ -2144,6 +2155,13 @@ fn setupExports(wasm: *Wasm) !void { |
| 2144 | return error.FlushFailure; | 2155 | return error.FlushFailure; |
| 2145 | } | 2156 | } |
| 2146 | } | 2157 | } |
| 2158 | } | ||
| 2159 | |||
| 2160 | fn setupExports(wasm: *Wasm) !void { | ||
| 2161 | const comp = wasm.base.comp; | ||
| 2162 | const gpa = comp.gpa; | ||
| 2163 | if (comp.config.output_mode == .Obj) return; | ||
| 2164 | log.debug("Building exports from symbols", .{}); | ||
| 2147 | 2165 | ||
| 2148 | for (wasm.resolved_symbols.keys()) |sym_loc| { | 2166 | for (wasm.resolved_symbols.keys()) |sym_loc| { |
| 2149 | const symbol = sym_loc.getSymbol(wasm); | 2167 | const symbol = sym_loc.getSymbol(wasm); |
| ... | @@ -2272,6 +2290,7 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2272,6 +2290,7 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2272 | memory_ptr = mem.alignForward(u64, memory_ptr, 4); | 2290 | memory_ptr = mem.alignForward(u64, memory_ptr, 4); |
| 2273 | const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data); | 2291 | const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data); |
| 2274 | const sym = loc.getSymbol(wasm); | 2292 | const sym = loc.getSymbol(wasm); |
| 2293 | sym.mark(); | ||
| 2275 | sym.virtual_address = @as(u32, @intCast(memory_ptr)); | 2294 | sym.virtual_address = @as(u32, @intCast(memory_ptr)); |
| 2276 | memory_ptr += 4; | 2295 | memory_ptr += 4; |
| 2277 | } | 2296 | } |
| ... | @@ -2561,6 +2580,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -2561,6 +2580,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 2561 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 2580 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2562 | try wasm.resolveLazySymbols(); | 2581 | try wasm.resolveLazySymbols(); |
| 2563 | try wasm.checkUndefinedSymbols(); | 2582 | try wasm.checkUndefinedSymbols(); |
| 2583 | try wasm.checkExportNames(); | ||
| 2564 | 2584 | ||
| 2565 | try wasm.setupInitFunctions(); | 2585 | try wasm.setupInitFunctions(); |
| 2566 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 2586 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| ... | @@ -4044,6 +4064,7 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { | ... | @@ -4044,6 +4064,7 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { |
| 4044 | return; | 4064 | return; |
| 4045 | } | 4065 | } |
| 4046 | symbol.mark(); | 4066 | symbol.mark(); |
| 4067 | gc_log.debug("Marked symbol '{s}'", .{loc.getName(wasm)}); | ||
| 4047 | if (symbol.isUndefined()) { | 4068 | if (symbol.isUndefined()) { |
| 4048 | // undefined symbols do not have an associated `Atom` and therefore also | 4069 | // undefined symbols do not have an associated `Atom` and therefore also |
| 4049 | // do not contain relocations. | 4070 | // do not contain relocations. |
src/link/Wasm/Object.zig+1-1| ... | @@ -15,7 +15,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -15,7 +15,7 @@ const Allocator = std.mem.Allocator; |
| 15 | const leb = std.leb; | 15 | const leb = std.leb; |
| 16 | const meta = std.meta; | 16 | const meta = std.meta; |
| 17 | 17 | ||
| 18 | const log = std.log.scoped(.link); | 18 | const log = std.log.scoped(.object); |
| 19 | 19 | ||
| 20 | /// Index into the list of relocatable object files within the linker driver. | 20 | /// Index into the list of relocatable object files within the linker driver. |
| 21 | index: File.Index = .null, | 21 | index: File.Index = .null, |
src/link/Wasm/ZigObject.zig+6-4| ... | @@ -315,7 +315,7 @@ fn finishUpdateDecl( | ... | @@ -315,7 +315,7 @@ fn finishUpdateDecl( |
| 315 | const atom_index = decl_info.atom; | 315 | const atom_index = decl_info.atom; |
| 316 | const atom = wasm_file.getAtomPtr(atom_index); | 316 | const atom = wasm_file.getAtomPtr(atom_index); |
| 317 | const sym = zig_object.symbol(atom.sym_index); | 317 | const sym = zig_object.symbol(atom.sym_index); |
| 318 | const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 318 | const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 319 | sym.name = try zig_object.string_table.insert(gpa, full_name); | 319 | sym.name = try zig_object.string_table.insert(gpa, full_name); |
| 320 | try atom.code.appendSlice(gpa, code); | 320 | try atom.code.appendSlice(gpa, code); |
| 321 | atom.size = @intCast(code.len); | 321 | atom.size = @intCast(code.len); |
| ... | @@ -401,7 +401,7 @@ pub fn getOrCreateAtomForDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_ind | ... | @@ -401,7 +401,7 @@ pub fn getOrCreateAtomForDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_ind |
| 401 | gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) }; | 401 | gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) }; |
| 402 | const mod = wasm_file.base.comp.module.?; | 402 | const mod = wasm_file.base.comp.module.?; |
| 403 | const decl = mod.declPtr(decl_index); | 403 | const decl = mod.declPtr(decl_index); |
| 404 | const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 404 | const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 405 | const sym = zig_object.symbol(sym_index); | 405 | const sym = zig_object.symbol(sym_index); |
| 406 | sym.name = try zig_object.string_table.insert(gpa, full_name); | 406 | sym.name = try zig_object.string_table.insert(gpa, full_name); |
| 407 | } | 407 | } |
| ... | @@ -455,7 +455,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu | ... | @@ -455,7 +455,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu |
| 455 | const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); | 455 | const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); |
| 456 | const parent_atom = wasm_file.getAtom(parent_atom_index); | 456 | const parent_atom = wasm_file.getAtom(parent_atom_index); |
| 457 | const local_index = parent_atom.locals.items.len; | 457 | const local_index = parent_atom.locals.items.len; |
| 458 | const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 458 | const fqn = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 459 | const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{ | 459 | const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{ |
| 460 | fqn, local_index, | 460 | fqn, local_index, |
| 461 | }); | 461 | }); |
| ... | @@ -838,6 +838,7 @@ pub fn updateExports( | ... | @@ -838,6 +838,7 @@ pub fn updateExports( |
| 838 | const atom = wasm_file.getAtom(atom_index); | 838 | const atom = wasm_file.getAtom(atom_index); |
| 839 | const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*; | 839 | const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*; |
| 840 | const gpa = mod.gpa; | 840 | const gpa = mod.gpa; |
| 841 | log.debug("Updating exports for decl '{s}'", .{mod.intern_pool.stringToSlice(decl.name)}); | ||
| 841 | 842 | ||
| 842 | for (exports) |exp| { | 843 | for (exports) |exp| { |
| 843 | if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| { | 844 | if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| { |
| ... | @@ -888,6 +889,7 @@ pub fn updateExports( | ... | @@ -888,6 +889,7 @@ pub fn updateExports( |
| 888 | if (exp.opts.visibility == .hidden) { | 889 | if (exp.opts.visibility == .hidden) { |
| 889 | sym.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 890 | sym.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 890 | } | 891 | } |
| 892 | log.debug(" with name '{s}' - {}", .{ export_string, sym }); | ||
| 891 | try zig_object.global_syms.put(gpa, export_name, sym_index); | 893 | try zig_object.global_syms.put(gpa, export_name, sym_index); |
| 892 | try wasm_file.symbol_atom.put(gpa, .{ .file = zig_object.index, .index = sym_index }, atom_index); | 894 | try wasm_file.symbol_atom.put(gpa, .{ .file = zig_object.index, .index = sym_index }, atom_index); |
| 893 | } | 895 | } |
| ... | @@ -1061,7 +1063,7 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm_file: *Wasm, inde | ... | @@ -1061,7 +1063,7 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm_file: *Wasm, inde |
| 1061 | pub fn updateDeclLineNumber(zig_object: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void { | 1063 | pub fn updateDeclLineNumber(zig_object: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void { |
| 1062 | if (zig_object.dwarf) |*dw| { | 1064 | if (zig_object.dwarf) |*dw| { |
| 1063 | const decl = mod.declPtr(decl_index); | 1065 | const decl = mod.declPtr(decl_index); |
| 1064 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 1066 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 1065 | 1067 | ||
| 1066 | log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); | 1068 | log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); |
| 1067 | try dw.updateDeclLineNumber(mod, decl_index); | 1069 | try dw.updateDeclLineNumber(mod, decl_index); |
test/link.zig+12-10| ... | @@ -35,11 +35,10 @@ pub const cases = [_]Case{ | ... | @@ -35,11 +35,10 @@ pub const cases = [_]Case{ |
| 35 | }, | 35 | }, |
| 36 | 36 | ||
| 37 | // WASM Cases | 37 | // WASM Cases |
| 38 | // https://github.com/ziglang/zig/issues/16938 | 38 | .{ |
| 39 | //.{ | 39 | .build_root = "test/link/wasm/archive", |
| 40 | // .build_root = "test/link/wasm/archive", | 40 | .import = @import("link/wasm/archive/build.zig"), |
| 41 | // .import = @import("link/wasm/archive/build.zig"), | 41 | }, |
| 42 | //}, | ||
| 43 | .{ | 42 | .{ |
| 44 | .build_root = "test/link/wasm/basic-features", | 43 | .build_root = "test/link/wasm/basic-features", |
| 45 | .import = @import("link/wasm/basic-features/build.zig"), | 44 | .import = @import("link/wasm/basic-features/build.zig"), |
| ... | @@ -52,11 +51,10 @@ pub const cases = [_]Case{ | ... | @@ -52,11 +51,10 @@ pub const cases = [_]Case{ |
| 52 | .build_root = "test/link/wasm/export", | 51 | .build_root = "test/link/wasm/export", |
| 53 | .import = @import("link/wasm/export/build.zig"), | 52 | .import = @import("link/wasm/export/build.zig"), |
| 54 | }, | 53 | }, |
| 55 | // https://github.com/ziglang/zig/issues/16937 | 54 | .{ |
| 56 | //.{ | 55 | .build_root = "test/link/wasm/export-data", |
| 57 | // .build_root = "test/link/wasm/export-data", | 56 | .import = @import("link/wasm/export-data/build.zig"), |
| 58 | // .import = @import("link/wasm/export-data/build.zig"), | 57 | }, |
| 59 | //}, | ||
| 60 | .{ | 58 | .{ |
| 61 | .build_root = "test/link/wasm/extern", | 59 | .build_root = "test/link/wasm/extern", |
| 62 | .import = @import("link/wasm/extern/build.zig"), | 60 | .import = @import("link/wasm/extern/build.zig"), |
| ... | @@ -81,6 +79,10 @@ pub const cases = [_]Case{ | ... | @@ -81,6 +79,10 @@ pub const cases = [_]Case{ |
| 81 | .build_root = "test/link/wasm/segments", | 79 | .build_root = "test/link/wasm/segments", |
| 82 | .import = @import("link/wasm/segments/build.zig"), | 80 | .import = @import("link/wasm/segments/build.zig"), |
| 83 | }, | 81 | }, |
| 82 | .{ | ||
| 83 | .build_root = "test/link/wasm/shared-memory", | ||
| 84 | .import = @import("link/wasm/shared-memory/build.zig"), | ||
| 85 | }, | ||
| 84 | .{ | 86 | .{ |
| 85 | .build_root = "test/link/wasm/stack_pointer", | 87 | .build_root = "test/link/wasm/stack_pointer", |
| 86 | .import = @import("link/wasm/stack_pointer/build.zig"), | 88 | .import = @import("link/wasm/stack_pointer/build.zig"), |
test/link/wasm/archive/build.zig+2-1| ... | @@ -19,12 +19,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize | ... | @@ -19,12 +19,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize |
| 19 | .name = "main", | 19 | .name = "main", |
| 20 | .root_source_file = .{ .path = "main.zig" }, | 20 | .root_source_file = .{ .path = "main.zig" }, |
| 21 | .optimize = optimize, | 21 | .optimize = optimize, |
| 22 | .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, | 22 | .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), |
| 23 | .strip = false, | 23 | .strip = false, |
| 24 | }); | 24 | }); |
| 25 | lib.entry = .disabled; | 25 | lib.entry = .disabled; |
| 26 | lib.use_llvm = false; | 26 | lib.use_llvm = false; |
| 27 | lib.use_lld = false; | 27 | lib.use_lld = false; |
| 28 | lib.root_module.export_symbol_names = &.{"foo"}; | ||
| 28 | 29 | ||
| 29 | const check = lib.checkObject(); | 30 | const check = lib.checkObject(); |
| 30 | check.checkInHeaders(); | 31 | check.checkInHeaders(); |
test/link/wasm/export-data/build.zig+1-1| ... | @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { | ... | @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { |
| 13 | .name = "lib", | 13 | .name = "lib", |
| 14 | .root_source_file = .{ .path = "lib.zig" }, | 14 | .root_source_file = .{ .path = "lib.zig" }, |
| 15 | .optimize = .ReleaseSafe, // to make the output deterministic in address positions | 15 | .optimize = .ReleaseSafe, // to make the output deterministic in address positions |
| 16 | .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, | 16 | .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), |
| 17 | }); | 17 | }); |
| 18 | lib.entry = .disabled; | 18 | lib.entry = .disabled; |
| 19 | lib.use_lld = false; | 19 | lib.use_lld = false; |
test/link/wasm/shared-memory/build.zig+40-45| ... | @@ -11,37 +11,39 @@ pub fn build(b: *std.Build) void { | ... | @@ -11,37 +11,39 @@ pub fn build(b: *std.Build) void { |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void { | 13 | fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void { |
| 14 | const lib = b.addExecutable(.{ | 14 | const exe = b.addExecutable(.{ |
| 15 | .name = "lib", | 15 | .name = "lib", |
| 16 | .root_source_file = .{ .path = "lib.zig" }, | 16 | .root_source_file = .{ .path = "lib.zig" }, |
| 17 | .target = .{ | 17 | .target = b.resolveTargetQuery(.{ |
| 18 | .cpu_arch = .wasm32, | 18 | .cpu_arch = .wasm32, |
| 19 | .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, | 19 | .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, |
| 20 | .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }), | 20 | .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }), |
| 21 | .os_tag = .freestanding, | 21 | .os_tag = .freestanding, |
| 22 | }, | 22 | }), |
| 23 | .optimize = optimize_mode, | 23 | .optimize = optimize_mode, |
| 24 | .strip = false, | 24 | .strip = false, |
| 25 | .single_threaded = false, | 25 | .single_threaded = false, |
| 26 | }); | 26 | }); |
| 27 | lib.entry = .disabled; | 27 | exe.entry = .disabled; |
| 28 | lib.use_lld = false; | 28 | exe.use_lld = false; |
| 29 | lib.import_memory = true; | 29 | exe.import_memory = true; |
| 30 | lib.export_memory = true; | 30 | exe.export_memory = true; |
| 31 | lib.shared_memory = true; | 31 | exe.shared_memory = true; |
| 32 | lib.max_memory = 67108864; | 32 | exe.max_memory = 67108864; |
| 33 | lib.root_module.export_symbol_names = &.{"foo"}; | 33 | exe.root_module.export_symbol_names = &.{"foo"}; |
| 34 | 34 | ||
| 35 | const check_lib = lib.checkObject(); | 35 | const check_exe = exe.checkObject(); |
| 36 | 36 | ||
| 37 | check_lib.checkStart("Section import"); | 37 | check_exe.checkInHeaders(); |
| 38 | check_lib.checkNext("entries 1"); | 38 | check_exe.checkExact("Section import"); |
| 39 | check_lib.checkNext("module env"); | 39 | check_exe.checkExact("entries 1"); |
| 40 | check_lib.checkNext("name memory"); // ensure we are importing memory | 40 | check_exe.checkExact("module env"); |
| 41 | check_exe.checkExact("name memory"); // ensure we are importing memory | ||
| 41 | 42 | ||
| 42 | check_lib.checkStart("Section export"); | 43 | check_exe.checkInHeaders(); |
| 43 | check_lib.checkNext("entries 2"); | 44 | check_exe.checkExact("Section export"); |
| 44 | check_lib.checkNext("name memory"); // ensure we also export memory again | 45 | check_exe.checkExact("entries 2"); |
| 46 | check_exe.checkExact("name memory"); // ensure we also export memory again | ||
| 45 | 47 | ||
| 46 | // This section *must* be emit as the start function is set to the index | 48 | // This section *must* be emit as the start function is set to the index |
| 47 | // of __wasm_init_memory | 49 | // of __wasm_init_memory |
| ... | @@ -49,49 +51,42 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt | ... | @@ -49,49 +51,42 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt |
| 49 | // This means we won't have __wasm_init_memory in such case, and therefore | 51 | // This means we won't have __wasm_init_memory in such case, and therefore |
| 50 | // should also not have a section "start" | 52 | // should also not have a section "start" |
| 51 | if (optimize_mode == .Debug) { | 53 | if (optimize_mode == .Debug) { |
| 52 | check_lib.checkStart("Section start"); | 54 | check_exe.checkInHeaders(); |
| 55 | check_exe.checkExact("Section start"); | ||
| 53 | } | 56 | } |
| 54 | 57 | ||
| 55 | // This section is only and *must* be emit when shared-memory is enabled | 58 | // This section is only and *must* be emit when shared-memory is enabled |
| 56 | // release modes will have the TLS segment optimized out in our test-case. | 59 | // release modes will have the TLS segment optimized out in our test-case. |
| 57 | if (optimize_mode == .Debug) { | 60 | if (optimize_mode == .Debug) { |
| 58 | check_lib.checkStart("Section data_count"); | 61 | check_exe.checkInHeaders(); |
| 59 | check_lib.checkNext("count 3"); | 62 | check_exe.checkExact("Section data_count"); |
| 63 | check_exe.checkExact("count 1"); | ||
| 60 | } | 64 | } |
| 61 | 65 | ||
| 62 | check_lib.checkStart("Section custom"); | 66 | check_exe.checkInHeaders(); |
| 63 | check_lib.checkNext("name name"); | 67 | check_exe.checkExact("Section custom"); |
| 64 | check_lib.checkNext("type function"); | 68 | check_exe.checkExact("name name"); |
| 69 | check_exe.checkExact("type function"); | ||
| 65 | if (optimize_mode == .Debug) { | 70 | if (optimize_mode == .Debug) { |
| 66 | check_lib.checkNext("name __wasm_init_memory"); | 71 | check_exe.checkExact("name __wasm_init_memory"); |
| 67 | } | 72 | } |
| 68 | check_lib.checkNext("name __wasm_init_tls"); | 73 | check_exe.checkExact("name __wasm_init_tls"); |
| 69 | check_lib.checkNext("type global"); | 74 | check_exe.checkExact("type global"); |
| 70 | 75 | ||
| 71 | // In debug mode the symbol __tls_base is resolved to an undefined symbol | 76 | // In debug mode the symbol __tls_base is resolved to an undefined symbol |
| 72 | // from the object file, hence its placement differs than in release modes | 77 | // from the object file, hence its placement differs than in release modes |
| 73 | // where the entire tls segment is optimized away, and tls_base will have | 78 | // where the entire tls segment is optimized away, and tls_base will have |
| 74 | // its original position. | 79 | // its original position. |
| 75 | if (optimize_mode == .Debug) { | 80 | check_exe.checkExact("name __tls_base"); |
| 76 | check_lib.checkNext("name __tls_size"); | 81 | check_exe.checkExact("name __tls_size"); |
| 77 | check_lib.checkNext("name __tls_align"); | 82 | check_exe.checkExact("name __tls_align"); |
| 78 | check_lib.checkNext("name __tls_base"); | ||
| 79 | } else { | ||
| 80 | check_lib.checkNext("name __tls_base"); | ||
| 81 | check_lib.checkNext("name __tls_size"); | ||
| 82 | check_lib.checkNext("name __tls_align"); | ||
| 83 | } | ||
| 84 | 83 | ||
| 85 | check_lib.checkNext("type data_segment"); | 84 | check_exe.checkExact("type data_segment"); |
| 86 | if (optimize_mode == .Debug) { | 85 | if (optimize_mode == .Debug) { |
| 87 | check_lib.checkNext("names 3"); | 86 | check_exe.checkExact("names 1"); |
| 88 | check_lib.checkNext("index 0"); | 87 | check_exe.checkExact("index 0"); |
| 89 | check_lib.checkNext("name .rodata"); | 88 | check_exe.checkExact("name .tdata"); |
| 90 | check_lib.checkNext("index 1"); | ||
| 91 | check_lib.checkNext("name .bss"); | ||
| 92 | check_lib.checkNext("index 2"); | ||
| 93 | check_lib.checkNext("name .tdata"); | ||
| 94 | } | 89 | } |
| 95 | 90 | ||
| 96 | test_step.dependOn(&check_lib.step); | 91 | test_step.dependOn(&check_exe.step); |
| 97 | } | 92 | } |
test/link/wasm/type/build.zig+17-16| ... | @@ -13,31 +13,32 @@ pub fn build(b: *std.Build) void { | ... | @@ -13,31 +13,32 @@ pub fn build(b: *std.Build) void { |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { | 15 | fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { |
| 16 | const lib = b.addExecutable(.{ | 16 | const exe = b.addExecutable(.{ |
| 17 | .name = "lib", | 17 | .name = "lib", |
| 18 | .root_source_file = .{ .path = "lib.zig" }, | 18 | .root_source_file = .{ .path = "lib.zig" }, |
| 19 | .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), | 19 | .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), |
| 20 | .optimize = optimize, | 20 | .optimize = optimize, |
| 21 | .strip = false, | 21 | .strip = false, |
| 22 | }); | 22 | }); |
| 23 | lib.entry = .disabled; | 23 | exe.entry = .disabled; |
| 24 | lib.use_llvm = false; | 24 | exe.use_llvm = false; |
| 25 | lib.use_lld = false; | 25 | exe.use_lld = false; |
| 26 | b.installArtifact(lib); | 26 | exe.root_module.export_symbol_names = &.{"foo"}; |
| 27 | b.installArtifact(exe); | ||
| 27 | 28 | ||
| 28 | const check_lib = lib.checkObject(); | 29 | const check_exe = exe.checkObject(); |
| 29 | check_lib.checkInHeaders(); | 30 | check_exe.checkInHeaders(); |
| 30 | check_lib.checkExact("Section type"); | 31 | check_exe.checkExact("Section type"); |
| 31 | // only 2 entries, although we have more functions. | 32 | // only 2 entries, although we have more functions. |
| 32 | // This is to test functions with the same function signature | 33 | // This is to test functions with the same function signature |
| 33 | // have their types deduplicated. | 34 | // have their types deduplicated. |
| 34 | check_lib.checkExact("entries 2"); | 35 | check_exe.checkExact("entries 2"); |
| 35 | check_lib.checkExact("params 1"); | 36 | check_exe.checkExact("params 1"); |
| 36 | check_lib.checkExact("type i32"); | 37 | check_exe.checkExact("type i32"); |
| 37 | check_lib.checkExact("returns 1"); | 38 | check_exe.checkExact("returns 1"); |
| 38 | check_lib.checkExact("type i64"); | 39 | check_exe.checkExact("type i64"); |
| 39 | check_lib.checkExact("params 0"); | 40 | check_exe.checkExact("params 0"); |
| 40 | check_lib.checkExact("returns 0"); | 41 | check_exe.checkExact("returns 0"); |
| 41 | 42 | ||
| 42 | test_step.dependOn(&check_lib.step); | 43 | test_step.dependOn(&check_exe.step); |
| 43 | } | 44 | } |