| ... | @@ -1718,7 +1718,7 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -1718,7 +1718,7 @@ fn mergeSections(wasm: *Wasm) !void { |
| 1718 | continue; | 1718 | continue; |
| 1719 | } | 1719 | } |
| 1720 | | 1720 | |
| 1721 | const object = wasm.objects.items[sym_loc.file.?]; | 1721 | const object = &wasm.objects.items[sym_loc.file.?]; |
| 1722 | const symbol = &object.symtable[sym_loc.index]; | 1722 | const symbol = &object.symtable[sym_loc.index]; |
| 1723 | if (symbol.isUndefined() or (symbol.tag != .function and symbol.tag != .global and symbol.tag != .table)) { | 1723 | if (symbol.isUndefined() or (symbol.tag != .function and symbol.tag != .global and symbol.tag != .table)) { |
| 1724 | // Skip undefined symbols as they go in the `import` section | 1724 | // Skip undefined symbols as they go in the `import` section |
| ... | @@ -1730,13 +1730,12 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -1730,13 +1730,12 @@ fn mergeSections(wasm: *Wasm) !void { |
| 1730 | const index = symbol.index - offset; | 1730 | const index = symbol.index - offset; |
| 1731 | switch (symbol.tag) { | 1731 | switch (symbol.tag) { |
| 1732 | .function => { | 1732 | .function => { |
| 1733 | const original_func = object.functions[index]; | | |
| 1734 | const gop = try wasm.functions.getOrPut( | 1733 | const gop = try wasm.functions.getOrPut( |
| 1735 | wasm.base.allocator, | 1734 | wasm.base.allocator, |
| 1736 | .{ .file = sym_loc.file, .index = symbol.index }, | 1735 | .{ .file = sym_loc.file, .index = symbol.index }, |
| 1737 | ); | 1736 | ); |
| 1738 | if (!gop.found_existing) { | 1737 | if (!gop.found_existing) { |
| 1739 | gop.value_ptr.* = original_func; | 1738 | gop.value_ptr.* = object.functions[index]; |
| 1740 | } | 1739 | } |
| 1741 | symbol.index = @intCast(u32, gop.index) + wasm.imported_functions_count; | 1740 | symbol.index = @intCast(u32, gop.index) + wasm.imported_functions_count; |
| 1742 | }, | 1741 | }, |
| ... | @@ -1784,7 +1783,7 @@ fn mergeTypes(wasm: *Wasm) !void { | ... | @@ -1784,7 +1783,7 @@ fn mergeTypes(wasm: *Wasm) !void { |
| 1784 | | 1783 | |
| 1785 | if (symbol.isUndefined()) { | 1784 | if (symbol.isUndefined()) { |
| 1786 | log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(wasm)}); | 1785 | log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(wasm)}); |
| 1787 | const import: *types.Import = wasm.imports.getPtr(sym_loc).?; | 1786 | const import: *types.Import = wasm.imports.getPtr(sym_loc) orelse continue; |
| 1788 | const original_type = object.func_types[import.kind.function]; | 1787 | const original_type = object.func_types[import.kind.function]; |
| 1789 | import.kind.function = try wasm.putOrGetFuncType(original_type); | 1788 | import.kind.function = try wasm.putOrGetFuncType(original_type); |
| 1790 | } else if (!dirty.contains(symbol.index)) { | 1789 | } else if (!dirty.contains(symbol.index)) { |
| ... | @@ -2235,22 +2234,112 @@ pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) lin | ... | @@ -2235,22 +2234,112 @@ pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) lin |
| 2235 | } | 2234 | } |
| 2236 | } | 2235 | } |
| 2237 | | 2236 | |
| | 2237 | /// Uses the in-house linker to link one or multiple object -and archive files into a WebAssembly binary. |
| 2238 | fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 2238 | fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 2239 | const tracy = trace(@src()); | 2239 | const tracy = trace(@src()); |
| 2240 | defer tracy.end(); | 2240 | defer tracy.end(); |
| 2241 | | 2241 | |
| 2242 | if (build_options.have_llvm) { | 2242 | const gpa = wasm.base.allocator; |
| 2243 | if (wasm.llvm_object) |llvm_object| { | 2243 | const options = wasm.base.options; |
| 2244 | return try llvm_object.flushModule(comp, prog_node); | 2244 | |
| | 2245 | // Used for all temporary memory allocated during flushin |
| | 2246 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| | 2247 | defer arena_instance.deinit(); |
| | 2248 | const arena = arena_instance.allocator(); |
| | 2249 | |
| | 2250 | const directory = options.emit.?.directory; // Just an alias to make it shorter to type. |
| | 2251 | const full_out_path = try directory.join(arena, &[_][]const u8{options.emit.?.sub_path}); |
| | 2252 | |
| | 2253 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| | 2254 | // will not be part of the linker line anyway. |
| | 2255 | const module_obj_path: ?[]const u8 = if (options.module != null) blk: { |
| | 2256 | assert(options.use_llvm); // `linkWithZld` should never be called when the Wasm backend is used |
| | 2257 | try wasm.flushModule(comp, prog_node); |
| | 2258 | |
| | 2259 | if (fs.path.dirname(full_out_path)) |dirname| { |
| | 2260 | break :blk try fs.path.join(arena, &.{ dirname, wasm.base.intermediary_basename.? }); |
| | 2261 | } else { |
| | 2262 | break :blk wasm.base.intermediary_basename.?; |
| 2245 | } | 2263 | } |
| 2246 | } | 2264 | } else null; |
| 2247 | | 2265 | |
| 2248 | var sub_prog_node = prog_node.start("Wasm Flush", 0); | 2266 | var sub_prog_node = prog_node.start("Wasm Flush", 0); |
| 2249 | sub_prog_node.activate(); | 2267 | sub_prog_node.activate(); |
| 2250 | defer sub_prog_node.end(); | 2268 | defer sub_prog_node.end(); |
| 2251 | | 2269 | |
| 2252 | // ensure the error names table is populated when an error name is referenced | 2270 | const is_obj = options.output_mode == .Obj; |
| 2253 | try wasm.populateErrorNameTable(); | 2271 | const compiler_rt_path: ?[]const u8 = if (options.include_compiler_rt and !is_obj) |
| | 2272 | comp.compiler_rt_lib.?.full_object_path |
| | 2273 | else |
| | 2274 | null; |
| | 2275 | const id_symlink_basename = "zld.id"; |
| | 2276 | |
| | 2277 | var man: Cache.Manifest = undefined; |
| | 2278 | defer if (!options.disable_lld_caching) man.deinit(); |
| | 2279 | var digest: [Cache.hex_digest_len]u8 = undefined; |
| | 2280 | |
| | 2281 | // NOTE: The following section must be maintained to be equal |
| | 2282 | // as the section defined in `linkWithLLD` |
| | 2283 | if (!options.disable_lld_caching) { |
| | 2284 | man = comp.cache_parent.obtain(); |
| | 2285 | |
| | 2286 | // We are about to obtain this lock, so here we give other processes a chance first. |
| | 2287 | wasm.base.releaseLock(); |
| | 2288 | |
| | 2289 | comptime assert(Compilation.link_hash_implementation_version == 7); |
| | 2290 | |
| | 2291 | for (options.objects) |obj| { |
| | 2292 | _ = try man.addFile(obj.path, null); |
| | 2293 | man.hash.add(obj.must_link); |
| | 2294 | } |
| | 2295 | for (comp.c_object_table.keys()) |key| { |
| | 2296 | _ = try man.addFile(key.status.success.object_path, null); |
| | 2297 | } |
| | 2298 | try man.addOptionalFile(module_obj_path); |
| | 2299 | try man.addOptionalFile(compiler_rt_path); |
| | 2300 | man.hash.addOptionalBytes(options.entry); |
| | 2301 | man.hash.addOptional(options.stack_size_override); |
| | 2302 | man.hash.add(options.import_memory); |
| | 2303 | man.hash.add(options.import_table); |
| | 2304 | man.hash.add(options.export_table); |
| | 2305 | man.hash.addOptional(options.initial_memory); |
| | 2306 | man.hash.addOptional(options.max_memory); |
| | 2307 | man.hash.add(options.shared_memory); |
| | 2308 | man.hash.addOptional(options.global_base); |
| | 2309 | man.hash.add(options.export_symbol_names.len); |
| | 2310 | // strip does not need to go into the linker hash because it is part of the hash namespace |
| | 2311 | for (options.export_symbol_names) |symbol_name| { |
| | 2312 | man.hash.addBytes(symbol_name); |
| | 2313 | } |
| | 2314 | |
| | 2315 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| | 2316 | _ = try man.hit(); |
| | 2317 | digest = man.final(); |
| | 2318 | |
| | 2319 | var prev_digest_buf: [digest.len]u8 = undefined; |
| | 2320 | const prev_digest: []u8 = Cache.readSmallFile( |
| | 2321 | directory.handle, |
| | 2322 | id_symlink_basename, |
| | 2323 | &prev_digest_buf, |
| | 2324 | ) catch |err| blk: { |
| | 2325 | log.debug("WASM LLD new_digest={s} error: {s}", .{ std.fmt.fmtSliceHexLower(&digest), @errorName(err) }); |
| | 2326 | // Handle this as a cache miss. |
| | 2327 | break :blk prev_digest_buf[0..0]; |
| | 2328 | }; |
| | 2329 | if (mem.eql(u8, prev_digest, &digest)) { |
| | 2330 | log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)}); |
| | 2331 | // Hot diggity dog! The output binary is already there. |
| | 2332 | wasm.base.lock = man.toOwnedLock(); |
| | 2333 | return; |
| | 2334 | } |
| | 2335 | log.debug("WASM LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) }); |
| | 2336 | |
| | 2337 | // We are about to change the output file to be different, so we invalidate the build hash now. |
| | 2338 | directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) { |
| | 2339 | error.FileNotFound => {}, |
| | 2340 | else => |e| return e, |
| | 2341 | }; |
| | 2342 | } |
| 2254 | | 2343 | |
| 2255 | // The amount of sections that will be written | 2344 | // The amount of sections that will be written |
| 2256 | var section_count: u32 = 0; | 2345 | var section_count: u32 = 0; |
| ... | @@ -2259,17 +2348,44 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2259,17 +2348,44 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2259 | // Index of the data section. Used to tell relocation table where the section lives. | 2348 | // Index of the data section. Used to tell relocation table where the section lives. |
| 2260 | var data_section_index: ?u32 = null; | 2349 | var data_section_index: ?u32 = null; |
| 2261 | | 2350 | |
| 2262 | // Used for all temporary memory allocated during flushin | | |
| 2263 | var arena_instance = std.heap.ArenaAllocator.init(wasm.base.allocator); | | |
| 2264 | defer arena_instance.deinit(); | | |
| 2265 | const arena = arena_instance.allocator(); | | |
| 2266 | | | |
| 2267 | // Positional arguments to the linker such as object files and static archives. | 2351 | // Positional arguments to the linker such as object files and static archives. |
| 2268 | var positionals = std.ArrayList([]const u8).init(arena); | 2352 | var positionals = std.ArrayList([]const u8).init(arena); |
| 2269 | try positionals.ensureUnusedCapacity(wasm.base.options.objects.len); | 2353 | try positionals.ensureUnusedCapacity(options.objects.len); |
| | 2354 | |
| | 2355 | // When the target os is WASI, we allow linking with WASI-LIBC |
| | 2356 | if (options.target.os.tag == .wasi) { |
| | 2357 | const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or |
| | 2358 | (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); |
| | 2359 | if (is_exe_or_dyn_lib) { |
| | 2360 | const wasi_emulated_libs = wasm.base.options.wasi_emulated_libs; |
| | 2361 | for (wasi_emulated_libs) |crt_file| { |
| | 2362 | try positionals.append(try comp.get_libc_crt_file( |
| | 2363 | arena, |
| | 2364 | wasi_libc.emulatedLibCRFileLibName(crt_file), |
| | 2365 | )); |
| | 2366 | } |
| 2270 | | 2367 | |
| 2271 | for (wasm.base.options.objects) |object| { | 2368 | if (wasm.base.options.link_libc) { |
| 2272 | positionals.appendAssumeCapacity(object.path); | 2369 | try positionals.append(try comp.get_libc_crt_file( |
| | 2370 | arena, |
| | 2371 | wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model), |
| | 2372 | )); |
| | 2373 | try positionals.append(try comp.get_libc_crt_file(arena, "libc.a")); |
| | 2374 | } |
| | 2375 | |
| | 2376 | if (wasm.base.options.link_libcpp) { |
| | 2377 | try positionals.append(comp.libcxx_static_lib.?.full_object_path); |
| | 2378 | try positionals.append(comp.libcxxabi_static_lib.?.full_object_path); |
| | 2379 | } |
| | 2380 | } |
| | 2381 | } |
| | 2382 | |
| | 2383 | if (module_obj_path) |path| { |
| | 2384 | try positionals.append(path); |
| | 2385 | } |
| | 2386 | |
| | 2387 | for (options.objects) |object| { |
| | 2388 | try positionals.append(object.path); |
| 2273 | } | 2389 | } |
| 2274 | | 2390 | |
| 2275 | for (comp.c_object_table.keys()) |c_object| { | 2391 | for (comp.c_object_table.keys()) |c_object| { |
| ... | @@ -2290,46 +2406,13 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2290,46 +2406,13 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2290 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; | 2406 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; |
| 2291 | try wasm.validateFeatures(&enabled_features, &emit_features_count); | 2407 | try wasm.validateFeatures(&enabled_features, &emit_features_count); |
| 2292 | try wasm.resolveSymbolsInArchives(); | 2408 | try wasm.resolveSymbolsInArchives(); |
| 2293 | try wasm.checkUndefinedSymbols(); | 2409 | // try wasm.checkUndefinedSymbols(); |
| 2294 | | 2410 | |
| 2295 | // When we finish/error we reset the state of the linker | | |
| 2296 | // So we can rebuild the binary file on each incremental update | | |
| 2297 | defer wasm.resetState(); | | |
| 2298 | try wasm.setupStart(); | 2411 | try wasm.setupStart(); |
| 2299 | try wasm.setupImports(); | 2412 | try wasm.setupImports(); |
| 2300 | if (wasm.base.options.module) |mod| { | | |
| 2301 | var decl_it = wasm.decls.keyIterator(); | | |
| 2302 | while (decl_it.next()) |decl_index_ptr| { | | |
| 2303 | const decl = mod.declPtr(decl_index_ptr.*); | | |
| 2304 | if (decl.isExtern()) continue; | | |
| 2305 | const atom = &decl.*.link.wasm; | | |
| 2306 | if (decl.ty.zigTypeTag() == .Fn) { | | |
| 2307 | try wasm.parseAtom(atom, .{ .function = decl.fn_link.wasm }); | | |
| 2308 | } else if (decl.getVariable()) |variable| { | | |
| 2309 | if (!variable.is_mutable) { | | |
| 2310 | try wasm.parseAtom(atom, .{ .data = .read_only }); | | |
| 2311 | } else if (variable.init.isUndefDeep()) { | | |
| 2312 | try wasm.parseAtom(atom, .{ .data = .uninitialized }); | | |
| 2313 | } else { | | |
| 2314 | try wasm.parseAtom(atom, .{ .data = .initialized }); | | |
| 2315 | } | | |
| 2316 | } else { | | |
| 2317 | try wasm.parseAtom(atom, .{ .data = .read_only }); | | |
| 2318 | } | | |
| 2319 | | | |
| 2320 | // also parse atoms for a decl's locals | | |
| 2321 | for (atom.locals.items) |*local_atom| { | | |
| 2322 | try wasm.parseAtom(local_atom, .{ .data = .read_only }); | | |
| 2323 | } | | |
| 2324 | } | | |
| 2325 | | | |
| 2326 | if (wasm.dwarf) |*dwarf| { | | |
| 2327 | try dwarf.flushModule(wasm.base.options.module.?); | | |
| 2328 | } | | |
| 2329 | } | | |
| 2330 | | 2413 | |
| 2331 | for (wasm.objects.items) |*object, object_index| { | 2414 | for (wasm.objects.items) |*object, object_index| { |
| 2332 | try object.parseIntoAtoms(wasm.base.allocator, @intCast(u16, object_index), wasm); | 2415 | try object.parseIntoAtoms(gpa, @intCast(u16, object_index), wasm); |
| 2333 | } | 2416 | } |
| 2334 | | 2417 | |
| 2335 | try wasm.allocateAtoms(); | 2418 | try wasm.allocateAtoms(); |
| ... | @@ -2340,9 +2423,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2340,9 +2423,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2340 | try wasm.setupExports(); | 2423 | try wasm.setupExports(); |
| 2341 | | 2424 | |
| 2342 | const header_size = 5 + 1; | 2425 | const header_size = 5 + 1; |
| 2343 | const is_obj = wasm.base.options.output_mode == .Obj; | | |
| 2344 | | 2426 | |
| 2345 | var binary_bytes = std.ArrayList(u8).init(wasm.base.allocator); | 2427 | var binary_bytes = std.ArrayList(u8).init(gpa); |
| 2346 | defer binary_bytes.deinit(); | 2428 | defer binary_bytes.deinit(); |
| 2347 | const binary_writer = binary_bytes.writer(); | 2429 | const binary_writer = binary_bytes.writer(); |
| 2348 | | 2430 | |
| ... | @@ -2380,16 +2462,16 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2380,16 +2462,16 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2380 | } | 2462 | } |
| 2381 | | 2463 | |
| 2382 | // Import section | 2464 | // Import section |
| 2383 | const import_memory = wasm.base.options.import_memory or is_obj; | 2465 | const import_memory = options.import_memory or is_obj; |
| 2384 | const import_table = wasm.base.options.import_table or is_obj; | 2466 | const import_table = options.import_table or is_obj; |
| 2385 | if (wasm.imports.count() != 0 or import_memory or import_table) { | 2467 | if (wasm.imports.count() != 0 or import_memory or import_table) { |
| 2386 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 2468 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 2387 | | 2469 | |
| 2388 | // import table is always first table so emit that first | 2470 | // import table is always first table so emit that first |
| 2389 | if (import_table) { | 2471 | if (import_table) { |
| 2390 | const table_imp: types.Import = .{ | 2472 | const table_imp: types.Import = .{ |
| 2391 | .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name), | 2473 | .module_name = try wasm.string_table.put(gpa, wasm.host_name), |
| 2392 | .name = try wasm.string_table.put(wasm.base.allocator, "__indirect_function_table"), | 2474 | .name = try wasm.string_table.put(gpa, "__indirect_function_table"), |
| 2393 | .kind = .{ | 2475 | .kind = .{ |
| 2394 | .table = .{ | 2476 | .table = .{ |
| 2395 | .limits = .{ | 2477 | .limits = .{ |
| ... | @@ -2413,8 +2495,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2413,8 +2495,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2413 | if (import_memory) { | 2495 | if (import_memory) { |
| 2414 | const mem_name = if (is_obj) "__linear_memory" else "memory"; | 2496 | const mem_name = if (is_obj) "__linear_memory" else "memory"; |
| 2415 | const mem_imp: types.Import = .{ | 2497 | const mem_imp: types.Import = .{ |
| 2416 | .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name), | 2498 | .module_name = try wasm.string_table.put(gpa, wasm.host_name), |
| 2417 | .name = try wasm.string_table.put(wasm.base.allocator, mem_name), | 2499 | .name = try wasm.string_table.put(gpa, mem_name), |
| 2418 | .kind = .{ .memory = wasm.memories.limits }, | 2500 | .kind = .{ .memory = wasm.memories.limits }, |
| 2419 | }; | 2501 | }; |
| 2420 | try wasm.emitImport(binary_writer, mem_imp); | 2502 | try wasm.emitImport(binary_writer, mem_imp); |
| ... | @@ -2448,7 +2530,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2448,7 +2530,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2448 | } | 2530 | } |
| 2449 | | 2531 | |
| 2450 | // Table section | 2532 | // Table section |
| 2451 | const export_table = wasm.base.options.export_table; | 2533 | const export_table = options.export_table; |
| 2452 | if (!import_table and wasm.function_table.count() != 0) { | 2534 | if (!import_table and wasm.function_table.count() != 0) { |
| 2453 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 2535 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 2454 | | 2536 | |
| ... | @@ -2704,13 +2786,13 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2704,13 +2786,13 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2704 | if (data_section_index) |data_index| { | 2786 | if (data_section_index) |data_index| { |
| 2705 | try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); | 2787 | try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); |
| 2706 | } | 2788 | } |
| 2707 | } else if (!wasm.base.options.strip) { | 2789 | } else if (!options.strip) { |
| 2708 | try wasm.emitNameSection(&binary_bytes, arena); | 2790 | try wasm.emitNameSection(&binary_bytes, arena); |
| 2709 | } | 2791 | } |
| 2710 | | 2792 | |
| 2711 | if (!wasm.base.options.strip) { | 2793 | if (!options.strip) { |
| 2712 | if (wasm.dwarf) |*dwarf| { | 2794 | if (wasm.dwarf) |*dwarf| { |
| 2713 | const mod = wasm.base.options.module.?; | 2795 | const mod = options.module.?; |
| 2714 | try dwarf.writeDbgAbbrev(); | 2796 | try dwarf.writeDbgAbbrev(); |
| 2715 | // for debug info and ranges, the address is always 0, | 2797 | // for debug info and ranges, the address is always 0, |
| 2716 | // as locations are always offsets relative to 'code' section. | 2798 | // as locations are always offsets relative to 'code' section. |
| ... | @@ -2719,7 +2801,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2719,7 +2801,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2719 | try dwarf.writeDbgLineHeader(); | 2801 | try dwarf.writeDbgLineHeader(); |
| 2720 | } | 2802 | } |
| 2721 | | 2803 | |
| 2722 | var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator); | 2804 | var debug_bytes = std.ArrayList(u8).init(gpa); |
| 2723 | defer debug_bytes.deinit(); | 2805 | defer debug_bytes.deinit(); |
| 2724 | | 2806 | |
| 2725 | const DebugSection = struct { | 2807 | const DebugSection = struct { |
| ... | @@ -2768,6 +2850,21 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2768,6 +2850,21 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2768 | .iov_len = binary_bytes.items.len, | 2850 | .iov_len = binary_bytes.items.len, |
| 2769 | }}; | 2851 | }}; |
| 2770 | try wasm.base.file.?.writevAll(&iovec); | 2852 | try wasm.base.file.?.writevAll(&iovec); |
| | 2853 | |
| | 2854 | if (!wasm.base.options.disable_lld_caching) { |
| | 2855 | // Update the file with the digest. If it fails we can continue; it only |
| | 2856 | // means that the next invocation will have an unnecessary cache miss. |
| | 2857 | Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { |
| | 2858 | log.warn("failed to save linking hash digest symlink: {s}", .{@errorName(err)}); |
| | 2859 | }; |
| | 2860 | // Again failure here only means an unnecessary cache miss. |
| | 2861 | man.writeManifest() catch |err| { |
| | 2862 | log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)}); |
| | 2863 | }; |
| | 2864 | // We hang on to this lock so that the output file path can be used without |
| | 2865 | // other processes clobbering it. |
| | 2866 | wasm.base.lock = man.toOwnedLock(); |
| | 2867 | } |
| 2771 | } | 2868 | } |
| 2772 | | 2869 | |
| 2773 | pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 2870 | pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| ... | @@ -3422,7 +3519,9 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem | ... | @@ -3422,7 +3519,9 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem |
| 3422 | for (wasm.resolved_symbols.keys()) |sym_loc| { | 3519 | for (wasm.resolved_symbols.keys()) |sym_loc| { |
| 3423 | const symbol = sym_loc.getSymbol(wasm).*; | 3520 | const symbol = sym_loc.getSymbol(wasm).*; |
| 3424 | const name = if (symbol.isUndefined()) blk: { | 3521 | const name = if (symbol.isUndefined()) blk: { |
| 3425 | break :blk wasm.string_table.get(wasm.imports.get(sym_loc).?.name); | 3522 | if (symbol.tag == .data) continue; |
| | 3523 | const imp = wasm.imports.get(sym_loc) orelse continue; |
| | 3524 | break :blk wasm.string_table.get(imp.name); |
| 3426 | } else sym_loc.getName(wasm); | 3525 | } else sym_loc.getName(wasm); |
| 3427 | switch (symbol.tag) { | 3526 | switch (symbol.tag) { |
| 3428 | .function => { | 3527 | .function => { |