zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 289ba5dfc2dbd5f6f179c49e974b0332f16604a6 (tree)
parent 7b7f45dc2a54aa9dfd6263b2654a5ccc8c5d2c82
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Wed,  6 Apr 2022 11:50:23 -0700

stage2: rename InternArena to InternPool

Diffstat:
Dsrc/InternArena.zig | 316-------------------------------------------------------------------------------
Asrc/InternPool.zig | 316+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/link/Dwarf.zig | 2+-
3 files changed, 317 insertions(+), 317 deletions(-)

diff --git a/src/InternArena.zig b/src/InternArena.zig @@ -1,316 +0,0 @@ -map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, -items: std.MultiArrayList(Item) = .{}, -extra: std.ArrayListUnmanaged(u32) = .{}, - -const InternArena = @This(); -const std = @import("std"); -const Allocator = std.mem.Allocator; -const assert = std.debug.assert; - -const KeyAdapter = struct { - intern_arena: *const InternArena, - - pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool { - _ = b_void; - return ctx.intern_arena.indexToKey(@intToEnum(Index, b_map_index)).eql(a); - } - - pub fn hash(ctx: @This(), a: Key) u32 { - _ = ctx; - return a.hash(); - } -}; - -pub const Key = union(enum) { - int_type: struct { - signedness: std.builtin.Signedness, - bits: u16, - }, - ptr_type: struct { - elem_type: Index, - sentinel: Index, - alignment: u16, - size: std.builtin.Type.Pointer.Size, - is_const: bool, - is_volatile: bool, - is_allowzero: bool, - address_space: std.builtin.AddressSpace, - }, - array_type: struct { - len: u64, - child: Index, - sentinel: Index, - }, - vector_type: struct { - len: u32, - child: Index, - }, - optional_type: struct { - payload_type: Index, - }, - error_union_type: struct { - error_set_type: Index, - payload_type: Index, - }, - simple: Simple, - - pub fn hash(key: Key) u32 { - var hasher = std.hash.Wyhash.init(0); - switch (key) { - .int_type => |int_type| { - std.hash.autoHash(&hasher, int_type); - }, - .array_type => |array_type| { - std.hash.autoHash(&hasher, array_type); - }, - else => @panic("TODO"), - } - return @truncate(u32, hasher.final()); - } - - pub fn eql(a: Key, b: Key) bool { - const KeyTag = std.meta.Tag(Key); - const a_tag: KeyTag = a; - const b_tag: KeyTag = b; - if (a_tag != b_tag) return false; - switch (a) { - .int_type => |a_info| { - const b_info = b.int_type; - return std.meta.eql(a_info, b_info); - }, - .array_type => |a_info| { - const b_info = b.array_type; - return std.meta.eql(a_info, b_info); - }, - else => @panic("TODO"), - } - } -}; - -pub const Item = struct { - tag: Tag, - /// The doc comments on the respective Tag explain how to interpret this. - data: u32, -}; - -/// Represents an index into `map`. It represents the canonical index -/// of a `Value` within this `InternArena`. The values are typed. -/// Two values which have the same type can be equality compared simply -/// by checking if their indexes are equal, provided they are both in -/// the same `InternArena`. -pub const Index = enum(u32) { - none = std.math.maxInt(u32), - _, -}; - -pub const Tag = enum(u8) { - /// An integer type. - /// data is number of bits - type_int_signed, - /// An integer type. - /// data is number of bits - type_int_unsigned, - /// An array type. - /// data is payload to Array. - type_array, - /// A type or value that can be represented with only an enum tag. - /// data is Simple enum value - simple, - /// An unsigned integer value that can be represented by u32. - /// data is integer value - int_u32, - /// An unsigned integer value that can be represented by i32. - /// data is integer value bitcasted to u32. - int_i32, - /// A positive integer value that does not fit in 32 bits. - /// data is a extra index to BigInt. - int_big_positive, - /// A negative integer value that does not fit in 32 bits. - /// data is a extra index to BigInt. - int_big_negative, - /// A float value that can be represented by f32. - /// data is float value bitcasted to u32. - float_f32, - /// A float value that can be represented by f64. - /// data is payload index to Float64. - float_f64, - /// A float value that can be represented by f128. - /// data is payload index to Float128. - float_f128, -}; - -pub const Simple = enum(u32) { - f16, - f32, - f64, - f80, - f128, - usize, - isize, - c_short, - c_ushort, - c_int, - c_uint, - c_long, - c_ulong, - c_longlong, - c_ulonglong, - c_longdouble, - anyopaque, - bool, - void, - type, - anyerror, - comptime_int, - comptime_float, - noreturn, - @"anyframe", - null_type, - undefined_type, - enum_literal_type, - @"undefined", - void_value, - @"null", - bool_true, - bool_false, -}; - -pub const Array = struct { - len: u32, - child: Index, -}; - -pub fn deinit(ia: *InternArena, gpa: Allocator) void { - ia.map.deinit(gpa); - ia.items.deinit(gpa); - ia.extra.deinit(gpa); -} - -pub fn indexToKey(ia: InternArena, index: Index) Key { - const item = ia.items.get(@enumToInt(index)); - const data = item.data; - return switch (item.tag) { - .type_int_signed => .{ - .int_type = .{ - .signedness = .signed, - .bits = @intCast(u16, data), - }, - }, - .type_int_unsigned => .{ - .int_type = .{ - .signedness = .unsigned, - .bits = @intCast(u16, data), - }, - }, - .type_array => { - const array_info = ia.extraData(Array, data); - return .{ .array_type = .{ - .len = array_info.len, - .child = array_info.child, - .sentinel = .none, - } }; - }, - .simple => .{ .simple = @intToEnum(Simple, data) }, - - else => @panic("TODO"), - }; -} - -pub fn get(ia: *InternArena, gpa: Allocator, key: Key) Allocator.Error!Index { - const adapter: KeyAdapter = .{ .intern_arena = ia }; - const gop = try ia.map.getOrPutAdapted(gpa, key, adapter); - if (gop.found_existing) { - return @intToEnum(Index, gop.index); - } - switch (key) { - .int_type => |int_type| { - const tag: Tag = switch (int_type.signedness) { - .signed => .type_int_signed, - .unsigned => .type_int_unsigned, - }; - try ia.items.append(gpa, .{ - .tag = tag, - .data = int_type.bits, - }); - }, - .array_type => |array_type| { - const len = @intCast(u32, array_type.len); // TODO have a big_array encoding - assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding - try ia.items.append(gpa, .{ - .tag = .type_array, - .data = try ia.addExtra(gpa, Array{ - .len = len, - .child = array_type.child, - }), - }); - }, - else => @panic("TODO"), - } - return @intToEnum(Index, ia.items.len - 1); -} - -fn addExtra(ia: *InternArena, gpa: Allocator, extra: anytype) Allocator.Error!u32 { - const fields = std.meta.fields(@TypeOf(extra)); - try ia.extra.ensureUnusedCapacity(gpa, fields.len); - return ia.addExtraAssumeCapacity(extra); -} - -fn addExtraAssumeCapacity(ia: *InternArena, extra: anytype) u32 { - const fields = std.meta.fields(@TypeOf(extra)); - const result = @intCast(u32, ia.extra.items.len); - inline for (fields) |field| { - ia.extra.appendAssumeCapacity(switch (field.field_type) { - u32 => @field(extra, field.name), - Index => @enumToInt(@field(extra, field.name)), - i32 => @bitCast(u32, @field(extra, field.name)), - else => @compileError("bad field type"), - }); - } - return result; -} - -fn extraData(ia: InternArena, comptime T: type, index: usize) T { - const fields = std.meta.fields(T); - var i: usize = index; - var result: T = undefined; - inline for (fields) |field| { - @field(result, field.name) = switch (field.field_type) { - u32 => ia.extra.items[i], - Index => @intToEnum(Index, ia.extra.items[i]), - i32 => @bitCast(i32, ia.extra.items[i]), - else => @compileError("bad field type"), - }; - i += 1; - } - return result; -} - -test "basic usage" { - const gpa = std.testing.allocator; - - var ia: InternArena = .{}; - defer ia.deinit(gpa); - - const i32_type = try ia.get(gpa, .{ .int_type = .{ - .signedness = .signed, - .bits = 32, - } }); - const array_i32 = try ia.get(gpa, .{ .array_type = .{ - .len = 10, - .child = i32_type, - .sentinel = .none, - } }); - - const another_i32_type = try ia.get(gpa, .{ .int_type = .{ - .signedness = .signed, - .bits = 32, - } }); - try std.testing.expect(another_i32_type == i32_type); - - const another_array_i32 = try ia.get(gpa, .{ .array_type = .{ - .len = 10, - .child = i32_type, - .sentinel = .none, - } }); - try std.testing.expect(another_array_i32 == array_i32); -} diff --git a/src/InternPool.zig b/src/InternPool.zig @@ -0,0 +1,316 @@ +map: std.AutoArrayHashMapUnmanaged(void, void) = .{}, +items: std.MultiArrayList(Item) = .{}, +extra: std.ArrayListUnmanaged(u32) = .{}, + +const InternPool = @This(); +const std = @import("std"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; + +const KeyAdapter = struct { + intern_pool: *const InternPool, + + pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool { + _ = b_void; + return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a); + } + + pub fn hash(ctx: @This(), a: Key) u32 { + _ = ctx; + return a.hash(); + } +}; + +pub const Key = union(enum) { + int_type: struct { + signedness: std.builtin.Signedness, + bits: u16, + }, + ptr_type: struct { + elem_type: Index, + sentinel: Index, + alignment: u16, + size: std.builtin.Type.Pointer.Size, + is_const: bool, + is_volatile: bool, + is_allowzero: bool, + address_space: std.builtin.AddressSpace, + }, + array_type: struct { + len: u64, + child: Index, + sentinel: Index, + }, + vector_type: struct { + len: u32, + child: Index, + }, + optional_type: struct { + payload_type: Index, + }, + error_union_type: struct { + error_set_type: Index, + payload_type: Index, + }, + simple: Simple, + + pub fn hash(key: Key) u32 { + var hasher = std.hash.Wyhash.init(0); + switch (key) { + .int_type => |int_type| { + std.hash.autoHash(&hasher, int_type); + }, + .array_type => |array_type| { + std.hash.autoHash(&hasher, array_type); + }, + else => @panic("TODO"), + } + return @truncate(u32, hasher.final()); + } + + pub fn eql(a: Key, b: Key) bool { + const KeyTag = std.meta.Tag(Key); + const a_tag: KeyTag = a; + const b_tag: KeyTag = b; + if (a_tag != b_tag) return false; + switch (a) { + .int_type => |a_info| { + const b_info = b.int_type; + return std.meta.eql(a_info, b_info); + }, + .array_type => |a_info| { + const b_info = b.array_type; + return std.meta.eql(a_info, b_info); + }, + else => @panic("TODO"), + } + } +}; + +pub const Item = struct { + tag: Tag, + /// The doc comments on the respective Tag explain how to interpret this. + data: u32, +}; + +/// Represents an index into `map`. It represents the canonical index +/// of a `Value` within this `InternPool`. The values are typed. +/// Two values which have the same type can be equality compared simply +/// by checking if their indexes are equal, provided they are both in +/// the same `InternPool`. +pub const Index = enum(u32) { + none = std.math.maxInt(u32), + _, +}; + +pub const Tag = enum(u8) { + /// An integer type. + /// data is number of bits + type_int_signed, + /// An integer type. + /// data is number of bits + type_int_unsigned, + /// An array type. + /// data is payload to Array. + type_array, + /// A type or value that can be represented with only an enum tag. + /// data is Simple enum value + simple, + /// An unsigned integer value that can be represented by u32. + /// data is integer value + int_u32, + /// An unsigned integer value that can be represented by i32. + /// data is integer value bitcasted to u32. + int_i32, + /// A positive integer value that does not fit in 32 bits. + /// data is a extra index to BigInt. + int_big_positive, + /// A negative integer value that does not fit in 32 bits. + /// data is a extra index to BigInt. + int_big_negative, + /// A float value that can be represented by f32. + /// data is float value bitcasted to u32. + float_f32, + /// A float value that can be represented by f64. + /// data is payload index to Float64. + float_f64, + /// A float value that can be represented by f128. + /// data is payload index to Float128. + float_f128, +}; + +pub const Simple = enum(u32) { + f16, + f32, + f64, + f80, + f128, + usize, + isize, + c_short, + c_ushort, + c_int, + c_uint, + c_long, + c_ulong, + c_longlong, + c_ulonglong, + c_longdouble, + anyopaque, + bool, + void, + type, + anyerror, + comptime_int, + comptime_float, + noreturn, + @"anyframe", + null_type, + undefined_type, + enum_literal_type, + @"undefined", + void_value, + @"null", + bool_true, + bool_false, +}; + +pub const Array = struct { + len: u32, + child: Index, +}; + +pub fn deinit(ip: *InternPool, gpa: Allocator) void { + ip.map.deinit(gpa); + ip.items.deinit(gpa); + ip.extra.deinit(gpa); +} + +pub fn indexToKey(ip: InternPool, index: Index) Key { + const item = ip.items.get(@enumToInt(index)); + const data = item.data; + return switch (item.tag) { + .type_int_signed => .{ + .int_type = .{ + .signedness = .signed, + .bits = @intCast(u16, data), + }, + }, + .type_int_unsigned => .{ + .int_type = .{ + .signedness = .unsigned, + .bits = @intCast(u16, data), + }, + }, + .type_array => { + const array_info = ip.extraData(Array, data); + return .{ .array_type = .{ + .len = array_info.len, + .child = array_info.child, + .sentinel = .none, + } }; + }, + .simple => .{ .simple = @intToEnum(Simple, data) }, + + else => @panic("TODO"), + }; +} + +pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { + const adapter: KeyAdapter = .{ .intern_pool = ip }; + const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); + if (gop.found_existing) { + return @intToEnum(Index, gop.index); + } + switch (key) { + .int_type => |int_type| { + const tag: Tag = switch (int_type.signedness) { + .signed => .type_int_signed, + .unsigned => .type_int_unsigned, + }; + try ip.items.append(gpa, .{ + .tag = tag, + .data = int_type.bits, + }); + }, + .array_type => |array_type| { + const len = @intCast(u32, array_type.len); // TODO have a big_array encoding + assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding + try ip.items.append(gpa, .{ + .tag = .type_array, + .data = try ip.addExtra(gpa, Array{ + .len = len, + .child = array_type.child, + }), + }); + }, + else => @panic("TODO"), + } + return @intToEnum(Index, ip.items.len - 1); +} + +fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 { + const fields = std.meta.fields(@TypeOf(extra)); + try ip.extra.ensureUnusedCapacity(gpa, fields.len); + return ip.addExtraAssumeCapacity(extra); +} + +fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { + const fields = std.meta.fields(@TypeOf(extra)); + const result = @intCast(u32, ip.extra.items.len); + inline for (fields) |field| { + ip.extra.appendAssumeCapacity(switch (field.field_type) { + u32 => @field(extra, field.name), + Index => @enumToInt(@field(extra, field.name)), + i32 => @bitCast(u32, @field(extra, field.name)), + else => @compileError("bad field type"), + }); + } + return result; +} + +fn extraData(ip: InternPool, comptime T: type, index: usize) T { + const fields = std.meta.fields(T); + var i: usize = index; + var result: T = undefined; + inline for (fields) |field| { + @field(result, field.name) = switch (field.field_type) { + u32 => ip.extra.items[i], + Index => @intToEnum(Index, ip.extra.items[i]), + i32 => @bitCast(i32, ip.extra.items[i]), + else => @compileError("bad field type"), + }; + i += 1; + } + return result; +} + +test "basic usage" { + const gpa = std.testing.allocator; + + var ip: InternPool = .{}; + defer ip.deinit(gpa); + + const i32_type = try ip.get(gpa, .{ .int_type = .{ + .signedness = .signed, + .bits = 32, + } }); + const array_i32 = try ip.get(gpa, .{ .array_type = .{ + .len = 10, + .child = i32_type, + .sentinel = .none, + } }); + + const another_i32_type = try ip.get(gpa, .{ .int_type = .{ + .signedness = .signed, + .bits = 32, + } }); + try std.testing.expect(another_i32_type == i32_type); + + const another_array_i32 = try ip.get(gpa, .{ .array_type = .{ + .len = 10, + .child = i32_type, + .sentinel = .none, + } }); + try std.testing.expect(another_array_i32 == array_i32); +} diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig @@ -39,7 +39,7 @@ atom_last: ?*Atom = null, abbrev_table_offset: ?u64 = null, -/// TODO replace with InternArena +/// TODO replace with InternPool /// Table of debug symbol names. strtab: std.ArrayListUnmanaged(u8) = .{},