aboutsummaryrefslogtreecommitdiff
path: root/src/link/table_section.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-04-18 17:11:27 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-04-21 22:44:27 +0200
commit8e3100ae02fef20ce08a679f6212b3d673a5c8f0 (patch)
tree899bb927fc750896681134079364610c4843ed20 /src/link/table_section.zig
parent8a3ad3f6204747b5621e14cae0564ee7929a7cd8 (diff)
downloadzig-8e3100ae02fef20ce08a679f6212b3d673a5c8f0.tar.gz
zig-8e3100ae02fef20ce08a679f6212b3d673a5c8f0.zip
elf: make TableSection a generic construct
Diffstat (limited to 'src/link/table_section.zig')
-rw-r--r--src/link/table_section.zig65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/link/table_section.zig b/src/link/table_section.zig
new file mode 100644
index 0000000000..4d5838adb9
--- /dev/null
+++ b/src/link/table_section.zig
@@ -0,0 +1,65 @@
+pub fn TableSection(comptime Entry: type) type {
+ return struct {
+ entries: std.ArrayListUnmanaged(Entry) = .{},
+ free_list: std.ArrayListUnmanaged(Index) = .{},
+ lookup: std.AutoHashMapUnmanaged(Entry, Index) = .{},
+
+ pub fn deinit(self: *Self, allocator: Allocator) void {
+ self.entries.deinit(allocator);
+ self.free_list.deinit(allocator);
+ self.lookup.deinit(allocator);
+ }
+
+ pub fn allocateEntry(self: *Self, allocator: Allocator, entry: Entry) Allocator.Error!Index {
+ try self.entries.ensureUnusedCapacity(allocator, 1);
+ const index = blk: {
+ if (self.free_list.popOrNull()) |index| {
+ log.debug(" (reusing entry index {d})", .{index});
+ break :blk index;
+ } else {
+ log.debug(" (allocating entry at index {d})", .{self.entries.items.len});
+ const index = @intCast(u32, self.entries.items.len);
+ _ = self.entries.addOneAssumeCapacity();
+ break :blk index;
+ }
+ };
+ self.entries.items[index] = entry;
+ try self.lookup.putNoClobber(allocator, entry, index);
+ return index;
+ }
+
+ pub fn freeEntry(self: *Self, allocator: Allocator, entry: Entry) void {
+ const index = self.lookup.get(entry) orelse return;
+ self.free_list.append(allocator, index) catch {};
+ self.entries.items[index] = undefined;
+ _ = self.lookup.remove(entry);
+ }
+
+ pub fn count(self: Self) usize {
+ return self.entries.items.len;
+ }
+
+ pub fn format(
+ self: Self,
+ comptime unused_format_string: []const u8,
+ options: std.fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ _ = options;
+ comptime assert(unused_format_string.len == 0);
+ try writer.writeAll("SectionTable:\n");
+ for (self.entries.items, 0..) |entry, i| {
+ try writer.print(" {d} => {}\n", .{ i, entry });
+ }
+ }
+
+ const Self = @This();
+ pub const Index = u32;
+ };
+}
+
+const std = @import("std");
+const assert = std.debug.assert;
+const log = std.log.scoped(.link);
+
+const Allocator = std.mem.Allocator;