Zir: use absolute nodes for declarations and type declarations

The justification for using relative source nodes in ZIR is that it
allows source locations -- which may be serialized across incremental
updates -- to be relative to the source location of their containing
declaration. However, having those "baseline" instructions themselves be
relative to their own parent is counterproductive, since the source
location updating problem is only being moved to `Decl`. Storing the
absolute node here instead makes more sense, since it allows for this
source location update logic to be elided entirely in the future by
storing a `TrackedInst.Index` to resolve a source location relative to
rather than a `Decl.Index`.
This commit is contained in:
mlugg 2024-06-10 01:22:54 +01:00
parent 82a934bb91
commit e39cc0dff7
No known key found for this signature in database
GPG Key ID: 3F5B7DCCBF4AF02E
5 changed files with 123 additions and 98 deletions

View File

@ -4011,7 +4011,7 @@ fn fnDecl(
// We insert this at the beginning so that its instruction index marks the
// start of the top level declaration.
const decl_inst = try gz.makeBlockInst(.declaration, fn_proto.ast.proto_node);
const decl_inst = try gz.makeDeclaration(fn_proto.ast.proto_node);
astgen.advanceSourceCursorToNode(decl_node);
var decl_gz: GenZir = .{
@ -4393,7 +4393,7 @@ fn globalVarDecl(
const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
// We do this at the beginning so that the instruction index marks the range start
// of the top level declaration.
const decl_inst = try gz.makeBlockInst(.declaration, node);
const decl_inst = try gz.makeDeclaration(node);
const name_token = var_decl.ast.mut_token + 1;
astgen.advanceSourceCursorToNode(node);
@ -4555,7 +4555,7 @@ fn comptimeDecl(
// Up top so the ZIR instruction index marks the start range of this
// top-level declaration.
const decl_inst = try gz.makeBlockInst(.declaration, node);
const decl_inst = try gz.makeDeclaration(node);
wip_members.nextDecl(decl_inst);
astgen.advanceSourceCursorToNode(node);
@ -4607,7 +4607,7 @@ fn usingnamespaceDecl(
};
// Up top so the ZIR instruction index marks the start range of this
// top-level declaration.
const decl_inst = try gz.makeBlockInst(.declaration, node);
const decl_inst = try gz.makeDeclaration(node);
wip_members.nextDecl(decl_inst);
astgen.advanceSourceCursorToNode(node);
@ -4651,7 +4651,7 @@ fn testDecl(
// Up top so the ZIR instruction index marks the start range of this
// top-level declaration.
const decl_inst = try gz.makeBlockInst(.declaration, node);
const decl_inst = try gz.makeDeclaration(node);
wip_members.nextDecl(decl_inst);
astgen.advanceSourceCursorToNode(node);
@ -13071,6 +13071,21 @@ const GenZir = struct {
return new_index;
}
/// Note that this returns a `Zir.Inst.Index` not a ref.
/// Does *not* append the block instruction to the scope.
/// Leaves the `payload_index` field undefined. Use `setDeclaration` to finalize.
fn makeDeclaration(gz: *GenZir, node: Ast.Node.Index) !Zir.Inst.Index {
const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
try gz.astgen.instructions.append(gz.astgen.gpa, .{
.tag = .declaration,
.data = .{ .declaration = .{
.src_node = node,
.payload_index = undefined,
} },
});
return new_index;
}
/// Note that this returns a `Zir.Inst.Index` not a ref.
/// Leaves the `payload_index` field undefined.
fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index {
@ -13117,7 +13132,7 @@ const GenZir = struct {
.fields_hash_1 = fields_hash_arr[1],
.fields_hash_2 = fields_hash_arr[2],
.fields_hash_3 = fields_hash_arr[3],
.src_node = gz.nodeIndexToRelative(args.src_node),
.src_node = args.src_node,
});
if (args.captures_len != 0) {
@ -13177,7 +13192,7 @@ const GenZir = struct {
.fields_hash_1 = fields_hash_arr[1],
.fields_hash_2 = fields_hash_arr[2],
.fields_hash_3 = fields_hash_arr[3],
.src_node = gz.nodeIndexToRelative(args.src_node),
.src_node = args.src_node,
});
if (args.tag_type != .none) {
@ -13238,7 +13253,7 @@ const GenZir = struct {
.fields_hash_1 = fields_hash_arr[1],
.fields_hash_2 = fields_hash_arr[2],
.fields_hash_3 = fields_hash_arr[3],
.src_node = gz.nodeIndexToRelative(args.src_node),
.src_node = args.src_node,
});
if (args.tag_type != .none) {
@ -13285,9 +13300,7 @@ const GenZir = struct {
assert(args.src_node != 0);
try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2);
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
.src_node = gz.nodeIndexToRelative(args.src_node),
});
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ .src_node = args.src_node });
if (args.captures_len != 0) {
astgen.extra.appendAssumeCapacity(args.captures_len);
@ -13897,7 +13910,7 @@ fn setDeclaration(
.has_align_linksection_addrspace = align_len != 0 or linksection_len != 0 or addrspace_len != 0,
},
};
astgen.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node.payload_index = try astgen.addExtra(extra);
astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index = try astgen.addExtra(extra);
if (extra.flags.has_doc_comment) {
try astgen.extra.append(gpa, @intFromEnum(true_doc_comment));
}

View File

@ -287,7 +287,7 @@ pub const Inst = struct {
/// namespace type, e.g. within a `struct_decl` instruction. It represents a
/// single source declaration (`const`/`var`/`fn`), containing the name,
/// attributes, type, and value of the declaration.
/// Uses the `pl_node` union field. Payload is `Declaration`.
/// Uses the `declaration` union field. Payload is `Declaration`.
declaration,
/// Implements `suspend {...}`.
/// Uses the `pl_node` union field. Payload is `Block`.
@ -1596,7 +1596,7 @@ pub const Inst = struct {
.block = .pl_node,
.block_comptime = .pl_node,
.block_inline = .pl_node,
.declaration = .pl_node,
.declaration = .declaration,
.suspend_block = .pl_node,
.bool_not = .un_node,
.bool_br_and = .pl_node,
@ -2370,6 +2370,16 @@ pub const Inst = struct {
/// The index being accessed.
idx: u32,
},
declaration: struct {
/// This node provides a new absolute baseline node for all instructions within this struct.
src_node: Ast.Node.Index,
/// index into extra to a `Declaration` payload.
payload_index: u32,
pub fn src(self: @This()) LazySrcLoc {
return .{ .node_abs = self.src_node };
}
},
// Make sure we don't accidentally add a field to make this union
// bigger than expected. Note that in Debug builds, Zig is allowed
@ -2408,6 +2418,7 @@ pub const Inst = struct {
defer_err_code,
save_err_ret_index,
elem_val_imm,
declaration,
};
};
@ -3018,10 +3029,11 @@ pub const Inst = struct {
fields_hash_1: u32,
fields_hash_2: u32,
fields_hash_3: u32,
src_node: i32,
/// This node provides a new absolute baseline node for all instructions within this struct.
src_node: Ast.Node.Index,
pub fn src(self: StructDecl) LazySrcLoc {
return LazySrcLoc.nodeOffset(self.src_node);
return .{ .node_abs = self.src_node };
}
pub const Small = packed struct {
@ -3150,10 +3162,11 @@ pub const Inst = struct {
fields_hash_1: u32,
fields_hash_2: u32,
fields_hash_3: u32,
src_node: i32,
/// This node provides a new absolute baseline node for all instructions within this struct.
src_node: Ast.Node.Index,
pub fn src(self: EnumDecl) LazySrcLoc {
return LazySrcLoc.nodeOffset(self.src_node);
return .{ .node_abs = self.src_node };
}
pub const Small = packed struct {
@ -3198,10 +3211,11 @@ pub const Inst = struct {
fields_hash_1: u32,
fields_hash_2: u32,
fields_hash_3: u32,
src_node: i32,
/// This node provides a new absolute baseline node for all instructions within this struct.
src_node: Ast.Node.Index,
pub fn src(self: UnionDecl) LazySrcLoc {
return LazySrcLoc.nodeOffset(self.src_node);
return .{ .node_abs = self.src_node };
}
pub const Small = packed struct {
@ -3230,10 +3244,11 @@ pub const Inst = struct {
/// 2. capture: Capture, // for every captures_len
/// 3. decl: Index, // for every decls_len; points to a `declaration` instruction
pub const OpaqueDecl = struct {
src_node: i32,
/// This node provides a new absolute baseline node for all instructions within this struct.
src_node: Ast.Node.Index,
pub fn src(self: OpaqueDecl) LazySrcLoc {
return LazySrcLoc.nodeOffset(self.src_node);
return .{ .node_abs = self.src_node };
}
pub const Small = packed struct {
@ -4046,7 +4061,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, u32 } {
assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);
const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].declaration;
const extra = zir.extraData(Inst.Declaration, pl_node.payload_index);
return .{
extra.data,

View File

@ -413,8 +413,8 @@ pub const Decl = struct {
pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies {
const zir = decl.getFileScope(zcu).zir;
const zir_index = decl.zir_decl_index.unwrap().?.resolve(&zcu.intern_pool);
const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
const declaration = zir.instructions.items(.data)[@intFromEnum(zir_index)].declaration;
const extra = zir.extraData(Zir.Inst.Declaration, declaration.payload_index);
return extra.data.getBodies(@intCast(extra.end), zir);
}
@ -4255,12 +4255,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
const zir = namespace.file_scope.zir;
const ip = &zcu.intern_pool;
const pl_node = zir.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node;
const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;
const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
const declaration = extra.data;
const line = iter.parent_decl.src_line + declaration.line_offset;
const decl_node = iter.parent_decl.relativeToNodeIndex(pl_node.src_node);
// Every Decl needs a name.
const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) {
@ -4348,14 +4347,14 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
const was_exported = decl.is_exported;
assert(decl.kind == kind); // ZIR tracking should preserve this
decl.name = decl_name;
decl.src_node = decl_node;
decl.src_node = inst_data.src_node;
decl.src_line = line;
decl.is_pub = declaration.flags.is_pub;
decl.is_exported = declaration.flags.is_export;
break :decl_index .{ was_exported, decl_index };
} else decl_index: {
// Create and set up a new Decl.
const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node);
const new_decl_index = try zcu.allocateNewDecl(namespace_index, inst_data.src_node);
const new_decl = zcu.declPtr(new_decl_index);
new_decl.kind = kind;
new_decl.name = decl_name;

View File

@ -2835,7 +2835,7 @@ fn zirStructDecl(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
extra.data.src_node,
Value.fromInterned(wip_ty.index),
small.name_strategy,
"struct",
@ -2872,7 +2872,7 @@ fn zirStructDecl(
fn createAnonymousDeclTypeNamed(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
src_node: std.zig.Ast.Node.Index,
val: Value,
name_strategy: Zir.Inst.NameStrategy,
anon_prefix: []const u8,
@ -2883,31 +2883,17 @@ fn createAnonymousDeclTypeNamed(
const gpa = sema.gpa;
const namespace = block.namespace;
const src_decl = zcu.declPtr(block.src_decl);
const src_node = src_decl.relativeToNodeIndex(src.node_offset.x);
const new_decl_index = try zcu.allocateNewDecl(namespace, src_node);
errdefer zcu.destroyDecl(new_decl_index);
switch (name_strategy) {
.anon => {
// It would be neat to have "struct:line:column" but this name has
// to survive incremental updates, where it may have been shifted down
// or up to a different line, but unchanged, and thus not unnecessarily
// semantically analyzed.
// This name is also used as the key in the parent namespace so it cannot be
// renamed.
const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index),
}, .no_embedded_nulls) catch unreachable;
try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
return new_decl_index;
},
.anon => {}, // handled after switch
.parent => {
const name = zcu.declPtr(block.src_decl).name;
try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
return new_decl_index;
},
.func => {
.func => func_strat: {
const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip));
const zir_tags = sema.code.instructions.items(.tag);
@ -2927,7 +2913,7 @@ fn createAnonymousDeclTypeNamed(
// function and the name doesn't matter since it will later
// result in a compile error.
const arg_val = sema.resolveConstValue(block, .unneeded, arg, undefined) catch
return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null);
break :func_strat; // fall through to anon strat
if (arg_i != 0) try writer.writeByte(',');
@ -2969,9 +2955,24 @@ fn createAnonymousDeclTypeNamed(
},
else => {},
};
return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null);
// fall through to anon strat
},
}
// anon strat handling.
// It would be neat to have "struct:line:column" but this name has
// to survive incremental updates, where it may have been shifted down
// or up to a different line, but unchanged, and thus not unnecessarily
// semantically analyzed.
// This name is also used as the key in the parent namespace so it cannot be
// renamed.
const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
src_decl.name.fmt(ip), anon_prefix, @intFromEnum(new_decl_index),
}, .no_embedded_nulls) catch unreachable;
try zcu.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name);
return new_decl_index;
}
fn zirEnumDecl(
@ -2991,7 +2992,6 @@ fn zirEnumDecl(
var extra_index: usize = extra.end;
const src = extra.data.src();
const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
const tag_type_ref = if (small.has_tag_type) blk: {
const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
@ -3071,7 +3071,7 @@ fn zirEnumDecl(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
extra.data.src_node,
Value.fromInterned(wip_ty.index),
small.name_strategy,
"enum",
@ -3140,14 +3140,17 @@ fn zirEnumDecl(
};
defer enum_block.instructions.deinit(sema.gpa);
// This source location applies in the context of `enum_block`.
const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };
if (body.len != 0) {
_ = try sema.analyzeInlineBody(&enum_block, body, inst);
}
if (tag_type_ref != .none) {
const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
const ty = try sema.resolveType(&enum_block, tag_ty_src, tag_type_ref);
if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) {
return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});
return sema.fail(&enum_block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});
}
break :ty ty;
} else if (fields_len == 0) {
@ -3342,7 +3345,7 @@ fn zirUnionDecl(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
extra.data.src_node,
Value.fromInterned(wip_ty.index),
small.name_strategy,
"union",
@ -3430,7 +3433,7 @@ fn zirOpaqueDecl(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
extra.data.src_node,
Value.fromInterned(wip_ty.index),
small.name_strategy,
"opaque",
@ -21658,7 +21661,7 @@ fn zirReify(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x),
Value.fromInterned(wip_ty.index),
name_strategy,
"opaque",
@ -21858,7 +21861,7 @@ fn reifyEnum(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x),
Value.fromInterned(wip_ty.index),
name_strategy,
"enum",
@ -22005,7 +22008,7 @@ fn reifyUnion(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x),
Value.fromInterned(wip_ty.index),
name_strategy,
"union",
@ -22264,7 +22267,7 @@ fn reifyStruct(
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
block,
src,
mod.declPtr(block.src_decl).relativeToNodeIndex(src.node_offset.x),
Value.fromInterned(wip_ty.index),
name_strategy,
"struct",

View File

@ -1390,9 +1390,14 @@ 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));
const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.data.src_node;
defer self.parent_decl_node = prev_parent_decl_node;
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
extra.data.fields_hash_0,
extra.data.fields_hash_1,
@ -1465,10 +1470,6 @@ const Writer = struct {
if (decls_len == 0) {
try stream.writeAll("{}, ");
} else {
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
defer self.parent_decl_node = prev_parent_decl_node;
try stream.writeAll("{\n");
self.indent += 2;
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
@ -1546,8 +1547,6 @@ const Writer = struct {
}
}
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
try stream.writeAll("{\n");
self.indent += 2;
@ -1595,18 +1594,22 @@ const Writer = struct {
try stream.writeAll(",\n");
}
self.parent_decl_node = prev_parent_decl_node;
self.indent -= 2;
try stream.writeByteNTimes(' ', self.indent);
try stream.writeAll("})");
}
try self.writeSrcNode(stream, extra.data.src_node);
try self.writeSrcNode(stream, 0);
}
fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));
const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.data.src_node;
defer self.parent_decl_node = prev_parent_decl_node;
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
extra.data.fields_hash_0,
extra.data.fields_hash_1,
@ -1670,10 +1673,6 @@ const Writer = struct {
if (decls_len == 0) {
try stream.writeAll("{}");
} else {
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
defer self.parent_decl_node = prev_parent_decl_node;
try stream.writeAll("{\n");
self.indent += 2;
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
@ -1690,7 +1689,7 @@ const Writer = struct {
if (fields_len == 0) {
try stream.writeAll("})");
try self.writeSrcNode(stream, extra.data.src_node);
try self.writeSrcNode(stream, 0);
return;
}
try stream.writeAll(", ");
@ -1698,8 +1697,6 @@ const Writer = struct {
const body = self.code.bodySlice(extra_index, body_len);
extra_index += body.len;
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
try self.writeBracedDecl(stream, body);
try stream.writeAll(", {\n");
@ -1763,17 +1760,21 @@ const Writer = struct {
try stream.writeAll(",\n");
}
self.parent_decl_node = prev_parent_decl_node;
self.indent -= 2;
try stream.writeByteNTimes(' ', self.indent);
try stream.writeAll("})");
try self.writeSrcNode(stream, extra.data.src_node);
try self.writeSrcNode(stream, 0);
}
fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.data.src_node;
defer self.parent_decl_node = prev_parent_decl_node;
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
extra.data.fields_hash_0,
extra.data.fields_hash_1,
@ -1835,10 +1836,6 @@ const Writer = struct {
if (decls_len == 0) {
try stream.writeAll("{}, ");
} else {
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
defer self.parent_decl_node = prev_parent_decl_node;
try stream.writeAll("{\n");
self.indent += 2;
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
@ -1856,12 +1853,9 @@ const Writer = struct {
const body = self.code.bodySlice(extra_index, body_len);
extra_index += body.len;
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
try self.writeBracedDecl(stream, body);
if (fields_len == 0) {
try stream.writeAll(", {})");
self.parent_decl_node = prev_parent_decl_node;
} else {
try stream.writeAll(", {\n");
@ -1900,12 +1894,11 @@ const Writer = struct {
}
try stream.writeAll(",\n");
}
self.parent_decl_node = prev_parent_decl_node;
self.indent -= 2;
try stream.writeByteNTimes(' ', self.indent);
try stream.writeAll("})");
}
try self.writeSrcNode(stream, extra.data.src_node);
try self.writeSrcNode(stream, 0);
}
fn writeOpaqueDecl(
@ -1915,6 +1908,11 @@ const Writer = struct {
) !void {
const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));
const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.data.src_node;
defer self.parent_decl_node = prev_parent_decl_node;
var extra_index: usize = extra.end;
const captures_len = if (small.has_captures_len) blk: {
@ -1948,10 +1946,6 @@ const Writer = struct {
if (decls_len == 0) {
try stream.writeAll("{})");
} else {
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(extra.data.src_node);
defer self.parent_decl_node = prev_parent_decl_node;
try stream.writeAll("{\n");
self.indent += 2;
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
@ -1959,7 +1953,7 @@ const Writer = struct {
try stream.writeByteNTimes(' ', self.indent);
try stream.writeAll("})");
}
try self.writeSrcNode(stream, extra.data.src_node);
try self.writeSrcNode(stream, 0);
}
fn writeErrorSetDecl(
@ -2729,11 +2723,16 @@ const Writer = struct {
}
fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].declaration;
const extra = self.code.extraData(Zir.Inst.Declaration, inst_data.payload_index);
const doc_comment: ?Zir.NullTerminatedString = if (extra.data.flags.has_doc_comment) dc: {
break :dc @enumFromInt(self.code.extra[extra.end]);
} else null;
const prev_parent_decl_node = self.parent_decl_node;
defer self.parent_decl_node = prev_parent_decl_node;
self.parent_decl_node = inst_data.src_node;
if (extra.data.flags.is_pub) try stream.writeAll("pub ");
if (extra.data.flags.is_export) try stream.writeAll("export ");
switch (extra.data.name) {
@ -2757,10 +2756,6 @@ const Writer = struct {
try stream.print(" line(+{d}) hash({})", .{ extra.data.line_offset, std.fmt.fmtSliceHexLower(&src_hash_bytes) });
{
const prev_parent_decl_node = self.parent_decl_node;
defer self.parent_decl_node = prev_parent_decl_node;
self.parent_decl_node = self.relativeToNodeIndex(inst_data.src_node);
const bodies = extra.data.getBodies(@intCast(extra.end), self.code);
try stream.writeAll(" value=");
@ -2783,7 +2778,7 @@ const Writer = struct {
}
try stream.writeAll(") ");
try self.writeSrc(stream, inst_data.src());
try self.writeSrcNode(stream, 0);
}
fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {