authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-11 23:20:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-11 23:20:22-07:00
log71afc3088009944fcd8339ac71e69a0b77a781ab
treed370c17e3561870b151d402c1ba1b32813bda83d
parent1ab1a96f87279375e656bba35280a85b62973255

stage2: more Decl lifetime fixes

* File stores `root_decl: Decl` instead of `namespace: *Namespace`. This maps more cleanly to the actual ownership, since the `File` does own the root decl, but it does not directly own the `Namespace`. * `semaFile` completes the creation of the `Decl` even when semantic analysis fails. The `analysis` field of the `Decl` will contain the results of semantic analysis. This prevents cleaning up of memory still referenced by other Decl objects. * `semaDecl` sets `Struct.zir_index` of the root struct decl, which fixes use of undefined value in case the first update contained a ZIR compile error.

3 files changed, 25 insertions(+), 21 deletions(-)

src/Module.zig+21-17
...@@ -822,7 +822,7 @@ pub const Scope = struct {...@@ -822,7 +822,7 @@ pub const Scope = struct {
822 pub fn namespace(scope: *Scope) *Namespace {822 pub fn namespace(scope: *Scope) *Namespace {
823 switch (scope.tag) {823 switch (scope.tag) {
824 .block => return scope.cast(Block).?.sema.owner_decl.namespace,824 .block => return scope.cast(Block).?.sema.owner_decl.namespace,
825 .file => return scope.cast(File).?.namespace.?,825 .file => return scope.cast(File).?.root_decl.?.namespace,
826 .namespace => return scope.cast(Namespace).?,826 .namespace => return scope.cast(Namespace).?,
827 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,827 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,
828 }828 }
...@@ -998,10 +998,8 @@ pub const Scope = struct {...@@ -998,10 +998,8 @@ pub const Scope = struct {
998 zir: Zir,998 zir: Zir,
999 /// Package that this file is a part of, managed externally.999 /// Package that this file is a part of, managed externally.
1000 pkg: *Package,1000 pkg: *Package,
1001 /// The namespace of the struct that represents this file.1001 /// The Decl of the struct that represents this File.
1002 /// Populated only when `have_decl` is true.1002 root_decl: ?*Decl,
1003 /// Owned by its owner Decl Value.
1004 namespace: ?*Namespace,
10051003
1006 /// Used by change detection algorithm, after astgen, contains the1004 /// Used by change detection algorithm, after astgen, contains the
1007 /// set of decls that existed in the previous ZIR but not in the new one.1005 /// set of decls that existed in the previous ZIR but not in the new one.
...@@ -1049,8 +1047,8 @@ pub const Scope = struct {...@@ -1049,8 +1047,8 @@ pub const Scope = struct {
1049 log.debug("deinit File {s}", .{file.sub_file_path});1047 log.debug("deinit File {s}", .{file.sub_file_path});
1050 file.deleted_decls.deinit(gpa);1048 file.deleted_decls.deinit(gpa);
1051 file.outdated_decls.deinit(gpa);1049 file.outdated_decls.deinit(gpa);
1052 if (file.namespace) |ns| {1050 if (file.root_decl) |root_decl| {
1053 ns.getDecl().destroy(mod);1051 root_decl.destroy(mod);
1054 }1052 }
1055 gpa.free(file.sub_file_path);1053 gpa.free(file.sub_file_path);
1056 file.unload(gpa);1054 file.unload(gpa);
...@@ -2576,11 +2574,11 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node...@@ -2576,11 +2574,11 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
2576 gpa.destroy(file_prev_zir);2574 gpa.destroy(file_prev_zir);
2577 file.prev_zir = null;2575 file.prev_zir = null;
2578 try updateZirRefs(gpa, file, prev_zir);2576 try updateZirRefs(gpa, file, prev_zir);
2579 } else if (file.namespace) |ns| {2577 } else if (file.root_decl) |root_decl| {
2580 // First time the File has succeeded ZIR. We must mark it outdated since2578 // First time the File has succeeded ZIR. We must mark it outdated since
2581 // we have already tried to semantically analyze it.2579 // we have already tried to semantically analyze it.
2582 try file.outdated_decls.resize(gpa, 1);2580 try file.outdated_decls.resize(gpa, 1);
2583 file.outdated_decls.items[0] = ns.getDecl();2581 file.outdated_decls.items[0] = root_decl;
2584 }2582 }
2585 } else {2583 } else {
2586 try updateZirRefs(gpa, file, prev_zir);2584 try updateZirRefs(gpa, file, prev_zir);
...@@ -2626,7 +2624,7 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {...@@ -2626,7 +2624,7 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
2626 var decl_stack: std.ArrayListUnmanaged(*Decl) = .{};2624 var decl_stack: std.ArrayListUnmanaged(*Decl) = .{};
2627 defer decl_stack.deinit(gpa);2625 defer decl_stack.deinit(gpa);
26282626
2629 const root_decl = file.namespace.?.getDecl();2627 const root_decl = file.root_decl.?;
2630 try decl_stack.append(gpa, root_decl);2628 try decl_stack.append(gpa, root_decl);
26312629
2632 file.deleted_decls.clearRetainingCapacity();2630 file.deleted_decls.clearRetainingCapacity();
...@@ -2848,7 +2846,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -2848,7 +2846,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
2848 const tracy = trace(@src());2846 const tracy = trace(@src());
2849 defer tracy.end();2847 defer tracy.end();
28502848
2851 if (file.namespace != null) return;2849 if (file.root_decl != null) return;
28522850
2853 const gpa = mod.gpa;2851 const gpa = mod.gpa;
2854 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);2852 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
...@@ -2870,8 +2868,8 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -2870,8 +2868,8 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
2870 .file_scope = file,2868 .file_scope = file,
2871 },2869 },
2872 };2870 };
2873 file.namespace = &struct_obj.namespace;
2874 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);2871 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);
2872 file.root_decl = new_decl;
2875 struct_obj.owner_decl = new_decl;2873 struct_obj.owner_decl = new_decl;
2876 new_decl.src_line = 0;2874 new_decl.src_line = 0;
2877 new_decl.name = try file.fullyQualifiedNameZ(gpa);2875 new_decl.name = try file.fullyQualifiedNameZ(gpa);
...@@ -2917,9 +2915,12 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -2917,9 +2915,12 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
2917 };2915 };
2918 defer block_scope.instructions.deinit(gpa);2916 defer block_scope.instructions.deinit(gpa);
29192917
2920 try sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj);2918 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
29212919 new_decl.analysis = .complete;
2922 new_decl.analysis = .complete;2920 } else |err| switch (err) {
2921 error.OutOfMemory => return error.OutOfMemory,
2922 error.AnalysisFail => {},
2923 }
2923 } else {2924 } else {
2924 new_decl.analysis = .file_failure;2925 new_decl.analysis = .file_failure;
2925 }2926 }
...@@ -2964,6 +2965,9 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -2964,6 +2965,9 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
2964 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });2965 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
2965 const main_struct_inst = zir.getMainStruct();2966 const main_struct_inst = zir.getMainStruct();
2966 const struct_obj = decl.getStruct().?;2967 const struct_obj = decl.getStruct().?;
2968 // This might not have gotten set in `semaFile` if the first time had
2969 // a ZIR failure, so we set it here in case.
2970 struct_obj.zir_index = main_struct_inst;
2967 try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);2971 try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
2968 decl.analysis = .complete;2972 decl.analysis = .complete;
2969 decl.generation = mod.generation;2973 decl.generation = mod.generation;
...@@ -3165,7 +3169,7 @@ pub fn importPkg(mod: *Module, cur_pkg: *Package, pkg: *Package) !ImportFileResu...@@ -3165,7 +3169,7 @@ pub fn importPkg(mod: *Module, cur_pkg: *Package, pkg: *Package) !ImportFileResu
3165 .zir = undefined,3169 .zir = undefined,
3166 .status = .never_loaded,3170 .status = .never_loaded,
3167 .pkg = pkg,3171 .pkg = pkg,
3168 .namespace = null,3172 .root_decl = null,
3169 };3173 };
3170 return ImportFileResult{3174 return ImportFileResult{
3171 .file = new_file,3175 .file = new_file,
...@@ -3231,7 +3235,7 @@ pub fn importFile(...@@ -3231,7 +3235,7 @@ pub fn importFile(
3231 .zir = undefined,3235 .zir = undefined,
3232 .status = .never_loaded,3236 .status = .never_loaded,
3233 .pkg = cur_file.pkg,3237 .pkg = cur_file.pkg,
3234 .namespace = null,3238 .root_decl = null,
3235 };3239 };
3236 return ImportFileResult{3240 return ImportFileResult{
3237 .file = new_file,3241 .file = new_file,
src/Sema.zig+2-2
...@@ -4409,7 +4409,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!...@@ -4409,7 +4409,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
4409 },4409 },
4410 };4410 };
4411 try mod.semaFile(result.file);4411 try mod.semaFile(result.file);
4412 return mod.constType(sema.arena, src, result.file.namespace.?.ty);4412 return mod.constType(sema.arena, src, result.file.root_decl.?.ty);
4413}4413}
44144414
4415fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {4415fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
...@@ -7307,7 +7307,7 @@ fn getBuiltinType(...@@ -7307,7 +7307,7 @@ fn getBuiltinType(
7307 const opt_builtin_inst = try sema.analyzeNamespaceLookup(7307 const opt_builtin_inst = try sema.analyzeNamespaceLookup(
7308 block,7308 block,
7309 src,7309 src,
7310 std_file.namespace.?,7310 std_file.root_decl.?.namespace,
7311 "builtin",7311 "builtin",
7312 );7312 );
7313 const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src);7313 const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src);
src/main.zig+2-2
...@@ -3656,7 +3656,7 @@ pub fn cmdAstgen(...@@ -3656,7 +3656,7 @@ pub fn cmdAstgen(
3656 .tree = undefined,3656 .tree = undefined,
3657 .zir = undefined,3657 .zir = undefined,
3658 .pkg = undefined,3658 .pkg = undefined,
3659 .namespace = undefined,3659 .root_decl = null,
3660 };3660 };
36613661
3662 const source = try arena.allocSentinel(u8, stat.size, 0);3662 const source = try arena.allocSentinel(u8, stat.size, 0);
...@@ -3766,7 +3766,7 @@ pub fn cmdChangelist(...@@ -3766,7 +3766,7 @@ pub fn cmdChangelist(
3766 .tree = undefined,3766 .tree = undefined,
3767 .zir = undefined,3767 .zir = undefined,
3768 .pkg = undefined,3768 .pkg = undefined,
3769 .namespace = undefined,3769 .root_decl = null,
3770 };3770 };
37713771
3772 const source = try arena.allocSentinel(u8, stat.size, 0);3772 const source = try arena.allocSentinel(u8, stat.size, 0);