aboutsummaryrefslogtreecommitdiff
path: root/src/link/Wasm/Atom.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2024-02-09 16:36:09 +0100
committerLuuk de Gram <luuk@degram.dev>2024-02-29 15:24:07 +0100
commit5ef832133895fd69fc8378463b86759eaab6913a (patch)
tree08bc27cd8f20de4c928ca0bdc411b6c8d59be465 /src/link/Wasm/Atom.zig
parentc99ef23862573269ae4052bd2236f9803f9e36a2 (diff)
downloadzig-5ef832133895fd69fc8378463b86759eaab6913a.tar.gz
zig-5ef832133895fd69fc8378463b86759eaab6913a.zip
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.
Diffstat (limited to 'src/link/Wasm/Atom.zig')
-rw-r--r--src/link/Wasm/Atom.zig30
1 files changed, 13 insertions, 17 deletions
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index ade66b687f..77d0790086 100644
--- a/src/link/Wasm/Atom.zig
+++ b/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;