authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-20 20:18:22-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log2dbf66dd698601ae8aaee86d5ba6a9078dda0a8e
tree99a3638fd838df2472dd1e051e0ec0b9838e6605
parentd1cde847a367c526c63d65714583189fa2912731

wasm linker: implement stack pointer global


3 files changed, 22 insertions(+), 5 deletions(-)

src/Compilation.zig+2
......@@ -118,6 +118,8 @@ link_task_queue_safety: std.debug.SafetyLock = .{},
118118link_task_queue_postponed: std.ArrayListUnmanaged(link.Task) = .empty,
119119/// Initialized with how many link input tasks are expected. After this reaches zero
120120/// the linker will begin the prelink phase.
121/// Initialized in the Compilation main thread before the pipeline; modified only in
122/// the linker task thread.
121123remaining_prelink_tasks: u32,
122124
123125work_queues: [
src/link/Wasm.zig+11-4
......@@ -361,12 +361,13 @@ pub const OutputFunctionIndex = enum(u32) {
361361pub const GlobalIndex = enum(u32) {
362362 _,
363363
364 /// This is only accurate when there is a Zcu.
364 /// This is only accurate when not emitting an object and there is a Zcu.
365365 pub const stack_pointer: GlobalIndex = @enumFromInt(0);
366366
367367 /// Same as `stack_pointer` but with a safety assertion.
368368 pub fn stackPointer(wasm: *const Wasm) Global.Index {
369369 const comp = wasm.base.comp;
370 assert(comp.config.output_mode != .Obj);
370371 assert(comp.zcu != null);
371372 return .stack_pointer;
372373 }
......@@ -2450,7 +2451,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
24502451 .variable => |variable| .{ variable.init, variable.owner_nav },
24512452 else => .{ nav.status.resolved.val, nav_index },
24522453 };
2453 log.debug("updateNav {} {}", .{ nav.fqn.fmt(ip), chased_nav_index });
2454 //log.debug("updateNav {} {}", .{ nav.fqn.fmt(ip), chased_nav_index });
24542455 assert(!wasm.imports.contains(chased_nav_index));
24552456
24562457 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
......@@ -2578,6 +2579,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
25782579 const comp = wasm.base.comp;
25792580 const gpa = comp.gpa;
25802581 const rdynamic = comp.config.rdynamic;
2582 const is_obj = comp.config.output_mode == .Obj;
25812583
25822584 assert(wasm.missing_exports.entries.len == 0);
25832585 for (wasm.export_symbol_names) |exp_name| {
......@@ -2614,8 +2616,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
26142616
26152617 if (comp.zcu != null) {
26162618 // Zig always depends on a stack pointer global.
2617 try wasm.globals.put(gpa, .__stack_pointer, {});
2618 assert(wasm.globals.entries.len - 1 == @intFromEnum(GlobalIndex.stack_pointer));
2619 // If emitting an object, it's an import. Otherwise, the linker synthesizes it.
2620 if (is_obj) {
2621 @panic("TODO");
2622 } else {
2623 try wasm.globals.put(gpa, .__stack_pointer, {});
2624 assert(wasm.globals.entries.len - 1 == @intFromEnum(GlobalIndex.stack_pointer));
2625 }
26192626 }
26202627
26212628 // These loops do both recursive marking of alive symbols well as checking for undefined symbols.
src/link/Wasm/Flush.zig+9-1
......@@ -565,7 +565,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
565565 .unresolved => unreachable,
566566 .__heap_base => @panic("TODO"),
567567 .__heap_end => @panic("TODO"),
568 .__stack_pointer => @panic("TODO"),
568 .__stack_pointer => {
569 try binary_bytes.appendSlice(gpa, &.{
570 @intFromEnum(std.wasm.Valtype.i32),
571 @intFromBool(true), // mutable
572 @intFromEnum(std.wasm.Opcode.i32_const),
573 0, // leb128 init value
574 @intFromEnum(std.wasm.Opcode.end),
575 });
576 },
569577 .__tls_align => @panic("TODO"),
570578 .__tls_base => @panic("TODO"),
571579 .__tls_size => @panic("TODO"),