diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 2844bda55a..fca6d74e21 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -3615,145 +3615,155 @@ pub const DeclIterator = struct { }; pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { - const tags = zir.instructions.items(.tag); - const datas = zir.instructions.items(.data); - switch (tags[@intFromEnum(decl_inst)]) { - // Functions are allowed and yield no iterations. - // This is because they are returned by `findDecls`. - .func, .func_inferred, .func_fancy => return .{ - .extra_index = undefined, - .decls_remaining = 0, - .zir = zir, - }, + const inst = zir.instructions.get(@intFromEnum(decl_inst)); + assert(inst.tag == .extended); + const extended = inst.data.extended; + switch (extended.opcode) { + .struct_decl => { + const small: Inst.StructDecl.Small = @bitCast(extended.small); + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).@"struct".fields.len); + const captures_len = if (small.has_captures_len) captures_len: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :captures_len captures_len; + } else 0; + extra_index += @intFromBool(small.has_fields_len); + const decls_len = if (small.has_decls_len) decls_len: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :decls_len decls_len; + } else 0; - .extended => { - const extended = datas[@intFromEnum(decl_inst)].extended; - switch (extended.opcode) { - // Reifications are allowed and yield no iterations. - // This is because they are returned by `findDecls`. - .reify => return .{ - .extra_index = undefined, - .decls_remaining = 0, - .zir = zir, - }, - .struct_decl => { - const small: Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).@"struct".fields.len); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; + extra_index += captures_len; - extra_index += captures_len; - - if (small.has_backing_int) { - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; // backing_int_body_len - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - extra_index += backing_int_body_len; // backing_int_body_inst - } - } - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .enum_decl => { - const small: Inst.EnumDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).@"struct".fields.len); - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .union_decl => { - const small: Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).@"struct".fields.len); - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .opaque_decl => { - const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.OpaqueDecl).@"struct".fields.len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - - extra_index += captures_len; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - else => unreachable, + if (small.has_backing_int) { + const backing_int_body_len = zir.extra[extra_index]; + extra_index += 1; // backing_int_body_len + if (backing_int_body_len == 0) { + extra_index += 1; // backing_int_ref + } else { + extra_index += backing_int_body_len; // backing_int_body_inst + } } + + return .{ + .extra_index = extra_index, + .decls_remaining = decls_len, + .zir = zir, + }; + }, + .enum_decl => { + const small: Inst.EnumDecl.Small = @bitCast(extended.small); + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).@"struct".fields.len); + extra_index += @intFromBool(small.has_tag_type); + const captures_len = if (small.has_captures_len) captures_len: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :captures_len captures_len; + } else 0; + extra_index += @intFromBool(small.has_body_len); + extra_index += @intFromBool(small.has_fields_len); + const decls_len = if (small.has_decls_len) decls_len: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :decls_len decls_len; + } else 0; + + extra_index += captures_len; + + return .{ + .extra_index = extra_index, + .decls_remaining = decls_len, + .zir = zir, + }; + }, + .union_decl => { + const small: Inst.UnionDecl.Small = @bitCast(extended.small); + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).@"struct".fields.len); + extra_index += @intFromBool(small.has_tag_type); + const captures_len = if (small.has_captures_len) captures_len: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :captures_len captures_len; + } else 0; + extra_index += @intFromBool(small.has_body_len); + extra_index += @intFromBool(small.has_fields_len); + const decls_len = if (small.has_decls_len) decls_len: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :decls_len decls_len; + } else 0; + + extra_index += captures_len; + + return .{ + .extra_index = extra_index, + .decls_remaining = decls_len, + .zir = zir, + }; + }, + .opaque_decl => { + const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.OpaqueDecl).@"struct".fields.len); + const decls_len = if (small.has_decls_len) decls_len: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :decls_len decls_len; + } else 0; + const captures_len = if (small.has_captures_len) captures_len: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :captures_len captures_len; + } else 0; + + extra_index += captures_len; + + return .{ + .extra_index = extra_index, + .decls_remaining = decls_len, + .zir = zir, + }; }, else => unreachable, } } -/// Find all type declarations, recursively, within a `declaration` instruction. Does not recurse through -/// said type declarations' declarations; to find all declarations, call this function on the declarations -/// of the discovered types recursively. -/// The iterator would have to allocate memory anyway to iterate, so an `ArrayList` is populated as the result. -pub fn findDecls(zir: Zir, gpa: Allocator, list: *std.ArrayListUnmanaged(Inst.Index), decl_inst: Zir.Inst.Index) !void { - list.clearRetainingCapacity(); +/// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`. +/// These instructions are partitioned into a few different sets, since this makes ZIR instruction mapping +/// more effective. +pub const DeclContents = struct { + /// This is a simple optional because ZIR guarantees that a `func`/`func_inferred`/`func_fancy` instruction + /// can only occur once per `declaration`. + func_decl: ?Inst.Index, + explicit_types: std.ArrayListUnmanaged(Inst.Index), + other: std.ArrayListUnmanaged(Inst.Index), + + pub const init: DeclContents = .{ + .func_decl = null, + .explicit_types = .empty, + .other = .empty, + }; + + pub fn clear(contents: *DeclContents) void { + contents.func_decl = null; + contents.explicit_types.clearRetainingCapacity(); + contents.other.clearRetainingCapacity(); + } + + pub fn deinit(contents: *DeclContents, gpa: Allocator) void { + contents.explicit_types.deinit(gpa); + contents.other.deinit(gpa); + } +}; + +/// Find all tracked ZIR instructions, recursively, within a `declaration` instruction. Does not recurse through +/// nested declarations; to find all declarations, call this function recursively on the type declarations discovered +/// in `contents.explicit_types`. +/// +/// This populates an `ArrayListUnmanaged` because an iterator would need to allocate memory anyway. +pub fn findTrackable(zir: Zir, gpa: Allocator, contents: *DeclContents, decl_inst: Zir.Inst.Index) !void { + contents.clear(); + const declaration, const extra_end = zir.getDeclaration(decl_inst); const bodies = declaration.getBodies(extra_end, zir); @@ -3762,27 +3772,27 @@ pub fn findDecls(zir: Zir, gpa: Allocator, list: *std.ArrayListUnmanaged(Inst.In var found_defers: std.AutoHashMapUnmanaged(u32, void) = .empty; defer found_defers.deinit(gpa); - try zir.findDeclsBody(gpa, list, &found_defers, bodies.value_body); - if (bodies.align_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b); - if (bodies.linksection_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b); - if (bodies.addrspace_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b); + try zir.findTrackableBody(gpa, contents, &found_defers, bodies.value_body); + if (bodies.align_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b); + if (bodies.linksection_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b); + if (bodies.addrspace_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b); } -/// Like `findDecls`, but only considers the `main_struct_inst` instruction. This may return more than +/// Like `findTrackable`, but only considers the `main_struct_inst` instruction. This may return more than /// just that instruction because it will also traverse fields. -pub fn findDeclsRoot(zir: Zir, gpa: Allocator, list: *std.ArrayListUnmanaged(Inst.Index)) !void { - list.clearRetainingCapacity(); +pub fn findTrackableRoot(zir: Zir, gpa: Allocator, contents: *DeclContents) !void { + contents.clear(); var found_defers: std.AutoHashMapUnmanaged(u32, void) = .empty; defer found_defers.deinit(gpa); - try zir.findDeclsInner(gpa, list, &found_defers, .main_struct_inst); + try zir.findTrackableInner(gpa, contents, &found_defers, .main_struct_inst); } -fn findDeclsInner( +fn findTrackableInner( zir: Zir, gpa: Allocator, - list: *std.ArrayListUnmanaged(Inst.Index), + contents: *DeclContents, defers: *std.AutoHashMapUnmanaged(u32, void), inst: Inst.Index, ) Allocator.Error!void { @@ -4026,7 +4036,7 @@ fn findDeclsInner( .struct_init, .struct_init_ref, .struct_init_anon, - => return list.append(gpa, inst), + => return contents.other.append(gpa, inst), .extended => { const extended = datas[@intFromEnum(inst)].extended; @@ -4093,15 +4103,15 @@ fn findDeclsInner( .typeof_peer => { const extra = zir.extraData(Zir.Inst.TypeOfPeer, extended.operand); const body = zir.bodySlice(extra.data.body_index, extra.data.body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, // Reifications and opaque declarations need tracking, but have no body. - .reify, .opaque_decl => return list.append(gpa, inst), + .reify, .opaque_decl => return contents.other.append(gpa, inst), // Struct declarations need tracking and have bodies. .struct_decl => { - try list.append(gpa, inst); + try contents.explicit_types.append(gpa, inst); const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); @@ -4130,7 +4140,7 @@ fn findDeclsInner( } else { const body = zir.bodySlice(extra_index, backing_int_body_len); extra_index += backing_int_body_len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } } extra_index += decls_len; @@ -4186,12 +4196,12 @@ fn findDeclsInner( // Now, `fields_extra_index` points to `bodies`. Let's treat this as one big body. const merged_bodies = zir.bodySlice(fields_extra_index, total_bodies_len); - try zir.findDeclsBody(gpa, list, defers, merged_bodies); + try zir.findTrackableBody(gpa, contents, defers, merged_bodies); }, // Union declarations need tracking and have a body. .union_decl => { - try list.append(gpa, inst); + try contents.explicit_types.append(gpa, inst); const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); @@ -4216,12 +4226,12 @@ fn findDeclsInner( extra_index += captures_len; extra_index += decls_len; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, // Enum declarations need tracking and have a body. .enum_decl => { - try list.append(gpa, inst); + try contents.explicit_types.append(gpa, inst); const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); @@ -4246,7 +4256,7 @@ fn findDeclsInner( extra_index += captures_len; extra_index += decls_len; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, } }, @@ -4255,7 +4265,8 @@ fn findDeclsInner( .func, .func_inferred, => { - try list.append(gpa, inst); + assert(contents.func_decl == null); + contents.func_decl = inst; const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = zir.extraData(Inst.Func, inst_data.payload_index); @@ -4266,14 +4277,15 @@ fn findDeclsInner( else => { const body = zir.bodySlice(extra_index, extra.data.ret_body_len); extra_index += body.len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, } const body = zir.bodySlice(extra_index, extra.data.body_len); - return zir.findDeclsBody(gpa, list, defers, body); + return zir.findTrackableBody(gpa, contents, defers, body); }, .func_fancy => { - try list.append(gpa, inst); + assert(contents.func_decl == null); + contents.func_decl = inst; const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index); @@ -4284,7 +4296,7 @@ fn findDeclsInner( const body_len = zir.extra[extra_index]; extra_index += 1; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); extra_index += body.len; } else if (extra.data.bits.has_align_ref) { extra_index += 1; @@ -4294,7 +4306,7 @@ fn findDeclsInner( const body_len = zir.extra[extra_index]; extra_index += 1; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); extra_index += body.len; } else if (extra.data.bits.has_addrspace_ref) { extra_index += 1; @@ -4304,7 +4316,7 @@ fn findDeclsInner( const body_len = zir.extra[extra_index]; extra_index += 1; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); extra_index += body.len; } else if (extra.data.bits.has_section_ref) { extra_index += 1; @@ -4314,7 +4326,7 @@ fn findDeclsInner( const body_len = zir.extra[extra_index]; extra_index += 1; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); extra_index += body.len; } else if (extra.data.bits.has_cc_ref) { extra_index += 1; @@ -4324,7 +4336,7 @@ fn findDeclsInner( const body_len = zir.extra[extra_index]; extra_index += 1; const body = zir.bodySlice(extra_index, body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); extra_index += body.len; } else if (extra.data.bits.has_ret_ty_ref) { extra_index += 1; @@ -4333,7 +4345,7 @@ fn findDeclsInner( extra_index += @intFromBool(extra.data.bits.has_any_noalias); const body = zir.bodySlice(extra_index, extra.data.body_len); - return zir.findDeclsBody(gpa, list, defers, body); + return zir.findTrackableBody(gpa, contents, defers, body); }, // Block instructions, recurse over the bodies. @@ -4348,24 +4360,24 @@ fn findDeclsInner( const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = zir.extraData(Inst.Block, inst_data.payload_index); const body = zir.bodySlice(extra.end, extra.data.body_len); - return zir.findDeclsBody(gpa, list, defers, body); + return zir.findTrackableBody(gpa, contents, defers, body); }, .condbr, .condbr_inline => { const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = zir.extraData(Inst.CondBr, inst_data.payload_index); const then_body = zir.bodySlice(extra.end, extra.data.then_body_len); const else_body = zir.bodySlice(extra.end + then_body.len, extra.data.else_body_len); - try zir.findDeclsBody(gpa, list, defers, then_body); - try zir.findDeclsBody(gpa, list, defers, else_body); + try zir.findTrackableBody(gpa, contents, defers, then_body); + try zir.findTrackableBody(gpa, contents, defers, else_body); }, .@"try", .try_ptr => { const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = zir.extraData(Inst.Try, inst_data.payload_index); const body = zir.bodySlice(extra.end, extra.data.body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, - .switch_block, .switch_block_ref => return zir.findDeclsSwitch(gpa, list, defers, inst, .normal), - .switch_block_err_union => return zir.findDeclsSwitch(gpa, list, defers, inst, .err_union), + .switch_block, .switch_block_ref => return zir.findTrackableSwitch(gpa, contents, defers, inst, .normal), + .switch_block_err_union => return zir.findTrackableSwitch(gpa, contents, defers, inst, .err_union), .suspend_block => @panic("TODO iterate suspend block"), @@ -4373,7 +4385,7 @@ fn findDeclsInner( const inst_data = datas[@intFromEnum(inst)].pl_tok; const extra = zir.extraData(Inst.Param, inst_data.payload_index); const body = zir.bodySlice(extra.end, extra.data.body_len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); }, inline .call, .field_call => |tag| { @@ -4389,7 +4401,7 @@ fn findDeclsInner( const first_arg_start_off = args_len; const final_arg_end_off = zir.extra[extra.end + args_len - 1]; const args_body = zir.bodySlice(extra.end + first_arg_start_off, final_arg_end_off - first_arg_start_off); - try zir.findDeclsBody(gpa, list, defers, args_body); + try zir.findTrackableBody(gpa, contents, defers, args_body); } }, .@"defer" => { @@ -4397,7 +4409,7 @@ fn findDeclsInner( const gop = try defers.getOrPut(gpa, inst_data.index); if (!gop.found_existing) { const body = zir.bodySlice(inst_data.index, inst_data.len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } }, .defer_err_code => { @@ -4406,16 +4418,16 @@ fn findDeclsInner( const gop = try defers.getOrPut(gpa, extra.index); if (!gop.found_existing) { const body = zir.bodySlice(extra.index, extra.len); - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } }, } } -fn findDeclsSwitch( +fn findTrackableSwitch( zir: Zir, gpa: Allocator, - list: *std.ArrayListUnmanaged(Inst.Index), + contents: *DeclContents, defers: *std.AutoHashMapUnmanaged(u32, void), inst: Inst.Index, /// Distinguishes between `switch_block[_ref]` and `switch_block_err_union`. @@ -4451,7 +4463,7 @@ fn findDeclsSwitch( const body = zir.bodySlice(extra_index, prong_info.body_len); extra_index += body.len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); break :has_special extra.data.bits.has_else; }, @@ -4463,7 +4475,7 @@ fn findDeclsSwitch( const body = zir.bodySlice(extra_index, prong_info.body_len); extra_index += body.len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } { @@ -4475,7 +4487,7 @@ fn findDeclsSwitch( const body = zir.bodySlice(extra_index, prong_info.body_len); extra_index += body.len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } } { @@ -4492,20 +4504,20 @@ fn findDeclsSwitch( const body = zir.bodySlice(extra_index, prong_info.body_len); extra_index += body.len; - try zir.findDeclsBody(gpa, list, defers, body); + try zir.findTrackableBody(gpa, contents, defers, body); } } } -fn findDeclsBody( +fn findTrackableBody( zir: Zir, gpa: Allocator, - list: *std.ArrayListUnmanaged(Inst.Index), + contents: *DeclContents, defers: *std.AutoHashMapUnmanaged(u32, void), body: []const Inst.Index, ) Allocator.Error!void { for (body) |member| { - try zir.findDeclsInner(gpa, list, defers, member); + try zir.findTrackableInner(gpa, contents, defers, member); } } diff --git a/src/Zcu.zig b/src/Zcu.zig index d03eb4cc9a..bb2dc2a8df 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2593,26 +2593,44 @@ pub fn mapOldZirToNew( defer match_stack.deinit(gpa); // Used as temporary buffers for namespace declaration instructions - var old_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty; - defer old_decls.deinit(gpa); - var new_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty; - defer new_decls.deinit(gpa); + var old_contents: Zir.DeclContents = .init; + defer old_contents.deinit(gpa); + var new_contents: Zir.DeclContents = .init; + defer new_contents.deinit(gpa); // Map the main struct inst (and anything in its fields) { - try old_zir.findDeclsRoot(gpa, &old_decls); - try new_zir.findDeclsRoot(gpa, &new_decls); + try old_zir.findTrackableRoot(gpa, &old_contents); + try new_zir.findTrackableRoot(gpa, &new_contents); - assert(old_decls.items[0] == .main_struct_inst); - assert(new_decls.items[0] == .main_struct_inst); + assert(old_contents.explicit_types.items[0] == .main_struct_inst); + assert(new_contents.explicit_types.items[0] == .main_struct_inst); - // We don't have any smart way of matching up these type declarations, so we always - // correlate them based on source order. - const n = @min(old_decls.items.len, new_decls.items.len); - try match_stack.ensureUnusedCapacity(gpa, n); - for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| { + assert(old_contents.func_decl == null); + assert(new_contents.func_decl == null); + + // We don't have any smart way of matching up these instructions, so we correlate them based on source order + // in their respective arrays. + + const num_explicit_types = @min(old_contents.explicit_types.items.len, new_contents.explicit_types.items.len); + try match_stack.ensureUnusedCapacity(gpa, @intCast(num_explicit_types)); + for ( + old_contents.explicit_types.items[0..num_explicit_types], + new_contents.explicit_types.items[0..num_explicit_types], + ) |old_inst, new_inst| { + // Here we use `match_stack`, so that we will recursively consider declarations on these types. match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst }); } + + const num_other = @min(old_contents.other.items.len, new_contents.other.items.len); + try inst_map.ensureUnusedCapacity(gpa, @intCast(num_other)); + for ( + old_contents.other.items[0..num_other], + new_contents.other.items[0..num_other], + ) |old_inst, new_inst| { + // These instructions don't have declarations, so we just modify `inst_map` directly. + inst_map.putAssumeCapacity(old_inst, new_inst); + } } while (match_stack.popOrNull()) |match_item| { @@ -2700,17 +2718,39 @@ pub fn mapOldZirToNew( // Match the `declaration` instruction try inst_map.put(gpa, old_decl_inst, new_decl_inst); - // Find container type declarations within this declaration - try old_zir.findDecls(gpa, &old_decls, old_decl_inst); - try new_zir.findDecls(gpa, &new_decls, new_decl_inst); + // Find trackable instructions within this declaration + try old_zir.findTrackable(gpa, &old_contents, old_decl_inst); + try new_zir.findTrackable(gpa, &new_contents, new_decl_inst); - // We don't have any smart way of matching up these type declarations, so we always - // correlate them based on source order. - const n = @min(old_decls.items.len, new_decls.items.len); - try match_stack.ensureUnusedCapacity(gpa, n); - for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| { + // We don't have any smart way of matching up these instructions, so we correlate them based on source order + // in their respective arrays. + + const num_explicit_types = @min(old_contents.explicit_types.items.len, new_contents.explicit_types.items.len); + try match_stack.ensureUnusedCapacity(gpa, @intCast(num_explicit_types)); + for ( + old_contents.explicit_types.items[0..num_explicit_types], + new_contents.explicit_types.items[0..num_explicit_types], + ) |old_inst, new_inst| { + // Here we use `match_stack`, so that we will recursively consider declarations on these types. match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst }); } + + const num_other = @min(old_contents.other.items.len, new_contents.other.items.len); + try inst_map.ensureUnusedCapacity(gpa, @intCast(num_other)); + for ( + old_contents.other.items[0..num_other], + new_contents.other.items[0..num_other], + ) |old_inst, new_inst| { + // These instructions don't have declarations, so we just modify `inst_map` directly. + inst_map.putAssumeCapacity(old_inst, new_inst); + } + + if (old_contents.func_decl) |old_func_inst| { + if (new_contents.func_decl) |new_func_inst| { + // There are no declarations on a function either, so again, we just directly add it to `inst_map`. + try inst_map.put(gpa, old_func_inst, new_func_inst); + } + } } } }