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 }