Commit bf88059591
Changed files (3)
src
link
src/link/Wasm/Flush.zig
@@ -335,8 +335,6 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max});
}
- // Size of each section header
- const header_size = 5 + 1;
var section_index: u32 = 0;
// Index of the code section. Used to tell relocation table where the section lives.
var code_section_index: ?u32 = null;
@@ -369,54 +367,50 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
}
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .type,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.func_types.entries.len),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(wasm.func_types.entries.len));
section_index += 1;
}
// Import section
- const total_imports_len = wasm.function_imports.entries.len + wasm.global_imports.entries.len +
- wasm.table_imports.entries.len + wasm.object_memory_imports.items.len + @intFromBool(import_memory);
-
- if (total_imports_len > 0) {
+ {
+ var total_imports: usize = 0;
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- for (wasm.function_imports.values()) |*function_import| {
- const module_name = function_import.moduleName(wasm).slice(wasm);
+ for (wasm.function_imports.values()) |id| {
+ const module_name = id.moduleName(wasm).slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
try binary_writer.writeAll(module_name);
- const name = function_import.name(wasm).slice(wasm);
+ const name = id.name(wasm).slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
try binary_writer.writeAll(name);
try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
- try leb.writeUleb128(binary_writer, @intFromEnum(function_import.functionType(wasm)));
+ try leb.writeUleb128(binary_writer, @intFromEnum(id.functionType(wasm)));
}
+ total_imports += wasm.function_imports.entries.len;
- for (wasm.table_imports.values()) |*table_import| {
- const module_name = table_import.moduleName(wasm).slice(wasm);
+ for (wasm.table_imports.values()) |id| {
+ const table_import = id.value(wasm);
+ const module_name = table_import.module_name.slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
try binary_writer.writeAll(module_name);
- const name = table_import.name(wasm).slice(wasm);
+ const name = id.key(wasm).slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
try binary_writer.writeAll(name);
try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.table));
- try leb.writeUleb128(binary_writer, std.wasm.reftype(table_import.reftype));
- try emitLimits(binary_writer, table_import.limits);
+ try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to())));
+ try emitLimits(gpa, binary_bytes, table_import.limits());
}
+ total_imports += wasm.table_imports.entries.len;
for (wasm.object_memory_imports.items) |*memory_import| {
- try emitMemoryImport(wasm, binary_writer, memory_import);
+ try emitMemoryImport(wasm, binary_bytes, memory_import);
+ total_imports += 1;
} else if (import_memory) {
- try emitMemoryImport(wasm, binary_writer, &.{
+ try emitMemoryImport(wasm, binary_bytes, &.{
.module_name = wasm.host_name,
.name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory,
.limits_min = wasm.memories.limits.min,
@@ -424,100 +418,87 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
.limits_has_max = wasm.memories.limits.flags.has_max,
.limits_is_shared = wasm.memories.limits.flags.is_shared,
});
+ total_imports += 1;
}
- for (wasm.global_imports.values()) |*global_import| {
- const module_name = global_import.module_name.slice(wasm);
+ for (wasm.global_imports.values()) |id| {
+ const module_name = id.moduleName(wasm).slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
try binary_writer.writeAll(module_name);
- const name = global_import.name.slice(wasm);
+ const name = id.name(wasm).slice(wasm);
try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
try binary_writer.writeAll(name);
try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.global));
- try leb.writeUleb128(binary_writer, @intFromEnum(global_import.valtype));
- try binary_writer.writeByte(@intFromBool(global_import.mutable));
+ const global_type = id.globalType(wasm);
+ try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.Valtype, global_type.valtype)));
+ try binary_writer.writeByte(@intFromBool(global_type.mutable));
}
+ total_imports += wasm.global_imports.entries.len;
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .import,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(total_imports_len),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .import, @intCast(total_imports));
section_index += 1;
}
// Function section
if (wasm.functions.count() != 0) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- for (wasm.functions.values()) |function| {
- try leb.writeUleb128(binary_writer, function.func.type_index);
+ for (wasm.functions.keys()) |function| {
+ try leb.writeUleb128(binary_writer, @intFromEnum(function.typeIndex(wasm)));
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .function,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.functions.count()),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count()));
section_index += 1;
}
// Table section
- if (wasm.tables.items.len > 0) {
+ if (wasm.tables.entries.len > 0) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- for (wasm.tables.items) |table| {
- try leb.writeUleb128(binary_writer, std.wasm.reftype(table.reftype));
- try emitLimits(binary_writer, table.limits);
+ for (wasm.tables.keys()) |table| {
+ try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table.refType(wasm))));
+ try emitLimits(gpa, binary_bytes, table.limits(wasm));
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .table,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.tables.items.len),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .table, @intCast(wasm.tables.entries.len));
section_index += 1;
}
- // Memory section
+ // Memory section. wasm currently only supports 1 linear memory segment.
if (!import_memory) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
-
- try emitLimits(binary_writer, wasm.memories.limits);
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .memory,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- 1, // wasm currently only supports 1 linear memory segment
- );
+ try emitLimits(gpa, binary_bytes, wasm.memories.limits);
+ replaceVecSectionHeader(binary_bytes, header_offset, .memory, 1);
section_index += 1;
}
// Global section (used to emit stack pointer)
- if (wasm.output_globals.items.len > 0) {
+ if (wasm.globals.entries.len > 0) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- for (wasm.output_globals.items) |global| {
- try binary_writer.writeByte(@intFromEnum(global.global_type.valtype));
- try binary_writer.writeByte(@intFromBool(global.global_type.mutable));
- try emitInit(binary_writer, global.init);
+ for (wasm.globals.keys()) |global_resolution| {
+ switch (global_resolution.unpack(wasm)) {
+ .unresolved => unreachable,
+ .__heap_base => @panic("TODO"),
+ .__heap_end => @panic("TODO"),
+ .__stack_pointer => @panic("TODO"),
+ .__tls_align => @panic("TODO"),
+ .__tls_base => @panic("TODO"),
+ .__tls_size => @panic("TODO"),
+ .__zig_error_name_table => @panic("TODO"),
+ .object_global => |i| {
+ const global = i.ptr(wasm);
+ try binary_writer.writeByte(@intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())));
+ try binary_writer.writeByte(@intFromBool(global.flags.global_type.mutable));
+ try emitExpr(wasm, binary_bytes, global.expr);
+ },
+ .nav_exe => @panic("TODO"),
+ .nav_obj => @panic("TODO"),
+ }
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .global,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.output_globals.items.len),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .global, @intCast(wasm.globals.entries.len));
section_index += 1;
}
@@ -540,25 +521,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
try leb.writeUleb128(binary_writer, @as(u32, 0));
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .@"export",
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.exports.items.len + @intFromBool(export_memory)),
- );
+ const n_items: u32 = @intCast(wasm.exports.items.len + @intFromBool(export_memory));
+ replaceVecSectionHeader(binary_bytes, header_offset, .@"export", n_items);
section_index += 1;
}
- if (wasm.entry) |entry_index| {
+ if (Wasm.FunctionIndex.fromResolution(wasm.entry_resolution)) |entry_index| {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .start,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- entry_index,
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .start, @intFromEnum(entry_index));
}
// element section (function table)
@@ -586,26 +556,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
try leb.writeUleb128(binary_writer, sym.index);
}
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .element,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- 1,
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .element, 1);
section_index += 1;
}
// When the shared-memory option is enabled, we *must* emit the 'data count' section.
if (f.data_segment_groups.items.len > 0 and shared_memory) {
const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .data_count,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(f.data_segment_groups.items.len),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));
}
// Code section.
@@ -636,13 +594,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
},
};
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .code,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- @intCast(wasm.functions.count()),
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .code, @intCast(wasm.functions.entries.len));
code_section_index = section_index;
section_index += 1;
}
@@ -682,13 +634,7 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) !void {
}
assert(group_index == f.data_segment_groups.items.len);
- try writeVecSectionHeader(
- binary_bytes.items,
- header_offset,
- .data,
- @intCast(binary_bytes.items.len - header_offset - header_size),
- group_index,
- );
+ replaceVecSectionHeader(binary_bytes, header_offset, .data, group_index);
data_section_index = section_index;
section_index += 1;
}
@@ -768,7 +714,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), arena
};
var globals: std.MultiArrayList(NamedIndex) = .empty;
- try globals.ensureTotalCapacityPrecise(arena, wasm.output_globals.items.len + wasm.global_imports.items.len);
+ try globals.ensureTotalCapacityPrecise(arena, wasm.globals.items.len + wasm.global_imports.items.len);
var segments: std.MultiArrayList(NamedIndex) = .empty;
try segments.ensureTotalCapacityPrecise(arena, wasm.data_segments.count());
@@ -844,10 +790,8 @@ fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void {
}
fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 {
- // unlike regular section, we don't emit the count
- const header_size = 1 + 5;
- try bytes.appendNTimes(gpa, 0, header_size);
- return @intCast(bytes.items.len - header_size);
+ try bytes.appendNTimes(gpa, 0, section_header_size);
+ return @intCast(bytes.items.len - section_header_size);
}
fn emitNameSubsection(
@@ -1106,38 +1050,57 @@ fn wantSegmentMerge(wasm: *const Wasm, a_index: Wasm.DataSegment.Index, b_index:
return a_prefix.len > 0 and mem.eql(u8, a_prefix, b_prefix);
}
+/// section id + fixed leb contents size + fixed leb vector length
+const section_header_reserve_size = 1 + 5 + 5;
+const section_header_size = 5 + 1;
+
fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 {
- // section id + fixed leb contents size + fixed leb vector length
- const header_size = 1 + 5 + 5;
- try bytes.appendNTimes(gpa, 0, header_size);
- return @intCast(bytes.items.len - header_size);
+ try bytes.appendNTimes(gpa, 0, section_header_reserve_size);
+ return @intCast(bytes.items.len - section_header_reserve_size);
}
-fn writeVecSectionHeader(buffer: []u8, offset: u32, section: std.wasm.Section, size: u32, items: u32) !void {
- var buf: [1 + 5 + 5]u8 = undefined;
- buf[0] = @intFromEnum(section);
- leb.writeUnsignedFixed(5, buf[1..6], size);
- leb.writeUnsignedFixed(5, buf[6..], items);
- buffer[offset..][0..buf.len].* = buf;
+fn replaceVecSectionHeader(
+ bytes: *std.ArrayListUnmanaged(u8),
+ offset: u32,
+ section: std.wasm.Section,
+ n_items: u32,
+) void {
+ const size: u32 = @intCast(bytes.items.len - offset - section_header_size);
+ var buf: [section_header_reserve_size]u8 = undefined;
+ var fbw = std.io.fixedBufferStream(&buf);
+ const w = fbw.writer();
+ w.writeByte(@intFromEnum(section)) catch unreachable;
+ leb.writeUleb128(w, size) catch unreachable;
+ leb.writeUleb128(w, n_items) catch unreachable;
+ bytes.replaceRangeAssumeCapacity(offset, section_header_reserve_size, fbw.getWritten());
}
-fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void {
- try writer.writeByte(limits.flags);
- try leb.writeUleb128(writer, limits.min);
- if (limits.flags.has_max) try leb.writeUleb128(writer, limits.max);
+fn emitLimits(
+ gpa: Allocator,
+ binary_bytes: *std.ArrayListUnmanaged(u8),
+ limits: std.wasm.Limits,
+) Allocator.Error!void {
+ try binary_bytes.append(gpa, @bitCast(limits.flags));
+ try leb.writeUleb128(binary_bytes.writer(gpa), limits.min);
+ if (limits.flags.has_max) try leb.writeUleb128(binary_bytes.writer(gpa), limits.max);
}
-fn emitMemoryImport(wasm: *Wasm, writer: anytype, memory_import: *const Wasm.MemoryImport) Allocator.Error!void {
+fn emitMemoryImport(
+ wasm: *Wasm,
+ binary_bytes: *std.ArrayListUnmanaged(u8),
+ memory_import: *const Wasm.MemoryImport,
+) Allocator.Error!void {
+ const gpa = wasm.base.comp.gpa;
const module_name = memory_import.module_name.slice(wasm);
- try leb.writeUleb128(writer, @as(u32, @intCast(module_name.len)));
- try writer.writeAll(module_name);
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len)));
+ try binary_bytes.appendSlice(gpa, module_name);
const name = memory_import.name.slice(wasm);
- try leb.writeUleb128(writer, @as(u32, @intCast(name.len)));
- try writer.writeAll(name);
+ try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
+ try binary_bytes.appendSlice(gpa, name);
- try writer.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));
- try emitLimits(writer, memory_import.limits());
+ try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory));
+ try emitLimits(gpa, binary_bytes, memory_import.limits());
}
pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void {
@@ -1166,6 +1129,12 @@ pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void {
try writer.writeByte(@intFromEnum(std.wasm.Opcode.end));
}
+pub fn emitExpr(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), expr: Wasm.Expr) Allocator.Error!void {
+ const gpa = wasm.base.comp.gpa;
+ const slice = expr.slice(wasm);
+ try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode
+}
+
//fn emitLinkSection(
// wasm: *Wasm,
// binary_bytes: *std.ArrayListUnmanaged(u8),
src/link/Wasm/Object.zig
@@ -1040,9 +1040,9 @@ fn readInit(wasm: *Wasm, bytes: []const u8, pos: usize) !struct { Wasm.Expr, usi
return .{ try wasm.addExpr(bytes[pos..end_pos]), end_pos };
}
-fn skipInit(bytes: []const u8, pos: usize) !usize {
+pub fn exprEndPos(bytes: []const u8, pos: usize) error{InvalidInitOpcode}!usize {
const opcode = bytes[pos];
- const end_pos = switch (@as(std.wasm.Opcode, @enumFromInt(opcode))) {
+ return switch (@as(std.wasm.Opcode, @enumFromInt(opcode))) {
.i32_const => readLeb(i32, bytes, pos + 1)[1],
.i64_const => readLeb(i64, bytes, pos + 1)[1],
.f32_const => pos + 5,
@@ -1050,6 +1050,10 @@ fn skipInit(bytes: []const u8, pos: usize) !usize {
.global_get => readLeb(u32, bytes, pos + 1)[1],
else => return error.InvalidInitOpcode,
};
+}
+
+fn skipInit(bytes: []const u8, pos: usize) !usize {
+ const end_pos = try exprEndPos(bytes, pos);
const op, const final_pos = readEnum(std.wasm.Opcode, bytes, end_pos);
if (op != .end) return error.InitExprMissingEnd;
return final_pos;
src/link/Wasm.zig
@@ -404,7 +404,7 @@ pub const SymbolFlags = packed struct(u32) {
/// Zig-specific. Data segments only.
alignment: Alignment = .none,
/// Zig-specific. Globals only.
- global_type: Global.Type = .zero,
+ global_type: GlobalType4 = .zero,
/// Zig-specific. Tables only.
limits_has_max: bool = false,
/// Zig-specific. Tables only.
@@ -481,6 +481,48 @@ pub const SymbolFlags = packed struct(u32) {
}
};
+pub const GlobalType4 = packed struct(u4) {
+ valtype: Valtype3,
+ mutable: bool,
+
+ pub const zero: GlobalType4 = @bitCast(@as(u4, 0));
+
+ pub fn to(gt: GlobalType4) Global.Type {
+ return .{
+ .valtype = gt.valtype.to(),
+ .mutable = gt.mutable,
+ };
+ }
+};
+
+pub const Valtype3 = enum(u3) {
+ i32,
+ i64,
+ f32,
+ f64,
+ v128,
+
+ pub fn from(v: std.wasm.Valtype) Valtype3 {
+ return switch (v) {
+ .i32 => .i32,
+ .i64 => .i64,
+ .f32 => .f32,
+ .f64 => .f64,
+ .v128 => .v128,
+ };
+ }
+
+ pub fn to(v: Valtype3) std.wasm.Valtype {
+ return switch (v) {
+ .i32 => .i32,
+ .i64 => .i64,
+ .f32 => .f32,
+ .f64 => .f64,
+ .v128 => .v128,
+ };
+ }
+};
+
pub const NavObj = extern struct {
code: DataSegment.Payload,
/// Empty if not emitting an object.
@@ -591,7 +633,7 @@ pub const FunctionImport = extern struct {
__zig_error_names,
object_function: ObjectFunctionIndex,
nav_exe: NavExe.Index,
- nav_obj: NavExe.Index,
+ nav_obj: NavObj.Index,
};
pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked {
@@ -649,6 +691,20 @@ pub const FunctionImport = extern struct {
else => false,
};
}
+
+ pub fn typeIndex(r: Resolution, wasm: *const Wasm) FunctionType.Index {
+ return switch (unpack(r, wasm)) {
+ .unresolved => unreachable,
+ .__wasm_apply_global_tls_relocs => @panic("TODO"),
+ .__wasm_call_ctors => @panic("TODO"),
+ .__wasm_init_memory => @panic("TODO"),
+ .__wasm_init_tls => @panic("TODO"),
+ .__zig_error_names => @panic("TODO"),
+ .object_function => |i| i.ptr(wasm).type_index,
+ .nav_exe => @panic("TODO"),
+ .nav_obj => @panic("TODO"),
+ };
+ }
};
/// Index into `object_function_imports`.
@@ -731,11 +787,13 @@ pub const GlobalImport = extern struct {
pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked {
return switch (r) {
.unresolved => .unresolved,
- .__wasm_apply_global_tls_relocs => .__wasm_apply_global_tls_relocs,
- .__wasm_call_ctors => .__wasm_call_ctors,
- .__wasm_init_memory => .__wasm_init_memory,
- .__wasm_init_tls => .__wasm_init_tls,
- .__zig_error_names => .__zig_error_names,
+ .__heap_base => .__heap_base,
+ .__heap_end => .__heap_end,
+ .__stack_pointer => .__stack_pointer,
+ .__tls_align => .__tls_align,
+ .__tls_base => .__tls_base,
+ .__tls_size => .__tls_size,
+ .__zig_error_name_table => .__zig_error_name_table,
_ => {
const i: u32 = @intFromEnum(r);
const object_global_index = i - first_object_global;
@@ -780,12 +838,28 @@ pub const GlobalImport = extern struct {
}
};
- /// Index into `object_global_imports`.
+ /// Index into `Wasm.object_global_imports`.
pub const Index = enum(u32) {
_,
- pub fn ptr(index: Index, wasm: *const Wasm) *GlobalImport {
- return &wasm.object_global_imports.items[@intFromEnum(index)];
+ pub fn key(index: Index, wasm: *const Wasm) *String {
+ return &wasm.object_global_imports.keys()[@intFromEnum(index)];
+ }
+
+ pub fn value(index: Index, wasm: *const Wasm) *GlobalImport {
+ return &wasm.object_global_imports.values()[@intFromEnum(index)];
+ }
+
+ pub fn name(index: Index, wasm: *const Wasm) String {
+ return index.key(wasm).*;
+ }
+
+ pub fn moduleName(index: Index, wasm: *const Wasm) String {
+ return index.value(wasm).module_name;
+ }
+
+ pub fn globalType(index: Index, wasm: *const Wasm) Global.Type {
+ return value(index, wasm).flags.global_type.to();
}
};
};
@@ -796,39 +870,9 @@ pub const Global = extern struct {
flags: SymbolFlags,
expr: Expr,
- pub const Type = packed struct(u4) {
- valtype: Valtype,
+ pub const Type = struct {
+ valtype: std.wasm.Valtype,
mutable: bool,
-
- pub const zero: Type = @bitCast(@as(u4, 0));
- };
-
- pub const Valtype = enum(u3) {
- i32,
- i64,
- f32,
- f64,
- v128,
-
- pub fn from(v: std.wasm.Valtype) Valtype {
- return switch (v) {
- .i32 => .i32,
- .i64 => .i64,
- .f32 => .f32,
- .f64 => .f64,
- .v128 => .v128,
- };
- }
-
- pub fn to(v: Valtype) std.wasm.Valtype {
- return switch (v) {
- .i32 => .i32,
- .i64 => .i64,
- .f32 => .f32,
- .f64 => .f64,
- .v128 => .v128,
- };
- }
};
};
@@ -865,6 +909,38 @@ pub const TableImport = extern struct {
__indirect_function_table,
// Next, index into `object_tables`.
_,
+
+ const first_object_table = @intFromEnum(Resolution.__indirect_function_table) + 1;
+
+ pub const Unpacked = union(enum) {
+ unresolved,
+ __indirect_function_table,
+ object_table: ObjectTableIndex,
+ };
+
+ pub fn unpack(r: Resolution) Unpacked {
+ return switch (r) {
+ .unresolved => .unresolved,
+ .__indirect_function_table => .__indirect_function_table,
+ _ => .{ .object_table = @enumFromInt(@intFromEnum(r) - first_object_table) },
+ };
+ }
+
+ pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType {
+ return switch (unpack(r)) {
+ .unresolved => unreachable,
+ .__indirect_function_table => @panic("TODO"),
+ .object_table => |i| i.ptr(wasm).flags.ref_type.to(),
+ };
+ }
+
+ pub fn limits(r: Resolution, wasm: *const Wasm) std.wasm.Limits {
+ return switch (unpack(r)) {
+ .unresolved => unreachable,
+ .__indirect_function_table => @panic("TODO"),
+ .object_table => |i| i.ptr(wasm).limits(),
+ };
+ }
};
/// Index into `object_table_imports`.
@@ -878,7 +954,26 @@ pub const TableImport = extern struct {
pub fn value(index: Index, wasm: *const Wasm) *TableImport {
return &wasm.object_table_imports.values()[@intFromEnum(index)];
}
+
+ pub fn name(index: Index, wasm: *const Wasm) String {
+ return index.key(wasm).*;
+ }
+
+ pub fn moduleName(index: Index, wasm: *const Wasm) String {
+ return index.value(wasm).module_name;
+ }
};
+
+ pub fn limits(ti: *const TableImport) std.wasm.Limits {
+ return .{
+ .flags = .{
+ .has_max = ti.flags.limits_has_max,
+ .is_shared = ti.flags.limits_is_shared,
+ },
+ .min = ti.limits_min,
+ .max = ti.limits_max,
+ };
+ }
};
pub const Table = extern struct {
@@ -887,6 +982,17 @@ pub const Table = extern struct {
flags: SymbolFlags,
limits_min: u32,
limits_max: u32,
+
+ pub fn limits(t: *const Table) std.wasm.Limits {
+ return .{
+ .flags = .{
+ .has_max = t.flags.limits_has_max,
+ .is_shared = t.flags.limits_is_shared,
+ },
+ .min = t.limits_min,
+ .max = t.limits_max,
+ };
+ }
};
/// Uniquely identifies a section across all objects. By subtracting
@@ -910,9 +1016,13 @@ pub const GlobalImportIndex = enum(u32) {
_,
};
-/// Index into `object_globals`.
+/// Index into `Wasm.object_globals`.
pub const ObjectGlobalIndex = enum(u32) {
_,
+
+ pub fn ptr(index: ObjectGlobalIndex, wasm: *const Wasm) *Global {
+ return &wasm.object_globals.items[@intFromEnum(index)];
+ }
};
/// Index into `Wasm.object_memories`.
@@ -992,6 +1102,16 @@ pub const CustomSegment = extern struct {
/// An index into string_bytes where a wasm expression is found.
pub const Expr = enum(u32) {
_,
+
+ pub const end = @intFromEnum(std.wasm.Opcode.end);
+
+ pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {
+ const start_slice = wasm.string_bytes.items[@intFromEnum(index)..];
+ const end_pos = Object.exprEndPos(start_slice, 0) catch |err| switch (err) {
+ error.InvalidInitOpcode => unreachable,
+ };
+ return start_slice[0..end_pos :end];
+ }
};
pub const FunctionType = extern struct {
@@ -1162,6 +1282,12 @@ pub const ZcuImportIndex = enum(u32) {
const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?;
return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?;
}
+
+ pub fn globalType(index: ZcuImportIndex, wasm: *const Wasm) Global.Type {
+ _ = index;
+ _ = wasm;
+ unreachable; // Zig has no way to create Wasm globals yet.
+ }
};
/// 0. Index into `object_function_imports`.
@@ -1274,6 +1400,24 @@ pub const GlobalImportId = enum(u32) {
.zcu_import => return .zig_object_nofile, // TODO give a better source location
}
}
+
+ pub fn name(id: GlobalImportId, wasm: *const Wasm) String {
+ return switch (unpack(id, wasm)) {
+ inline .object_global_import, .zcu_import => |i| i.name(wasm),
+ };
+ }
+
+ pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) String {
+ return switch (unpack(id, wasm)) {
+ inline .object_global_import, .zcu_import => |i| i.moduleName(wasm),
+ };
+ }
+
+ pub fn globalType(id: GlobalImportId, wasm: *Wasm) Global.Type {
+ return switch (unpack(id, wasm)) {
+ inline .object_global_import, .zcu_import => |i| i.globalType(wasm),
+ };
+ }
};
/// Index into `Wasm.symbol_table`.
@@ -1384,6 +1528,17 @@ pub const MemoryImport = extern struct {
limits_has_max: bool,
limits_is_shared: bool,
padding: [2]u8 = .{ 0, 0 },
+
+ pub fn limits(mi: *const MemoryImport) std.wasm.Limits {
+ return .{
+ .flags = .{
+ .has_max = mi.limits_has_max,
+ .is_shared = mi.limits_is_shared,
+ },
+ .min = mi.limits_min,
+ .max = mi.limits_max,
+ };
+ }
};
pub const Alignment = InternPool.Alignment;