authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-23 23:29:51-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-23 23:29:51-04:00
logb1b7708cc8380ad9518715e3e285db3011f5a6a4
tree14f2ef168d5d8c38c78f4d07e9b46b0e506e1727
parentd9c1d8fed3e121c4fe91d5aea301574ff763ef95

self-hosted: hook up incremental compilation to .zig source code


2 files changed, 202 insertions(+), 208 deletions(-)

src-self-hosted/Module.zig+198-208
......@@ -74,9 +74,9 @@ const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope
7474const WorkItem = union(enum) {
7575 /// Write the machine code for a Decl to the output file.
7676 codegen_decl: *Decl,
77 /// Decl has been determined to be outdated; perform semantic analysis again.
78 re_analyze_decl: *Decl,
7977 /// The Decl needs to be analyzed and possibly export itself.
78 /// It may have already be analyzed, or it may have been determined
79 /// to be outdated; in this case perform semantic analysis again.
8080 analyze_decl: *Decl,
8181};
8282
......@@ -403,6 +403,17 @@ pub const Scope = struct {
403403 }
404404 }
405405
406 /// Asserts the scope is a namespace Scope and removes the Decl from the namespace.
407 pub fn removeDecl(base: *Scope, child: *Decl) void {
408 switch (base.tag) {
409 .file => return @fieldParentPtr(File, "base", base).removeDecl(child),
410 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).removeDecl(child),
411 .block => unreachable,
412 .gen_zir => unreachable,
413 .decl => unreachable,
414 }
415 }
416
406417 /// Asserts the scope is a File or ZIRModule and deinitializes it, then deallocates it.
407418 pub fn destroy(base: *Scope, allocator: *Allocator) void {
408419 switch (base.tag) {
......@@ -462,6 +473,9 @@ pub const Scope = struct {
462473 loaded_success,
463474 },
464475
476 /// Direct children of the file.
477 decls: ArrayListUnmanaged(*Decl),
478
465479 pub fn unload(self: *File, allocator: *Allocator) void {
466480 switch (self.status) {
467481 .never_loaded,
......@@ -484,10 +498,20 @@ pub const Scope = struct {
484498 }
485499
486500 pub fn deinit(self: *File, allocator: *Allocator) void {
501 self.decls.deinit(allocator);
487502 self.unload(allocator);
488503 self.* = undefined;
489504 }
490505
506 pub fn removeDecl(self: *File, child: *Decl) void {
507 for (self.decls.items) |item, i| {
508 if (item == child) {
509 _ = self.decls.swapRemove(i);
510 return;
511 }
512 }
513 }
514
491515 pub fn dumpSrc(self: *File, src: usize) void {
492516 const loc = std.zig.findLineColumn(self.source.bytes, src);
493517 std.debug.warn("{}:{}:{}\n", .{ self.sub_file_path, loc.line + 1, loc.column + 1 });
......@@ -540,6 +564,11 @@ pub const Scope = struct {
540564 loaded_success,
541565 },
542566
567 /// Even though .zir files only have 1 module, this set is still needed
568 /// because of anonymous Decls, which can exist in the global set, but
569 /// not this one.
570 decls: ArrayListUnmanaged(*Decl),
571
543572 pub fn unload(self: *ZIRModule, allocator: *Allocator) void {
544573 switch (self.status) {
545574 .never_loaded,
......@@ -569,10 +598,20 @@ pub const Scope = struct {
569598 }
570599
571600 pub fn deinit(self: *ZIRModule, allocator: *Allocator) void {
601 self.decls.deinit(allocator);
572602 self.unload(allocator);
573603 self.* = undefined;
574604 }
575605
606 pub fn removeDecl(self: *ZIRModule, child: *Decl) void {
607 for (self.decls.items) |item, i| {
608 if (item == child) {
609 _ = self.decls.swapRemove(i);
610 return;
611 }
612 }
613 }
614
576615 pub fn dumpSrc(self: *ZIRModule, src: usize) void {
577616 const loc = std.zig.findLineColumn(self.source.bytes, src);
578617 std.debug.warn("{}:{}:{}\n", .{ self.sub_file_path, loc.line + 1, loc.column + 1 });
......@@ -700,6 +739,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
700739 .source = .{ .unloaded = {} },
701740 .contents = .{ .not_available = {} },
702741 .status = .never_loaded,
742 .decls = .{},
703743 };
704744 break :blk &root_scope.base;
705745 } else if (mem.endsWith(u8, options.root_pkg.root_src_path, ".zir")) {
......@@ -709,6 +749,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
709749 .source = .{ .unloaded = {} },
710750 .contents = .{ .not_available = {} },
711751 .status = .never_loaded,
752 .decls = .{},
712753 };
713754 break :blk &root_scope.base;
714755 } else {
......@@ -828,13 +869,14 @@ pub fn update(self: *Module) !void {
828869 try self.performAllTheWork();
829870
830871 // Process the deletion set.
831 while (self.deletion_set.popOrNull()) |decl| {
872 for (self.deletion_set.items) |decl| {
832873 if (decl.dependants.items.len != 0) {
833874 decl.deletion_flag = false;
834875 continue;
835876 }
836877 try self.deleteDecl(decl);
837878 }
879 self.deletion_set.shrink(self.allocator, 0);
838880
839881 self.link_error_flags = self.bin_file.error_flags;
840882
......@@ -969,49 +1011,6 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
9691011 };
9701012 },
9711013 },
972 .re_analyze_decl => |decl| switch (decl.analysis) {
973 .unreferenced => unreachable,
974 .in_progress => unreachable,
975
976 .sema_failure,
977 .codegen_failure,
978 .dependency_failure,
979 .complete,
980 .codegen_failure_retryable,
981 .sema_failure_retryable,
982 => continue,
983
984 .outdated => {
985 if (decl.scope.cast(Scope.File)) |file_scope| {
986 @panic("TODO re_analyze_decl for .zig files");
987 } else if (decl.scope.cast(Scope.ZIRModule)) |zir_scope| {
988 const zir_module = self.getSrcModule(zir_scope) catch |err| switch (err) {
989 error.OutOfMemory => return error.OutOfMemory,
990 else => {
991 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
992 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
993 self.allocator,
994 decl.src(),
995 "unable to load source file '{}': {}",
996 .{ zir_scope.sub_file_path, @errorName(err) },
997 ));
998 decl.analysis = .codegen_failure_retryable;
999 continue;
1000 },
1001 };
1002 const decl_name = mem.spanZ(decl.name);
1003 // We already detected deletions, so we know this will be found.
1004 const src_decl_and_index = zir_module.findDecl(decl_name).?;
1005 decl.src_index = src_decl_and_index.index;
1006 self.reAnalyzeDecl(decl, src_decl_and_index.decl.inst) catch |err| switch (err) {
1007 error.OutOfMemory => return error.OutOfMemory,
1008 error.AnalysisFail => continue,
1009 };
1010 } else {
1011 unreachable;
1012 }
1013 },
1014 },
10151014 .analyze_decl => |decl| {
10161015 self.ensureDeclAnalyzed(decl) catch |err| switch (err) {
10171016 error.OutOfMemory => return error.OutOfMemory,
......@@ -1022,9 +1021,12 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
10221021}
10231022
10241023fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1025 switch (decl.analysis) {
1024 const tracy = trace(@src());
1025 defer tracy.end();
1026
1027 const subsequent_analysis = switch (decl.analysis) {
1028 .complete => return,
10261029 .in_progress => unreachable,
1027 .outdated => unreachable,
10281030
10291031 .sema_failure,
10301032 .sema_failure_retryable,
......@@ -1033,29 +1035,73 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
10331035 .codegen_failure_retryable,
10341036 => return error.AnalysisFail,
10351037
1036 .complete => return,
1038 .outdated => blk: {
1039 //std.debug.warn("re-analyzing {}\n", .{decl.name});
1040
1041 // The exports this Decl performs will be re-discovered, so we remove them here
1042 // prior to re-analysis.
1043 self.deleteDeclExports(decl);
1044 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
1045 for (decl.dependencies.items) |dep| {
1046 dep.removeDependant(decl);
1047 if (dep.dependants.items.len == 0) {
1048 // We don't perform a deletion here, because this Decl or another one
1049 // may end up referencing it before the update is complete.
1050 assert(!dep.deletion_flag);
1051 dep.deletion_flag = true;
1052 try self.deletion_set.append(self.allocator, dep);
1053 }
1054 }
1055 decl.dependencies.shrink(self.allocator, 0);
10371056
1038 .unreferenced => {
1039 self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
1040 error.OutOfMemory => return error.OutOfMemory,
1041 error.AnalysisFail => return error.AnalysisFail,
1042 else => {
1043 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
1044 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
1045 self.allocator,
1046 decl.src(),
1047 "unable to analyze: {}",
1048 .{@errorName(err)},
1049 ));
1050 decl.analysis = .sema_failure_retryable;
1051 return error.AnalysisFail;
1052 },
1053 };
1057 break :blk true;
1058 },
1059
1060 .unreferenced => false,
1061 };
1062
1063 const type_changed = self.astGenAndAnalyzeDecl(decl) catch |err| switch (err) {
1064 error.OutOfMemory => return error.OutOfMemory,
1065 error.AnalysisFail => return error.AnalysisFail,
1066 else => {
1067 try self.failed_decls.ensureCapacity(self.failed_decls.size + 1);
1068 self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
1069 self.allocator,
1070 decl.src(),
1071 "unable to analyze: {}",
1072 .{@errorName(err)},
1073 ));
1074 decl.analysis = .sema_failure_retryable;
1075 return error.AnalysisFail;
10541076 },
1077 };
1078
1079 if (subsequent_analysis) {
1080 // We may need to chase the dependants and re-analyze them.
1081 // However, if the decl is a function, and the type is the same, we do not need to.
1082 if (type_changed or decl.typed_value.most_recent.typed_value.val.tag() != .function) {
1083 for (decl.dependants.items) |dep| {
1084 switch (dep.analysis) {
1085 .unreferenced => unreachable,
1086 .in_progress => unreachable,
1087 .outdated => continue, // already queued for update
1088
1089 .dependency_failure,
1090 .sema_failure,
1091 .sema_failure_retryable,
1092 .codegen_failure,
1093 .codegen_failure_retryable,
1094 .complete,
1095 => if (dep.generation != self.generation) {
1096 try self.markOutdatedDecl(dep);
1097 },
1098 }
1099 }
1100 }
10551101 }
10561102}
10571103
1058fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
1104fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
10591105 const tracy = trace(@src());
10601106 defer tracy.end();
10611107
......@@ -1170,6 +1216,16 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
11701216 };
11711217 fn_payload.* = .{ .func = new_func };
11721218
1219 var prev_type_has_bits = false;
1220 var type_changed = true;
1221
1222 if (decl.typedValueManaged()) |tvm| {
1223 prev_type_has_bits = tvm.typed_value.ty.hasCodeGenBits();
1224 type_changed = !tvm.typed_value.ty.eql(fn_type);
1225
1226 tvm.deinit(self.allocator);
1227 }
1228
11731229 decl_arena_state.* = decl_arena.state;
11741230 decl.typed_value = .{
11751231 .most_recent = .{
......@@ -1183,11 +1239,15 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
11831239 decl.analysis = .complete;
11841240 decl.generation = self.generation;
11851241
1186 // We don't fully codegen the decl until later, but we do need to reserve a global
1187 // offset table index for it. This allows us to codegen decls out of dependency order,
1188 // increasing how many computations can be done in parallel.
1189 try self.bin_file.allocateDeclIndexes(decl);
1190 try self.work_queue.writeItem(.{ .codegen_decl = decl });
1242 if (fn_type.hasCodeGenBits()) {
1243 // We don't fully codegen the decl until later, but we do need to reserve a global
1244 // offset table index for it. This allows us to codegen decls out of dependency order,
1245 // increasing how many computations can be done in parallel.
1246 try self.bin_file.allocateDeclIndexes(decl);
1247 try self.work_queue.writeItem(.{ .codegen_decl = decl });
1248 } else if (prev_type_has_bits) {
1249 self.bin_file.freeDecl(decl);
1250 }
11911251
11921252 if (fn_proto.extern_export_inline_token) |maybe_export_token| {
11931253 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
......@@ -1198,6 +1258,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !void {
11981258 try self.analyzeExport(&block_scope.base, export_src, name, decl);
11991259 }
12001260 }
1261 return type_changed;
12011262 },
12021263 .VarDecl => @panic("TODO var decl"),
12031264 .Comptime => @panic("TODO comptime decl"),
......@@ -1602,40 +1663,63 @@ fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
16021663}
16031664
16041665fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1605 switch (root_scope.status) {
1606 .never_loaded => {
1607 const tree = try self.getAstTree(root_scope);
1608 const decls = tree.root_node.decls();
1609
1610 try self.work_queue.ensureUnusedCapacity(decls.len);
1611
1612 for (decls) |src_decl, decl_i| {
1613 if (src_decl.cast(ast.Node.FnProto)) |fn_proto| {
1614 // We will create a Decl for it regardless of analysis status.
1615 const name_tok = fn_proto.name_token orelse
1616 @panic("TODO handle missing function name in the parser");
1617 const name_loc = tree.token_locs[name_tok];
1618 const name = tree.tokenSliceLoc(name_loc);
1619 const name_hash = root_scope.fullyQualifiedNameHash(name);
1620 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
1621 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1622 if (fn_proto.extern_export_inline_token) |maybe_export_token| {
1623 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1624 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
1625 }
1666 // We may be analyzing it for the first time, or this may be
1667 // an incremental update. This code handles both cases.
1668 const tree = try self.getAstTree(root_scope);
1669 const decls = tree.root_node.decls();
1670
1671 try self.work_queue.ensureUnusedCapacity(decls.len);
1672 try root_scope.decls.ensureCapacity(self.allocator, decls.len);
1673
1674 // Keep track of the decls that we expect to see in this file so that
1675 // we know which ones have been deleted.
1676 var deleted_decls = std.AutoHashMap(*Decl, void).init(self.allocator);
1677 defer deleted_decls.deinit();
1678 try deleted_decls.ensureCapacity(root_scope.decls.items.len);
1679 for (root_scope.decls.items) |file_decl| {
1680 deleted_decls.putAssumeCapacityNoClobber(file_decl, {});
1681 }
1682
1683 for (decls) |src_decl, decl_i| {
1684 if (src_decl.cast(ast.Node.FnProto)) |fn_proto| {
1685 // We will create a Decl for it regardless of analysis status.
1686 const name_tok = fn_proto.name_token orelse
1687 @panic("TODO handle missing function name in the parser");
1688 const name_loc = tree.token_locs[name_tok];
1689 const name = tree.tokenSliceLoc(name_loc);
1690 const name_hash = root_scope.fullyQualifiedNameHash(name);
1691 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
1692 if (self.decl_table.get(name_hash)) |kv| {
1693 const decl = kv.value;
1694 // Update the AST Node index of the decl, even if its contents are unchanged, it may
1695 // have been re-ordered.
1696 decl.src_index = decl_i;
1697 deleted_decls.removeAssertDiscard(decl);
1698 if (!srcHashEql(decl.contents_hash, contents_hash)) {
1699 try self.markOutdatedDecl(decl);
1700 decl.contents_hash = contents_hash;
1701 }
1702 } else {
1703 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1704 root_scope.decls.appendAssumeCapacity(new_decl);
1705 if (fn_proto.extern_export_inline_token) |maybe_export_token| {
1706 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
1707 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
16261708 }
16271709 }
1628 // TODO also look for global variable declarations
1629 // TODO also look for comptime blocks and exported globals
16301710 }
1631 },
1632
1633 .unloaded_parse_failure,
1634 .unloaded_success,
1635 .loaded_success,
1636 => {
1637 @panic("TODO process update");
1638 },
1711 }
1712 // TODO also look for global variable declarations
1713 // TODO also look for comptime blocks and exported globals
1714 }
1715 {
1716 // Handle explicitly deleted decls from the source code. Not to be confused
1717 // with when we delete decls because they are no longer referenced.
1718 var it = deleted_decls.iterator();
1719 while (it.next()) |kv| {
1720 //std.debug.warn("noticed '{}' deleted from source\n", .{kv.key.name});
1721 try self.deleteDecl(kv.key);
1722 }
16391723 }
16401724}
16411725
......@@ -1684,7 +1768,7 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
16841768 const decl = kv.value;
16851769 deleted_decls.removeAssertDiscard(decl);
16861770 //std.debug.warn("'{}' contents: '{}'\n", .{ src_decl.name, src_decl.contents });
1687 if (!mem.eql(u8, &src_decl.contents_hash, &decl.contents_hash)) {
1771 if (!srcHashEql(src_decl.contents_hash, decl.contents_hash)) {
16881772 try self.markOutdatedDecl(decl);
16891773 decl.contents_hash = src_decl.contents_hash;
16901774 }
......@@ -1711,6 +1795,10 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
17111795fn deleteDecl(self: *Module, decl: *Decl) !void {
17121796 try self.deletion_set.ensureCapacity(self.allocator, self.deletion_set.items.len + decl.dependencies.items.len);
17131797
1798 // Remove from the namespace it resides in. In the case of an anonymous Decl it will
1799 // not be present in the set, and this does nothing.
1800 decl.scope.removeDecl(decl);
1801
17141802 //std.debug.warn("deleting decl '{}'\n", .{decl.name});
17151803 const name_hash = decl.fullyQualifiedNameHash();
17161804 self.decl_table.removeAssertDiscard(name_hash);
......@@ -1799,110 +1887,9 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
17991887 //std.debug.warn("set {} to success\n", .{decl.name});
18001888}
18011889
1802fn reAnalyzeDecl(self: *Module, decl: *Decl, old_inst: *zir.Inst) InnerError!void {
1803 switch (decl.analysis) {
1804 .unreferenced => unreachable,
1805 .in_progress => unreachable,
1806 .dependency_failure,
1807 .sema_failure,
1808 .sema_failure_retryable,
1809 .codegen_failure,
1810 .codegen_failure_retryable,
1811 .complete,
1812 => return,
1813
1814 .outdated => {}, // Decl re-analysis
1815 }
1816 //std.debug.warn("re-analyzing {}\n", .{decl.name});
1817
1818 // The exports this Decl performs will be re-discovered, so we remove them here
1819 // prior to re-analysis.
1820 self.deleteDeclExports(decl);
1821 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
1822 for (decl.dependencies.items) |dep| {
1823 dep.removeDependant(decl);
1824 if (dep.dependants.items.len == 0) {
1825 // We don't perform a deletion here, because this Decl or another one
1826 // may end up referencing it before the update is complete.
1827 assert(!dep.deletion_flag);
1828 dep.deletion_flag = true;
1829 try self.deletion_set.append(self.allocator, dep);
1830 }
1831 }
1832 decl.dependencies.shrink(self.allocator, 0);
1833 var decl_scope: Scope.DeclAnalysis = .{
1834 .decl = decl,
1835 .arena = std.heap.ArenaAllocator.init(self.allocator),
1836 };
1837 errdefer decl_scope.arena.deinit();
1838
1839 const typed_value = self.analyzeConstInst(&decl_scope.base, old_inst) catch |err| switch (err) {
1840 error.OutOfMemory => return error.OutOfMemory,
1841 error.AnalysisFail => {
1842 switch (decl.analysis) {
1843 .in_progress => decl.analysis = .dependency_failure,
1844 else => {},
1845 }
1846 decl.generation = self.generation;
1847 return error.AnalysisFail;
1848 },
1849 };
1850 const arena_state = try decl_scope.arena.allocator.create(std.heap.ArenaAllocator.State);
1851 arena_state.* = decl_scope.arena.state;
1852
1853 var prev_type_has_bits = false;
1854 var type_changed = true;
1855
1856 if (decl.typedValueManaged()) |tvm| {
1857 prev_type_has_bits = tvm.typed_value.ty.hasCodeGenBits();
1858 type_changed = !tvm.typed_value.ty.eql(typed_value.ty);
1859
1860 tvm.deinit(self.allocator);
1861 }
1862 decl.typed_value = .{
1863 .most_recent = .{
1864 .typed_value = typed_value,
1865 .arena = arena_state,
1866 },
1867 };
1868 decl.analysis = .complete;
1869 decl.generation = self.generation;
1870 if (typed_value.ty.hasCodeGenBits()) {
1871 // We don't fully codegen the decl until later, but we do need to reserve a global
1872 // offset table index for it. This allows us to codegen decls out of dependency order,
1873 // increasing how many computations can be done in parallel.
1874 try self.bin_file.allocateDeclIndexes(decl);
1875 try self.work_queue.writeItem(.{ .codegen_decl = decl });
1876 } else if (prev_type_has_bits) {
1877 self.bin_file.freeDecl(decl);
1878 }
1879
1880 // If the decl is a function, and the type is the same, we do not need
1881 // to chase the dependants.
1882 if (type_changed or typed_value.val.tag() != .function) {
1883 for (decl.dependants.items) |dep| {
1884 switch (dep.analysis) {
1885 .unreferenced => unreachable,
1886 .in_progress => unreachable,
1887 .outdated => continue, // already queued for update
1888
1889 .dependency_failure,
1890 .sema_failure,
1891 .sema_failure_retryable,
1892 .codegen_failure,
1893 .codegen_failure_retryable,
1894 .complete,
1895 => if (dep.generation != self.generation) {
1896 try self.markOutdatedDecl(dep);
1897 },
1898 }
1899 }
1900 }
1901}
1902
19031890fn markOutdatedDecl(self: *Module, decl: *Decl) !void {
19041891 //std.debug.warn("mark {} outdated\n", .{decl.name});
1905 try self.work_queue.writeItem(.{ .re_analyze_decl = decl });
1892 try self.work_queue.writeItem(.{ .analyze_decl = decl });
19061893 if (self.failed_decls.remove(decl)) |entry| {
19071894 entry.value.destroy(self.allocator);
19081895 }
......@@ -2381,11 +2368,10 @@ fn createAnonymousDecl(
23812368 decl_arena: *std.heap.ArenaAllocator,
23822369 typed_value: TypedValue,
23832370) !*Decl {
2384 var name_buf: [32]u8 = undefined;
23852371 const name_index = self.getNextAnonNameIndex();
2386 const name = std.fmt.bufPrint(&name_buf, "unnamed_{}", .{name_index}) catch unreachable;
2387 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
23882372 const scope_decl = scope.decl().?;
2373 const name = try std.fmt.allocPrint(self.allocator, "{}${}", .{ scope_decl.name, name_index });
2374 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
23892375 const src_hash: std.zig.SrcHash = undefined;
23902376 const new_decl = try self.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash);
23912377 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
......@@ -3360,3 +3346,7 @@ pub const ErrorMsg = struct {
33603346 self.* = undefined;
33613347 }
33623348};
3349
3350fn srcHashEql(a: std.zig.SrcHash, b: std.zig.SrcHash) bool {
3351 return @bitCast(u128, a) == @bitCast(u128, b);
3352}
src-self-hosted/main.zig+4
......@@ -487,7 +487,9 @@ fn buildOutputType(
487487}
488488
489489fn updateModule(gpa: *Allocator, module: *Module, zir_out_path: ?[]const u8) !void {
490 var timer = try std.time.Timer.start();
490491 try module.update();
492 const update_nanos = timer.read();
491493
492494 var errors = try module.getAllErrorsAlloc();
493495 defer errors.deinit(module.allocator);
......@@ -501,6 +503,8 @@ fn updateModule(gpa: *Allocator, module: *Module, zir_out_path: ?[]const u8) !vo
501503 full_err_msg.msg,
502504 });
503505 }
506 } else {
507 std.debug.print("Update completed in {} ms\n", .{update_nanos / std.time.ns_per_ms});
504508 }
505509
506510 if (zir_out_path) |zop| {