authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-07 14:52:45-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-09-07 14:52:45-04:00
loga48e5af69df17f225cc06658f8a616d54f31d090
treecf2d4a3e98ea8ea598799a2cac21b1862cb96805
parentfd2c1d860503ec6cd71ab9a692ad2dbf6bd3c269
parent5672ee4ed7de11fa3c39ba43619035fdbfc507a5
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9684 from FnControlOption/astgen-string-table

AstGen: use string index as key for string table

4 files changed, 69 insertions(+), 63 deletions(-)

lib/std/hash_map.zig+28
...@@ -92,6 +92,34 @@ pub fn hashString(s: []const u8) u64 {...@@ -92,6 +92,34 @@ pub fn hashString(s: []const u8) u64 {
92 return std.hash.Wyhash.hash(0, s);92 return std.hash.Wyhash.hash(0, s);
93}93}
9494
95pub const StringIndexContext = struct {
96 bytes: *std.ArrayListUnmanaged(u8),
97
98 pub fn eql(self: @This(), a: u32, b: u32) bool {
99 _ = self;
100 return a == b;
101 }
102
103 pub fn hash(self: @This(), x: u32) u64 {
104 const x_slice = mem.spanZ(@ptrCast([*:0]const u8, self.bytes.items.ptr) + x);
105 return hashString(x_slice);
106 }
107};
108
109pub const StringIndexAdapter = struct {
110 bytes: *std.ArrayListUnmanaged(u8),
111
112 pub fn eql(self: @This(), a_slice: []const u8, b: u32) bool {
113 const b_slice = mem.spanZ(@ptrCast([*:0]const u8, self.bytes.items.ptr) + b);
114 return mem.eql(u8, a_slice, b_slice);
115 }
116
117 pub fn hash(self: @This(), adapted_key: []const u8) u64 {
118 _ = self;
119 return hashString(adapted_key);
120 }
121};
122
95/// Deprecated use `default_max_load_percentage`123/// Deprecated use `default_max_load_percentage`
96pub const DefaultMaxLoadPercentage = default_max_load_percentage;124pub const DefaultMaxLoadPercentage = default_max_load_percentage;
97125
src/AstGen.zig+17-15
...@@ -7,6 +7,8 @@ const mem = std.mem;...@@ -7,6 +7,8 @@ const mem = std.mem;
7const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const ArrayListUnmanaged = std.ArrayListUnmanaged;9const ArrayListUnmanaged = std.ArrayListUnmanaged;
10const StringIndexAdapter = std.hash_map.StringIndexAdapter;
11const StringIndexContext = std.hash_map.StringIndexContext;
1012
11const Zir = @import("Zir.zig");13const Zir = @import("Zir.zig");
12const trace = @import("tracy.zig").trace;14const trace = @import("tracy.zig").trace;
...@@ -30,7 +32,7 @@ source_column: u32 = 0,...@@ -30,7 +32,7 @@ source_column: u32 = 0,
30/// Used for temporary allocations; freed after AstGen is complete.32/// Used for temporary allocations; freed after AstGen is complete.
31/// The resulting ZIR code has no references to anything in this arena.33/// The resulting ZIR code has no references to anything in this arena.
32arena: *Allocator,34arena: *Allocator,
33string_table: std.StringHashMapUnmanaged(u32) = .{},35string_table: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
34compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},36compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
35/// The topmost block of the current function.37/// The topmost block of the current function.
36fn_block: ?*GenZir = null,38fn_block: ?*GenZir = null,
...@@ -8781,16 +8783,16 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {...@@ -8781,16 +8783,16 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
8781 const str_index = @intCast(u32, string_bytes.items.len);8783 const str_index = @intCast(u32, string_bytes.items.len);
8782 try astgen.appendIdentStr(ident_token, string_bytes);8784 try astgen.appendIdentStr(ident_token, string_bytes);
8783 const key = string_bytes.items[str_index..];8785 const key = string_bytes.items[str_index..];
8784 const gop = try astgen.string_table.getOrPut(gpa, key);8786 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, @as([]const u8, key), StringIndexAdapter{
8787 .bytes = string_bytes,
8788 }, StringIndexContext{
8789 .bytes = string_bytes,
8790 });
8785 if (gop.found_existing) {8791 if (gop.found_existing) {
8786 string_bytes.shrinkRetainingCapacity(str_index);8792 string_bytes.shrinkRetainingCapacity(str_index);
8787 return gop.value_ptr.*;8793 return gop.key_ptr.*;
8788 } else {8794 } else {
8789 // We have to dupe the key into the arena, otherwise the memory8795 gop.key_ptr.* = str_index;
8790 // becomes invalidated when string_bytes gets data appended.
8791 // TODO https://github.com/ziglang/zig/issues/8528
8792 gop.key_ptr.* = try astgen.arena.dupe(u8, key);
8793 gop.value_ptr.* = str_index;
8794 try string_bytes.append(gpa, 0);8796 try string_bytes.append(gpa, 0);
8795 return str_index;8797 return str_index;
8796 }8798 }
...@@ -8805,19 +8807,19 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {...@@ -8805,19 +8807,19 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
8805 const token_bytes = astgen.tree.tokenSlice(str_lit_token);8807 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
8806 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);8808 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
8807 const key = string_bytes.items[str_index..];8809 const key = string_bytes.items[str_index..];
8808 const gop = try astgen.string_table.getOrPut(gpa, key);8810 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, @as([]const u8, key), StringIndexAdapter{
8811 .bytes = string_bytes,
8812 }, StringIndexContext{
8813 .bytes = string_bytes,
8814 });
8809 if (gop.found_existing) {8815 if (gop.found_existing) {
8810 string_bytes.shrinkRetainingCapacity(str_index);8816 string_bytes.shrinkRetainingCapacity(str_index);
8811 return IndexSlice{8817 return IndexSlice{
8812 .index = gop.value_ptr.*,8818 .index = gop.key_ptr.*,
8813 .len = @intCast(u32, key.len),8819 .len = @intCast(u32, key.len),
8814 };8820 };
8815 } else {8821 } else {
8816 // We have to dupe the key into the arena, otherwise the memory8822 gop.key_ptr.* = str_index;
8817 // becomes invalidated when string_bytes gets data appended.
8818 // TODO https://github.com/ziglang/zig/issues/8528
8819 gop.key_ptr.* = try astgen.arena.dupe(u8, key);
8820 gop.value_ptr.* = str_index;
8821 // Still need a null byte because we are using the same table8823 // Still need a null byte because we are using the same table
8822 // to lookup null terminated strings, so if we get a match, it has to8824 // to lookup null terminated strings, so if we get a match, it has to
8823 // be null terminated for that to work.8825 // be null terminated for that to work.
src/link/MachO.zig+19-44
...@@ -37,6 +37,8 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;...@@ -37,6 +37,8 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
37const LoadCommand = commands.LoadCommand;37const LoadCommand = commands.LoadCommand;
38const Module = @import("../Module.zig");38const Module = @import("../Module.zig");
39const SegmentCommand = commands.SegmentCommand;39const SegmentCommand = commands.SegmentCommand;
40const StringIndexAdapter = std.hash_map.StringIndexAdapter;
41const StringIndexContext = std.hash_map.StringIndexContext;
40pub const TextBlock = @import("MachO/TextBlock.zig");42pub const TextBlock = @import("MachO/TextBlock.zig");
41const Trie = @import("MachO/Trie.zig");43const Trie = @import("MachO/Trie.zig");
4244
...@@ -224,33 +226,6 @@ decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},...@@ -224,33 +226,6 @@ decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
224/// somewhere else in the codegen.226/// somewhere else in the codegen.
225active_decl: ?*Module.Decl = null,227active_decl: ?*Module.Decl = null,
226228
227const StringIndexContext = struct {
228 strtab: *std.ArrayListUnmanaged(u8),
229
230 pub fn eql(_: StringIndexContext, a: u32, b: u32) bool {
231 return a == b;
232 }
233
234 pub fn hash(self: StringIndexContext, x: u32) u64 {
235 const x_slice = mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr) + x);
236 return std.hash_map.hashString(x_slice);
237 }
238};
239
240pub const StringSliceAdapter = struct {
241 strtab: *std.ArrayListUnmanaged(u8),
242
243 pub fn eql(self: StringSliceAdapter, a_slice: []const u8, b: u32) bool {
244 const b_slice = mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr) + b);
245 return mem.eql(u8, a_slice, b_slice);
246 }
247
248 pub fn hash(self: StringSliceAdapter, adapted_key: []const u8) u64 {
249 _ = self;
250 return std.hash_map.hashString(adapted_key);
251 }
252};
253
254const SymbolWithLoc = struct {229const SymbolWithLoc = struct {
255 // Table where the symbol can be found.230 // Table where the symbol can be found.
256 where: enum {231 where: enum {
...@@ -938,8 +913,8 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -938,8 +913,8 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
938913
939 {914 {
940 // Add dyld_stub_binder as the final GOT entry.915 // Add dyld_stub_binder as the final GOT entry.
941 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{916 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
942 .strtab = &self.strtab,917 .bytes = &self.strtab,
943 }) orelse unreachable;918 }) orelse unreachable;
944 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;919 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
945 const got_index = @intCast(u32, self.got_entries.items.len);920 const got_index = @intCast(u32, self.got_entries.items.len);
...@@ -1966,8 +1941,8 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -1966,8 +1941,8 @@ fn writeStubHelperCommon(self: *MachO) !void {
1966 code[9] = 0xff;1941 code[9] = 0xff;
1967 code[10] = 0x25;1942 code[10] = 0x25;
1968 {1943 {
1969 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{1944 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
1970 .strtab = &self.strtab,1945 .bytes = &self.strtab,
1971 }) orelse unreachable;1946 }) orelse unreachable;
1972 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;1947 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
1973 const got_index = self.got_entries_map.get(.{1948 const got_index = self.got_entries_map.get(.{
...@@ -2017,8 +1992,8 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -2017,8 +1992,8 @@ fn writeStubHelperCommon(self: *MachO) !void {
2017 code[10] = 0xbf;1992 code[10] = 0xbf;
2018 code[11] = 0xa9;1993 code[11] = 0xa9;
2019 binder_blk_outer: {1994 binder_blk_outer: {
2020 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{1995 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
2021 .strtab = &self.strtab,1996 .bytes = &self.strtab,
2022 }) orelse unreachable;1997 }) orelse unreachable;
2023 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;1998 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
2024 const got_index = self.got_entries_map.get(.{1999 const got_index = self.got_entries_map.get(.{
...@@ -2435,8 +2410,8 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2435,8 +2410,8 @@ fn resolveSymbols(self: *MachO) !void {
2435 }2410 }
24362411
2437 // Fourth pass, handle synthetic symbols and flag any undefined references.2412 // Fourth pass, handle synthetic symbols and flag any undefined references.
2438 if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringSliceAdapter{2413 if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringIndexAdapter{
2439 .strtab = &self.strtab,2414 .bytes = &self.strtab,
2440 })) |n_strx| blk: {2415 })) |n_strx| blk: {
2441 const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk;2416 const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk;
2442 if (resolv.where != .undef) break :blk;2417 if (resolv.where != .undef) break :blk;
...@@ -2985,8 +2960,8 @@ fn setEntryPoint(self: *MachO) !void {...@@ -2985,8 +2960,8 @@ fn setEntryPoint(self: *MachO) !void {
2985 // TODO we should respect the -entry flag passed in by the user to set a custom2960 // TODO we should respect the -entry flag passed in by the user to set a custom
2986 // entrypoint. For now, assume default of `_main`.2961 // entrypoint. For now, assume default of `_main`.
2987 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2962 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2988 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "_main"), StringSliceAdapter{2963 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "_main"), StringIndexAdapter{
2989 .strtab = &self.strtab,2964 .bytes = &self.strtab,
2990 }) orelse {2965 }) orelse {
2991 log.err("'_main' export not found", .{});2966 log.err("'_main' export not found", .{});
2992 return error.MissingMainEntrypoint;2967 return error.MissingMainEntrypoint;
...@@ -4475,8 +4450,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4475,8 +4450,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4475 });4450 });
4476 self.load_commands_dirty = true;4451 self.load_commands_dirty = true;
4477 }4452 }
4478 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{4453 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
4479 .strtab = &self.strtab,4454 .bytes = &self.strtab,
4480 })) {4455 })) {
4481 const import_sym_index = @intCast(u32, self.undefs.items.len);4456 const import_sym_index = @intCast(u32, self.undefs.items.len);
4482 const n_strx = try self.makeString("dyld_stub_binder");4457 const n_strx = try self.makeString("dyld_stub_binder");
...@@ -4616,8 +4591,8 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {...@@ -4616,8 +4591,8 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4616 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});4591 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});
4617 defer self.base.allocator.free(sym_name);4592 defer self.base.allocator.free(sym_name);
46184593
4619 if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringSliceAdapter{4594 if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
4620 .strtab = &self.strtab,4595 .bytes = &self.strtab,
4621 })) |n_strx| {4596 })) |n_strx| {
4622 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;4597 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
4623 return resolv.where_index;4598 return resolv.where_index;
...@@ -5858,10 +5833,10 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {...@@ -5858,10 +5833,10 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
5858}5833}
58595834
5860pub fn makeString(self: *MachO, string: []const u8) !u32 {5835pub fn makeString(self: *MachO, string: []const u8) !u32 {
5861 const gop = try self.strtab_dir.getOrPutContextAdapted(self.base.allocator, @as([]const u8, string), StringSliceAdapter{5836 const gop = try self.strtab_dir.getOrPutContextAdapted(self.base.allocator, @as([]const u8, string), StringIndexAdapter{
5862 .strtab = &self.strtab,5837 .bytes = &self.strtab,
5863 }, StringIndexContext{5838 }, StringIndexContext{
5864 .strtab = &self.strtab,5839 .bytes = &self.strtab,
5865 });5840 });
5866 if (gop.found_existing) {5841 if (gop.found_existing) {
5867 const off = gop.key_ptr.*;5842 const off = gop.key_ptr.*;
src/link/MachO/TextBlock.zig+5-4
...@@ -14,6 +14,7 @@ const Allocator = mem.Allocator;...@@ -14,6 +14,7 @@ const Allocator = mem.Allocator;
14const Arch = std.Target.Cpu.Arch;14const Arch = std.Target.Cpu.Arch;
15const MachO = @import("../MachO.zig");15const MachO = @import("../MachO.zig");
16const Object = @import("Object.zig");16const Object = @import("Object.zig");
17const StringIndexAdapter = std.hash_map.StringIndexAdapter;
1718
18/// Each decl always gets a local symbol with the fully qualified name.19/// Each decl always gets a local symbol with the fully qualified name.
19/// The vaddr and size are found here directly.20/// The vaddr and size are found here directly.
...@@ -656,8 +657,8 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc...@@ -656,8 +657,8 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
656 parsed_rel.where = .local;657 parsed_rel.where = .local;
657 parsed_rel.where_index = where_index;658 parsed_rel.where_index = where_index;
658 } else {659 } else {
659 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{660 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
660 .strtab = &context.macho_file.strtab,661 .bytes = &context.macho_file.strtab,
661 }) orelse unreachable;662 }) orelse unreachable;
662 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;663 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
663 switch (resolv.where) {664 switch (resolv.where) {
...@@ -717,8 +718,8 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -717,8 +718,8 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
717 const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;718 const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
718 subtractor = where_index;719 subtractor = where_index;
719 } else {720 } else {
720 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{721 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
721 .strtab = &context.macho_file.strtab,722 .bytes = &context.macho_file.strtab,
722 }) orelse unreachable;723 }) orelse unreachable;
723 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;724 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
724 assert(resolv.where == .global);725 assert(resolv.where == .global);