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
signature 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,...@@ -32,6 +32,9 @@ bin_file_path: []const u8,
32/// Decl pointers to details about them being exported.32/// Decl pointers to details about them being exported.
33/// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table.33/// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table.
34decl_exports: std.AutoHashMap(*Decl, []*Export),34decl_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),
35/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl38/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl
36/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that39/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that
37/// is performing the export of another Decl.40/// is performing the export of another Decl.
...@@ -772,6 +775,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {...@@ -772,6 +775,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
772 .optimize_mode = options.optimize_mode,775 .optimize_mode = options.optimize_mode,
773 .decl_table = DeclTable.init(gpa),776 .decl_table = DeclTable.init(gpa),
774 .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa),777 .decl_exports = std.AutoHashMap(*Decl, []*Export).init(gpa),
778 .symbol_exports = std.StringHashMap(*Export).init(gpa),
775 .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa),779 .export_owners = std.AutoHashMap(*Decl, []*Export).init(gpa),
776 .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa),780 .failed_decls = std.AutoHashMap(*Decl, *ErrorMsg).init(gpa),
777 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),781 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),
...@@ -829,6 +833,7 @@ pub fn deinit(self: *Module) void {...@@ -829,6 +833,7 @@ pub fn deinit(self: *Module) void {
829 }833 }
830 self.export_owners.deinit();834 self.export_owners.deinit();
831 }835 }
836 self.symbol_exports.deinit();
832 self.root_scope.destroy(allocator);837 self.root_scope.destroy(allocator);
833 self.* = undefined;838 self.* = undefined;
834}839}
...@@ -1869,6 +1874,7 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {...@@ -1869,6 +1874,7 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
1869 if (self.failed_exports.remove(exp)) |entry| {1874 if (self.failed_exports.remove(exp)) |entry| {
1870 entry.value.destroy(self.allocator);1875 entry.value.destroy(self.allocator);
1871 }1876 }
1877 _ = self.symbol_exports.remove(exp.options.name);
1872 self.allocator.destroy(exp);1878 self.allocator.destroy(exp);
1873 }1879 }
1874 self.allocator.free(kv.value);1880 self.allocator.free(kv.value);
...@@ -2104,20 +2110,6 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const...@@ -2104,20 +2110,6 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
2104 else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),2110 else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
2105 }2111 }
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
2121 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);2113 try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
2122 try self.export_owners.ensureCapacity(self.export_owners.size + 1);2114 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...@@ -2153,7 +2145,7 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
2153 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;2145 de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;
2154 errdefer de_gop.kv.value = self.allocator.shrink(de_gop.kv.value, de_gop.kv.value.len - 1);2146 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)) |_| {
2157 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);2149 try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
2158 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(2150 self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
2159 self.allocator,2151 self.allocator,
...@@ -2161,9 +2153,12 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const...@@ -2161,9 +2153,12 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
2161 "exported symbol collision: {}",2153 "exported symbol collision: {}",
2162 .{symbol_name},2154 .{symbol_name},
2163 ));2155 ));
2156 // TODO: add a note
2164 new_export.status = .failed;2157 new_export.status = .failed;
2165 return;2158 return;
2166 }2159 }
2160
2161 try self.symbol_exports.putNoClobber(symbol_name, new_export);
2167 self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {2162 self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {
2168 error.OutOfMemory => return error.OutOfMemory,2163 error.OutOfMemory => return error.OutOfMemory,
2169 else => {2164 else => {