authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-10-20 02:34:51-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-11-01 05:42:32-04:00
log65c27e8e6612b8d649ae1481c27c8e7f0e78ad32
treef084ec93c06b48fa7380920c10751bf3e5644d4c
parent92d2aa1b48c2171d58eec51552ca30d1cc0fe206

astgen.zig: delay adding closure_capture instructions to preserve GenZir nesting. Only containers create Namespaces, so the declaring_gz is always the GenZir passed to containerDecl, and containerDecl will always add exactly one instruction (an extended *_decl) to that GenZir. Thus, closure_capture instructions are always lined up immediately after a container decl instruction, so rather than adding them at the point of first mention, where we're nested arbitrarily deep, simply walk through the Namespace captures hash map at the end of each containerDecl branch and add them then.


1 files changed, 23 insertions(+), 4 deletions(-)

src/AstGen.zig+23-4
......@@ -3850,6 +3850,7 @@ fn structDeclInner(
38503850 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
38513851 astgen.extra.appendSliceAssumeCapacity(fields_slice);
38523852
3853 try gz.addNamespaceCaptures(&namespace);
38533854 return indexToRef(decl_inst);
38543855}
38553856
......@@ -3993,6 +3994,7 @@ fn unionDeclInner(
39933994 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
39943995 astgen.extra.appendSliceAssumeCapacity(fields_slice);
39953996
3997 try gz.addNamespaceCaptures(&namespace);
39963998 return indexToRef(decl_inst);
39973999}
39984000
......@@ -4234,6 +4236,7 @@ fn containerDecl(
42344236 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
42354237 astgen.extra.appendSliceAssumeCapacity(fields_slice);
42364238
4239 try gz.addNamespaceCaptures(&namespace);
42374240 return rvalue(gz, rl, indexToRef(decl_inst), node);
42384241 },
42394242 .keyword_opaque => {
......@@ -4268,6 +4271,7 @@ fn containerDecl(
42684271 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len);
42694272 astgen.extra.appendSliceAssumeCapacity(decls_slice);
42704273
4274 try gz.addNamespaceCaptures(&namespace);
42714275 return rvalue(gz, rl, indexToRef(decl_inst), node);
42724276 },
42734277 else => unreachable,
......@@ -6108,9 +6112,15 @@ fn tunnelThroughClosure(
61086112 // already has one for this value.
61096113 const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?);
61106114 if (!gop.found_existing) {
6111 // Make a new capture for this value
6112 const capture_ref = try ns.?.declaring_gz.?.addUnTok(.closure_capture, value, token);
6113 gop.value_ptr.* = refToIndex(capture_ref).?;
6115 // Make a new capture for this value but don't add it to the declaring_gz yet
6116 try gz.astgen.instructions.append(gz.astgen.gpa, .{
6117 .tag = .closure_capture,
6118 .data = .{ .un_tok = .{
6119 .operand = value,
6120 .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token),
6121 } },
6122 });
6123 gop.value_ptr.* = @intCast(Zir.Inst.Index, gz.astgen.instructions.len - 1);
61146124 }
61156125
61166126 // Add an instruction to get the value from the closure into
......@@ -8736,7 +8746,7 @@ const Scope = struct {
87368746
87378747 /// Map from the raw captured value to the instruction
87388748 /// ref of the capture for decls in this namespace
8739 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
8749 captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
87408750
87418751 pub fn deinit(self: *Namespace, gpa: *Allocator) void {
87428752 self.decls.deinit(gpa);
......@@ -9876,6 +9886,15 @@ const GenZir = struct {
98769886 else => unreachable,
98779887 }
98789888 }
9889
9890 fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void {
9891 if (namespace.captures.count() > 0) {
9892 try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count());
9893 for (namespace.captures.values()) |capture| {
9894 gz.instructions.appendAssumeCapacity(capture);
9895 }
9896 }
9897 }
98799898};
98809899
98819900/// This can only be for short-lived references; the memory becomes invalidated