lib/choir/src/backends/artifact/model/linkage/owner.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const linkage = @import("root.zig");
3
4 const Allocator = std.mem.Allocator;
5
6 pub const Linkage = struct {
7 allocator: Allocator,
8 required_symbols: std.ArrayListUnmanaged(linkage.Symbol) = .empty,
9 provided_symbols: std.ArrayListUnmanaged(linkage.Symbol) = .empty,
10 relocations: std.ArrayListUnmanaged(linkage.Relocation) = .empty,
11
12 pub fn init(allocator: Allocator) Linkage {
13 return .{ .allocator = allocator };
14 }
15
16 pub fn addRequired(self: *Linkage, symbol: linkage.Symbol) Allocator.Error!void {
17 try self.required_symbols.ensureTotalCapacity(self.allocator, self.required_symbols.items.len + 1);
18 const owned = try symbol.dupe(self.allocator);
19 self.required_symbols.appendAssumeCapacity(owned);
20 }
21
22 pub fn addProvided(self: *Linkage, symbol: linkage.Symbol) Allocator.Error!void {
23 try self.provided_symbols.ensureTotalCapacity(self.allocator, self.provided_symbols.items.len + 1);
24 const owned = try symbol.dupe(self.allocator);
25 self.provided_symbols.appendAssumeCapacity(owned);
26 }
27
28 pub fn addRelocation(self: *Linkage, relocation: linkage.Relocation) Allocator.Error!void {
29 try self.relocations.ensureTotalCapacity(self.allocator, self.relocations.items.len + 1);
30 const owned = try relocation.dupe(self.allocator);
31 self.relocations.appendAssumeCapacity(owned);
32 }
33
34 pub fn hasRequired(self: Linkage, name: []const u8) bool {
35 return has(self.required_symbols.items, name);
36 }
37
38 pub fn hasProvided(self: Linkage, name: []const u8) bool {
39 return has(self.provided_symbols.items, name);
40 }
41
42 pub fn cloneInto(self: Linkage, target: *Linkage) Allocator.Error!void {
43 for (self.required_symbols.items) |symbol| try target.addRequired(symbol);
44 for (self.provided_symbols.items) |symbol| try target.addProvided(symbol);
45 for (self.relocations.items) |relocation| try target.addRelocation(relocation);
46 }
47
48 pub fn deinit(self: *Linkage) void {
49 for (self.required_symbols.items) |symbol| symbol.deinit(self.allocator);
50 self.required_symbols.deinit(self.allocator);
51 for (self.provided_symbols.items) |symbol| symbol.deinit(self.allocator);
52 self.provided_symbols.deinit(self.allocator);
53 for (self.relocations.items) |relocation| relocation.deinit(self.allocator);
54 self.relocations.deinit(self.allocator);
55 self.* = undefined;
56 }
57
58 pub fn eql(self: Linkage, other: Linkage) bool {
59 if (self.required_symbols.items.len != other.required_symbols.items.len or
60 self.provided_symbols.items.len != other.provided_symbols.items.len or
61 self.relocations.items.len != other.relocations.items.len)
62 {
63 return false;
64 }
65 for (self.required_symbols.items, other.required_symbols.items) |left, right| {
66 if (!left.eql(right)) return false;
67 }
68 for (self.provided_symbols.items, other.provided_symbols.items) |left, right| {
69 if (!left.eql(right)) return false;
70 }
71 for (self.relocations.items, other.relocations.items) |left, right| {
72 if (!left.eql(right)) return false;
73 }
74 return true;
75 }
76 };
77
78 fn has(symbols: []const linkage.Symbol, name: []const u8) bool {
79 for (symbols) |symbol| {
80 if (std.mem.eql(u8, symbol.name, name)) return true;
81 }
82 return false;
83 }