From 1e91ee1e05f08013e3a4edec5d9f0aef978f3f0b Mon Sep 17 00:00:00 2001 From: mlugg Date: Sat, 3 Feb 2024 01:22:56 +0000 Subject: [PATCH] Zir: store extra source hashes required for incremental Also add corresponding invaidation logic to Zcu. Therefore, the only invalidation logic which is not yet in place is `decl_val` dependencies. --- lib/std/zig.zig | 5 +- src/AstGen.zig | 109 +++++++++++++++++++++++++++++++------ src/Autodoc.zig | 6 +-- src/Module.zig | 12 +++++ src/Sema.zig | 14 ++--- src/Zir.zig | 134 ++++++++++++++++++++++++++++++++++++++++++++-- src/print_zir.zig | 37 +++++++++++-- 7 files changed, 283 insertions(+), 34 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 84feb2cf0a..e0787e7312 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -27,11 +27,12 @@ pub const parseNumberLiteral = number_literal.parseNumberLiteral; pub const c_builtins = @import("zig/c_builtins.zig"); pub const c_translation = @import("zig/c_translation.zig"); +pub const SrcHasher = std.crypto.hash.Blake3; pub const SrcHash = [16]u8; pub fn hashSrc(src: []const u8) SrcHash { var out: SrcHash = undefined; - std.crypto.hash.Blake3.hash(src, &out, .{}); + SrcHasher.hash(src, &out, .{}); return out; } @@ -41,7 +42,7 @@ pub fn srcHashEql(a: SrcHash, b: SrcHash) bool { pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { var out: SrcHash = undefined; - var hasher = std.crypto.hash.Blake3.init(.{}); + var hasher = SrcHasher.init(.{}); hasher.update(&parent_hash); hasher.update(sep); hasher.update(name); diff --git a/src/AstGen.zig b/src/AstGen.zig index caa0efa851..e444f836bb 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -4815,6 +4815,7 @@ fn structDeclInner( .any_comptime_fields = false, .any_default_inits = false, .any_aligned_fields = false, + .fields_hash = std.zig.hashSrc(@tagName(layout)), }); return decl_inst.toRef(); } @@ -4936,6 +4937,12 @@ fn structDeclInner( } }; + var fields_hasher = std.zig.SrcHasher.init(.{}); + fields_hasher.update(@tagName(layout)); + if (backing_int_node != 0) { + fields_hasher.update(tree.getNodeSource(backing_int_node)); + } + var sfba = std.heap.stackFallback(256, astgen.arena); const sfba_allocator = sfba.get(); @@ -4956,6 +4963,8 @@ fn structDeclInner( .field => |field| field, }; + fields_hasher.update(tree.getNodeSource(member_node)); + if (!is_tuple) { const field_name = try astgen.identAsString(member.ast.main_token); @@ -5083,6 +5092,9 @@ fn structDeclInner( return error.AnalysisFail; } + var fields_hash: std.zig.SrcHash = undefined; + fields_hasher.final(&fields_hash); + try gz.setStruct(decl_inst, .{ .src_node = node, .layout = layout, @@ -5096,6 +5108,7 @@ fn structDeclInner( .any_comptime_fields = any_comptime_fields, .any_default_inits = any_default_inits, .any_aligned_fields = any_aligned_fields, + .fields_hash = fields_hash, }); wip_members.finishBits(bits_per_field); @@ -5174,6 +5187,13 @@ fn unionDeclInner( var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); defer wip_members.deinit(); + var fields_hasher = std.zig.SrcHasher.init(.{}); + fields_hasher.update(@tagName(layout)); + fields_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); + if (arg_node != 0) { + fields_hasher.update(astgen.tree.getNodeSource(arg_node)); + } + var sfba = std.heap.stackFallback(256, astgen.arena); const sfba_allocator = sfba.get(); @@ -5188,6 +5208,7 @@ fn unionDeclInner( .decl => continue, .field => |field| field, }; + fields_hasher.update(astgen.tree.getNodeSource(member_node)); member.convertToNonTupleLike(astgen.tree.nodes); if (member.ast.tuple_like) { return astgen.failTok(member.ast.main_token, "union field missing name", .{}); @@ -5289,6 +5310,9 @@ fn unionDeclInner( return error.AnalysisFail; } + var fields_hash: std.zig.SrcHash = undefined; + fields_hasher.final(&fields_hash); + if (!block_scope.isEmpty()) { _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); } @@ -5305,6 +5329,7 @@ fn unionDeclInner( .decls_len = decl_count, .auto_enum_tag = auto_enum_tok != null, .any_aligned_fields = any_aligned_fields, + .fields_hash = fields_hash, }); wip_members.finishBits(bits_per_field); @@ -5498,6 +5523,12 @@ fn containerDecl( var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); defer wip_members.deinit(); + var fields_hasher = std.zig.SrcHasher.init(.{}); + if (container_decl.ast.arg != 0) { + fields_hasher.update(tree.getNodeSource(container_decl.ast.arg)); + } + fields_hasher.update(&.{@intFromBool(nonexhaustive)}); + var sfba = std.heap.stackFallback(256, astgen.arena); const sfba_allocator = sfba.get(); @@ -5510,6 +5541,7 @@ fn containerDecl( for (container_decl.ast.members) |member_node| { if (member_node == counts.nonexhaustive_node) continue; + fields_hasher.update(tree.getNodeSource(member_node)); namespace.base.tag = .namespace; var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { .decl => continue, @@ -5590,6 +5622,9 @@ fn containerDecl( _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); } + var fields_hash: std.zig.SrcHash = undefined; + fields_hasher.final(&fields_hash); + const body = block_scope.instructionsSlice(); const body_len = astgen.countBodyLenAfterFixups(body); @@ -5600,6 +5635,7 @@ fn containerDecl( .body_len = body_len, .fields_len = @intCast(counts.total_fields), .decls_len = @intCast(counts.decls), + .fields_hash = fields_hash, }); wip_members.finishBits(bits_per_field); @@ -11900,8 +11936,8 @@ const GenZir = struct { var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; - var src_locs_buffer: [3]u32 = undefined; - var src_locs: []u32 = src_locs_buffer[0..0]; + var src_locs_and_hash_buffer: [7]u32 = undefined; + var src_locs_and_hash: []u32 = src_locs_and_hash_buffer[0..0]; if (args.body_gz) |body_gz| { const tree = astgen.tree; const node_tags = tree.nodes.items(.tag); @@ -11916,10 +11952,27 @@ const GenZir = struct { const rbrace_column: u32 = @intCast(astgen.source_column); const columns = args.lbrace_column | (rbrace_column << 16); - src_locs_buffer[0] = args.lbrace_line; - src_locs_buffer[1] = rbrace_line; - src_locs_buffer[2] = columns; - src_locs = &src_locs_buffer; + + const proto_hash: std.zig.SrcHash = switch (node_tags[fn_decl]) { + .fn_decl => sig_hash: { + const proto_node = node_datas[fn_decl].lhs; + break :sig_hash std.zig.hashSrc(tree.getNodeSource(proto_node)); + }, + .test_decl => std.zig.hashSrc(""), // tests don't have a prototype + else => unreachable, + }; + const proto_hash_arr: [4]u32 = @bitCast(proto_hash); + + src_locs_and_hash_buffer = .{ + args.lbrace_line, + rbrace_line, + columns, + proto_hash_arr[0], + proto_hash_arr[1], + proto_hash_arr[2], + proto_hash_arr[3], + }; + src_locs_and_hash = &src_locs_and_hash_buffer; body = body_gz.instructionsSlice(); if (args.ret_gz) |ret_gz| @@ -11953,7 +12006,7 @@ const GenZir = struct { fancyFnExprExtraLen(astgen, section_body, args.section_ref) + fancyFnExprExtraLen(astgen, cc_body, args.cc_ref) + fancyFnExprExtraLen(astgen, ret_body, ret_ref) + - body_len + src_locs.len + + body_len + src_locs_and_hash.len + @intFromBool(args.lib_name != .empty) + @intFromBool(args.noalias_bits != 0), ); @@ -12040,7 +12093,7 @@ const GenZir = struct { } astgen.appendBodyWithFixups(body); - astgen.extra.appendSliceAssumeCapacity(src_locs); + astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); // Order is important when unstacking. if (args.body_gz) |body_gz| body_gz.unstack(); @@ -12068,7 +12121,7 @@ const GenZir = struct { gpa, @typeInfo(Zir.Inst.Func).Struct.fields.len + 1 + fancyFnExprExtraLen(astgen, ret_body, ret_ref) + - body_len + src_locs.len, + body_len + src_locs_and_hash.len, ); const ret_body_len = if (ret_body.len != 0) @@ -12092,7 +12145,7 @@ const GenZir = struct { astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref)); } astgen.appendBodyWithFixups(body); - astgen.extra.appendSliceAssumeCapacity(src_locs); + astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); // Order is important when unstacking. if (args.body_gz) |body_gz| body_gz.unstack(); @@ -12853,12 +12906,20 @@ const GenZir = struct { any_comptime_fields: bool, any_default_inits: bool, any_aligned_fields: bool, + fields_hash: std.zig.SrcHash, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; - try astgen.extra.ensureUnusedCapacity(gpa, 6); - const payload_index: u32 = @intCast(astgen.extra.items.len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 6); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ + .fields_hash_0 = fields_hash_arr[0], + .fields_hash_1 = fields_hash_arr[1], + .fields_hash_2 = fields_hash_arr[2], + .fields_hash_3 = fields_hash_arr[3], + }); if (args.src_node != 0) { const node_offset = gz.nodeIndexToRelative(args.src_node); @@ -12908,12 +12969,20 @@ const GenZir = struct { layout: std.builtin.Type.ContainerLayout, auto_enum_tag: bool, any_aligned_fields: bool, + fields_hash: std.zig.SrcHash, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; - try astgen.extra.ensureUnusedCapacity(gpa, 5); - const payload_index: u32 = @intCast(astgen.extra.items.len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 5); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ + .fields_hash_0 = fields_hash_arr[0], + .fields_hash_1 = fields_hash_arr[1], + .fields_hash_2 = fields_hash_arr[2], + .fields_hash_3 = fields_hash_arr[3], + }); if (args.src_node != 0) { const node_offset = gz.nodeIndexToRelative(args.src_node); @@ -12958,12 +13027,20 @@ const GenZir = struct { fields_len: u32, decls_len: u32, nonexhaustive: bool, + fields_hash: std.zig.SrcHash, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; - try astgen.extra.ensureUnusedCapacity(gpa, 5); - const payload_index: u32 = @intCast(astgen.extra.items.len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 5); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ + .fields_hash_0 = fields_hash_arr[0], + .fields_hash_1 = fields_hash_arr[1], + .fields_hash_2 = fields_hash_arr[2], + .fields_hash_3 = fields_hash_arr[3], + }); if (args.src_node != 0) { const node_offset = gz.nodeIndexToRelative(args.src_node); diff --git a/src/Autodoc.zig b/src/Autodoc.zig index 619d58c3ce..fb027567eb 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -3497,7 +3497,7 @@ fn walkInstruction( }; const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); @@ -3627,7 +3627,7 @@ fn walkInstruction( }; const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); @@ -3778,7 +3778,7 @@ fn walkInstruction( }; const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); diff --git a/src/Module.zig b/src/Module.zig index d6ee0485ce..93b5066192 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2957,6 +2957,18 @@ fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { continue; }; + if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: { + if (new_zir.getAssociatedSrcHash(ti.inst)) |new_hash| { + if (std.zig.srcHashEql(old_hash, new_hash)) { + break :hash_changed; + } + } + // The source hash associated with this instruction changed - invalidate relevant dependencies. + zcu.comp.mutex.lock(); + defer zcu.comp.mutex.unlock(); + try zcu.markDependeeOutdated(.{ .src_hash = ti_idx }); + } + // If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies. const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) { .extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) { diff --git a/src/Sema.zig b/src/Sema.zig index abbf7f69ec..0f604d2236 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2718,7 +2718,7 @@ pub fn getStructType( assert(extended.opcode == .struct_decl); const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; extra_index += @intFromBool(small.has_src_node); const fields_len = if (small.has_fields_len) blk: { const fields_len = sema.code.extra[extra_index]; @@ -2773,7 +2773,7 @@ fn zirStructDecl( const ip = &mod.intern_pool; const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); const src: LazySrcLoc = if (small.has_src_node) blk: { - const node_offset: i32 = @bitCast(sema.code.extra[extended.operand]); + const node_offset: i32 = @bitCast(sema.code.extra[extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len]); break :blk LazySrcLoc.nodeOffset(node_offset); } else sema.src; @@ -2933,7 +2933,7 @@ fn zirEnumDecl( const mod = sema.mod; const gpa = sema.gpa; const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len; const src: LazySrcLoc = if (small.has_src_node) blk: { const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); @@ -3204,7 +3204,7 @@ fn zirUnionDecl( const mod = sema.mod; const gpa = sema.gpa; const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; const src: LazySrcLoc = if (small.has_src_node) blk: { const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); @@ -35742,7 +35742,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); if (small.has_backing_int) { - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; extra_index += @intFromBool(small.has_src_node); extra_index += @intFromBool(small.has_fields_len); extra_index += @intFromBool(small.has_decls_len); @@ -36457,7 +36457,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; assert(extended.opcode == .struct_decl); const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; extra_index += @intFromBool(small.has_src_node); @@ -36925,7 +36925,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; assert(extended.opcode == .union_decl); const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand; + var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; const src = LazySrcLoc.nodeOffset(0); extra_index += @intFromBool(small.has_src_node); diff --git a/src/Zir.zig b/src/Zir.zig index 4462083b1f..c313ab8563 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -2497,6 +2497,7 @@ pub const Inst = struct { /// } /// 2. body: Index // for each body_len /// 3. src_locs: SrcLocs // if body_len != 0 + /// 4. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype pub const Func = struct { /// If this is 0 it means a void return type. /// If this is 1 it means return_type is a simple Ref @@ -2558,6 +2559,7 @@ pub const Inst = struct { /// - each bit starting with LSB corresponds to parameter indexes /// 17. body: Index // for each body_len /// 18. src_locs: Func.SrcLocs // if body_len != 0 + /// 19. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype pub const FuncFancy = struct { /// Points to the block that contains the param instructions for this function. /// If this is a `declaration`, it refers to the declaration's value body. @@ -3040,6 +3042,12 @@ pub const Inst = struct { /// init_body_inst: Inst, // for each init_body_len /// } pub const StructDecl = struct { + // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. + // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc). + fields_hash_0: u32, + fields_hash_1: u32, + fields_hash_2: u32, + fields_hash_3: u32, pub const Small = packed struct { has_src_node: bool, has_fields_len: bool, @@ -3102,6 +3110,12 @@ pub const Inst = struct { /// value: Ref, // if corresponding bit is set /// } pub const EnumDecl = struct { + // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. + // This hash contains the source of all fields, and the backing type if specified. + fields_hash_0: u32, + fields_hash_1: u32, + fields_hash_2: u32, + fields_hash_3: u32, pub const Small = packed struct { has_src_node: bool, has_tag_type: bool, @@ -3137,6 +3151,12 @@ pub const Inst = struct { /// tag_value: Ref, // if corresponding bit is set /// } pub const UnionDecl = struct { + // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. + // This hash contains the source of all fields, and any specified attributes (`extern` etc). + fields_hash_0: u32, + fields_hash_1: u32, + fields_hash_2: u32, + fields_hash_3: u32, pub const Small = packed struct { has_src_node: bool, has_tag_type: bool, @@ -3455,7 +3475,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { switch (extended.opcode) { .struct_decl => { const small: Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: u32 = extended.operand; + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); extra_index += @intFromBool(small.has_src_node); extra_index += @intFromBool(small.has_fields_len); const decls_len = if (small.has_decls_len) decls_len: { @@ -3482,7 +3502,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { }, .enum_decl => { const small: Inst.EnumDecl.Small = @bitCast(extended.small); - var extra_index: u32 = extended.operand; + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); extra_index += @intFromBool(small.has_src_node); extra_index += @intFromBool(small.has_tag_type); extra_index += @intFromBool(small.has_body_len); @@ -3501,7 +3521,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { }, .union_decl => { const small: Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: u32 = extended.operand; + var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); extra_index += @intFromBool(small.has_src_node); extra_index += @intFromBool(small.has_tag_type); extra_index += @intFromBool(small.has_body_len); @@ -3938,3 +3958,111 @@ pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, @intCast(extra.end), }; } + +pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash { + const tag = zir.instructions.items(.tag); + const data = zir.instructions.items(.data); + switch (tag[@intFromEnum(inst)]) { + .declaration => { + const pl_node = data[@intFromEnum(inst)].pl_node; + const extra = zir.extraData(Inst.Declaration, pl_node.payload_index); + return @bitCast([4]u32{ + extra.data.src_hash_0, + extra.data.src_hash_1, + extra.data.src_hash_2, + extra.data.src_hash_3, + }); + }, + .func, .func_inferred => { + const pl_node = data[@intFromEnum(inst)].pl_node; + const extra = zir.extraData(Inst.Func, pl_node.payload_index); + if (extra.data.body_len == 0) { + // Function type or extern fn - no associated hash + return null; + } + const extra_index = extra.end + + 1 + + extra.data.body_len + + @typeInfo(Inst.Func.SrcLocs).Struct.fields.len; + return @bitCast([4]u32{ + zir.extra[extra_index + 0], + zir.extra[extra_index + 1], + zir.extra[extra_index + 2], + zir.extra[extra_index + 3], + }); + }, + .func_fancy => { + const pl_node = data[@intFromEnum(inst)].pl_node; + const extra = zir.extraData(Inst.FuncFancy, pl_node.payload_index); + if (extra.data.body_len == 0) { + // Function type or extern fn - no associated hash + return null; + } + const bits = extra.data.bits; + var extra_index = extra.end; + extra_index += @intFromBool(bits.has_lib_name); + if (bits.has_align_body) { + const body_len = zir.extra[extra_index]; + extra_index += 1 + body_len; + } else extra_index += @intFromBool(bits.has_align_ref); + if (bits.has_addrspace_body) { + const body_len = zir.extra[extra_index]; + extra_index += 1 + body_len; + } else extra_index += @intFromBool(bits.has_addrspace_ref); + if (bits.has_section_body) { + const body_len = zir.extra[extra_index]; + extra_index += 1 + body_len; + } else extra_index += @intFromBool(bits.has_section_ref); + if (bits.has_cc_body) { + const body_len = zir.extra[extra_index]; + extra_index += 1 + body_len; + } else extra_index += @intFromBool(bits.has_cc_ref); + if (bits.has_ret_ty_body) { + const body_len = zir.extra[extra_index]; + extra_index += 1 + body_len; + } else extra_index += @intFromBool(bits.has_ret_ty_ref); + extra_index += @intFromBool(bits.has_any_noalias); + extra_index += extra.data.body_len; + extra_index += @typeInfo(Zir.Inst.Func.SrcLocs).Struct.fields.len; + return @bitCast([4]u32{ + zir.extra[extra_index + 0], + zir.extra[extra_index + 1], + zir.extra[extra_index + 2], + zir.extra[extra_index + 3], + }); + }, + .extended => {}, + else => return null, + } + const extended = data[@intFromEnum(inst)].extended; + switch (extended.opcode) { + .struct_decl => { + const extra = zir.extraData(Inst.StructDecl, extended.operand).data; + return @bitCast([4]u32{ + extra.fields_hash_0, + extra.fields_hash_1, + extra.fields_hash_2, + extra.fields_hash_3, + }); + }, + .union_decl => { + const extra = zir.extraData(Inst.UnionDecl, extended.operand).data; + return @bitCast([4]u32{ + extra.fields_hash_0, + extra.fields_hash_1, + extra.fields_hash_2, + extra.fields_hash_3, + }); + }, + .enum_decl => { + const extra = zir.extraData(Inst.EnumDecl, extended.operand).data; + return @bitCast([4]u32{ + extra.fields_hash_0, + extra.fields_hash_1, + extra.fields_hash_2, + extra.fields_hash_3, + }); + }, + else => return null, + } +} diff --git a/src/print_zir.zig b/src/print_zir.zig index 32904d3a0a..f33d00c989 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -1401,7 +1401,17 @@ const Writer = struct { fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ + extra.data.fields_hash_0, + extra.data.fields_hash_1, + extra.data.fields_hash_2, + extra.data.fields_hash_3, + }); + + try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); + + var extra_index: usize = extra.end; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); @@ -1591,7 +1601,17 @@ const Writer = struct { fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ + extra.data.fields_hash_0, + extra.data.fields_hash_1, + extra.data.fields_hash_2, + extra.data.fields_hash_3, + }); + + try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); + + var extra_index: usize = extra.end; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); @@ -1733,7 +1753,18 @@ const Writer = struct { fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); - var extra_index: usize = extended.operand; + + const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); + const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ + extra.data.fields_hash_0, + extra.data.fields_hash_1, + extra.data.fields_hash_2, + extra.data.fields_hash_3, + }); + + try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); + + var extra_index: usize = extra.end; const src_node: ?i32 = if (small.has_src_node) blk: { const src_node = @as(i32, @bitCast(self.code.extra[extra_index]));