wasm linker: fix calling imported functions

and more disciplined type safety for output function indexes
This commit is contained in:
Andrew Kelley 2024-12-18 16:43:14 -08:00
parent 1a58ae2ed6
commit 91efc5c98b
3 changed files with 41 additions and 11 deletions

View File

@ -620,6 +620,14 @@ pub const Nav = struct {
};
}
/// Asserts that `status == .resolved`.
pub fn toExtern(nav: *const Nav, ip: *const InternPool) ?Key.Extern {
return switch (ip.indexToKey(nav.status.resolved.val)) {
.@"extern" => |ext| ext,
else => null,
};
}
/// Asserts that `status == .resolved`.
pub fn isThreadLocal(nav: Nav, ip: *const InternPool) bool {
const val = nav.status.resolved.val;

View File

@ -30,7 +30,6 @@ pub fn lowerToCode(emit: *Emit) Error!void {
const is_obj = comp.config.output_mode == .Obj;
const target = &comp.root_mod.resolved_target.result;
const is_wasm32 = target.cpu.arch == .wasm32;
const function_imports_len: u32 = @intCast(wasm.function_imports.entries.len);
const tags = mir.instruction_tags;
const datas = mir.instruction_datas;
@ -159,8 +158,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
});
code.appendNTimesAssumeCapacity(0, 5);
} else {
const func_index = Wasm.FunctionIndex.fromIpNav(wasm, datas[inst].nav_index).?;
leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable;
appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index));
}
inst += 1;
@ -200,8 +198,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
});
code.appendNTimesAssumeCapacity(0, 5);
} else {
const func_index = Wasm.FunctionIndex.fromTagNameType(wasm, datas[inst].ip_index).?;
leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable;
appendOutputFunctionIndex(code, .fromTagNameType(wasm, datas[inst].ip_index));
}
inst += 1;
@ -225,8 +222,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
});
code.appendNTimesAssumeCapacity(0, 5);
} else {
const func_index = Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name).?;
leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable;
appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name));
}
inst += 1;
@ -978,3 +974,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff
}
}
}
fn appendOutputFunctionIndex(code: *std.ArrayListUnmanaged(u8), i: Wasm.OutputFunctionIndex) void {
leb.writeUleb128(code.fixedWriter(), @intFromEnum(i)) catch unreachable;
}

View File

@ -283,10 +283,6 @@ pub const FunctionIndex = enum(u32) {
return &wasm.functions.keys()[@intFromEnum(index)];
}
pub fn toOutputFunctionIndex(index: FunctionIndex, wasm: *const Wasm) OutputFunctionIndex {
return @enumFromInt(wasm.function_imports.entries.len + @intFromEnum(index));
}
pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?FunctionIndex {
return fromResolution(wasm, .fromIpNav(wasm, nav_index));
}
@ -324,6 +320,31 @@ pub const GlobalExport = extern struct {
/// `flush`.
pub const OutputFunctionIndex = enum(u32) {
_,
pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex {
return @enumFromInt(wasm.function_imports.entries.len + @intFromEnum(index));
}
pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputFunctionIndex {
const zcu = wasm.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
if (nav.toExtern(ip)) |ext| {
const name = wasm.getExistingString(ext.name.toSlice(ip)).?;
if (wasm.function_imports.getIndex(name)) |i| return @enumFromInt(i);
return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?);
} else {
return fromFunctionIndex(wasm, FunctionIndex.fromIpNav(wasm, nav_index).?);
}
}
pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex {
return fromFunctionIndex(wasm, FunctionIndex.fromTagNameType(wasm, tag_type).?);
}
pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex {
return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?);
}
};
/// Index into `Wasm.globals`.
@ -788,6 +809,7 @@ pub const FunctionImport = extern struct {
const zcu = wasm.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
//log.debug("Resolution.fromIpNav {}({})", .{ nav.fqn.fmt(ip), nav_index });
return pack(wasm, .{
.zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(nav.status.resolved.val).?),
});