authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-06 11:50:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-06 11:50:23-07:00
log289ba5dfc2dbd5f6f179c49e974b0332f16604a6
tree8f04ab5cf1ffb0c7417e666c739cc89a632a9a52
parent7b7f45dc2a54aa9dfd6263b2654a5ccc8c5d2c82

stage2: rename InternArena to InternPool


3 files changed, 317 insertions(+), 317 deletions(-)

src/InternArena.zig deleted-316
......@@ -1,316 +0,0 @@
1map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
2items: std.MultiArrayList(Item) = .{},
3extra: std.ArrayListUnmanaged(u32) = .{},
4
5const InternArena = @This();
6const std = @import("std");
7const Allocator = std.mem.Allocator;
8const assert = std.debug.assert;
9
10const KeyAdapter = struct {
11 intern_arena: *const InternArena,
12
13 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
14 _ = b_void;
15 return ctx.intern_arena.indexToKey(@intToEnum(Index, b_map_index)).eql(a);
16 }
17
18 pub fn hash(ctx: @This(), a: Key) u32 {
19 _ = ctx;
20 return a.hash();
21 }
22};
23
24pub const Key = union(enum) {
25 int_type: struct {
26 signedness: std.builtin.Signedness,
27 bits: u16,
28 },
29 ptr_type: struct {
30 elem_type: Index,
31 sentinel: Index,
32 alignment: u16,
33 size: std.builtin.Type.Pointer.Size,
34 is_const: bool,
35 is_volatile: bool,
36 is_allowzero: bool,
37 address_space: std.builtin.AddressSpace,
38 },
39 array_type: struct {
40 len: u64,
41 child: Index,
42 sentinel: Index,
43 },
44 vector_type: struct {
45 len: u32,
46 child: Index,
47 },
48 optional_type: struct {
49 payload_type: Index,
50 },
51 error_union_type: struct {
52 error_set_type: Index,
53 payload_type: Index,
54 },
55 simple: Simple,
56
57 pub fn hash(key: Key) u32 {
58 var hasher = std.hash.Wyhash.init(0);
59 switch (key) {
60 .int_type => |int_type| {
61 std.hash.autoHash(&hasher, int_type);
62 },
63 .array_type => |array_type| {
64 std.hash.autoHash(&hasher, array_type);
65 },
66 else => @panic("TODO"),
67 }
68 return @truncate(u32, hasher.final());
69 }
70
71 pub fn eql(a: Key, b: Key) bool {
72 const KeyTag = std.meta.Tag(Key);
73 const a_tag: KeyTag = a;
74 const b_tag: KeyTag = b;
75 if (a_tag != b_tag) return false;
76 switch (a) {
77 .int_type => |a_info| {
78 const b_info = b.int_type;
79 return std.meta.eql(a_info, b_info);
80 },
81 .array_type => |a_info| {
82 const b_info = b.array_type;
83 return std.meta.eql(a_info, b_info);
84 },
85 else => @panic("TODO"),
86 }
87 }
88};
89
90pub const Item = struct {
91 tag: Tag,
92 /// The doc comments on the respective Tag explain how to interpret this.
93 data: u32,
94};
95
96/// Represents an index into `map`. It represents the canonical index
97/// of a `Value` within this `InternArena`. The values are typed.
98/// Two values which have the same type can be equality compared simply
99/// by checking if their indexes are equal, provided they are both in
100/// the same `InternArena`.
101pub const Index = enum(u32) {
102 none = std.math.maxInt(u32),
103 _,
104};
105
106pub const Tag = enum(u8) {
107 /// An integer type.
108 /// data is number of bits
109 type_int_signed,
110 /// An integer type.
111 /// data is number of bits
112 type_int_unsigned,
113 /// An array type.
114 /// data is payload to Array.
115 type_array,
116 /// A type or value that can be represented with only an enum tag.
117 /// data is Simple enum value
118 simple,
119 /// An unsigned integer value that can be represented by u32.
120 /// data is integer value
121 int_u32,
122 /// An unsigned integer value that can be represented by i32.
123 /// data is integer value bitcasted to u32.
124 int_i32,
125 /// A positive integer value that does not fit in 32 bits.
126 /// data is a extra index to BigInt.
127 int_big_positive,
128 /// A negative integer value that does not fit in 32 bits.
129 /// data is a extra index to BigInt.
130 int_big_negative,
131 /// A float value that can be represented by f32.
132 /// data is float value bitcasted to u32.
133 float_f32,
134 /// A float value that can be represented by f64.
135 /// data is payload index to Float64.
136 float_f64,
137 /// A float value that can be represented by f128.
138 /// data is payload index to Float128.
139 float_f128,
140};
141
142pub const Simple = enum(u32) {
143 f16,
144 f32,
145 f64,
146 f80,
147 f128,
148 usize,
149 isize,
150 c_short,
151 c_ushort,
152 c_int,
153 c_uint,
154 c_long,
155 c_ulong,
156 c_longlong,
157 c_ulonglong,
158 c_longdouble,
159 anyopaque,
160 bool,
161 void,
162 type,
163 anyerror,
164 comptime_int,
165 comptime_float,
166 noreturn,
167 @"anyframe",
168 null_type,
169 undefined_type,
170 enum_literal_type,
171 @"undefined",
172 void_value,
173 @"null",
174 bool_true,
175 bool_false,
176};
177
178pub const Array = struct {
179 len: u32,
180 child: Index,
181};
182
183pub fn deinit(ia: *InternArena, gpa: Allocator) void {
184 ia.map.deinit(gpa);
185 ia.items.deinit(gpa);
186 ia.extra.deinit(gpa);
187}
188
189pub fn indexToKey(ia: InternArena, index: Index) Key {
190 const item = ia.items.get(@enumToInt(index));
191 const data = item.data;
192 return switch (item.tag) {
193 .type_int_signed => .{
194 .int_type = .{
195 .signedness = .signed,
196 .bits = @intCast(u16, data),
197 },
198 },
199 .type_int_unsigned => .{
200 .int_type = .{
201 .signedness = .unsigned,
202 .bits = @intCast(u16, data),
203 },
204 },
205 .type_array => {
206 const array_info = ia.extraData(Array, data);
207 return .{ .array_type = .{
208 .len = array_info.len,
209 .child = array_info.child,
210 .sentinel = .none,
211 } };
212 },
213 .simple => .{ .simple = @intToEnum(Simple, data) },
214
215 else => @panic("TODO"),
216 };
217}
218
219pub fn get(ia: *InternArena, gpa: Allocator, key: Key) Allocator.Error!Index {
220 const adapter: KeyAdapter = .{ .intern_arena = ia };
221 const gop = try ia.map.getOrPutAdapted(gpa, key, adapter);
222 if (gop.found_existing) {
223 return @intToEnum(Index, gop.index);
224 }
225 switch (key) {
226 .int_type => |int_type| {
227 const tag: Tag = switch (int_type.signedness) {
228 .signed => .type_int_signed,
229 .unsigned => .type_int_unsigned,
230 };
231 try ia.items.append(gpa, .{
232 .tag = tag,
233 .data = int_type.bits,
234 });
235 },
236 .array_type => |array_type| {
237 const len = @intCast(u32, array_type.len); // TODO have a big_array encoding
238 assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding
239 try ia.items.append(gpa, .{
240 .tag = .type_array,
241 .data = try ia.addExtra(gpa, Array{
242 .len = len,
243 .child = array_type.child,
244 }),
245 });
246 },
247 else => @panic("TODO"),
248 }
249 return @intToEnum(Index, ia.items.len - 1);
250}
251
252fn addExtra(ia: *InternArena, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
253 const fields = std.meta.fields(@TypeOf(extra));
254 try ia.extra.ensureUnusedCapacity(gpa, fields.len);
255 return ia.addExtraAssumeCapacity(extra);
256}
257
258fn addExtraAssumeCapacity(ia: *InternArena, extra: anytype) u32 {
259 const fields = std.meta.fields(@TypeOf(extra));
260 const result = @intCast(u32, ia.extra.items.len);
261 inline for (fields) |field| {
262 ia.extra.appendAssumeCapacity(switch (field.field_type) {
263 u32 => @field(extra, field.name),
264 Index => @enumToInt(@field(extra, field.name)),
265 i32 => @bitCast(u32, @field(extra, field.name)),
266 else => @compileError("bad field type"),
267 });
268 }
269 return result;
270}
271
272fn extraData(ia: InternArena, comptime T: type, index: usize) T {
273 const fields = std.meta.fields(T);
274 var i: usize = index;
275 var result: T = undefined;
276 inline for (fields) |field| {
277 @field(result, field.name) = switch (field.field_type) {
278 u32 => ia.extra.items[i],
279 Index => @intToEnum(Index, ia.extra.items[i]),
280 i32 => @bitCast(i32, ia.extra.items[i]),
281 else => @compileError("bad field type"),
282 };
283 i += 1;
284 }
285 return result;
286}
287
288test "basic usage" {
289 const gpa = std.testing.allocator;
290
291 var ia: InternArena = .{};
292 defer ia.deinit(gpa);
293
294 const i32_type = try ia.get(gpa, .{ .int_type = .{
295 .signedness = .signed,
296 .bits = 32,
297 } });
298 const array_i32 = try ia.get(gpa, .{ .array_type = .{
299 .len = 10,
300 .child = i32_type,
301 .sentinel = .none,
302 } });
303
304 const another_i32_type = try ia.get(gpa, .{ .int_type = .{
305 .signedness = .signed,
306 .bits = 32,
307 } });
308 try std.testing.expect(another_i32_type == i32_type);
309
310 const another_array_i32 = try ia.get(gpa, .{ .array_type = .{
311 .len = 10,
312 .child = i32_type,
313 .sentinel = .none,
314 } });
315 try std.testing.expect(another_array_i32 == array_i32);
316}
src/InternPool.zig created+316
......@@ -0,0 +1,316 @@
1map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
2items: std.MultiArrayList(Item) = .{},
3extra: std.ArrayListUnmanaged(u32) = .{},
4
5const InternPool = @This();
6const std = @import("std");
7const Allocator = std.mem.Allocator;
8const assert = std.debug.assert;
9
10const KeyAdapter = struct {
11 intern_pool: *const InternPool,
12
13 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
14 _ = b_void;
15 return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a);
16 }
17
18 pub fn hash(ctx: @This(), a: Key) u32 {
19 _ = ctx;
20 return a.hash();
21 }
22};
23
24pub const Key = union(enum) {
25 int_type: struct {
26 signedness: std.builtin.Signedness,
27 bits: u16,
28 },
29 ptr_type: struct {
30 elem_type: Index,
31 sentinel: Index,
32 alignment: u16,
33 size: std.builtin.Type.Pointer.Size,
34 is_const: bool,
35 is_volatile: bool,
36 is_allowzero: bool,
37 address_space: std.builtin.AddressSpace,
38 },
39 array_type: struct {
40 len: u64,
41 child: Index,
42 sentinel: Index,
43 },
44 vector_type: struct {
45 len: u32,
46 child: Index,
47 },
48 optional_type: struct {
49 payload_type: Index,
50 },
51 error_union_type: struct {
52 error_set_type: Index,
53 payload_type: Index,
54 },
55 simple: Simple,
56
57 pub fn hash(key: Key) u32 {
58 var hasher = std.hash.Wyhash.init(0);
59 switch (key) {
60 .int_type => |int_type| {
61 std.hash.autoHash(&hasher, int_type);
62 },
63 .array_type => |array_type| {
64 std.hash.autoHash(&hasher, array_type);
65 },
66 else => @panic("TODO"),
67 }
68 return @truncate(u32, hasher.final());
69 }
70
71 pub fn eql(a: Key, b: Key) bool {
72 const KeyTag = std.meta.Tag(Key);
73 const a_tag: KeyTag = a;
74 const b_tag: KeyTag = b;
75 if (a_tag != b_tag) return false;
76 switch (a) {
77 .int_type => |a_info| {
78 const b_info = b.int_type;
79 return std.meta.eql(a_info, b_info);
80 },
81 .array_type => |a_info| {
82 const b_info = b.array_type;
83 return std.meta.eql(a_info, b_info);
84 },
85 else => @panic("TODO"),
86 }
87 }
88};
89
90pub const Item = struct {
91 tag: Tag,
92 /// The doc comments on the respective Tag explain how to interpret this.
93 data: u32,
94};
95
96/// Represents an index into `map`. It represents the canonical index
97/// of a `Value` within this `InternPool`. The values are typed.
98/// Two values which have the same type can be equality compared simply
99/// by checking if their indexes are equal, provided they are both in
100/// the same `InternPool`.
101pub const Index = enum(u32) {
102 none = std.math.maxInt(u32),
103 _,
104};
105
106pub const Tag = enum(u8) {
107 /// An integer type.
108 /// data is number of bits
109 type_int_signed,
110 /// An integer type.
111 /// data is number of bits
112 type_int_unsigned,
113 /// An array type.
114 /// data is payload to Array.
115 type_array,
116 /// A type or value that can be represented with only an enum tag.
117 /// data is Simple enum value
118 simple,
119 /// An unsigned integer value that can be represented by u32.
120 /// data is integer value
121 int_u32,
122 /// An unsigned integer value that can be represented by i32.
123 /// data is integer value bitcasted to u32.
124 int_i32,
125 /// A positive integer value that does not fit in 32 bits.
126 /// data is a extra index to BigInt.
127 int_big_positive,
128 /// A negative integer value that does not fit in 32 bits.
129 /// data is a extra index to BigInt.
130 int_big_negative,
131 /// A float value that can be represented by f32.
132 /// data is float value bitcasted to u32.
133 float_f32,
134 /// A float value that can be represented by f64.
135 /// data is payload index to Float64.
136 float_f64,
137 /// A float value that can be represented by f128.
138 /// data is payload index to Float128.
139 float_f128,
140};
141
142pub const Simple = enum(u32) {
143 f16,
144 f32,
145 f64,
146 f80,
147 f128,
148 usize,
149 isize,
150 c_short,
151 c_ushort,
152 c_int,
153 c_uint,
154 c_long,
155 c_ulong,
156 c_longlong,
157 c_ulonglong,
158 c_longdouble,
159 anyopaque,
160 bool,
161 void,
162 type,
163 anyerror,
164 comptime_int,
165 comptime_float,
166 noreturn,
167 @"anyframe",
168 null_type,
169 undefined_type,
170 enum_literal_type,
171 @"undefined",
172 void_value,
173 @"null",
174 bool_true,
175 bool_false,
176};
177
178pub const Array = struct {
179 len: u32,
180 child: Index,
181};
182
183pub fn deinit(ip: *InternPool, gpa: Allocator) void {
184 ip.map.deinit(gpa);
185 ip.items.deinit(gpa);
186 ip.extra.deinit(gpa);
187}
188
189pub fn indexToKey(ip: InternPool, index: Index) Key {
190 const item = ip.items.get(@enumToInt(index));
191 const data = item.data;
192 return switch (item.tag) {
193 .type_int_signed => .{
194 .int_type = .{
195 .signedness = .signed,
196 .bits = @intCast(u16, data),
197 },
198 },
199 .type_int_unsigned => .{
200 .int_type = .{
201 .signedness = .unsigned,
202 .bits = @intCast(u16, data),
203 },
204 },
205 .type_array => {
206 const array_info = ip.extraData(Array, data);
207 return .{ .array_type = .{
208 .len = array_info.len,
209 .child = array_info.child,
210 .sentinel = .none,
211 } };
212 },
213 .simple => .{ .simple = @intToEnum(Simple, data) },
214
215 else => @panic("TODO"),
216 };
217}
218
219pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
220 const adapter: KeyAdapter = .{ .intern_pool = ip };
221 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
222 if (gop.found_existing) {
223 return @intToEnum(Index, gop.index);
224 }
225 switch (key) {
226 .int_type => |int_type| {
227 const tag: Tag = switch (int_type.signedness) {
228 .signed => .type_int_signed,
229 .unsigned => .type_int_unsigned,
230 };
231 try ip.items.append(gpa, .{
232 .tag = tag,
233 .data = int_type.bits,
234 });
235 },
236 .array_type => |array_type| {
237 const len = @intCast(u32, array_type.len); // TODO have a big_array encoding
238 assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding
239 try ip.items.append(gpa, .{
240 .tag = .type_array,
241 .data = try ip.addExtra(gpa, Array{
242 .len = len,
243 .child = array_type.child,
244 }),
245 });
246 },
247 else => @panic("TODO"),
248 }
249 return @intToEnum(Index, ip.items.len - 1);
250}
251
252fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
253 const fields = std.meta.fields(@TypeOf(extra));
254 try ip.extra.ensureUnusedCapacity(gpa, fields.len);
255 return ip.addExtraAssumeCapacity(extra);
256}
257
258fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
259 const fields = std.meta.fields(@TypeOf(extra));
260 const result = @intCast(u32, ip.extra.items.len);
261 inline for (fields) |field| {
262 ip.extra.appendAssumeCapacity(switch (field.field_type) {
263 u32 => @field(extra, field.name),
264 Index => @enumToInt(@field(extra, field.name)),
265 i32 => @bitCast(u32, @field(extra, field.name)),
266 else => @compileError("bad field type"),
267 });
268 }
269 return result;
270}
271
272fn extraData(ip: InternPool, comptime T: type, index: usize) T {
273 const fields = std.meta.fields(T);
274 var i: usize = index;
275 var result: T = undefined;
276 inline for (fields) |field| {
277 @field(result, field.name) = switch (field.field_type) {
278 u32 => ip.extra.items[i],
279 Index => @intToEnum(Index, ip.extra.items[i]),
280 i32 => @bitCast(i32, ip.extra.items[i]),
281 else => @compileError("bad field type"),
282 };
283 i += 1;
284 }
285 return result;
286}
287
288test "basic usage" {
289 const gpa = std.testing.allocator;
290
291 var ip: InternPool = .{};
292 defer ip.deinit(gpa);
293
294 const i32_type = try ip.get(gpa, .{ .int_type = .{
295 .signedness = .signed,
296 .bits = 32,
297 } });
298 const array_i32 = try ip.get(gpa, .{ .array_type = .{
299 .len = 10,
300 .child = i32_type,
301 .sentinel = .none,
302 } });
303
304 const another_i32_type = try ip.get(gpa, .{ .int_type = .{
305 .signedness = .signed,
306 .bits = 32,
307 } });
308 try std.testing.expect(another_i32_type == i32_type);
309
310 const another_array_i32 = try ip.get(gpa, .{ .array_type = .{
311 .len = 10,
312 .child = i32_type,
313 .sentinel = .none,
314 } });
315 try std.testing.expect(another_array_i32 == array_i32);
316}
src/link/Dwarf.zig+1-1
......@@ -39,7 +39,7 @@ atom_last: ?*Atom = null,
3939
4040abbrev_table_offset: ?u64 = null,
4141
42/// TODO replace with InternArena
42/// TODO replace with InternPool
4343/// Table of debug symbol names.
4444strtab: std.ArrayListUnmanaged(u8) = .{},
4545