lib/choir/src/backends/artifact/model/metadata.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const Allocator = std.mem.Allocator;
3 const artifact = @import("root.zig");
4 const slice = artifact.slice;
5
6 pub const Architecture = enum(u8) {
7 unknown = 1,
8 x86_64 = 2,
9 aarch64 = 3,
10 wasm = 4,
11 };
12
13 pub const Endianness = enum(u8) {
14 little = 1,
15 big = 2,
16 };
17
18 pub const ArtifactKind = enum(u8) {
19 unknown = 1,
20 machine_code = 2,
21 object_file = 3,
22 webassembly_module = 4,
23 assembly = 5,
24 source_text = 6,
25 debug_info = 7,
26 container = 8,
27 };
28
29 pub const Target = struct {
30 architecture: Architecture = .unknown,
31 triple: ?[]const u8 = null,
32 vendor: ?[]const u8 = null,
33 os: ?[]const u8 = null,
34 environment: ?[]const u8 = null,
35 cpu: ?[]const u8 = null,
36 features: []const []const u8 = &.{},
37
38 pub fn dupe(self: Target, allocator: Allocator) Allocator.Error!Target {
39 var out = Target{ .architecture = self.architecture };
40 errdefer out.deinit(allocator);
41 out.triple = try slice.dupeOptional(allocator, self.triple);
42 out.vendor = try slice.dupeOptional(allocator, self.vendor);
43 out.os = try slice.dupeOptional(allocator, self.os);
44 out.environment = try slice.dupeOptional(allocator, self.environment);
45 out.cpu = try slice.dupeOptional(allocator, self.cpu);
46 out.features = try slice.dupeList(allocator, self.features);
47 return out;
48 }
49
50 pub fn deinit(self: *Target, allocator: Allocator) void {
51 slice.freeOptional(allocator, self.triple);
52 slice.freeOptional(allocator, self.vendor);
53 slice.freeOptional(allocator, self.os);
54 slice.freeOptional(allocator, self.environment);
55 slice.freeOptional(allocator, self.cpu);
56 slice.freeList(allocator, self.features);
57 self.* = .{};
58 }
59
60 pub fn eql(self: Target, other: Target) bool {
61 if (self.architecture != other.architecture or
62 !slice.optionalEqual(self.triple, other.triple) or
63 !slice.optionalEqual(self.vendor, other.vendor) or
64 !slice.optionalEqual(self.os, other.os) or
65 !slice.optionalEqual(self.environment, other.environment) or
66 !slice.optionalEqual(self.cpu, other.cpu) or
67 self.features.len != other.features.len)
68 {
69 return false;
70 }
71 for (self.features, other.features) |left, right| {
72 if (!std.mem.eql(u8, left, right)) return false;
73 }
74 return true;
75 }
76 };
77
78 pub const Abi = struct {
79 name: ?[]const u8 = null,
80 calling_convention: ?[]const u8 = null,
81 object_format: ?[]const u8 = null,
82 pointer_width_bits: ?u16 = null,
83 endianness: ?Endianness = null,
84
85 pub fn dupe(self: Abi, allocator: Allocator) Allocator.Error!Abi {
86 var out = Abi{
87 .pointer_width_bits = self.pointer_width_bits,
88 .endianness = self.endianness,
89 };
90 errdefer out.deinit(allocator);
91 out.name = try slice.dupeOptional(allocator, self.name);
92 out.calling_convention = try slice.dupeOptional(allocator, self.calling_convention);
93 out.object_format = try slice.dupeOptional(allocator, self.object_format);
94 return out;
95 }
96
97 pub fn deinit(self: *Abi, allocator: Allocator) void {
98 slice.freeOptional(allocator, self.name);
99 slice.freeOptional(allocator, self.calling_convention);
100 slice.freeOptional(allocator, self.object_format);
101 self.* = .{};
102 }
103
104 pub fn eql(self: Abi, other: Abi) bool {
105 return slice.optionalEqual(self.name, other.name) and
106 slice.optionalEqual(self.calling_convention, other.calling_convention) and
107 slice.optionalEqual(self.object_format, other.object_format) and
108 self.pointer_width_bits == other.pointer_width_bits and
109 self.endianness == other.endianness;
110 }
111 };
112
113 pub const Metadata = struct {
114 kind: ArtifactKind = .unknown,
115 producer: ?[]const u8 = null,
116 target: Target = .{},
117 abi: Abi = .{},
118
119 pub fn dupe(self: Metadata, allocator: Allocator) Allocator.Error!Metadata {
120 var out = Metadata{ .kind = self.kind };
121 errdefer out.deinit(allocator);
122 out.producer = try slice.dupeOptional(allocator, self.producer);
123 out.target = try self.target.dupe(allocator);
124 out.abi = try self.abi.dupe(allocator);
125 return out;
126 }
127
128 pub fn deinit(self: *Metadata, allocator: Allocator) void {
129 slice.freeOptional(allocator, self.producer);
130 self.target.deinit(allocator);
131 self.abi.deinit(allocator);
132 self.* = .{};
133 }
134
135 pub fn eql(self: Metadata, other: Metadata) bool {
136 return self.kind == other.kind and
137 slice.optionalEqual(self.producer, other.producer) and
138 self.target.eql(other.target) and
139 self.abi.eql(other.abi);
140 }
141 };