Commit 5ef8321338
Changed files (7)
src
arch
wasm
src/arch/wasm/CodeGen.zig
@@ -1286,8 +1286,9 @@ fn genFunc(func: *CodeGen) InnerError!void {
var prologue = std.ArrayList(Mir.Inst).init(func.gpa);
defer prologue.deinit();
+ const sp = @intFromEnum(func.bin_file.zigObjectPtr().?.stack_pointer_sym);
// load stack pointer
- try prologue.append(.{ .tag = .global_get, .data = .{ .label = 0 } });
+ try prologue.append(.{ .tag = .global_get, .data = .{ .label = sp } });
// store stack pointer so we can restore it when we return from the function
try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.initial_stack_value.local.value } });
// get the total stack size
@@ -1303,7 +1304,7 @@ fn genFunc(func: *CodeGen) InnerError!void {
try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.bottom_stack_value.local.value } });
// Store the current stack pointer value into the global stack pointer so other function calls will
// start from this value instead and not overwrite the current stack.
- try prologue.append(.{ .tag = .global_set, .data = .{ .label = 0 } });
+ try prologue.append(.{ .tag = .global_set, .data = .{ .label = sp } });
// reserve space and insert all prologue instructions at the front of the instruction list
// We insert them in reserve order as there is no insertSlice in multiArrayList.
@@ -1502,7 +1503,7 @@ fn restoreStackPointer(func: *CodeGen) !void {
try func.emitWValue(func.initial_stack_value);
// save its value in the global stack pointer
- try func.addLabel(.global_set, 0);
+ try func.addLabel(.global_set, @intFromEnum(func.bin_file.zigObjectPtr().?.stack_pointer_sym));
}
/// From a given type, will create space on the virtual stack to store the value of such type.
@@ -2205,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);
try func.bin_file.addOrUpdateImport(
mod.intern_pool.stringToSlice(ext_decl.name),
- atom.getSymbolIndex().?,
+ atom.sym_index,
mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name),
type_index,
);
@@ -2240,7 +2241,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
if (callee) |direct| {
const atom_index = func.bin_file.zigObjectPtr().?.decls_map.get(direct).?.atom;
- try func.addLabel(.call, func.bin_file.getAtom(atom_index).sym_index);
+ try func.addLabel(.call, @intFromEnum(func.bin_file.getAtom(atom_index).sym_index));
} else {
// in this case we call a function pointer
// so load its value onto the stack
@@ -3158,7 +3159,7 @@ fn lowerAnonDeclRef(
},
}
const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;
- const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?;
+ const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index);
if (is_fn_body) {
return WValue{ .function_index = target_sym_index };
} else if (offset == 0) {
@@ -3189,7 +3190,7 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl
const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
const atom = func.bin_file.getAtom(atom_index);
- const target_sym_index = atom.sym_index;
+ const target_sym_index = @intFromEnum(atom.sym_index);
if (decl.ty.zigTypeTag(mod) == .Fn) {
return WValue{ .function_index = target_sym_index };
} else if (offset == 0) {
@@ -3711,7 +3712,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
const operand = try func.resolveInst(un_op);
const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);
- const errors_len = WValue{ .memory = sym_index };
+ const errors_len = WValue{ .memory = @intFromEnum(sym_index) };
try func.emitWValue(operand);
const mod = func.bin_file.base.comp.module.?;
@@ -7153,7 +7154,7 @@ fn callIntrinsic(
args: []const WValue,
) InnerError!WValue {
assert(param_types.len == args.len);
- const symbol_index = func.bin_file.base.getGlobalSymbol(name, null) catch |err| {
+ const symbol_index = func.bin_file.getGlobalSymbol(name, null) catch |err| {
return func.fail("Could not find or create global symbol '{s}'", .{@errorName(err)});
};
@@ -7181,7 +7182,7 @@ fn callIntrinsic(
}
// Actually call our intrinsic
- try func.addLabel(.call, symbol_index);
+ try func.addLabel(.call, @intFromEnum(symbol_index));
if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
return WValue.none;
@@ -7224,7 +7225,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
// check if we already generated code for this.
if (func.bin_file.findGlobalSymbol(func_name)) |loc| {
- return loc.index;
+ return @intFromEnum(loc.index);
}
const int_tag_ty = enum_ty.intTagType(mod);
@@ -7364,7 +7365,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
const slice_ty = Type.slice_const_u8_sentinel_0;
const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
- return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
+ const sym_index = try func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
+ return @intFromEnum(sym_index);
}
fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
src/link/Wasm/Atom.zig
@@ -2,7 +2,7 @@
/// This is 'null' when the atom was generated by a synthetic linker symbol.
file: FileIndex,
/// symbol index of the symbol representing this atom
-sym_index: u32,
+sym_index: Symbol.Index,
/// Size of the atom, used to calculate section sizes in the final binary
size: u32 = 0,
/// List of relocations belonging to this atom
@@ -17,19 +17,19 @@ offset: u32 = 0,
/// The original offset within the object file. This value is substracted from
/// relocation offsets to determine where in the `data` to rewrite the value
original_offset: u32 = 0,
-/// Next atom in relation to this atom.
-/// When null, this atom is the last atom
-next: ?Atom.Index = null,
/// Previous atom in relation to this atom.
/// is null when this atom is the first in its order
-prev: ?Atom.Index = null,
+prev: Atom.Index = .null,
/// Contains atoms local to a decl, all managed by this `Atom`.
/// When the parent atom is being freed, it will also do so for all local atoms.
locals: std.ArrayListUnmanaged(Atom.Index) = .{},
-/// Alias to an unsigned 32-bit integer.
-// TODO: Make this a non-exhaustive enum.
-pub const Index = u32;
+/// Represents the index of an Atom where `null` is considered
+/// an invalid atom.
+pub const Index = enum(u32) {
+ null = std.math.maxInt(u32),
+ _,
+};
/// Frees all resources owned by this `Atom`.
pub fn deinit(atom: *Atom, gpa: std.mem.Allocator) void {
@@ -50,7 +50,7 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio
_ = fmt;
_ = options;
try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{
- atom.sym_index,
+ @intFromEnum(atom.sym_index),
atom.alignment,
atom.size,
atom.offset,
@@ -62,11 +62,6 @@ pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
return .{ .file = atom.file, .index = atom.sym_index };
}
-pub fn getSymbolIndex(atom: Atom) ?u32 {
- if (atom.sym_index == 0) return null;
- return atom.sym_index;
-}
-
/// Resolves the relocations within the atom, writing the new value
/// at the calculated offset.
pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
@@ -80,7 +75,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
for (atom.relocs.items) |reloc| {
const value = atom.relocationValue(reloc, wasm_bin);
log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{
- (Wasm.SymbolLoc{ .file = atom.file, .index = reloc.index }).getName(wasm_bin),
+ (Wasm.SymbolLoc{ .file = atom.file, .index = @enumFromInt(reloc.index) }).getName(wasm_bin),
symbol_name,
reloc.offset,
value,
@@ -119,7 +114,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
/// All values will be represented as a `u64` as all values can fit within it.
/// The final value must be casted to the correct size.
fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
- const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
+ const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = @enumFromInt(relocation.index) }).finalLoc(wasm_bin);
const symbol = target_loc.getSymbol(wasm_bin);
if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and
symbol.tag != .section and
@@ -135,7 +130,7 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
.R_WASM_TABLE_INDEX_I64,
.R_WASM_TABLE_INDEX_SLEB,
.R_WASM_TABLE_INDEX_SLEB64,
- => return wasm_bin.function_table.get(.{ .file = atom.file, .index = relocation.index }) orelse 0,
+ => return wasm_bin.function_table.get(.{ .file = atom.file, .index = @enumFromInt(relocation.index) }) orelse 0,
.R_WASM_TYPE_INDEX_LEB => {
const obj_file = wasm_bin.file(atom.file) orelse return relocation.index;
const original_type = obj_file.funcTypes()[relocation.index];
@@ -195,6 +190,7 @@ fn thombstone(atom: Atom, wasm: *const Wasm) ?i64 {
}
return null;
}
+
const leb = std.leb;
const log = std.log.scoped(.link);
const mem = std.mem;
src/link/Wasm/file.zig
@@ -20,10 +20,10 @@ pub const File = union(enum) {
};
}
- pub fn symbol(file: File, index: u32) *Symbol {
+ pub fn symbol(file: File, index: Symbol.Index) *Symbol {
return switch (file) {
- .zig_object => |obj| &obj.symbols.items[index],
- .object => |obj| &obj.symtable[index],
+ .zig_object => |obj| &obj.symbols.items[@intFromEnum(index)],
+ .object => |obj| &obj.symtable[@intFromEnum(index)],
};
}
@@ -34,20 +34,20 @@ pub const File = union(enum) {
};
}
- pub fn symbolName(file: File, index: u32) []const u8 {
+ pub fn symbolName(file: File, index: Symbol.Index) []const u8 {
switch (file) {
.zig_object => |obj| {
- const sym = obj.symbols.items[index];
+ const sym = obj.symbols.items[@intFromEnum(index)];
return obj.string_table.get(sym.name).?;
},
.object => |obj| {
- const sym = obj.symtable[index];
+ const sym = obj.symtable[@intFromEnum(index)];
return obj.string_table.get(sym.name);
},
}
}
- pub fn parseSymbolIntoAtom(file: File, wasm_file: *Wasm, index: u32) !AtomIndex {
+ pub fn parseSymbolIntoAtom(file: File, wasm_file: *Wasm, index: Symbol.Index) !AtomIndex {
return switch (file) {
inline else => |obj| obj.parseSymbolIntoAtom(wasm_file, index),
};
@@ -55,10 +55,10 @@ pub const File = union(enum) {
/// For a given symbol index, find its corresponding import.
/// Asserts import exists.
- pub fn import(file: File, symbol_index: u32) types.Import {
+ pub fn import(file: File, symbol_index: Symbol.Index) types.Import {
return switch (file) {
.zig_object => |obj| obj.imports.get(symbol_index).?,
- .object => |obj| obj.findImport(obj.symtable[symbol_index]),
+ .object => |obj| obj.findImport(obj.symtable[@intFromEnum(symbol_index)]),
};
}
@@ -89,14 +89,14 @@ pub const File = union(enum) {
};
}
- pub fn function(file: File, sym_index: u32) std.wasm.Func {
+ pub fn function(file: File, sym_index: Symbol.Index) std.wasm.Func {
switch (file) {
.zig_object => |obj| {
- const sym = obj.symbols.items[sym_index];
+ const sym = obj.symbols.items[@intFromEnum(sym_index)];
return obj.functions.items[sym.index];
},
.object => |obj| {
- const sym = obj.symtable[sym_index];
+ const sym = obj.symtable[@intFromEnum(sym_index)];
return obj.functions[sym.index - obj.imported_functions_count];
},
}
src/link/Wasm/Object.zig
@@ -907,10 +907,10 @@ fn assertEnd(reader: anytype) !void {
}
/// Parses an object file into atoms, for code and data sections
-pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Atom.Index {
+pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: Symbol.Index) !Atom.Index {
const comp = wasm.base.comp;
const gpa = comp.gpa;
- const symbol = &object.symtable[symbol_index];
+ const symbol = &object.symtable[@intFromEnum(symbol_index)];
const relocatable_data: RelocatableData = switch (symbol.tag) {
.function => object.relocatable_data.get(.code).?[symbol.index - object.imported_functions_count],
.data => object.relocatable_data.get(.data).?[symbol.index],
@@ -953,7 +953,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
=> {
try wasm.function_table.put(gpa, .{
.file = object.index,
- .index = reloc.index,
+ .index = @enumFromInt(reloc.index),
}, 0);
},
.R_WASM_GLOBAL_INDEX_I32,
@@ -961,7 +961,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
=> {
const sym = object.symtable[reloc.index];
if (sym.tag != .global) {
- try wasm.got_symbols.append(gpa, .{ .file = object.index, .index = reloc.index });
+ try wasm.got_symbols.append(gpa, .{ .file = object.index, .index = @enumFromInt(reloc.index) });
}
},
else => {},
src/link/Wasm/Symbol.zig
@@ -1,12 +1,8 @@
-//! Represents a wasm symbol. Containing all of its properties,
+//! Represents a WebAssembly symbol. Containing all of its properties,
//! as well as providing helper methods to determine its functionality
//! and how it will/must be linked.
//! The name of the symbol can be found by providing the offset, found
//! on the `name` field, to a string table in the wasm binary or object file.
-const Symbol = @This();
-
-const std = @import("std");
-const types = @import("types.zig");
/// Bitfield containings flags for a symbol
/// Can contain any of the flags defined in `Flag`
@@ -24,6 +20,12 @@ tag: Tag,
/// This differs from the offset of an `Atom` which is relative to the start of a segment.
virtual_address: u32,
+/// Represents a symbol index where `null` represents an invalid index.
+pub const Index = enum(u32) {
+ null,
+ _,
+};
+
pub const Tag = enum {
function,
data,
@@ -202,3 +204,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO
.{ kind_fmt, binding, visible, symbol.index, symbol.name, undef },
);
}
+
+const std = @import("std");
+const types = @import("types.zig");
+const Symbol = @This();
src/link/Wasm/ZigObject.zig
@@ -17,7 +17,7 @@ functions: std.ArrayListUnmanaged(std.wasm.Func) = .{},
/// List of indexes pointing to an entry within the `functions` list which has been removed.
functions_free_list: std.ArrayListUnmanaged(u32) = .{},
/// Map of symbol locations, represented by its `types.Import`.
-imports: std.AutoHashMapUnmanaged(u32, types.Import) = .{},
+imports: std.AutoHashMapUnmanaged(Symbol.Index, types.Import) = .{},
/// List of WebAssembly globals.
globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
/// Mapping between an `Atom` and its type index representing the Wasm
@@ -26,9 +26,9 @@ atom_types: std.AutoHashMapUnmanaged(Atom.Index, u32) = .{},
/// List of all symbols generated by Zig code.
symbols: std.ArrayListUnmanaged(Symbol) = .{},
/// Map from symbol name offset to their index into the `symbols` list.
-global_syms: std.AutoHashMapUnmanaged(u32, u32) = .{},
+global_syms: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
/// List of symbol indexes which are free to be used.
-symbols_free_list: std.ArrayListUnmanaged(u32) = .{},
+symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
/// Extra metadata about the linking section, such as alignment of segments and their name.
segment_info: std.ArrayListUnmanaged(types.Segment) = .{},
/// List of indexes which contain a free slot in the `segment_info` list.
@@ -42,7 +42,7 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{},
/// During initializion, a symbol with corresponding atom will be created that is
/// used to perform relocations to the pointer of this table.
/// The actual table is populated during `flush`.
-error_table_symbol: ?u32 = null,
+error_table_symbol: Symbol.Index = .null,
/// Amount of functions in the `import` sections.
imported_functions_count: u32 = 0,
/// Amount of globals in the `import` section.
@@ -50,7 +50,7 @@ imported_globals_count: u32 = 0,
/// Symbol index representing the stack pointer. This will be set upon initializion
/// of a new `ZigObject`. Codegen will make calls into this to create relocations for
/// this symbol each time the stack pointer is moved.
-stack_pointer_sym: u32,
+stack_pointer_sym: Symbol.Index,
/// Debug information for the Zig module.
dwarf: ?Dwarf = null,
// Debug section atoms. These are only set when the current compilation
@@ -83,10 +83,10 @@ debug_str_index: ?u32 = null,
debug_abbrev_index: ?u32 = null,
const DeclInfo = struct {
- atom: Atom.Index = std.math.maxInt(Atom.Index),
- exports: std.ArrayListUnmanaged(u32) = .{},
+ atom: Atom.Index = .null,
+ exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
- fn @"export"(di: DeclInfo, zig_object: *const ZigObject, name: []const u8) ?u32 {
+ fn @"export"(di: DeclInfo, zig_object: *const ZigObject, name: []const u8) ?Symbol.Index {
for (di.exports.items) |sym_index| {
const sym_name_index = zig_object.symbol(sym_index).name;
const sym_name = zig_object.string_table.getAssumeExists(sym_name_index);
@@ -97,11 +97,11 @@ const DeclInfo = struct {
return null;
}
- fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: u32) !void {
+ fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: Symbol.Index) !void {
return di.exports.append(gpa, sym_index);
}
- fn deleteExport(di: *DeclInfo, sym_index: u32) void {
+ fn deleteExport(di: *DeclInfo, sym_index: Symbol.Index) void {
for (di.exports.items, 0..) |idx, index| {
if (idx == sym_index) {
_ = di.exports.swapRemove(index);
@@ -138,8 +138,8 @@ fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void {
zig_object.stack_pointer_sym = sym_index;
}
-fn symbol(zig_object: *const ZigObject, index: u32) *Symbol {
- return &zig_object.symbols.items[index];
+fn symbol(zig_object: *const ZigObject, index: Symbol.Index) *Symbol {
+ return &zig_object.symbols.items[@intFromEnum(index)];
}
/// Frees and invalidates all memory of the incrementally compiled Zig module.
@@ -192,7 +192,7 @@ pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void {
/// Allocates a new symbol and returns its index.
/// Will re-use slots when a symbol was freed at an earlier stage.
-pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 {
+pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !Symbol.Index {
try zig_object.symbols.ensureUnusedCapacity(gpa, 1);
const sym: Symbol = .{
.name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls
@@ -202,10 +202,10 @@ pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 {
.virtual_address = std.math.maxInt(u32), // will be set during atom allocation
};
if (zig_object.symbols_free_list.popOrNull()) |index| {
- zig_object.symbols.items[index] = sym;
+ zig_object.symbols.items[@intFromEnum(index)] = sym;
return index;
}
- const index = @as(u32, @intCast(zig_object.symbols.items.len));
+ const index: Symbol.Index = @enumFromInt(zig_object.symbols.items.len);
zig_object.symbols.appendAssumeCapacity(sym);
return index;
}
@@ -247,7 +247,7 @@ pub fn updateDecl(
.{ .ty = decl.ty, .val = val },
&code_writer,
.none,
- .{ .parent_atom_index = atom.sym_index },
+ .{ .parent_atom_index = @intFromEnum(atom.sym_index) },
);
const code = switch (res) {
@@ -464,7 +464,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu
switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) {
.ok => |atom_index| {
try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);
- return wasm_file.getAtom(atom_index).getSymbolIndex().?;
+ return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
},
.fail => |em| {
decl.analysis = .codegen_failure;
@@ -494,7 +494,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
atom.alignment = tv.ty.abiAlignment(mod);
const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name });
errdefer gpa.free(segment_name);
- zig_object.symbols.items[sym_index] = .{
+ zig_object.symbol(sym_index).* = .{
.name = try zig_object.string_table.insert(gpa, name),
.flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
.tag = .data,
@@ -513,7 +513,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
&value_bytes,
.none,
.{
- .parent_atom_index = atom.sym_index,
+ .parent_atom_index = @intFromEnum(atom.sym_index),
.addend = null,
},
);
@@ -534,9 +534,9 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
/// Returns the symbol index of the error name table.
///
/// When the symbol does not yet exist, it will create a new one instead.
-pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {
- if (zig_object.error_table_symbol) |sym| {
- return sym;
+pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !Symbol.Index {
+ if (zig_object.error_table_symbol != .null) {
+ return zig_object.error_table_symbol;
}
// no error was referenced yet, so create a new symbol and atom for it
@@ -561,7 +561,7 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {
.virtual_address = undefined,
};
- log.debug("Error name table was created with symbol index: ({d})", .{sym_index});
+ log.debug("Error name table was created with symbol index: ({d})", .{@intFromEnum(sym_index)});
zig_object.error_table_symbol = sym_index;
return sym_index;
}
@@ -571,9 +571,9 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {
/// This creates a table that consists of pointers and length to each error name.
/// The table is what is being pointed to within the runtime bodies that are generated.
fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
- const symbol_index = zig_object.error_table_symbol orelse return;
+ if (zig_object.error_table_symbol == .null) return;
const gpa = wasm_file.base.comp.gpa;
- const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = symbol_index }).?;
+ const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = zig_object.error_table_symbol }).?;
// Rather than creating a symbol for each individual error name,
// we create a symbol for the entire region of error names. We then calculate
@@ -584,7 +584,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
names_atom.alignment = .@"1";
const sym_name = try zig_object.string_table.insert(gpa, "__zig_err_names");
const segment_name = try gpa.dupe(u8, ".rodata.__zig_err_names");
- const names_symbol = &zig_object.symbols.items[names_sym_index];
+ const names_symbol = zig_object.symbol(names_sym_index);
names_symbol.* = .{
.name = sym_name,
.tag = .data,
@@ -611,7 +611,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
try atom.code.writer(gpa).writeInt(u32, len - 1, .little);
// create relocation to the error name
try atom.relocs.append(gpa, .{
- .index = names_atom.sym_index,
+ .index = @intFromEnum(names_atom.sym_index),
.relocation_type = .R_WASM_MEMORY_ADDR_I32,
.offset = offset,
.addend = @as(i32, @intCast(addend)),
@@ -638,7 +638,7 @@ pub fn addOrUpdateImport(
/// Name of the import
name: []const u8,
/// Symbol index that is external
- symbol_index: u32,
+ symbol_index: Symbol.Index,
/// Optional library name (i.e. `extern "c" fn foo() void`
lib_name: ?[:0]const u8,
/// The index of the type that represents the function signature
@@ -647,7 +647,7 @@ pub fn addOrUpdateImport(
type_index: ?u32,
) !void {
const gpa = wasm_file.base.comp.gpa;
- std.debug.assert(symbol_index != 0);
+ std.debug.assert(symbol_index != .null);
// For the import name, we use the decl's name, rather than the fully qualified name
// Also mangle the name when the lib name is set and not equal to "C" so imports with the same
// name but different module can be resolved correctly.
@@ -659,7 +659,7 @@ pub fn addOrUpdateImport(
defer if (mangle_name) gpa.free(full_name);
const decl_name_index = try zig_object.string_table.insert(gpa, full_name);
- const sym: *Symbol = &zig_object.symbols.items[symbol_index];
+ const sym: *Symbol = &zig_object.symbols.items[@intFromEnum(symbol_index)];
sym.setUndefined(true);
sym.setGlobal(true);
sym.name = decl_name_index;
@@ -689,7 +689,7 @@ pub fn addOrUpdateImport(
/// such as an exported or imported symbol.
/// If the symbol does not yet exist, creates a new one symbol instead
/// and then returns the index to it.
-pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8) !u32 {
+pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8) !Symbol.Index {
const name_index = try zig_object.string_table.insert(gpa, name);
const gop = try zig_object.global_syms.getOrPut(gpa, name_index);
if (gop.found_existing) {
@@ -707,12 +707,12 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c
sym.setUndefined(true);
const sym_index = if (zig_object.symbols_free_list.popOrNull()) |index| index else blk: {
- const index: u32 = @intCast(zig_object.symbols.items.len);
+ const index: Symbol.Index = @enumFromInt(zig_object.symbols.items.len);
try zig_object.symbols.ensureUnusedCapacity(gpa, 1);
zig_object.symbols.items.len += 1;
break :blk index;
};
- zig_object.symbols.items[sym_index] = sym;
+ zig_object.symbol(sym_index).* = sym;
gop.value_ptr.* = sym_index;
return sym_index;
}
@@ -731,10 +731,10 @@ pub fn getDeclVAddr(
const decl = mod.declPtr(decl_index);
const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
- const target_symbol_index = wasm_file.getAtom(target_atom_index).sym_index;
+ const target_symbol_index = @intFromEnum(wasm_file.getAtom(target_atom_index).sym_index);
std.debug.assert(reloc_info.parent_atom_index != 0);
- const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = reloc_info.parent_atom_index }).?;
+ const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
const atom = wasm_file.getAtomPtr(atom_index);
const is_wasm32 = target.cpu.arch == .wasm32;
if (decl.ty.zigTypeTag(mod) == .Fn) {
@@ -769,9 +769,9 @@ pub fn getAnonDeclVAddr(
const gpa = wasm_file.base.comp.gpa;
const target = wasm_file.base.comp.root_mod.resolved_target.result;
const atom_index = zig_object.anon_decls.get(decl_val).?;
- const target_symbol_index = wasm_file.getAtom(atom_index).getSymbolIndex().?;
+ const target_symbol_index = @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
- const parent_atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = reloc_info.parent_atom_index }).?;
+ const parent_atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
const parent_atom = wasm_file.getAtomPtr(parent_atom_index);
const is_wasm32 = target.cpu.arch == .wasm32;
const mod = wasm_file.base.comp.module.?;
@@ -930,17 +930,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool
// dwarf.freeDecl(decl_index);
// }
- if (atom.next) |next_atom_index| {
- const next_atom = wasm_file.getAtomPtr(next_atom_index);
- next_atom.prev = atom.prev;
- atom.next = null;
- }
- if (atom.prev) |prev_index| {
- const prev_atom = wasm_file.getAtomPtr(prev_index);
- prev_atom.next = atom.next;
- atom.prev = null;
- }
-
+ atom.prev = null;
sym.tag = .dead;
if (sym.isGlobal()) {
std.debug.assert(zig_object.global_syms.remove(atom.sym_index));
@@ -998,7 +988,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
// if not, allcoate a new atom.
const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {
const atom = wasm_file.getAtomPtr(index);
- atom.prev = null;
+ atom.prev = .null;
atom.deinit(gpa);
break :blk index;
} else idx: {
@@ -1022,7 +1012,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
try atom.code.writer(gpa).writeInt(u16, @intCast(errors_len), .little);
}
-fn findGlobalSymbol(zig_object: *ZigObject, name: []const u8) ?u32 {
+fn findGlobalSymbol(zig_object: *ZigObject, name: []const u8) ?Symbol.Index {
const offset = zig_object.string_table.getOffset(name) orelse return null;
return zig_object.global_syms.get(offset);
}
@@ -1121,7 +1111,7 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:
/// The symbols in ZigObject are already represented by an atom as we need to store its data.
/// So rather than creating a new Atom and returning its index, we use this oppertunity to scan
/// its relocations and create any GOT symbols or function table indexes it may require.
-pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) !Atom.Index {
+pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: Symbol.Index) !Atom.Index {
const gpa = wasm_file.base.comp.gpa;
const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = index };
const atom_index = wasm_file.symbol_atom.get(loc).?;
@@ -1129,6 +1119,7 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)
try wasm_file.appendAtomAtIndex(final_index, atom_index);
const atom = wasm_file.getAtom(atom_index);
for (atom.relocs.items) |reloc| {
+ const reloc_index: Symbol.Index = @enumFromInt(reloc.index);
switch (reloc.relocation_type) {
.R_WASM_TABLE_INDEX_I32,
.R_WASM_TABLE_INDEX_I64,
@@ -1137,17 +1128,17 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)
=> {
try wasm_file.function_table.put(gpa, .{
.file = zig_object.index,
- .index = reloc.index,
+ .index = reloc_index,
}, 0);
},
.R_WASM_GLOBAL_INDEX_I32,
.R_WASM_GLOBAL_INDEX_LEB,
=> {
- const sym = zig_object.symbol(reloc.index);
+ const sym = zig_object.symbol(reloc_index);
if (sym.tag != .global) {
try wasm_file.got_symbols.append(gpa, .{
.file = zig_object.index,
- .index = reloc.index,
+ .index = reloc_index,
});
}
},
@@ -1166,10 +1157,10 @@ pub fn createFunction(
func_ty: std.wasm.Type,
function_body: *std.ArrayList(u8),
relocations: *std.ArrayList(types.Relocation),
-) !u32 {
+) !Symbol.Index {
const gpa = wasm_file.base.comp.gpa;
const sym_index = try zig_object.allocateSymbol(gpa);
- const sym = &zig_object.symbols.items[sym_index];
+ const sym = zig_object.symbol(sym_index);
sym.tag = .function;
sym.name = try zig_object.string_table.insert(gpa, symbol_name);
const type_index = try zig_object.putOrGetFuncType(gpa, func_ty);
src/link/Wasm.zig
@@ -127,7 +127,7 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
/// This allows us to map multiple symbols to the same function.
functions: std.AutoArrayHashMapUnmanaged(
struct { file: File.Index, index: u32 },
- struct { func: std.wasm.Func, sym_index: u32 },
+ struct { func: std.wasm.Func, sym_index: Symbol.Index },
) = .{},
/// Output global section
wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
@@ -208,13 +208,9 @@ pub const Segment = struct {
}
};
-pub const Export = struct {
- sym_index: ?u32 = null,
-};
-
pub const SymbolLoc = struct {
/// The index of the symbol within the specified file
- index: u32,
+ index: Symbol.Index,
/// The index of the object file where the symbol resides.
file: File.Index,
@@ -226,7 +222,7 @@ pub const SymbolLoc = struct {
if (wasm_file.file(loc.file)) |obj_file| {
return obj_file.symbol(loc.index);
}
- return &wasm_file.synthetic_symbols.items[loc.index];
+ return &wasm_file.synthetic_symbols.items[@intFromEnum(loc.index)];
}
/// From a given location, returns the name of the symbol.
@@ -237,7 +233,8 @@ pub const SymbolLoc = struct {
if (wasm_file.file(loc.file)) |obj_file| {
return obj_file.symbolName(loc.index);
}
- return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name);
+ const sym = wasm_file.synthetic_symbols.items[@intFromEnum(loc.index)];
+ return wasm_file.string_table.get(sym.name);
}
/// From a given symbol location, returns the final location.
@@ -272,7 +269,7 @@ pub const InitFuncLoc = struct {
/// Turns the given `InitFuncLoc` into a `SymbolLoc`
fn getSymbolLoc(loc: InitFuncLoc) SymbolLoc {
- return .{ .file = loc.file, .index = loc.index };
+ return .{ .file = loc.file, .index = @enumFromInt(loc.index) };
}
/// Returns true when `lhs` has a higher priority (e.i. value closer to 0) than `rhs`.
@@ -566,7 +563,7 @@ pub fn createEmpty(
var zig_object: ZigObject = .{
.index = index,
.path = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(zcu.main_mod.root_src_path)}),
- .stack_pointer_sym = undefined,
+ .stack_pointer_sym = .null,
};
try zig_object.init(wasm);
try wasm.files.append(gpa, .{ .zig_object = zig_object });
@@ -607,7 +604,7 @@ pub fn addOrUpdateImport(
/// Name of the import
name: []const u8,
/// Symbol index that is external
- symbol_index: u32,
+ symbol_index: Symbol.Index,
/// Optional library name (i.e. `extern "c" fn foo() void`
lib_name: ?[:0]const u8,
/// The index of the type that represents the function signature
@@ -627,7 +624,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol
}
fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc {
- const sym_index = @as(u32, @intCast(wasm.synthetic_symbols.items.len));
+ const sym_index: Symbol.Index = @enumFromInt(wasm.synthetic_symbols.items.len);
const loc: SymbolLoc = .{ .index = sym_index, .file = .null };
const gpa = wasm.base.comp.gpa;
try wasm.synthetic_symbols.append(gpa, .{
@@ -670,9 +667,9 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
}
/// Creates a new empty `Atom` and returns its `Atom.Index`
-pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Index {
+pub fn createAtom(wasm: *Wasm, sym_index: Symbol.Index, file_index: File.Index) !Atom.Index {
const gpa = wasm.base.comp.gpa;
- const index: Atom.Index = @intCast(wasm.managed_atoms.items.len);
+ const index: Atom.Index = @enumFromInt(wasm.managed_atoms.items.len);
const atom = try wasm.managed_atoms.addOne(gpa);
atom.* = .{ .file = file_index, .sym_index = sym_index };
try wasm.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), index);
@@ -681,11 +678,11 @@ pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Ind
}
pub inline fn getAtom(wasm: *const Wasm, index: Atom.Index) Atom {
- return wasm.managed_atoms.items[index];
+ return wasm.managed_atoms.items[@intFromEnum(index)];
}
pub inline fn getAtomPtr(wasm: *Wasm, index: Atom.Index) *Atom {
- return &wasm.managed_atoms.items[index];
+ return &wasm.managed_atoms.items[@intFromEnum(index)];
}
/// Parses an archive file and will then parse each object file
@@ -757,7 +754,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void {
log.debug("Resolving symbols in object: '{s}'", .{obj_file.path()});
for (obj_file.symbols(), 0..) |symbol, i| {
- const sym_index: u32 = @intCast(i);
+ const sym_index: Symbol.Index = @enumFromInt(i);
const location: SymbolLoc = .{ .file = file_index, .index = sym_index };
const sym_name = obj_file.string(symbol.name);
if (mem.eql(u8, sym_name, "__indirect_function_table")) {
@@ -1489,7 +1486,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec
/// such as an exported or imported symbol.
/// If the symbol does not yet exist, creates a new one symbol instead
/// and then returns the index to it.
-pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 {
+pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !Symbol.Index {
_ = lib_name;
return wasm.zigObjectPtr().?.getGlobalSymbol(wasm.base.comp.gpa, name);
}
@@ -1609,19 +1606,20 @@ fn allocateAtoms(wasm: *Wasm) !void {
const sym = if (wasm.file(symbol_loc.file)) |obj_file|
obj_file.symbol(symbol_loc.index).*
else
- wasm.synthetic_symbols.items[symbol_loc.index];
+ wasm.synthetic_symbols.items[@intFromEnum(symbol_loc.index)];
// Dead symbols must be unlinked from the linked-list to prevent them
// from being emit into the binary.
if (sym.isDead()) {
- if (entry.value_ptr.* == atom_index and atom.prev != null) {
+ if (entry.value_ptr.* == atom_index and atom.prev != .null) {
// When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update
// the entry to point it to the previous atom to ensure we do not start with a dead symbol that
// was removed and therefore do not emit any code at all.
- entry.value_ptr.* = atom.prev.?;
+ entry.value_ptr.* = atom.prev;
}
- atom_index = atom.prev orelse break;
- atom.prev = null;
+ if (atom.prev == .null) break;
+ atom_index = atom.prev;
+ atom.prev = .null;
continue;
}
offset = @intCast(atom.alignment.forward(offset));
@@ -1633,7 +1631,8 @@ fn allocateAtoms(wasm: *Wasm) !void {
atom.size,
});
offset += atom.size;
- atom_index = atom.prev orelse break;
+ if (atom.prev == .null) break;
+ atom_index = atom.prev;
}
segment.size = @intCast(segment.alignment.forward(offset));
}
@@ -1738,7 +1737,7 @@ fn setupInitFunctions(wasm: *Wasm) !void {
.file = file_index,
.priority = init_func.priority,
});
- try wasm.mark(.{ .index = init_func.symbol_index, .file = file_index });
+ try wasm.mark(.{ .index = @enumFromInt(init_func.symbol_index), .file = file_index });
}
}
@@ -1844,7 +1843,7 @@ pub fn createFunction(
func_ty: std.wasm.Type,
function_body: *std.ArrayList(u8),
relocations: *std.ArrayList(Relocation),
-) !u32 {
+) !Symbol.Index {
return wasm.zigObjectPtr().?.createFunction(wasm, symbol_name, func_ty, function_body, relocations);
}
@@ -2324,11 +2323,11 @@ fn setupMemory(wasm: *Wasm) !void {
/// From a given object's index and the index of the segment, returns the corresponding
/// index of the segment within the final data section. When the segment does not yet
/// exist, a new one will be initialized and appended. The new index will be returned in that case.
-pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32) !u32 {
+pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: Symbol.Index) !u32 {
const comp = wasm.base.comp;
const gpa = comp.gpa;
const obj_file = wasm.file(file_index).?;
- const symbol = obj_file.symbols()[symbol_index];
+ const symbol = obj_file.symbols()[@intFromEnum(symbol_index)];
const index: u32 = @intCast(wasm.segments.items.len);
const shared_memory = comp.config.shared_memory;
@@ -2889,8 +2888,8 @@ fn writeToFile(
try binary_writer.writeAll(atom.code.items);
current_offset += atom.size;
- if (atom.prev) |prev| {
- atom_index = prev;
+ if (atom.prev != .null) {
+ atom_index = atom.prev;
} else {
// also pad with zeroes when last atom to ensure
// segments are aligned.
@@ -2984,7 +2983,8 @@ fn writeToFile(
while (true) {
atom.resolveRelocs(wasm);
try debug_bytes.appendSlice(atom.code.items);
- atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
+ if (atom.prev == .null) break;
+ atom = wasm.getAtomPtr(atom.prev);
}
try emitDebugSection(&binary_bytes, debug_bytes.items, item.name);
debug_bytes.clearRetainingCapacity();
@@ -3853,7 +3853,7 @@ fn emitCodeRelocations(
size_offset += getULEB128Size(atom.size);
for (atom.relocs.items) |relocation| {
count += 1;
- const sym_loc: SymbolLoc = .{ .file = atom.file, .index = relocation.index };
+ const sym_loc: SymbolLoc = .{ .file = atom.file, .index = @enumFromInt(relocation.index) };
const symbol_index = symbol_table.get(sym_loc).?;
try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));
const offset = atom.offset + relocation.offset + size_offset;
@@ -3864,7 +3864,8 @@ fn emitCodeRelocations(
}
log.debug("Emit relocation: {}", .{relocation});
}
- atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
+ if (atom.prev == .null) break;
+ atom = wasm.getAtomPtr(atom.prev);
}
if (count == 0) return;
var buf: [5]u8 = undefined;
@@ -3900,7 +3901,7 @@ fn emitDataRelocations(
size_offset += getULEB128Size(atom.size);
for (atom.relocs.items) |relocation| {
count += 1;
- const sym_loc: SymbolLoc = .{ .file = atom.file, .index = relocation.index };
+ const sym_loc: SymbolLoc = .{ .file = atom.file, .index = @enumFromInt(relocation.index) };
const symbol_index = symbol_table.get(sym_loc).?;
try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));
const offset = atom.offset + relocation.offset + size_offset;
@@ -3911,7 +3912,8 @@ fn emitDataRelocations(
}
log.debug("Emit relocation: {}", .{relocation});
}
- atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;
+ if (atom.prev == .null) break;
+ atom = wasm.getAtomPtr(atom.prev);
}
}
if (count == 0) return;
@@ -3969,7 +3971,8 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s
///
/// When the symbol does not yet exist, it will create a new one instead.
pub fn getErrorTableSymbol(wasm_file: *Wasm) !u32 {
- return wasm_file.zigObjectPtr().?.getErrorTableSymbol(wasm_file);
+ const sym_index = try wasm_file.zigObjectPtr().?.getErrorTableSymbol(wasm_file);
+ return @intFromEnum(sym_index);
}
/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`.
@@ -4029,7 +4032,7 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void {
const atom = wasm.getAtom(atom_index);
for (atom.relocs.items) |reloc| {
- const target_loc: SymbolLoc = .{ .index = reloc.index, .file = loc.file };
+ const target_loc: SymbolLoc = .{ .index = @enumFromInt(reloc.index), .file = loc.file };
try wasm.mark(target_loc.finalLoc(wasm));
}
}