authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-27 21:50:59-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-06-27 21:50:59-04:00
log80b70470c016ad0d1db47d0edc4d48f1f75af258
tree69aa3403ab333951bfbd4c73fbcd37e33ebf984b
parentffca1569d12d4e8ce83418bb87e358e6ec9ac0bc
signaturelock-open Commit is signed but in an unrecognized format.

Stage2/Module: Add symbol -> export lookup table


1 files changed, 10 insertions(+), 15 deletions(-)

src-self-hosted/Module.zig+10-15
......@@ -32,6 +32,9 @@ bin_file_path: []const u8,
3232/// Decl pointers to details about them being exported.
3333/// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table.
3434decl_exports: std.AutoHashMap(*Decl, []*Export),
35/// We track which export is associated with the given symbol name for quick
36/// detection of symbol collisions.
37symbol_exports: std.StringHashMap(*Export),
3538/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl
3639/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that
3740/// is performing the export of another Decl.
......@@ -772,6 +775,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
772775 .optimize_mode = options.optimize_mode,
773776 .decl_table = DeclTable.init(gpa),
774777 .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa),
778 .symbol_exports = std.StringHashMap(*Export).init(gpa),
775779 .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa),
776780 .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa),
777781 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),
......@@ -829,6 +833,7 @@ pub fn deinit(self: *Module) void {
829833 }
830834 self.export_owners.deinit();
831835 }
836 self.symbol_exports.deinit();
832837 self.root_scope.destroy(allocator);
833838 self.* = undefined;
834839}
......@@ -1869,6 +1874,7 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
18691874 if (self.failed_exports.remove(exp)) |entry| {
18701875 entry.value.destroy(self.allocator);
18711876 }
1877 _ = self.symbol_exports.remove(exp.options.name);
18721878 self.allocator.destroy(exp);
18731879 }
18741880 self.allocator.free(kv.value);
......@@ -2104,20 +2110,6 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
21042110 else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
21052111 }
21062112
2107 var already_exported = false;
2108 {
2109 var it = self.decl_exports.iterator();
2110 while (it.next()) |kv| {
2111 const export_list = kv.value;
2112 for (export_list) |e| {
2113 if (std.mem.eql(u8, e.options.name, symbol_name)) {
2114 already_exported = true;
2115 break;
2116 }
2117 }
2118 }
2119 }
2120
21212113 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
21222114 try self.export_owners.ensureCapacity(self.export_owners.size + 1);
21232115
......@@ -2153,7 +2145,7 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
21532145 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;
21542146 errdefer de_gop.kv.value = self.allocator.shrink(de_gop.kv.value, de_gop.kv.value.len - 1);
21552147
2156 if (already_exported) {
2148 if (self.symbol_exports.get(symbol_name)) |_| {
21572149 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
21582150 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
21592151 self.allocator,
......@@ -2161,9 +2153,12 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
21612153 "exported symbol collision: {}",
21622154 .{symbol_name},
21632155 ));
2156 // TODO: add a note
21642157 new_export.status = .failed;
21652158 return;
21662159 }
2160
2161 try self.symbol_exports.putNoClobber(symbol_name, new_export);
21672162 self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {
21682163 error.OutOfMemory => return error.OutOfMemory,
21692164 else => {