authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-02-09 16:36:09+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-02-29 15:24:07+01:00
log5ef832133895fd69fc8378463b86759eaab6913a
tree08bc27cd8f20de4c928ca0bdc411b6c8d59be465
parentc99ef23862573269ae4052bd2236f9803f9e36a2
signaturelock-open Commit is signed but in an unrecognized format.

wasm: make symbol indexes a non-exhaustive enum

This introduces some type safety so we cannot accidently give an atom index as a symbol index. This also means we do not have to store any optionals and therefore allow for memory optimizations. Lastly, we can now always simply access the symbol index of an atom, rather than having to call `getSymbolIndex` as it is easy to forget.

7 files changed, 141 insertions(+), 143 deletions(-)

src/arch/wasm/CodeGen.zig+14-12
...@@ -1286,8 +1286,9 @@ fn genFunc(func: *CodeGen) InnerError!void {...@@ -1286,8 +1286,9 @@ fn genFunc(func: *CodeGen) InnerError!void {
1286 var prologue = std.ArrayList(Mir.Inst).init(func.gpa);1286 var prologue = std.ArrayList(Mir.Inst).init(func.gpa);
1287 defer prologue.deinit();1287 defer prologue.deinit();
12881288
1289 const sp = @intFromEnum(func.bin_file.zigObjectPtr().?.stack_pointer_sym);
1289 // load stack pointer1290 // load stack pointer
1290 try prologue.append(.{ .tag = .global_get, .data = .{ .label = 0 } });1291 try prologue.append(.{ .tag = .global_get, .data = .{ .label = sp } });
1291 // store stack pointer so we can restore it when we return from the function1292 // store stack pointer so we can restore it when we return from the function
1292 try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.initial_stack_value.local.value } });1293 try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.initial_stack_value.local.value } });
1293 // get the total stack size1294 // get the total stack size
...@@ -1303,7 +1304,7 @@ fn genFunc(func: *CodeGen) InnerError!void {...@@ -1303,7 +1304,7 @@ fn genFunc(func: *CodeGen) InnerError!void {
1303 try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.bottom_stack_value.local.value } });1304 try prologue.append(.{ .tag = .local_tee, .data = .{ .label = func.bottom_stack_value.local.value } });
1304 // Store the current stack pointer value into the global stack pointer so other function calls will1305 // Store the current stack pointer value into the global stack pointer so other function calls will
1305 // start from this value instead and not overwrite the current stack.1306 // start from this value instead and not overwrite the current stack.
1306 try prologue.append(.{ .tag = .global_set, .data = .{ .label = 0 } });1307 try prologue.append(.{ .tag = .global_set, .data = .{ .label = sp } });
13071308
1308 // reserve space and insert all prologue instructions at the front of the instruction list1309 // reserve space and insert all prologue instructions at the front of the instruction list
1309 // We insert them in reserve order as there is no insertSlice in multiArrayList.1310 // We insert them in reserve order as there is no insertSlice in multiArrayList.
...@@ -1502,7 +1503,7 @@ fn restoreStackPointer(func: *CodeGen) !void {...@@ -1502,7 +1503,7 @@ fn restoreStackPointer(func: *CodeGen) !void {
1502 try func.emitWValue(func.initial_stack_value);1503 try func.emitWValue(func.initial_stack_value);
15031504
1504 // save its value in the global stack pointer1505 // save its value in the global stack pointer
1505 try func.addLabel(.global_set, 0);1506 try func.addLabel(.global_set, @intFromEnum(func.bin_file.zigObjectPtr().?.stack_pointer_sym));
1506}1507}
15071508
1508/// From a given type, will create space on the virtual stack to store the value of such type.1509/// 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...@@ -2205,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2205 const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);2206 const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);
2206 try func.bin_file.addOrUpdateImport(2207 try func.bin_file.addOrUpdateImport(
2207 mod.intern_pool.stringToSlice(ext_decl.name),2208 mod.intern_pool.stringToSlice(ext_decl.name),
2208 atom.getSymbolIndex().?,2209 atom.sym_index,
2209 mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name),2210 mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name),
2210 type_index,2211 type_index,
2211 );2212 );
...@@ -2240,7 +2241,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2240,7 +2241,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22402241
2241 if (callee) |direct| {2242 if (callee) |direct| {
2242 const atom_index = func.bin_file.zigObjectPtr().?.decls_map.get(direct).?.atom;2243 const atom_index = func.bin_file.zigObjectPtr().?.decls_map.get(direct).?.atom;
2243 try func.addLabel(.call, func.bin_file.getAtom(atom_index).sym_index);2244 try func.addLabel(.call, @intFromEnum(func.bin_file.getAtom(atom_index).sym_index));
2244 } else {2245 } else {
2245 // in this case we call a function pointer2246 // in this case we call a function pointer
2246 // so load its value onto the stack2247 // so load its value onto the stack
...@@ -3158,7 +3159,7 @@ fn lowerAnonDeclRef(...@@ -3158,7 +3159,7 @@ fn lowerAnonDeclRef(
3158 },3159 },
3159 }3160 }
3160 const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;3161 const target_atom_index = func.bin_file.zigObjectPtr().?.anon_decls.get(decl_val).?;
3161 const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?;3162 const target_sym_index = @intFromEnum(func.bin_file.getAtom(target_atom_index).sym_index);
3162 if (is_fn_body) {3163 if (is_fn_body) {
3163 return WValue{ .function_index = target_sym_index };3164 return WValue{ .function_index = target_sym_index };
3164 } else if (offset == 0) {3165 } else if (offset == 0) {
...@@ -3189,7 +3190,7 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl...@@ -3189,7 +3190,7 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl
3189 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);3190 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
3190 const atom = func.bin_file.getAtom(atom_index);3191 const atom = func.bin_file.getAtom(atom_index);
31913192
3192 const target_sym_index = atom.sym_index;3193 const target_sym_index = @intFromEnum(atom.sym_index);
3193 if (decl.ty.zigTypeTag(mod) == .Fn) {3194 if (decl.ty.zigTypeTag(mod) == .Fn) {
3194 return WValue{ .function_index = target_sym_index };3195 return WValue{ .function_index = target_sym_index };
3195 } else if (offset == 0) {3196 } else if (offset == 0) {
...@@ -3711,7 +3712,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3711,7 +3712,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3711 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3712 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3712 const operand = try func.resolveInst(un_op);3713 const operand = try func.resolveInst(un_op);
3713 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);3714 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);
3714 const errors_len = WValue{ .memory = sym_index };3715 const errors_len = WValue{ .memory = @intFromEnum(sym_index) };
37153716
3716 try func.emitWValue(operand);3717 try func.emitWValue(operand);
3717 const mod = func.bin_file.base.comp.module.?;3718 const mod = func.bin_file.base.comp.module.?;
...@@ -7153,7 +7154,7 @@ fn callIntrinsic(...@@ -7153,7 +7154,7 @@ fn callIntrinsic(
7153 args: []const WValue,7154 args: []const WValue,
7154) InnerError!WValue {7155) InnerError!WValue {
7155 assert(param_types.len == args.len);7156 assert(param_types.len == args.len);
7156 const symbol_index = func.bin_file.base.getGlobalSymbol(name, null) catch |err| {7157 const symbol_index = func.bin_file.getGlobalSymbol(name, null) catch |err| {
7157 return func.fail("Could not find or create global symbol '{s}'", .{@errorName(err)});7158 return func.fail("Could not find or create global symbol '{s}'", .{@errorName(err)});
7158 };7159 };
71597160
...@@ -7181,7 +7182,7 @@ fn callIntrinsic(...@@ -7181,7 +7182,7 @@ fn callIntrinsic(
7181 }7182 }
71827183
7183 // Actually call our intrinsic7184 // Actually call our intrinsic
7184 try func.addLabel(.call, symbol_index);7185 try func.addLabel(.call, @intFromEnum(symbol_index));
71857186
7186 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {7187 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
7187 return WValue.none;7188 return WValue.none;
...@@ -7224,7 +7225,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -7224,7 +7225,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
72247225
7225 // check if we already generated code for this.7226 // check if we already generated code for this.
7226 if (func.bin_file.findGlobalSymbol(func_name)) |loc| {7227 if (func.bin_file.findGlobalSymbol(func_name)) |loc| {
7227 return loc.index;7228 return @intFromEnum(loc.index);
7228 }7229 }
72297230
7230 const int_tag_ty = enum_ty.intTagType(mod);7231 const int_tag_ty = enum_ty.intTagType(mod);
...@@ -7364,7 +7365,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -7364,7 +7365,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
73647365
7365 const slice_ty = Type.slice_const_u8_sentinel_0;7366 const slice_ty = Type.slice_const_u8_sentinel_0;
7366 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);7367 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
7367 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);7368 const sym_index = try func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
7369 return @intFromEnum(sym_index);
7368}7370}
73697371
7370fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {7372fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
src/link/Wasm.zig+40-37
...@@ -127,7 +127,7 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},...@@ -127,7 +127,7 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
127/// This allows us to map multiple symbols to the same function.127/// This allows us to map multiple symbols to the same function.
128functions: std.AutoArrayHashMapUnmanaged(128functions: std.AutoArrayHashMapUnmanaged(
129 struct { file: File.Index, index: u32 },129 struct { file: File.Index, index: u32 },
130 struct { func: std.wasm.Func, sym_index: u32 },130 struct { func: std.wasm.Func, sym_index: Symbol.Index },
131) = .{},131) = .{},
132/// Output global section132/// Output global section
133wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},133wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
...@@ -208,13 +208,9 @@ pub const Segment = struct {...@@ -208,13 +208,9 @@ pub const Segment = struct {
208 }208 }
209};209};
210210
211pub const Export = struct {
212 sym_index: ?u32 = null,
213};
214
215pub const SymbolLoc = struct {211pub const SymbolLoc = struct {
216 /// The index of the symbol within the specified file212 /// The index of the symbol within the specified file
217 index: u32,213 index: Symbol.Index,
218 /// The index of the object file where the symbol resides.214 /// The index of the object file where the symbol resides.
219 file: File.Index,215 file: File.Index,
220216
...@@ -226,7 +222,7 @@ pub const SymbolLoc = struct {...@@ -226,7 +222,7 @@ pub const SymbolLoc = struct {
226 if (wasm_file.file(loc.file)) |obj_file| {222 if (wasm_file.file(loc.file)) |obj_file| {
227 return obj_file.symbol(loc.index);223 return obj_file.symbol(loc.index);
228 }224 }
229 return &wasm_file.synthetic_symbols.items[loc.index];225 return &wasm_file.synthetic_symbols.items[@intFromEnum(loc.index)];
230 }226 }
231227
232 /// From a given location, returns the name of the symbol.228 /// From a given location, returns the name of the symbol.
...@@ -237,7 +233,8 @@ pub const SymbolLoc = struct {...@@ -237,7 +233,8 @@ pub const SymbolLoc = struct {
237 if (wasm_file.file(loc.file)) |obj_file| {233 if (wasm_file.file(loc.file)) |obj_file| {
238 return obj_file.symbolName(loc.index);234 return obj_file.symbolName(loc.index);
239 }235 }
240 return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name);236 const sym = wasm_file.synthetic_symbols.items[@intFromEnum(loc.index)];
237 return wasm_file.string_table.get(sym.name);
241 }238 }
242239
243 /// From a given symbol location, returns the final location.240 /// From a given symbol location, returns the final location.
...@@ -272,7 +269,7 @@ pub const InitFuncLoc = struct {...@@ -272,7 +269,7 @@ pub const InitFuncLoc = struct {
272269
273 /// Turns the given `InitFuncLoc` into a `SymbolLoc`270 /// Turns the given `InitFuncLoc` into a `SymbolLoc`
274 fn getSymbolLoc(loc: InitFuncLoc) SymbolLoc {271 fn getSymbolLoc(loc: InitFuncLoc) SymbolLoc {
275 return .{ .file = loc.file, .index = loc.index };272 return .{ .file = loc.file, .index = @enumFromInt(loc.index) };
276 }273 }
277274
278 /// Returns true when `lhs` has a higher priority (e.i. value closer to 0) than `rhs`.275 /// Returns true when `lhs` has a higher priority (e.i. value closer to 0) than `rhs`.
...@@ -566,7 +563,7 @@ pub fn createEmpty(...@@ -566,7 +563,7 @@ pub fn createEmpty(
566 var zig_object: ZigObject = .{563 var zig_object: ZigObject = .{
567 .index = index,564 .index = index,
568 .path = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(zcu.main_mod.root_src_path)}),565 .path = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(zcu.main_mod.root_src_path)}),
569 .stack_pointer_sym = undefined,566 .stack_pointer_sym = .null,
570 };567 };
571 try zig_object.init(wasm);568 try zig_object.init(wasm);
572 try wasm.files.append(gpa, .{ .zig_object = zig_object });569 try wasm.files.append(gpa, .{ .zig_object = zig_object });
...@@ -607,7 +604,7 @@ pub fn addOrUpdateImport(...@@ -607,7 +604,7 @@ pub fn addOrUpdateImport(
607 /// Name of the import604 /// Name of the import
608 name: []const u8,605 name: []const u8,
609 /// Symbol index that is external606 /// Symbol index that is external
610 symbol_index: u32,607 symbol_index: Symbol.Index,
611 /// Optional library name (i.e. `extern "c" fn foo() void`608 /// Optional library name (i.e. `extern "c" fn foo() void`
612 lib_name: ?[:0]const u8,609 lib_name: ?[:0]const u8,
613 /// The index of the type that represents the function signature610 /// 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...@@ -627,7 +624,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol
627}624}
628625
629fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc {626fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc {
630 const sym_index = @as(u32, @intCast(wasm.synthetic_symbols.items.len));627 const sym_index: Symbol.Index = @enumFromInt(wasm.synthetic_symbols.items.len);
631 const loc: SymbolLoc = .{ .index = sym_index, .file = .null };628 const loc: SymbolLoc = .{ .index = sym_index, .file = .null };
632 const gpa = wasm.base.comp.gpa;629 const gpa = wasm.base.comp.gpa;
633 try wasm.synthetic_symbols.append(gpa, .{630 try wasm.synthetic_symbols.append(gpa, .{
...@@ -670,9 +667,9 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {...@@ -670,9 +667,9 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
670}667}
671668
672/// Creates a new empty `Atom` and returns its `Atom.Index`669/// Creates a new empty `Atom` and returns its `Atom.Index`
673pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Index {670pub fn createAtom(wasm: *Wasm, sym_index: Symbol.Index, file_index: File.Index) !Atom.Index {
674 const gpa = wasm.base.comp.gpa;671 const gpa = wasm.base.comp.gpa;
675 const index: Atom.Index = @intCast(wasm.managed_atoms.items.len);672 const index: Atom.Index = @enumFromInt(wasm.managed_atoms.items.len);
676 const atom = try wasm.managed_atoms.addOne(gpa);673 const atom = try wasm.managed_atoms.addOne(gpa);
677 atom.* = .{ .file = file_index, .sym_index = sym_index };674 atom.* = .{ .file = file_index, .sym_index = sym_index };
678 try wasm.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), index);675 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...@@ -681,11 +678,11 @@ pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Ind
681}678}
682679
683pub inline fn getAtom(wasm: *const Wasm, index: Atom.Index) Atom {680pub inline fn getAtom(wasm: *const Wasm, index: Atom.Index) Atom {
684 return wasm.managed_atoms.items[index];681 return wasm.managed_atoms.items[@intFromEnum(index)];
685}682}
686683
687pub inline fn getAtomPtr(wasm: *Wasm, index: Atom.Index) *Atom {684pub inline fn getAtomPtr(wasm: *Wasm, index: Atom.Index) *Atom {
688 return &wasm.managed_atoms.items[index];685 return &wasm.managed_atoms.items[@intFromEnum(index)];
689}686}
690687
691/// Parses an archive file and will then parse each object file688/// Parses an archive file and will then parse each object file
...@@ -757,7 +754,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void {...@@ -757,7 +754,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void {
757 log.debug("Resolving symbols in object: '{s}'", .{obj_file.path()});754 log.debug("Resolving symbols in object: '{s}'", .{obj_file.path()});
758755
759 for (obj_file.symbols(), 0..) |symbol, i| {756 for (obj_file.symbols(), 0..) |symbol, i| {
760 const sym_index: u32 = @intCast(i);757 const sym_index: Symbol.Index = @enumFromInt(i);
761 const location: SymbolLoc = .{ .file = file_index, .index = sym_index };758 const location: SymbolLoc = .{ .file = file_index, .index = sym_index };
762 const sym_name = obj_file.string(symbol.name);759 const sym_name = obj_file.string(symbol.name);
763 if (mem.eql(u8, sym_name, "__indirect_function_table")) {760 if (mem.eql(u8, sym_name, "__indirect_function_table")) {
...@@ -1489,7 +1486,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec...@@ -1489,7 +1486,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec
1489/// such as an exported or imported symbol.1486/// such as an exported or imported symbol.
1490/// If the symbol does not yet exist, creates a new one symbol instead1487/// If the symbol does not yet exist, creates a new one symbol instead
1491/// and then returns the index to it.1488/// and then returns the index to it.
1492pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 {1489pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !Symbol.Index {
1493 _ = lib_name;1490 _ = lib_name;
1494 return wasm.zigObjectPtr().?.getGlobalSymbol(wasm.base.comp.gpa, name);1491 return wasm.zigObjectPtr().?.getGlobalSymbol(wasm.base.comp.gpa, name);
1495}1492}
...@@ -1609,19 +1606,20 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1609,19 +1606,20 @@ fn allocateAtoms(wasm: *Wasm) !void {
1609 const sym = if (wasm.file(symbol_loc.file)) |obj_file|1606 const sym = if (wasm.file(symbol_loc.file)) |obj_file|
1610 obj_file.symbol(symbol_loc.index).*1607 obj_file.symbol(symbol_loc.index).*
1611 else1608 else
1612 wasm.synthetic_symbols.items[symbol_loc.index];1609 wasm.synthetic_symbols.items[@intFromEnum(symbol_loc.index)];
16131610
1614 // Dead symbols must be unlinked from the linked-list to prevent them1611 // Dead symbols must be unlinked from the linked-list to prevent them
1615 // from being emit into the binary.1612 // from being emit into the binary.
1616 if (sym.isDead()) {1613 if (sym.isDead()) {
1617 if (entry.value_ptr.* == atom_index and atom.prev != null) {1614 if (entry.value_ptr.* == atom_index and atom.prev != .null) {
1618 // When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update1615 // When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update
1619 // the entry to point it to the previous atom to ensure we do not start with a dead symbol that1616 // the entry to point it to the previous atom to ensure we do not start with a dead symbol that
1620 // was removed and therefore do not emit any code at all.1617 // was removed and therefore do not emit any code at all.
1621 entry.value_ptr.* = atom.prev.?;1618 entry.value_ptr.* = atom.prev;
1622 }1619 }
1623 atom_index = atom.prev orelse break;1620 if (atom.prev == .null) break;
1624 atom.prev = null;1621 atom_index = atom.prev;
1622 atom.prev = .null;
1625 continue;1623 continue;
1626 }1624 }
1627 offset = @intCast(atom.alignment.forward(offset));1625 offset = @intCast(atom.alignment.forward(offset));
...@@ -1633,7 +1631,8 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1633,7 +1631,8 @@ fn allocateAtoms(wasm: *Wasm) !void {
1633 atom.size,1631 atom.size,
1634 });1632 });
1635 offset += atom.size;1633 offset += atom.size;
1636 atom_index = atom.prev orelse break;1634 if (atom.prev == .null) break;
1635 atom_index = atom.prev;
1637 }1636 }
1638 segment.size = @intCast(segment.alignment.forward(offset));1637 segment.size = @intCast(segment.alignment.forward(offset));
1639 }1638 }
...@@ -1738,7 +1737,7 @@ fn setupInitFunctions(wasm: *Wasm) !void {...@@ -1738,7 +1737,7 @@ fn setupInitFunctions(wasm: *Wasm) !void {
1738 .file = file_index,1737 .file = file_index,
1739 .priority = init_func.priority,1738 .priority = init_func.priority,
1740 });1739 });
1741 try wasm.mark(.{ .index = init_func.symbol_index, .file = file_index });1740 try wasm.mark(.{ .index = @enumFromInt(init_func.symbol_index), .file = file_index });
1742 }1741 }
1743 }1742 }
17441743
...@@ -1844,7 +1843,7 @@ pub fn createFunction(...@@ -1844,7 +1843,7 @@ pub fn createFunction(
1844 func_ty: std.wasm.Type,1843 func_ty: std.wasm.Type,
1845 function_body: *std.ArrayList(u8),1844 function_body: *std.ArrayList(u8),
1846 relocations: *std.ArrayList(Relocation),1845 relocations: *std.ArrayList(Relocation),
1847) !u32 {1846) !Symbol.Index {
1848 return wasm.zigObjectPtr().?.createFunction(wasm, symbol_name, func_ty, function_body, relocations);1847 return wasm.zigObjectPtr().?.createFunction(wasm, symbol_name, func_ty, function_body, relocations);
1849}1848}
18501849
...@@ -2324,11 +2323,11 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -2324,11 +2323,11 @@ fn setupMemory(wasm: *Wasm) !void {
2324/// From a given object's index and the index of the segment, returns the corresponding2323/// From a given object's index and the index of the segment, returns the corresponding
2325/// index of the segment within the final data section. When the segment does not yet2324/// index of the segment within the final data section. When the segment does not yet
2326/// exist, a new one will be initialized and appended. The new index will be returned in that case.2325/// exist, a new one will be initialized and appended. The new index will be returned in that case.
2327pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32) !u32 {2326pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: Symbol.Index) !u32 {
2328 const comp = wasm.base.comp;2327 const comp = wasm.base.comp;
2329 const gpa = comp.gpa;2328 const gpa = comp.gpa;
2330 const obj_file = wasm.file(file_index).?;2329 const obj_file = wasm.file(file_index).?;
2331 const symbol = obj_file.symbols()[symbol_index];2330 const symbol = obj_file.symbols()[@intFromEnum(symbol_index)];
2332 const index: u32 = @intCast(wasm.segments.items.len);2331 const index: u32 = @intCast(wasm.segments.items.len);
2333 const shared_memory = comp.config.shared_memory;2332 const shared_memory = comp.config.shared_memory;
23342333
...@@ -2889,8 +2888,8 @@ fn writeToFile(...@@ -2889,8 +2888,8 @@ fn writeToFile(
2889 try binary_writer.writeAll(atom.code.items);2888 try binary_writer.writeAll(atom.code.items);
28902889
2891 current_offset += atom.size;2890 current_offset += atom.size;
2892 if (atom.prev) |prev| {2891 if (atom.prev != .null) {
2893 atom_index = prev;2892 atom_index = atom.prev;
2894 } else {2893 } else {
2895 // also pad with zeroes when last atom to ensure2894 // also pad with zeroes when last atom to ensure
2896 // segments are aligned.2895 // segments are aligned.
...@@ -2984,7 +2983,8 @@ fn writeToFile(...@@ -2984,7 +2983,8 @@ fn writeToFile(
2984 while (true) {2983 while (true) {
2985 atom.resolveRelocs(wasm);2984 atom.resolveRelocs(wasm);
2986 try debug_bytes.appendSlice(atom.code.items);2985 try debug_bytes.appendSlice(atom.code.items);
2987 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;2986 if (atom.prev == .null) break;
2987 atom = wasm.getAtomPtr(atom.prev);
2988 }2988 }
2989 try emitDebugSection(&binary_bytes, debug_bytes.items, item.name);2989 try emitDebugSection(&binary_bytes, debug_bytes.items, item.name);
2990 debug_bytes.clearRetainingCapacity();2990 debug_bytes.clearRetainingCapacity();
...@@ -3853,7 +3853,7 @@ fn emitCodeRelocations(...@@ -3853,7 +3853,7 @@ fn emitCodeRelocations(
3853 size_offset += getULEB128Size(atom.size);3853 size_offset += getULEB128Size(atom.size);
3854 for (atom.relocs.items) |relocation| {3854 for (atom.relocs.items) |relocation| {
3855 count += 1;3855 count += 1;
3856 const sym_loc: SymbolLoc = .{ .file = atom.file, .index = relocation.index };3856 const sym_loc: SymbolLoc = .{ .file = atom.file, .index = @enumFromInt(relocation.index) };
3857 const symbol_index = symbol_table.get(sym_loc).?;3857 const symbol_index = symbol_table.get(sym_loc).?;
3858 try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));3858 try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));
3859 const offset = atom.offset + relocation.offset + size_offset;3859 const offset = atom.offset + relocation.offset + size_offset;
...@@ -3864,7 +3864,8 @@ fn emitCodeRelocations(...@@ -3864,7 +3864,8 @@ fn emitCodeRelocations(
3864 }3864 }
3865 log.debug("Emit relocation: {}", .{relocation});3865 log.debug("Emit relocation: {}", .{relocation});
3866 }3866 }
3867 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;3867 if (atom.prev == .null) break;
3868 atom = wasm.getAtomPtr(atom.prev);
3868 }3869 }
3869 if (count == 0) return;3870 if (count == 0) return;
3870 var buf: [5]u8 = undefined;3871 var buf: [5]u8 = undefined;
...@@ -3900,7 +3901,7 @@ fn emitDataRelocations(...@@ -3900,7 +3901,7 @@ fn emitDataRelocations(
3900 size_offset += getULEB128Size(atom.size);3901 size_offset += getULEB128Size(atom.size);
3901 for (atom.relocs.items) |relocation| {3902 for (atom.relocs.items) |relocation| {
3902 count += 1;3903 count += 1;
3903 const sym_loc: SymbolLoc = .{ .file = atom.file, .index = relocation.index };3904 const sym_loc: SymbolLoc = .{ .file = atom.file, .index = @enumFromInt(relocation.index) };
3904 const symbol_index = symbol_table.get(sym_loc).?;3905 const symbol_index = symbol_table.get(sym_loc).?;
3905 try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));3906 try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type));
3906 const offset = atom.offset + relocation.offset + size_offset;3907 const offset = atom.offset + relocation.offset + size_offset;
...@@ -3911,7 +3912,8 @@ fn emitDataRelocations(...@@ -3911,7 +3912,8 @@ fn emitDataRelocations(
3911 }3912 }
3912 log.debug("Emit relocation: {}", .{relocation});3913 log.debug("Emit relocation: {}", .{relocation});
3913 }3914 }
3914 atom = if (atom.prev) |prev| wasm.getAtomPtr(prev) else break;3915 if (atom.prev == .null) break;
3916 atom = wasm.getAtomPtr(atom.prev);
3915 }3917 }
3916 }3918 }
3917 if (count == 0) return;3919 if (count == 0) return;
...@@ -3969,7 +3971,8 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s...@@ -3969,7 +3971,8 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s
3969///3971///
3970/// When the symbol does not yet exist, it will create a new one instead.3972/// When the symbol does not yet exist, it will create a new one instead.
3971pub fn getErrorTableSymbol(wasm_file: *Wasm) !u32 {3973pub fn getErrorTableSymbol(wasm_file: *Wasm) !u32 {
3972 return wasm_file.zigObjectPtr().?.getErrorTableSymbol(wasm_file);3974 const sym_index = try wasm_file.zigObjectPtr().?.getErrorTableSymbol(wasm_file);
3975 return @intFromEnum(sym_index);
3973}3976}
39743977
3975/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`.3978/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`.
...@@ -4029,7 +4032,7 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void {...@@ -4029,7 +4032,7 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void {
40294032
4030 const atom = wasm.getAtom(atom_index);4033 const atom = wasm.getAtom(atom_index);
4031 for (atom.relocs.items) |reloc| {4034 for (atom.relocs.items) |reloc| {
4032 const target_loc: SymbolLoc = .{ .index = reloc.index, .file = loc.file };4035 const target_loc: SymbolLoc = .{ .index = @enumFromInt(reloc.index), .file = loc.file };
4033 try wasm.mark(target_loc.finalLoc(wasm));4036 try wasm.mark(target_loc.finalLoc(wasm));
4034 }4037 }
4035}4038}
src/link/Wasm/Atom.zig+13-17
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2/// This is 'null' when the atom was generated by a synthetic linker symbol.2/// This is 'null' when the atom was generated by a synthetic linker symbol.
3file: FileIndex,3file: FileIndex,
4/// symbol index of the symbol representing this atom4/// symbol index of the symbol representing this atom
5sym_index: u32,5sym_index: Symbol.Index,
6/// Size of the atom, used to calculate section sizes in the final binary6/// Size of the atom, used to calculate section sizes in the final binary
7size: u32 = 0,7size: u32 = 0,
8/// List of relocations belonging to this atom8/// List of relocations belonging to this atom
...@@ -17,19 +17,19 @@ offset: u32 = 0,...@@ -17,19 +17,19 @@ offset: u32 = 0,
17/// The original offset within the object file. This value is substracted from17/// The original offset within the object file. This value is substracted from
18/// relocation offsets to determine where in the `data` to rewrite the value18/// relocation offsets to determine where in the `data` to rewrite the value
19original_offset: u32 = 0,19original_offset: u32 = 0,
20/// Next atom in relation to this atom.
21/// When null, this atom is the last atom
22next: ?Atom.Index = null,
23/// Previous atom in relation to this atom.20/// Previous atom in relation to this atom.
24/// is null when this atom is the first in its order21/// is null when this atom is the first in its order
25prev: ?Atom.Index = null,22prev: Atom.Index = .null,
26/// Contains atoms local to a decl, all managed by this `Atom`.23/// Contains atoms local to a decl, all managed by this `Atom`.
27/// When the parent atom is being freed, it will also do so for all local atoms.24/// When the parent atom is being freed, it will also do so for all local atoms.
28locals: std.ArrayListUnmanaged(Atom.Index) = .{},25locals: std.ArrayListUnmanaged(Atom.Index) = .{},
2926
30/// Alias to an unsigned 32-bit integer.27/// Represents the index of an Atom where `null` is considered
31// TODO: Make this a non-exhaustive enum.28/// an invalid atom.
32pub const Index = u32;29pub const Index = enum(u32) {
30 null = std.math.maxInt(u32),
31 _,
32};
3333
34/// Frees all resources owned by this `Atom`.34/// Frees all resources owned by this `Atom`.
35pub fn deinit(atom: *Atom, gpa: std.mem.Allocator) void {35pub 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...@@ -50,7 +50,7 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio
50 _ = fmt;50 _ = fmt;
51 _ = options;51 _ = options;
52 try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{52 try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{
53 atom.sym_index,53 @intFromEnum(atom.sym_index),
54 atom.alignment,54 atom.alignment,
55 atom.size,55 atom.size,
56 atom.offset,56 atom.offset,
...@@ -62,11 +62,6 @@ pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {...@@ -62,11 +62,6 @@ pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
62 return .{ .file = atom.file, .index = atom.sym_index };62 return .{ .file = atom.file, .index = atom.sym_index };
63}63}
6464
65pub fn getSymbolIndex(atom: Atom) ?u32 {
66 if (atom.sym_index == 0) return null;
67 return atom.sym_index;
68}
69
70/// Resolves the relocations within the atom, writing the new value65/// Resolves the relocations within the atom, writing the new value
71/// at the calculated offset.66/// at the calculated offset.
72pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {67pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
...@@ -80,7 +75,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {...@@ -80,7 +75,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
80 for (atom.relocs.items) |reloc| {75 for (atom.relocs.items) |reloc| {
81 const value = atom.relocationValue(reloc, wasm_bin);76 const value = atom.relocationValue(reloc, wasm_bin);
82 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{77 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{
83 (Wasm.SymbolLoc{ .file = atom.file, .index = reloc.index }).getName(wasm_bin),78 (Wasm.SymbolLoc{ .file = atom.file, .index = @enumFromInt(reloc.index) }).getName(wasm_bin),
84 symbol_name,79 symbol_name,
85 reloc.offset,80 reloc.offset,
86 value,81 value,
...@@ -119,7 +114,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {...@@ -119,7 +114,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
119/// All values will be represented as a `u64` as all values can fit within it.114/// All values will be represented as a `u64` as all values can fit within it.
120/// The final value must be casted to the correct size.115/// The final value must be casted to the correct size.
121fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {116fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
122 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);117 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = @enumFromInt(relocation.index) }).finalLoc(wasm_bin);
123 const symbol = target_loc.getSymbol(wasm_bin);118 const symbol = target_loc.getSymbol(wasm_bin);
124 if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and119 if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and
125 symbol.tag != .section and120 symbol.tag != .section and
...@@ -135,7 +130,7 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -135,7 +130,7 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
135 .R_WASM_TABLE_INDEX_I64,130 .R_WASM_TABLE_INDEX_I64,
136 .R_WASM_TABLE_INDEX_SLEB,131 .R_WASM_TABLE_INDEX_SLEB,
137 .R_WASM_TABLE_INDEX_SLEB64,132 .R_WASM_TABLE_INDEX_SLEB64,
138 => return wasm_bin.function_table.get(.{ .file = atom.file, .index = relocation.index }) orelse 0,133 => return wasm_bin.function_table.get(.{ .file = atom.file, .index = @enumFromInt(relocation.index) }) orelse 0,
139 .R_WASM_TYPE_INDEX_LEB => {134 .R_WASM_TYPE_INDEX_LEB => {
140 const obj_file = wasm_bin.file(atom.file) orelse return relocation.index;135 const obj_file = wasm_bin.file(atom.file) orelse return relocation.index;
141 const original_type = obj_file.funcTypes()[relocation.index];136 const original_type = obj_file.funcTypes()[relocation.index];
...@@ -195,6 +190,7 @@ fn thombstone(atom: Atom, wasm: *const Wasm) ?i64 {...@@ -195,6 +190,7 @@ fn thombstone(atom: Atom, wasm: *const Wasm) ?i64 {
195 }190 }
196 return null;191 return null;
197}192}
193
198const leb = std.leb;194const leb = std.leb;
199const log = std.log.scoped(.link);195const log = std.log.scoped(.link);
200const mem = std.mem;196const mem = std.mem;
src/link/Wasm/Object.zig+4-4
...@@ -907,10 +907,10 @@ fn assertEnd(reader: anytype) !void {...@@ -907,10 +907,10 @@ fn assertEnd(reader: anytype) !void {
907}907}
908908
909/// Parses an object file into atoms, for code and data sections909/// Parses an object file into atoms, for code and data sections
910pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Atom.Index {910pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: Symbol.Index) !Atom.Index {
911 const comp = wasm.base.comp;911 const comp = wasm.base.comp;
912 const gpa = comp.gpa;912 const gpa = comp.gpa;
913 const symbol = &object.symtable[symbol_index];913 const symbol = &object.symtable[@intFromEnum(symbol_index)];
914 const relocatable_data: RelocatableData = switch (symbol.tag) {914 const relocatable_data: RelocatableData = switch (symbol.tag) {
915 .function => object.relocatable_data.get(.code).?[symbol.index - object.imported_functions_count],915 .function => object.relocatable_data.get(.code).?[symbol.index - object.imported_functions_count],
916 .data => object.relocatable_data.get(.data).?[symbol.index],916 .data => object.relocatable_data.get(.data).?[symbol.index],
...@@ -953,7 +953,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato...@@ -953,7 +953,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
953 => {953 => {
954 try wasm.function_table.put(gpa, .{954 try wasm.function_table.put(gpa, .{
955 .file = object.index,955 .file = object.index,
956 .index = reloc.index,956 .index = @enumFromInt(reloc.index),
957 }, 0);957 }, 0);
958 },958 },
959 .R_WASM_GLOBAL_INDEX_I32,959 .R_WASM_GLOBAL_INDEX_I32,
...@@ -961,7 +961,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato...@@ -961,7 +961,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
961 => {961 => {
962 const sym = object.symtable[reloc.index];962 const sym = object.symtable[reloc.index];
963 if (sym.tag != .global) {963 if (sym.tag != .global) {
964 try wasm.got_symbols.append(gpa, .{ .file = object.index, .index = reloc.index });964 try wasm.got_symbols.append(gpa, .{ .file = object.index, .index = @enumFromInt(reloc.index) });
965 }965 }
966 },966 },
967 else => {},967 else => {},
src/link/Wasm/Symbol.zig+11-5
...@@ -1,12 +1,8 @@...@@ -1,12 +1,8 @@
1//! Represents a wasm symbol. Containing all of its properties,1//! Represents a WebAssembly symbol. Containing all of its properties,
2//! as well as providing helper methods to determine its functionality2//! as well as providing helper methods to determine its functionality
3//! and how it will/must be linked.3//! and how it will/must be linked.
4//! The name of the symbol can be found by providing the offset, found4//! The name of the symbol can be found by providing the offset, found
5//! on the `name` field, to a string table in the wasm binary or object file.5//! on the `name` field, to a string table in the wasm binary or object file.
6const Symbol = @This();
7
8const std = @import("std");
9const types = @import("types.zig");
106
11/// Bitfield containings flags for a symbol7/// Bitfield containings flags for a symbol
12/// Can contain any of the flags defined in `Flag`8/// Can contain any of the flags defined in `Flag`
...@@ -24,6 +20,12 @@ tag: Tag,...@@ -24,6 +20,12 @@ tag: Tag,
24/// This differs from the offset of an `Atom` which is relative to the start of a segment.20/// This differs from the offset of an `Atom` which is relative to the start of a segment.
25virtual_address: u32,21virtual_address: u32,
2622
23/// Represents a symbol index where `null` represents an invalid index.
24pub const Index = enum(u32) {
25 null,
26 _,
27};
28
27pub const Tag = enum {29pub const Tag = enum {
28 function,30 function,
29 data,31 data,
...@@ -202,3 +204,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO...@@ -202,3 +204,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO
202 .{ kind_fmt, binding, visible, symbol.index, symbol.name, undef },204 .{ kind_fmt, binding, visible, symbol.index, symbol.name, undef },
203 );205 );
204}206}
207
208const std = @import("std");
209const types = @import("types.zig");
210const Symbol = @This();
src/link/Wasm/ZigObject.zig+47-56
...@@ -17,7 +17,7 @@ functions: std.ArrayListUnmanaged(std.wasm.Func) = .{},...@@ -17,7 +17,7 @@ functions: std.ArrayListUnmanaged(std.wasm.Func) = .{},
17/// List of indexes pointing to an entry within the `functions` list which has been removed.17/// List of indexes pointing to an entry within the `functions` list which has been removed.
18functions_free_list: std.ArrayListUnmanaged(u32) = .{},18functions_free_list: std.ArrayListUnmanaged(u32) = .{},
19/// Map of symbol locations, represented by its `types.Import`.19/// Map of symbol locations, represented by its `types.Import`.
20imports: std.AutoHashMapUnmanaged(u32, types.Import) = .{},20imports: std.AutoHashMapUnmanaged(Symbol.Index, types.Import) = .{},
21/// List of WebAssembly globals.21/// List of WebAssembly globals.
22globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},22globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
23/// Mapping between an `Atom` and its type index representing the Wasm23/// Mapping between an `Atom` and its type index representing the Wasm
...@@ -26,9 +26,9 @@ atom_types: std.AutoHashMapUnmanaged(Atom.Index, u32) = .{},...@@ -26,9 +26,9 @@ atom_types: std.AutoHashMapUnmanaged(Atom.Index, u32) = .{},
26/// List of all symbols generated by Zig code.26/// List of all symbols generated by Zig code.
27symbols: std.ArrayListUnmanaged(Symbol) = .{},27symbols: std.ArrayListUnmanaged(Symbol) = .{},
28/// Map from symbol name offset to their index into the `symbols` list.28/// Map from symbol name offset to their index into the `symbols` list.
29global_syms: std.AutoHashMapUnmanaged(u32, u32) = .{},29global_syms: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
30/// List of symbol indexes which are free to be used.30/// List of symbol indexes which are free to be used.
31symbols_free_list: std.ArrayListUnmanaged(u32) = .{},31symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
32/// Extra metadata about the linking section, such as alignment of segments and their name.32/// Extra metadata about the linking section, such as alignment of segments and their name.
33segment_info: std.ArrayListUnmanaged(types.Segment) = .{},33segment_info: std.ArrayListUnmanaged(types.Segment) = .{},
34/// List of indexes which contain a free slot in the `segment_info` list.34/// 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) = .{},...@@ -42,7 +42,7 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{},
42/// During initializion, a symbol with corresponding atom will be created that is42/// During initializion, a symbol with corresponding atom will be created that is
43/// used to perform relocations to the pointer of this table.43/// used to perform relocations to the pointer of this table.
44/// The actual table is populated during `flush`.44/// The actual table is populated during `flush`.
45error_table_symbol: ?u32 = null,45error_table_symbol: Symbol.Index = .null,
46/// Amount of functions in the `import` sections.46/// Amount of functions in the `import` sections.
47imported_functions_count: u32 = 0,47imported_functions_count: u32 = 0,
48/// Amount of globals in the `import` section.48/// Amount of globals in the `import` section.
...@@ -50,7 +50,7 @@ imported_globals_count: u32 = 0,...@@ -50,7 +50,7 @@ imported_globals_count: u32 = 0,
50/// Symbol index representing the stack pointer. This will be set upon initializion50/// Symbol index representing the stack pointer. This will be set upon initializion
51/// of a new `ZigObject`. Codegen will make calls into this to create relocations for51/// of a new `ZigObject`. Codegen will make calls into this to create relocations for
52/// this symbol each time the stack pointer is moved.52/// this symbol each time the stack pointer is moved.
53stack_pointer_sym: u32,53stack_pointer_sym: Symbol.Index,
54/// Debug information for the Zig module.54/// Debug information for the Zig module.
55dwarf: ?Dwarf = null,55dwarf: ?Dwarf = null,
56// Debug section atoms. These are only set when the current compilation56// Debug section atoms. These are only set when the current compilation
...@@ -83,10 +83,10 @@ debug_str_index: ?u32 = null,...@@ -83,10 +83,10 @@ debug_str_index: ?u32 = null,
83debug_abbrev_index: ?u32 = null,83debug_abbrev_index: ?u32 = null,
8484
85const DeclInfo = struct {85const DeclInfo = struct {
86 atom: Atom.Index = std.math.maxInt(Atom.Index),86 atom: Atom.Index = .null,
87 exports: std.ArrayListUnmanaged(u32) = .{},87 exports: std.ArrayListUnmanaged(Symbol.Index) = .{},
8888
89 fn @"export"(di: DeclInfo, zig_object: *const ZigObject, name: []const u8) ?u32 {89 fn @"export"(di: DeclInfo, zig_object: *const ZigObject, name: []const u8) ?Symbol.Index {
90 for (di.exports.items) |sym_index| {90 for (di.exports.items) |sym_index| {
91 const sym_name_index = zig_object.symbol(sym_index).name;91 const sym_name_index = zig_object.symbol(sym_index).name;
92 const sym_name = zig_object.string_table.getAssumeExists(sym_name_index);92 const sym_name = zig_object.string_table.getAssumeExists(sym_name_index);
...@@ -97,11 +97,11 @@ const DeclInfo = struct {...@@ -97,11 +97,11 @@ const DeclInfo = struct {
97 return null;97 return null;
98 }98 }
9999
100 fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: u32) !void {100 fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: Symbol.Index) !void {
101 return di.exports.append(gpa, sym_index);101 return di.exports.append(gpa, sym_index);
102 }102 }
103103
104 fn deleteExport(di: *DeclInfo, sym_index: u32) void {104 fn deleteExport(di: *DeclInfo, sym_index: Symbol.Index) void {
105 for (di.exports.items, 0..) |idx, index| {105 for (di.exports.items, 0..) |idx, index| {
106 if (idx == sym_index) {106 if (idx == sym_index) {
107 _ = di.exports.swapRemove(index);107 _ = di.exports.swapRemove(index);
...@@ -138,8 +138,8 @@ fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void {...@@ -138,8 +138,8 @@ fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void {
138 zig_object.stack_pointer_sym = sym_index;138 zig_object.stack_pointer_sym = sym_index;
139}139}
140140
141fn symbol(zig_object: *const ZigObject, index: u32) *Symbol {141fn symbol(zig_object: *const ZigObject, index: Symbol.Index) *Symbol {
142 return &zig_object.symbols.items[index];142 return &zig_object.symbols.items[@intFromEnum(index)];
143}143}
144144
145/// Frees and invalidates all memory of the incrementally compiled Zig module.145/// 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 {...@@ -192,7 +192,7 @@ pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void {
192192
193/// Allocates a new symbol and returns its index.193/// Allocates a new symbol and returns its index.
194/// Will re-use slots when a symbol was freed at an earlier stage.194/// Will re-use slots when a symbol was freed at an earlier stage.
195pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 {195pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !Symbol.Index {
196 try zig_object.symbols.ensureUnusedCapacity(gpa, 1);196 try zig_object.symbols.ensureUnusedCapacity(gpa, 1);
197 const sym: Symbol = .{197 const sym: Symbol = .{
198 .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls198 .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 {...@@ -202,10 +202,10 @@ pub fn allocateSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator) !u32 {
202 .virtual_address = std.math.maxInt(u32), // will be set during atom allocation202 .virtual_address = std.math.maxInt(u32), // will be set during atom allocation
203 };203 };
204 if (zig_object.symbols_free_list.popOrNull()) |index| {204 if (zig_object.symbols_free_list.popOrNull()) |index| {
205 zig_object.symbols.items[index] = sym;205 zig_object.symbols.items[@intFromEnum(index)] = sym;
206 return index;206 return index;
207 }207 }
208 const index = @as(u32, @intCast(zig_object.symbols.items.len));208 const index: Symbol.Index = @enumFromInt(zig_object.symbols.items.len);
209 zig_object.symbols.appendAssumeCapacity(sym);209 zig_object.symbols.appendAssumeCapacity(sym);
210 return index;210 return index;
211}211}
...@@ -247,7 +247,7 @@ pub fn updateDecl(...@@ -247,7 +247,7 @@ pub fn updateDecl(
247 .{ .ty = decl.ty, .val = val },247 .{ .ty = decl.ty, .val = val },
248 &code_writer,248 &code_writer,
249 .none,249 .none,
250 .{ .parent_atom_index = atom.sym_index },250 .{ .parent_atom_index = @intFromEnum(atom.sym_index) },
251 );251 );
252252
253 const code = switch (res) {253 const code = switch (res) {
...@@ -464,7 +464,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu...@@ -464,7 +464,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu
464 switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) {464 switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) {
465 .ok => |atom_index| {465 .ok => |atom_index| {
466 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);466 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);
467 return wasm_file.getAtom(atom_index).getSymbolIndex().?;467 return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
468 },468 },
469 .fail => |em| {469 .fail => |em| {
470 decl.analysis = .codegen_failure;470 decl.analysis = .codegen_failure;
...@@ -494,7 +494,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -494,7 +494,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
494 atom.alignment = tv.ty.abiAlignment(mod);494 atom.alignment = tv.ty.abiAlignment(mod);
495 const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name });495 const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name });
496 errdefer gpa.free(segment_name);496 errdefer gpa.free(segment_name);
497 zig_object.symbols.items[sym_index] = .{497 zig_object.symbol(sym_index).* = .{
498 .name = try zig_object.string_table.insert(gpa, name),498 .name = try zig_object.string_table.insert(gpa, name),
499 .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),499 .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
500 .tag = .data,500 .tag = .data,
...@@ -513,7 +513,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -513,7 +513,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
513 &value_bytes,513 &value_bytes,
514 .none,514 .none,
515 .{515 .{
516 .parent_atom_index = atom.sym_index,516 .parent_atom_index = @intFromEnum(atom.sym_index),
517 .addend = null,517 .addend = null,
518 },518 },
519 );519 );
...@@ -534,9 +534,9 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty...@@ -534,9 +534,9 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty
534/// Returns the symbol index of the error name table.534/// Returns the symbol index of the error name table.
535///535///
536/// When the symbol does not yet exist, it will create a new one instead.536/// When the symbol does not yet exist, it will create a new one instead.
537pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {537pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !Symbol.Index {
538 if (zig_object.error_table_symbol) |sym| {538 if (zig_object.error_table_symbol != .null) {
539 return sym;539 return zig_object.error_table_symbol;
540 }540 }
541541
542 // no error was referenced yet, so create a new symbol and atom for it542 // 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 {...@@ -561,7 +561,7 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {
561 .virtual_address = undefined,561 .virtual_address = undefined,
562 };562 };
563563
564 log.debug("Error name table was created with symbol index: ({d})", .{sym_index});564 log.debug("Error name table was created with symbol index: ({d})", .{@intFromEnum(sym_index)});
565 zig_object.error_table_symbol = sym_index;565 zig_object.error_table_symbol = sym_index;
566 return sym_index;566 return sym_index;
567}567}
...@@ -571,9 +571,9 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {...@@ -571,9 +571,9 @@ pub fn getErrorTableSymbol(zig_object: *ZigObject, wasm_file: *Wasm) !u32 {
571/// This creates a table that consists of pointers and length to each error name.571/// This creates a table that consists of pointers and length to each error name.
572/// The table is what is being pointed to within the runtime bodies that are generated.572/// The table is what is being pointed to within the runtime bodies that are generated.
573fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {573fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
574 const symbol_index = zig_object.error_table_symbol orelse return;574 if (zig_object.error_table_symbol == .null) return;
575 const gpa = wasm_file.base.comp.gpa;575 const gpa = wasm_file.base.comp.gpa;
576 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = symbol_index }).?;576 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = zig_object.error_table_symbol }).?;
577577
578 // Rather than creating a symbol for each individual error name,578 // Rather than creating a symbol for each individual error name,
579 // we create a symbol for the entire region of error names. We then calculate579 // 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 {...@@ -584,7 +584,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
584 names_atom.alignment = .@"1";584 names_atom.alignment = .@"1";
585 const sym_name = try zig_object.string_table.insert(gpa, "__zig_err_names");585 const sym_name = try zig_object.string_table.insert(gpa, "__zig_err_names");
586 const segment_name = try gpa.dupe(u8, ".rodata.__zig_err_names");586 const segment_name = try gpa.dupe(u8, ".rodata.__zig_err_names");
587 const names_symbol = &zig_object.symbols.items[names_sym_index];587 const names_symbol = zig_object.symbol(names_sym_index);
588 names_symbol.* = .{588 names_symbol.* = .{
589 .name = sym_name,589 .name = sym_name,
590 .tag = .data,590 .tag = .data,
...@@ -611,7 +611,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {...@@ -611,7 +611,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void {
611 try atom.code.writer(gpa).writeInt(u32, len - 1, .little);611 try atom.code.writer(gpa).writeInt(u32, len - 1, .little);
612 // create relocation to the error name612 // create relocation to the error name
613 try atom.relocs.append(gpa, .{613 try atom.relocs.append(gpa, .{
614 .index = names_atom.sym_index,614 .index = @intFromEnum(names_atom.sym_index),
615 .relocation_type = .R_WASM_MEMORY_ADDR_I32,615 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
616 .offset = offset,616 .offset = offset,
617 .addend = @as(i32, @intCast(addend)),617 .addend = @as(i32, @intCast(addend)),
...@@ -638,7 +638,7 @@ pub fn addOrUpdateImport(...@@ -638,7 +638,7 @@ pub fn addOrUpdateImport(
638 /// Name of the import638 /// Name of the import
639 name: []const u8,639 name: []const u8,
640 /// Symbol index that is external640 /// Symbol index that is external
641 symbol_index: u32,641 symbol_index: Symbol.Index,
642 /// Optional library name (i.e. `extern "c" fn foo() void`642 /// Optional library name (i.e. `extern "c" fn foo() void`
643 lib_name: ?[:0]const u8,643 lib_name: ?[:0]const u8,
644 /// The index of the type that represents the function signature644 /// The index of the type that represents the function signature
...@@ -647,7 +647,7 @@ pub fn addOrUpdateImport(...@@ -647,7 +647,7 @@ pub fn addOrUpdateImport(
647 type_index: ?u32,647 type_index: ?u32,
648) !void {648) !void {
649 const gpa = wasm_file.base.comp.gpa;649 const gpa = wasm_file.base.comp.gpa;
650 std.debug.assert(symbol_index != 0);650 std.debug.assert(symbol_index != .null);
651 // For the import name, we use the decl's name, rather than the fully qualified name651 // For the import name, we use the decl's name, rather than the fully qualified name
652 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same652 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same
653 // name but different module can be resolved correctly.653 // name but different module can be resolved correctly.
...@@ -659,7 +659,7 @@ pub fn addOrUpdateImport(...@@ -659,7 +659,7 @@ pub fn addOrUpdateImport(
659 defer if (mangle_name) gpa.free(full_name);659 defer if (mangle_name) gpa.free(full_name);
660660
661 const decl_name_index = try zig_object.string_table.insert(gpa, full_name);661 const decl_name_index = try zig_object.string_table.insert(gpa, full_name);
662 const sym: *Symbol = &zig_object.symbols.items[symbol_index];662 const sym: *Symbol = &zig_object.symbols.items[@intFromEnum(symbol_index)];
663 sym.setUndefined(true);663 sym.setUndefined(true);
664 sym.setGlobal(true);664 sym.setGlobal(true);
665 sym.name = decl_name_index;665 sym.name = decl_name_index;
...@@ -689,7 +689,7 @@ pub fn addOrUpdateImport(...@@ -689,7 +689,7 @@ pub fn addOrUpdateImport(
689/// such as an exported or imported symbol.689/// such as an exported or imported symbol.
690/// If the symbol does not yet exist, creates a new one symbol instead690/// If the symbol does not yet exist, creates a new one symbol instead
691/// and then returns the index to it.691/// and then returns the index to it.
692pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8) !u32 {692pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8) !Symbol.Index {
693 const name_index = try zig_object.string_table.insert(gpa, name);693 const name_index = try zig_object.string_table.insert(gpa, name);
694 const gop = try zig_object.global_syms.getOrPut(gpa, name_index);694 const gop = try zig_object.global_syms.getOrPut(gpa, name_index);
695 if (gop.found_existing) {695 if (gop.found_existing) {
...@@ -707,12 +707,12 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c...@@ -707,12 +707,12 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c
707 sym.setUndefined(true);707 sym.setUndefined(true);
708708
709 const sym_index = if (zig_object.symbols_free_list.popOrNull()) |index| index else blk: {709 const sym_index = if (zig_object.symbols_free_list.popOrNull()) |index| index else blk: {
710 const index: u32 = @intCast(zig_object.symbols.items.len);710 const index: Symbol.Index = @enumFromInt(zig_object.symbols.items.len);
711 try zig_object.symbols.ensureUnusedCapacity(gpa, 1);711 try zig_object.symbols.ensureUnusedCapacity(gpa, 1);
712 zig_object.symbols.items.len += 1;712 zig_object.symbols.items.len += 1;
713 break :blk index;713 break :blk index;
714 };714 };
715 zig_object.symbols.items[sym_index] = sym;715 zig_object.symbol(sym_index).* = sym;
716 gop.value_ptr.* = sym_index;716 gop.value_ptr.* = sym_index;
717 return sym_index;717 return sym_index;
718}718}
...@@ -731,10 +731,10 @@ pub fn getDeclVAddr(...@@ -731,10 +731,10 @@ pub fn getDeclVAddr(
731 const decl = mod.declPtr(decl_index);731 const decl = mod.declPtr(decl_index);
732732
733 const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);733 const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
734 const target_symbol_index = wasm_file.getAtom(target_atom_index).sym_index;734 const target_symbol_index = @intFromEnum(wasm_file.getAtom(target_atom_index).sym_index);
735735
736 std.debug.assert(reloc_info.parent_atom_index != 0);736 std.debug.assert(reloc_info.parent_atom_index != 0);
737 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = reloc_info.parent_atom_index }).?;737 const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
738 const atom = wasm_file.getAtomPtr(atom_index);738 const atom = wasm_file.getAtomPtr(atom_index);
739 const is_wasm32 = target.cpu.arch == .wasm32;739 const is_wasm32 = target.cpu.arch == .wasm32;
740 if (decl.ty.zigTypeTag(mod) == .Fn) {740 if (decl.ty.zigTypeTag(mod) == .Fn) {
...@@ -769,9 +769,9 @@ pub fn getAnonDeclVAddr(...@@ -769,9 +769,9 @@ pub fn getAnonDeclVAddr(
769 const gpa = wasm_file.base.comp.gpa;769 const gpa = wasm_file.base.comp.gpa;
770 const target = wasm_file.base.comp.root_mod.resolved_target.result;770 const target = wasm_file.base.comp.root_mod.resolved_target.result;
771 const atom_index = zig_object.anon_decls.get(decl_val).?;771 const atom_index = zig_object.anon_decls.get(decl_val).?;
772 const target_symbol_index = wasm_file.getAtom(atom_index).getSymbolIndex().?;772 const target_symbol_index = @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
773773
774 const parent_atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = reloc_info.parent_atom_index }).?;774 const parent_atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
775 const parent_atom = wasm_file.getAtomPtr(parent_atom_index);775 const parent_atom = wasm_file.getAtomPtr(parent_atom_index);
776 const is_wasm32 = target.cpu.arch == .wasm32;776 const is_wasm32 = target.cpu.arch == .wasm32;
777 const mod = wasm_file.base.comp.module.?;777 const mod = wasm_file.base.comp.module.?;
...@@ -930,17 +930,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool...@@ -930,17 +930,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool
930 // dwarf.freeDecl(decl_index);930 // dwarf.freeDecl(decl_index);
931 // }931 // }
932932
933 if (atom.next) |next_atom_index| {933 atom.prev = null;
934 const next_atom = wasm_file.getAtomPtr(next_atom_index);
935 next_atom.prev = atom.prev;
936 atom.next = null;
937 }
938 if (atom.prev) |prev_index| {
939 const prev_atom = wasm_file.getAtomPtr(prev_index);
940 prev_atom.next = atom.next;
941 atom.prev = null;
942 }
943
944 sym.tag = .dead;934 sym.tag = .dead;
945 if (sym.isGlobal()) {935 if (sym.isGlobal()) {
946 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));936 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));
...@@ -998,7 +988,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {...@@ -998,7 +988,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
998 // if not, allcoate a new atom.988 // if not, allcoate a new atom.
999 const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {989 const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {
1000 const atom = wasm_file.getAtomPtr(index);990 const atom = wasm_file.getAtomPtr(index);
1001 atom.prev = null;991 atom.prev = .null;
1002 atom.deinit(gpa);992 atom.deinit(gpa);
1003 break :blk index;993 break :blk index;
1004 } else idx: {994 } else idx: {
...@@ -1022,7 +1012,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {...@@ -1022,7 +1012,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
1022 try atom.code.writer(gpa).writeInt(u16, @intCast(errors_len), .little);1012 try atom.code.writer(gpa).writeInt(u16, @intCast(errors_len), .little);
1023}1013}
10241014
1025fn findGlobalSymbol(zig_object: *ZigObject, name: []const u8) ?u32 {1015fn findGlobalSymbol(zig_object: *ZigObject, name: []const u8) ?Symbol.Index {
1026 const offset = zig_object.string_table.getOffset(name) orelse return null;1016 const offset = zig_object.string_table.getOffset(name) orelse return null;
1027 return zig_object.global_syms.get(offset);1017 return zig_object.global_syms.get(offset);
1028}1018}
...@@ -1121,7 +1111,7 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:...@@ -1121,7 +1111,7 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:
1121/// The symbols in ZigObject are already represented by an atom as we need to store its data.1111/// The symbols in ZigObject are already represented by an atom as we need to store its data.
1122/// So rather than creating a new Atom and returning its index, we use this oppertunity to scan1112/// So rather than creating a new Atom and returning its index, we use this oppertunity to scan
1123/// its relocations and create any GOT symbols or function table indexes it may require.1113/// its relocations and create any GOT symbols or function table indexes it may require.
1124pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) !Atom.Index {1114pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: Symbol.Index) !Atom.Index {
1125 const gpa = wasm_file.base.comp.gpa;1115 const gpa = wasm_file.base.comp.gpa;
1126 const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = index };1116 const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = index };
1127 const atom_index = wasm_file.symbol_atom.get(loc).?;1117 const atom_index = wasm_file.symbol_atom.get(loc).?;
...@@ -1129,6 +1119,7 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)...@@ -1129,6 +1119,7 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)
1129 try wasm_file.appendAtomAtIndex(final_index, atom_index);1119 try wasm_file.appendAtomAtIndex(final_index, atom_index);
1130 const atom = wasm_file.getAtom(atom_index);1120 const atom = wasm_file.getAtom(atom_index);
1131 for (atom.relocs.items) |reloc| {1121 for (atom.relocs.items) |reloc| {
1122 const reloc_index: Symbol.Index = @enumFromInt(reloc.index);
1132 switch (reloc.relocation_type) {1123 switch (reloc.relocation_type) {
1133 .R_WASM_TABLE_INDEX_I32,1124 .R_WASM_TABLE_INDEX_I32,
1134 .R_WASM_TABLE_INDEX_I64,1125 .R_WASM_TABLE_INDEX_I64,
...@@ -1137,17 +1128,17 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)...@@ -1137,17 +1128,17 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)
1137 => {1128 => {
1138 try wasm_file.function_table.put(gpa, .{1129 try wasm_file.function_table.put(gpa, .{
1139 .file = zig_object.index,1130 .file = zig_object.index,
1140 .index = reloc.index,1131 .index = reloc_index,
1141 }, 0);1132 }, 0);
1142 },1133 },
1143 .R_WASM_GLOBAL_INDEX_I32,1134 .R_WASM_GLOBAL_INDEX_I32,
1144 .R_WASM_GLOBAL_INDEX_LEB,1135 .R_WASM_GLOBAL_INDEX_LEB,
1145 => {1136 => {
1146 const sym = zig_object.symbol(reloc.index);1137 const sym = zig_object.symbol(reloc_index);
1147 if (sym.tag != .global) {1138 if (sym.tag != .global) {
1148 try wasm_file.got_symbols.append(gpa, .{1139 try wasm_file.got_symbols.append(gpa, .{
1149 .file = zig_object.index,1140 .file = zig_object.index,
1150 .index = reloc.index,1141 .index = reloc_index,
1151 });1142 });
1152 }1143 }
1153 },1144 },
...@@ -1166,10 +1157,10 @@ pub fn createFunction(...@@ -1166,10 +1157,10 @@ pub fn createFunction(
1166 func_ty: std.wasm.Type,1157 func_ty: std.wasm.Type,
1167 function_body: *std.ArrayList(u8),1158 function_body: *std.ArrayList(u8),
1168 relocations: *std.ArrayList(types.Relocation),1159 relocations: *std.ArrayList(types.Relocation),
1169) !u32 {1160) !Symbol.Index {
1170 const gpa = wasm_file.base.comp.gpa;1161 const gpa = wasm_file.base.comp.gpa;
1171 const sym_index = try zig_object.allocateSymbol(gpa);1162 const sym_index = try zig_object.allocateSymbol(gpa);
1172 const sym = &zig_object.symbols.items[sym_index];1163 const sym = zig_object.symbol(sym_index);
1173 sym.tag = .function;1164 sym.tag = .function;
1174 sym.name = try zig_object.string_table.insert(gpa, symbol_name);1165 sym.name = try zig_object.string_table.insert(gpa, symbol_name);
1175 const type_index = try zig_object.putOrGetFuncType(gpa, func_ty);1166 const type_index = try zig_object.putOrGetFuncType(gpa, func_ty);
src/link/Wasm/file.zig+12-12
...@@ -20,10 +20,10 @@ pub const File = union(enum) {...@@ -20,10 +20,10 @@ pub const File = union(enum) {
20 };20 };
21 }21 }
2222
23 pub fn symbol(file: File, index: u32) *Symbol {23 pub fn symbol(file: File, index: Symbol.Index) *Symbol {
24 return switch (file) {24 return switch (file) {
25 .zig_object => |obj| &obj.symbols.items[index],25 .zig_object => |obj| &obj.symbols.items[@intFromEnum(index)],
26 .object => |obj| &obj.symtable[index],26 .object => |obj| &obj.symtable[@intFromEnum(index)],
27 };27 };
28 }28 }
2929
...@@ -34,20 +34,20 @@ pub const File = union(enum) {...@@ -34,20 +34,20 @@ pub const File = union(enum) {
34 };34 };
35 }35 }
3636
37 pub fn symbolName(file: File, index: u32) []const u8 {37 pub fn symbolName(file: File, index: Symbol.Index) []const u8 {
38 switch (file) {38 switch (file) {
39 .zig_object => |obj| {39 .zig_object => |obj| {
40 const sym = obj.symbols.items[index];40 const sym = obj.symbols.items[@intFromEnum(index)];
41 return obj.string_table.get(sym.name).?;41 return obj.string_table.get(sym.name).?;
42 },42 },
43 .object => |obj| {43 .object => |obj| {
44 const sym = obj.symtable[index];44 const sym = obj.symtable[@intFromEnum(index)];
45 return obj.string_table.get(sym.name);45 return obj.string_table.get(sym.name);
46 },46 },
47 }47 }
48 }48 }
4949
50 pub fn parseSymbolIntoAtom(file: File, wasm_file: *Wasm, index: u32) !AtomIndex {50 pub fn parseSymbolIntoAtom(file: File, wasm_file: *Wasm, index: Symbol.Index) !AtomIndex {
51 return switch (file) {51 return switch (file) {
52 inline else => |obj| obj.parseSymbolIntoAtom(wasm_file, index),52 inline else => |obj| obj.parseSymbolIntoAtom(wasm_file, index),
53 };53 };
...@@ -55,10 +55,10 @@ pub const File = union(enum) {...@@ -55,10 +55,10 @@ pub const File = union(enum) {
5555
56 /// For a given symbol index, find its corresponding import.56 /// For a given symbol index, find its corresponding import.
57 /// Asserts import exists.57 /// Asserts import exists.
58 pub fn import(file: File, symbol_index: u32) types.Import {58 pub fn import(file: File, symbol_index: Symbol.Index) types.Import {
59 return switch (file) {59 return switch (file) {
60 .zig_object => |obj| obj.imports.get(symbol_index).?,60 .zig_object => |obj| obj.imports.get(symbol_index).?,
61 .object => |obj| obj.findImport(obj.symtable[symbol_index]),61 .object => |obj| obj.findImport(obj.symtable[@intFromEnum(symbol_index)]),
62 };62 };
63 }63 }
6464
...@@ -89,14 +89,14 @@ pub const File = union(enum) {...@@ -89,14 +89,14 @@ pub const File = union(enum) {
89 };89 };
90 }90 }
9191
92 pub fn function(file: File, sym_index: u32) std.wasm.Func {92 pub fn function(file: File, sym_index: Symbol.Index) std.wasm.Func {
93 switch (file) {93 switch (file) {
94 .zig_object => |obj| {94 .zig_object => |obj| {
95 const sym = obj.symbols.items[sym_index];95 const sym = obj.symbols.items[@intFromEnum(sym_index)];
96 return obj.functions.items[sym.index];96 return obj.functions.items[sym.index];
97 },97 },
98 .object => |obj| {98 .object => |obj| {
99 const sym = obj.symtable[sym_index];99 const sym = obj.symtable[@intFromEnum(sym_index)];
100 return obj.functions[sym.index - obj.imported_functions_count];100 return obj.functions[sym.index - obj.imported_functions_count];
101 },101 },
102 }102 }