wasm linker: implement stack pointer global

This commit is contained in:
Andrew Kelley 2024-12-20 20:18:22 -08:00
parent d1cde847a3
commit 2dbf66dd69
3 changed files with 22 additions and 5 deletions

View File

@ -118,6 +118,8 @@ link_task_queue_safety: std.debug.SafetyLock = .{},
link_task_queue_postponed: std.ArrayListUnmanaged(link.Task) = .empty,
/// Initialized with how many link input tasks are expected. After this reaches zero
/// the linker will begin the prelink phase.
/// Initialized in the Compilation main thread before the pipeline; modified only in
/// the linker task thread.
remaining_prelink_tasks: u32,
work_queues: [

View File

@ -361,12 +361,13 @@ pub const OutputFunctionIndex = enum(u32) {
pub const GlobalIndex = enum(u32) {
_,
/// This is only accurate when there is a Zcu.
/// This is only accurate when not emitting an object and there is a Zcu.
pub const stack_pointer: GlobalIndex = @enumFromInt(0);
/// Same as `stack_pointer` but with a safety assertion.
pub fn stackPointer(wasm: *const Wasm) Global.Index {
const comp = wasm.base.comp;
assert(comp.config.output_mode != .Obj);
assert(comp.zcu != null);
return .stack_pointer;
}
@ -2450,7 +2451,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
.variable => |variable| .{ variable.init, variable.owner_nav },
else => .{ nav.status.resolved.val, nav_index },
};
log.debug("updateNav {} {}", .{ nav.fqn.fmt(ip), chased_nav_index });
//log.debug("updateNav {} {}", .{ nav.fqn.fmt(ip), chased_nav_index });
assert(!wasm.imports.contains(chased_nav_index));
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
const comp = wasm.base.comp;
const gpa = comp.gpa;
const rdynamic = comp.config.rdynamic;
const is_obj = comp.config.output_mode == .Obj;
assert(wasm.missing_exports.entries.len == 0);
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
if (comp.zcu != null) {
// Zig always depends on a stack pointer global.
try wasm.globals.put(gpa, .__stack_pointer, {});
assert(wasm.globals.entries.len - 1 == @intFromEnum(GlobalIndex.stack_pointer));
// If emitting an object, it's an import. Otherwise, the linker synthesizes it.
if (is_obj) {
@panic("TODO");
} else {
try wasm.globals.put(gpa, .__stack_pointer, {});
assert(wasm.globals.entries.len - 1 == @intFromEnum(GlobalIndex.stack_pointer));
}
}
// These loops do both recursive marking of alive symbols well as checking for undefined symbols.

View File

@ -565,7 +565,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
.unresolved => unreachable,
.__heap_base => @panic("TODO"),
.__heap_end => @panic("TODO"),
.__stack_pointer => @panic("TODO"),
.__stack_pointer => {
try binary_bytes.appendSlice(gpa, &.{
@intFromEnum(std.wasm.Valtype.i32),
@intFromBool(true), // mutable
@intFromEnum(std.wasm.Opcode.i32_const),
0, // leb128 init value
@intFromEnum(std.wasm.Opcode.end),
});
},
.__tls_align => @panic("TODO"),
.__tls_base => @panic("TODO"),
.__tls_size => @panic("TODO"),