authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-19 16:01:18-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log5e0d33f00fea077b362f468d89a979aee270df0b
tree189b5a32eb1ce645ff876a928267dc620ff142ef
parent389b29fd8c13707891486dfed64ed2b9df3f1a39

wasm linker: also call lowerZcuData in updateFunc

codegen can generate zcu data dependencies that need to be populated

2 files changed, 91 insertions(+), 41 deletions(-)

src/link/Wasm.zig+90-39
...@@ -675,6 +675,88 @@ pub const ZcuDataExe = extern struct {...@@ -675,6 +675,88 @@ pub const ZcuDataExe = extern struct {
675 count: u32,675 count: u32,
676};676};
677677
678/// An abstraction for calling `lowerZcuData` repeatedly until all data entries
679/// are populated.
680const ZcuDataStarts = struct {
681 uavs_i: u32,
682 navs_i: u32,
683
684 fn init(wasm: *const Wasm) ZcuDataStarts {
685 const comp = wasm.base.comp;
686 const is_obj = comp.config.output_mode == .Obj;
687 return if (is_obj) initObj(wasm) else initExe(wasm);
688 }
689
690 fn initObj(wasm: *const Wasm) ZcuDataStarts {
691 return .{
692 .uavs_i = @intCast(wasm.uavs_obj.entries.len),
693 .navs_i = @intCast(wasm.navs_obj.entries.len),
694 };
695 }
696
697 fn initExe(wasm: *const Wasm) ZcuDataStarts {
698 return .{
699 .uavs_i = @intCast(wasm.uavs_exe.entries.len),
700 .navs_i = @intCast(wasm.navs_exe.entries.len),
701 };
702 }
703
704 fn finish(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void {
705 const comp = wasm.base.comp;
706 const is_obj = comp.config.output_mode == .Obj;
707 return if (is_obj) finishObj(zds, wasm, pt) else finishExe(zds, wasm, pt);
708 }
709
710 fn finishObj(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void {
711 const zcu = wasm.base.comp.zcu.?;
712 const ip = &zcu.intern_pool;
713 var uavs_i = zds.uavs_i;
714 var navs_i = zds.navs_i;
715 while (true) {
716 while (navs_i < wasm.navs_obj.entries.len) : (navs_i += 1) {
717 const elem_nav = ip.getNav(wasm.navs_obj.keys()[navs_i]);
718 const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) {
719 .variable => |variable| variable.init,
720 else => elem_nav.status.resolved.val,
721 };
722 // Call to `lowerZcuData` here possibly creates more entries in these tables.
723 wasm.navs_obj.values()[navs_i] = try lowerZcuData(wasm, pt, elem_nav_init);
724 }
725 while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) {
726 // Call to `lowerZcuData` here possibly creates more entries in these tables.
727 wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]);
728 }
729 if (navs_i >= wasm.navs_obj.entries.len) break;
730 }
731 }
732
733 fn finishExe(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void {
734 const zcu = wasm.base.comp.zcu.?;
735 const ip = &zcu.intern_pool;
736 var uavs_i = zds.uavs_i;
737 var navs_i = zds.navs_i;
738 while (true) {
739 while (navs_i < wasm.navs_exe.entries.len) : (navs_i += 1) {
740 const elem_nav = ip.getNav(wasm.navs_exe.keys()[navs_i]);
741 const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) {
742 .variable => |variable| variable.init,
743 else => elem_nav.status.resolved.val,
744 };
745 // Call to `lowerZcuData` here possibly creates more entries in these tables.
746 const zcu_data = try lowerZcuData(wasm, pt, elem_nav_init);
747 assert(zcu_data.relocs.len == 0);
748 wasm.navs_exe.values()[navs_i].code = zcu_data.code;
749 }
750 while (uavs_i < wasm.uavs_exe.entries.len) : (uavs_i += 1) {
751 // Call to `lowerZcuData` here possibly creates more entries in these tables.
752 const zcu_data = try lowerZcuData(wasm, pt, wasm.uavs_exe.keys()[uavs_i]);
753 wasm.uavs_exe.values()[uavs_i].code = zcu_data.code;
754 }
755 if (navs_i >= wasm.navs_exe.entries.len) break;
756 }
757 }
758};
759
678pub const ZcuFunc = extern struct {760pub const ZcuFunc = extern struct {
679 function: CodeGen.Function,761 function: CodeGen.Function,
680762
...@@ -2306,6 +2388,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -2306,6 +2388,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
2306 try wasm.functions.ensureUnusedCapacity(gpa, 1);2388 try wasm.functions.ensureUnusedCapacity(gpa, 1);
2307 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);2389 try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1);
23082390
2391 const zds: ZcuDataStarts = .init(wasm);
2392
2309 // This converts AIR to MIR but does not yet lower to wasm code.2393 // This converts AIR to MIR but does not yet lower to wasm code.
2310 // That lowering happens during `flush`, after garbage collection, which2394 // That lowering happens during `flush`, after garbage collection, which
2311 // can affect function and global indexes, which affects the LEB integer2395 // can affect function and global indexes, which affects the LEB integer
...@@ -2314,6 +2398,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -2314,6 +2398,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
2314 .function = try CodeGen.function(wasm, pt, func_index, air, liveness),2398 .function = try CodeGen.function(wasm, pt, func_index, air, liveness),
2315 });2399 });
2316 wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});2400 wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {});
2401
2402 try zds.finish(wasm, pt);
2317}2403}
23182404
2319// Generate code for the "Nav", storing it in memory to be later written to2405// Generate code for the "Nav", storing it in memory to be later written to
...@@ -2365,48 +2451,13 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -2365,48 +2451,13 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
2365 }2451 }
23662452
2367 if (is_obj) {2453 if (is_obj) {
2368 var uavs_i = wasm.uavs_obj.entries.len;2454 const zcu_data_starts: ZcuDataStarts = .initObj(wasm);
2369 var navs_i = wasm.navs_obj.entries.len;
2370 _ = try refNavObj(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_obj`.2455 _ = try refNavObj(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_obj`.
2371 while (true) {2456 try zcu_data_starts.finishObj(wasm, pt);
2372 while (navs_i < wasm.navs_obj.entries.len) : (navs_i += 1) {
2373 const elem_nav = ip.getNav(wasm.navs_obj.keys()[navs_i]);
2374 const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) {
2375 .variable => |variable| variable.init,
2376 else => elem_nav.status.resolved.val,
2377 };
2378 // Call to `lowerZcuData` here possibly creates more entries in these tables.
2379 wasm.navs_obj.values()[navs_i] = try lowerZcuData(wasm, pt, elem_nav_init);
2380 }
2381 while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) {
2382 // Call to `lowerZcuData` here possibly creates more entries in these tables.
2383 wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]);
2384 }
2385 if (navs_i >= wasm.navs_obj.entries.len) break;
2386 }
2387 } else {2457 } else {
2388 var uavs_i = wasm.uavs_exe.entries.len;2458 const zcu_data_starts: ZcuDataStarts = .initExe(wasm);
2389 var navs_i = wasm.navs_exe.entries.len;
2390 _ = try refNavExe(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_exe`.2459 _ = try refNavExe(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_exe`.
2391 while (true) {2460 try zcu_data_starts.finishExe(wasm, pt);
2392 while (navs_i < wasm.navs_exe.entries.len) : (navs_i += 1) {
2393 const elem_nav = ip.getNav(wasm.navs_exe.keys()[navs_i]);
2394 const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) {
2395 .variable => |variable| variable.init,
2396 else => elem_nav.status.resolved.val,
2397 };
2398 // Call to `lowerZcuData` here possibly creates more entries in these tables.
2399 const zcu_data = try lowerZcuData(wasm, pt, elem_nav_init);
2400 assert(zcu_data.relocs.len == 0);
2401 wasm.navs_exe.values()[navs_i].code = zcu_data.code;
2402 }
2403 while (uavs_i < wasm.uavs_exe.entries.len) : (uavs_i += 1) {
2404 // Call to `lowerZcuData` here possibly creates more entries in these tables.
2405 const zcu_data = try lowerZcuData(wasm, pt, wasm.uavs_exe.keys()[uavs_i]);
2406 wasm.uavs_exe.values()[uavs_i].code = zcu_data.code;
2407 }
2408 if (navs_i >= wasm.navs_exe.entries.len) break;
2409 }
2410 }2461 }
2411}2462}
24122463
src/link/Wasm/Flush.zig+1-2
...@@ -644,8 +644,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -644,8 +644,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
644 const code_start = try reserveSize(gpa, binary_bytes);644 const code_start = try reserveSize(gpa, binary_bytes);
645 defer replaceSize(binary_bytes, code_start);645 defer replaceSize(binary_bytes, code_start);
646646
647 const function = &i.value(wasm).function;647 try i.value(wasm).function.lower(wasm, binary_bytes);
648 try function.lower(wasm, binary_bytes);
649 },648 },
650 };649 };
651650