aboutsummaryrefslogtreecommitdiff
path: root/src/link/Wasm/Atom.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-02-01 18:55:35 +0100
committerLuuk de Gram <luuk@degram.dev>2023-02-01 19:10:56 +0100
commit46f54b23ae604c3f99f51ca719d9085530f6b59c (patch)
tree66547a2f4b33e876afb0b29ea6799795959699fb /src/link/Wasm/Atom.zig
parent1aa0f8aa2f382fb56639ea6833a62c4b8b031247 (diff)
downloadzig-46f54b23ae604c3f99f51ca719d9085530f6b59c.tar.gz
zig-46f54b23ae604c3f99f51ca719d9085530f6b59c.zip
link: make Wasm atoms fully owned by the linker
Diffstat (limited to 'src/link/Wasm/Atom.zig')
-rw-r--r--src/link/Wasm/Atom.zig44
1 files changed, 20 insertions, 24 deletions
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index 554f98b5ca..e719f8dfcc 100644
--- a/src/link/Wasm/Atom.zig
+++ b/src/link/Wasm/Atom.zig
@@ -29,14 +29,17 @@ file: ?u16,
/// Next atom in relation to this atom.
/// When null, this atom is the last atom
-next: ?*Atom,
+next: ?Atom.Index,
/// Previous atom in relation to this atom.
/// is null when this atom is the first in its order
-prev: ?*Atom,
+prev: ?Atom.Index,
/// 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) = .{},
+locals: std.ArrayListUnmanaged(Atom.Index) = .{},
+
+/// Alias to an unsigned 32-bit integer
+pub const Index = u32;
/// Represents a default empty wasm `Atom`
pub const empty: Atom = .{
@@ -50,14 +53,12 @@ pub const empty: Atom = .{
};
/// Frees all resources owned by this `Atom`.
-pub fn deinit(atom: *Atom, gpa: Allocator) void {
+pub fn deinit(atom: *Atom, wasm: *Wasm) void {
+ const gpa = wasm.base.allocator;
atom.relocs.deinit(gpa);
atom.code.deinit(gpa);
-
- for (atom.locals.items) |*local| {
- local.deinit(gpa);
- }
atom.locals.deinit(gpa);
+ atom.* = undefined;
}
/// Sets the length of relocations and code to '0',
@@ -78,24 +79,11 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio
});
}
-/// Returns the first `Atom` from a given atom
-pub fn getFirst(atom: *Atom) *Atom {
- var tmp = atom;
- while (tmp.prev) |prev| tmp = prev;
- return tmp;
-}
-
/// Returns the location of the symbol that represents this `Atom`
pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
return .{ .file = atom.file, .index = atom.sym_index };
}
-pub fn ensureInitialized(atom: *Atom, wasm_bin: *Wasm) !void {
- if (atom.getSymbolIndex() != null) return; // already initialized
- atom.sym_index = try wasm_bin.allocateSymbol();
- try wasm_bin.symbol_atom.putNoClobber(wasm_bin.base.allocator, atom.symbolLoc(), atom);
-}
-
pub fn getSymbolIndex(atom: Atom) ?u32 {
if (atom.sym_index == 0) return null;
return atom.sym_index;
@@ -198,20 +186,28 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
if (symbol.isUndefined()) {
return 0;
}
- const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
+ const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {
+ // this can only occur during incremental-compilation when a relocation
+ // still points to a freed decl. It is fine to emit the value 0 here
+ // as no actual code will point towards it.
+ return 0;
+ };
+ const target_atom = wasm_bin.getAtom(target_atom_index);
const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol));
return @intCast(u32, va + relocation.addend);
},
.R_WASM_EVENT_INDEX_LEB => return symbol.index,
.R_WASM_SECTION_OFFSET_I32 => {
- const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
+ const target_atom_index = wasm_bin.symbol_atom.get(target_loc).?;
+ const target_atom = wasm_bin.getAtom(target_atom_index);
const rel_value = @intCast(i32, target_atom.offset) + relocation.addend;
return @intCast(u32, rel_value);
},
.R_WASM_FUNCTION_OFFSET_I32 => {
- const target_atom = wasm_bin.symbol_atom.get(target_loc) orelse {
+ const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse {
return @bitCast(u32, @as(i32, -1));
};
+ const target_atom = wasm_bin.getAtom(target_atom_index);
const offset: u32 = 11 + Wasm.getULEB128Size(target_atom.size); // Header (11 bytes fixed-size) + body size (leb-encoded)
const rel_value = @intCast(i32, target_atom.offset + offset) + relocation.addend;
return @intCast(u32, rel_value);