| author | |
| committer | |
| log | 289ba5dfc2dbd5f6f179c49e974b0332f16604a6 |
| tree | 8f04ab5cf1ffb0c7417e666c739cc89a632a9a52 |
| parent | 7b7f45dc2a54aa9dfd6263b2654a5ccc8c5d2c82 |
3 files changed, 317 insertions(+), 317 deletions(-)
src/InternArena.zig deleted-316| ... | @@ -1,316 +0,0 @@ | ||
| 1 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | ||
| 2 | items: std.MultiArrayList(Item) = .{}, | ||
| 3 | extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 4 | |||
| 5 | const InternArena = @This(); | ||
| 6 | const std = @import("std"); | ||
| 7 | const Allocator = std.mem.Allocator; | ||
| 8 | const assert = std.debug.assert; | ||
| 9 | |||
| 10 | const 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 | |||
| 24 | pub 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 | |||
| 90 | pub 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`. | ||
| 101 | pub const Index = enum(u32) { | ||
| 102 | none = std.math.maxInt(u32), | ||
| 103 | _, | ||
| 104 | }; | ||
| 105 | |||
| 106 | pub 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 | |||
| 142 | pub 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 | |||
| 178 | pub const Array = struct { | ||
| 179 | len: u32, | ||
| 180 | child: Index, | ||
| 181 | }; | ||
| 182 | |||
| 183 | pub fn deinit(ia: *InternArena, gpa: Allocator) void { | ||
| 184 | ia.map.deinit(gpa); | ||
| 185 | ia.items.deinit(gpa); | ||
| 186 | ia.extra.deinit(gpa); | ||
| 187 | } | ||
| 188 | |||
| 189 | pub 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 | |||
| 219 | pub 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 | |||
| 252 | fn 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 | |||
| 258 | fn 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 | |||
| 272 | fn 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 | |||
| 288 | test "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 @@ | ||
| 1 | map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, | ||
| 2 | items: std.MultiArrayList(Item) = .{}, | ||
| 3 | extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 4 | |||
| 5 | const InternPool = @This(); | ||
| 6 | const std = @import("std"); | ||
| 7 | const Allocator = std.mem.Allocator; | ||
| 8 | const assert = std.debug.assert; | ||
| 9 | |||
| 10 | const 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 | |||
| 24 | pub 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 | |||
| 90 | pub 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`. | ||
| 101 | pub const Index = enum(u32) { | ||
| 102 | none = std.math.maxInt(u32), | ||
| 103 | _, | ||
| 104 | }; | ||
| 105 | |||
| 106 | pub 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 | |||
| 142 | pub 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 | |||
| 178 | pub const Array = struct { | ||
| 179 | len: u32, | ||
| 180 | child: Index, | ||
| 181 | }; | ||
| 182 | |||
| 183 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ||
| 184 | ip.map.deinit(gpa); | ||
| 185 | ip.items.deinit(gpa); | ||
| 186 | ip.extra.deinit(gpa); | ||
| 187 | } | ||
| 188 | |||
| 189 | pub 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 | |||
| 219 | pub 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 | |||
| 252 | fn 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 | |||
| 258 | fn 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 | |||
| 272 | fn 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 | |||
| 288 | test "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, | ... | @@ -39,7 +39,7 @@ atom_last: ?*Atom = null, |
| 39 | 39 | ||
| 40 | abbrev_table_offset: ?u64 = null, | 40 | abbrev_table_offset: ?u64 = null, |
| 41 | 41 | ||
| 42 | /// TODO replace with InternArena | 42 | /// TODO replace with InternPool |
| 43 | /// Table of debug symbol names. | 43 | /// Table of debug symbol names. |
| 44 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 44 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 45 | 45 |