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
signaturebadge-question-mark 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 {
9292 return std.hash.Wyhash.hash(0, s);
9393}
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
95123/// Deprecated use `default_max_load_percentage`
96124pub const DefaultMaxLoadPercentage = default_max_load_percentage;
97125
src/AstGen.zig+17-15
......@@ -7,6 +7,8 @@ const mem = std.mem;
77const Allocator = std.mem.Allocator;
88const assert = std.debug.assert;
99const ArrayListUnmanaged = std.ArrayListUnmanaged;
10const StringIndexAdapter = std.hash_map.StringIndexAdapter;
11const StringIndexContext = std.hash_map.StringIndexContext;
1012
1113const Zir = @import("Zir.zig");
1214const trace = @import("tracy.zig").trace;
......@@ -30,7 +32,7 @@ source_column: u32 = 0,
3032/// Used for temporary allocations; freed after AstGen is complete.
3133/// The resulting ZIR code has no references to anything in this arena.
3234arena: *Allocator,
33string_table: std.StringHashMapUnmanaged(u32) = .{},
35string_table: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
3436compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
3537/// The topmost block of the current function.
3638fn_block: ?*GenZir = null,
......@@ -8781,16 +8783,16 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
87818783 const str_index = @intCast(u32, string_bytes.items.len);
87828784 try astgen.appendIdentStr(ident_token, string_bytes);
87838785 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 });
87858791 if (gop.found_existing) {
87868792 string_bytes.shrinkRetainingCapacity(str_index);
8787 return gop.value_ptr.*;
8793 return gop.key_ptr.*;
87888794 } else {
8789 // We have to dupe the key into the arena, otherwise the memory
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;
8795 gop.key_ptr.* = str_index;
87948796 try string_bytes.append(gpa, 0);
87958797 return str_index;
87968798 }
......@@ -8805,19 +8807,19 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
88058807 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
88068808 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
88078809 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 });
88098815 if (gop.found_existing) {
88108816 string_bytes.shrinkRetainingCapacity(str_index);
88118817 return IndexSlice{
8812 .index = gop.value_ptr.*,
8818 .index = gop.key_ptr.*,
88138819 .len = @intCast(u32, key.len),
88148820 };
88158821 } else {
8816 // We have to dupe the key into the arena, otherwise the memory
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;
8822 gop.key_ptr.* = str_index;
88218823 // Still need a null byte because we are using the same table
88228824 // to lookup null terminated strings, so if we get a match, it has to
88238825 // be null terminated for that to work.
src/link/MachO.zig+19-44
......@@ -37,6 +37,8 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
3737const LoadCommand = commands.LoadCommand;
3838const Module = @import("../Module.zig");
3939const SegmentCommand = commands.SegmentCommand;
40const StringIndexAdapter = std.hash_map.StringIndexAdapter;
41const StringIndexContext = std.hash_map.StringIndexContext;
4042pub const TextBlock = @import("MachO/TextBlock.zig");
4143const Trie = @import("MachO/Trie.zig");
4244
......@@ -224,33 +226,6 @@ decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
224226/// somewhere else in the codegen.
225227active_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
254229const SymbolWithLoc = struct {
255230 // Table where the symbol can be found.
256231 where: enum {
......@@ -938,8 +913,8 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
938913
939914 {
940915 // Add dyld_stub_binder as the final GOT entry.
941 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
942 .strtab = &self.strtab,
916 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
917 .bytes = &self.strtab,
943918 }) orelse unreachable;
944919 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
945920 const got_index = @intCast(u32, self.got_entries.items.len);
......@@ -1966,8 +1941,8 @@ fn writeStubHelperCommon(self: *MachO) !void {
19661941 code[9] = 0xff;
19671942 code[10] = 0x25;
19681943 {
1969 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
1970 .strtab = &self.strtab,
1944 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
1945 .bytes = &self.strtab,
19711946 }) orelse unreachable;
19721947 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
19731948 const got_index = self.got_entries_map.get(.{
......@@ -2017,8 +1992,8 @@ fn writeStubHelperCommon(self: *MachO) !void {
20171992 code[10] = 0xbf;
20181993 code[11] = 0xa9;
20191994 binder_blk_outer: {
2020 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
2021 .strtab = &self.strtab,
1995 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
1996 .bytes = &self.strtab,
20221997 }) orelse unreachable;
20231998 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
20241999 const got_index = self.got_entries_map.get(.{
......@@ -2435,8 +2410,8 @@ fn resolveSymbols(self: *MachO) !void {
24352410 }
24362411
24372412 // Fourth pass, handle synthetic symbols and flag any undefined references.
2438 if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringSliceAdapter{
2439 .strtab = &self.strtab,
2413 if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringIndexAdapter{
2414 .bytes = &self.strtab,
24402415 })) |n_strx| blk: {
24412416 const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk;
24422417 if (resolv.where != .undef) break :blk;
......@@ -2985,8 +2960,8 @@ fn setEntryPoint(self: *MachO) !void {
29852960 // TODO we should respect the -entry flag passed in by the user to set a custom
29862961 // entrypoint. For now, assume default of `_main`.
29872962 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{
2989 .strtab = &self.strtab,
2963 const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "_main"), StringIndexAdapter{
2964 .bytes = &self.strtab,
29902965 }) orelse {
29912966 log.err("'_main' export not found", .{});
29922967 return error.MissingMainEntrypoint;
......@@ -4475,8 +4450,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
44754450 });
44764451 self.load_commands_dirty = true;
44774452 }
4478 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
4479 .strtab = &self.strtab,
4453 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringIndexAdapter{
4454 .bytes = &self.strtab,
44804455 })) {
44814456 const import_sym_index = @intCast(u32, self.undefs.items.len);
44824457 const n_strx = try self.makeString("dyld_stub_binder");
......@@ -4616,8 +4591,8 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
46164591 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});
46174592 defer self.base.allocator.free(sym_name);
46184593
4619 if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringSliceAdapter{
4620 .strtab = &self.strtab,
4594 if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
4595 .bytes = &self.strtab,
46214596 })) |n_strx| {
46224597 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
46234598 return resolv.where_index;
......@@ -5858,10 +5833,10 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
58585833}
58595834
58605835pub fn makeString(self: *MachO, string: []const u8) !u32 {
5861 const gop = try self.strtab_dir.getOrPutContextAdapted(self.base.allocator, @as([]const u8, string), StringSliceAdapter{
5862 .strtab = &self.strtab,
5836 const gop = try self.strtab_dir.getOrPutContextAdapted(self.base.allocator, @as([]const u8, string), StringIndexAdapter{
5837 .bytes = &self.strtab,
58635838 }, StringIndexContext{
5864 .strtab = &self.strtab,
5839 .bytes = &self.strtab,
58655840 });
58665841 if (gop.found_existing) {
58675842 const off = gop.key_ptr.*;
src/link/MachO/TextBlock.zig+5-4
......@@ -14,6 +14,7 @@ const Allocator = mem.Allocator;
1414const Arch = std.Target.Cpu.Arch;
1515const MachO = @import("../MachO.zig");
1616const Object = @import("Object.zig");
17const StringIndexAdapter = std.hash_map.StringIndexAdapter;
1718
1819/// Each decl always gets a local symbol with the fully qualified name.
1920/// The vaddr and size are found here directly.
......@@ -656,8 +657,8 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
656657 parsed_rel.where = .local;
657658 parsed_rel.where_index = where_index;
658659 } else {
659 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
660 .strtab = &context.macho_file.strtab,
660 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
661 .bytes = &context.macho_file.strtab,
661662 }) orelse unreachable;
662663 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
663664 switch (resolv.where) {
......@@ -717,8 +718,8 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
717718 const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
718719 subtractor = where_index;
719720 } else {
720 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
721 .strtab = &context.macho_file.strtab,
721 const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
722 .bytes = &context.macho_file.strtab,
722723 }) orelse unreachable;
723724 const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
724725 assert(resolv.where == .global);