aboutsummaryrefslogtreecommitdiff
path: root/src/link/table_section.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-04-22 13:39:07 +0200
committerGitHub <noreply@github.com>2023-04-22 13:39:07 +0200
commitc4a63389e4eefb78c1ee2028047447094bb864dc (patch)
tree95edea0e36efa81c2a6ea8d0574feeb5ba90f25e /src/link/table_section.zig
parent68e4a5784791f733774e161b72a283b69a75b0de (diff)
parent14dfbbc21365131c7ac85f08f543058f43fca0c2 (diff)
downloadzig-c4a63389e4eefb78c1ee2028047447094bb864dc.tar.gz
zig-c4a63389e4eefb78c1ee2028047447094bb864dc.zip
Merge pull request #15371 from ziglang/better-elf
link: make GOT (and other synthetic sections) handling common across linkers
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..891f3b1a50
--- /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("TableSection:\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;