aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-01-07 00:42:30 +0000
committermlugg <mlugg@mlugg.co.uk>2024-01-23 21:19:53 +0000
commit06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87 (patch)
treec71cc2ab5af1f24f224031f947c9ac0396df2562 /src/Sema.zig
parentae845a33c04fb287ae5a7445743c2b570e40ca1f (diff)
downloadzig-06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87.tar.gz
zig-06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87.zip
InternPool: introduce TrackedInst
It is problematic for the cached `InternPool` state to directly reference ZIR instruction indices, as these are not stable across incremental updates. The existing ZIR mapping logic attempts to handle this by iterating the existing Decl graph for a file after `AstGen` and update ZIR indices on `Decl`s, struct types, etc. However, this is unreliable due to generic instantiations, and relies on specialized logic for everything which may refer to a ZIR instruction (e.g. a struct's owner decl). I therefore determined that a prerequisite change for incremental compilation would be to rework how we store these indices. This commit introduces a `TrackedInst` type which provides a stable index (`TrackedInst.Index`) for a single ZIR instruction in the compilation. The `InternPool` now stores these values in place of ZIR instruction indices. This makes the ZIR mapping logic relatively trivial: after `AstGen` completes, we simply iterate all `TrackedInst` values and update those indices which have changed. In future, if the corresponding ZIR instruction has been removed, we must also invalidate any dependencies on this instruction to trigger any required re-analysis, however the dependency system does not yet exist.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig38
1 files changed, 21 insertions, 17 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index fc6cf0c017..7e0e317ffb 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2708,11 +2708,12 @@ pub fn getStructType(
sema: *Sema,
decl: InternPool.DeclIndex,
namespace: InternPool.NamespaceIndex,
- zir_index: Zir.Inst.Index,
+ tracked_inst: InternPool.TrackedInst.Index,
) !InternPool.Index {
const mod = sema.mod;
const gpa = sema.gpa;
const ip = &mod.intern_pool;
+ const zir_index = tracked_inst.resolve(ip);
const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;
assert(extended.opcode == .struct_decl);
const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
@@ -2747,7 +2748,7 @@ pub fn getStructType(
const ty = try ip.getStructType(gpa, .{
.decl = decl,
.namespace = namespace.toOptional(),
- .zir_index = zir_index,
+ .zir_index = tracked_inst,
.layout = small.layout,
.known_non_opv = small.known_non_opv,
.is_tuple = small.is_tuple,
@@ -2797,7 +2798,8 @@ fn zirStructDecl(
errdefer mod.destroyNamespace(new_namespace_index);
const struct_ty = ty: {
- const ty = try sema.getStructType(new_decl_index, new_namespace_index, inst);
+ const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst);
+ const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst);
if (sema.builtin_type_target_index != .none) {
ip.resolveBuiltinType(sema.builtin_type_target_index, ty);
break :ty sema.builtin_type_target_index;
@@ -2856,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(
return new_decl_index;
},
.func => {
- const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index));
+ const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip));
const zir_tags = sema.code.instructions.items(.tag);
var buf = std.ArrayList(u8).init(gpa);
@@ -3252,7 +3254,7 @@ fn zirUnionDecl(
},
.decl = new_decl_index,
.namespace = new_namespace_index,
- .zir_index = inst,
+ .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst),
.fields_len = fields_len,
.enum_tag_ty = .none,
.field_types = &.{},
@@ -7446,7 +7448,7 @@ fn analyzeCall(
// the AIR instructions of the callsite. The callee could be a generic function
// which means its parameter type expressions must be resolved in order and used
// to successively coerce the arguments.
- const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst);
+ const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst.resolve(ip));
try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
var arg_i: u32 = 0;
@@ -7494,7 +7496,7 @@ fn analyzeCall(
// each of the parameters, resolving the return type and providing it to the child
// `Sema` so that it can be used for the `ret_ptr` instruction.
const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
- try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst)
+ try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip))
else
try sema.resolveInst(fn_info.ret_ty_ref);
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
@@ -7885,7 +7887,7 @@ fn instantiateGenericCall(
const namespace_index = fn_owner_decl.src_namespace;
const namespace = mod.namespacePtr(namespace_index);
const fn_zir = namespace.file_scope.zir;
- const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);
+ const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip));
const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
@memset(comptime_args, .none);
@@ -9467,7 +9469,7 @@ fn funcCommon(
.is_generic = final_is_generic,
.is_noinline = is_noinline,
- .zir_body_inst = func_inst,
+ .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
.lbrace_line = src_locs.lbrace_line,
.rbrace_line = src_locs.rbrace_line,
.lbrace_column = @as(u16, @truncate(src_locs.columns)),
@@ -9545,7 +9547,7 @@ fn funcCommon(
.ty = func_ty,
.cc = cc,
.is_noinline = is_noinline,
- .zir_body_inst = func_inst,
+ .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
.lbrace_line = src_locs.lbrace_line,
.rbrace_line = src_locs.rbrace_line,
.lbrace_column = @as(u16, @truncate(src_locs.columns)),
@@ -21553,7 +21555,7 @@ fn zirReify(
.namespace = new_namespace_index,
.enum_tag_ty = enum_tag_ty,
.fields_len = fields_len,
- .zir_index = inst,
+ .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
.flags = .{
.layout = layout,
.status = .have_field_types,
@@ -21721,7 +21723,7 @@ fn reifyStruct(
const ty = try ip.getStructType(gpa, .{
.decl = new_decl_index,
.namespace = .none,
- .zir_index = inst,
+ .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
.layout = layout,
.known_non_opv = false,
.fields_len = fields_len,
@@ -35593,7 +35595,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
break :blk accumulator;
};
- const extended = zir.instructions.items(.data)[@intFromEnum(struct_type.zir_index)].extended;
+ const zir_index = struct_type.zir_index.resolve(ip);
+ const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
assert(extended.opcode == .struct_decl);
const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
@@ -35613,7 +35616,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
} else {
const body = zir.bodySlice(extra_index, backing_int_body_len);
- const ty_ref = try sema.resolveBody(&block, body, struct_type.zir_index);
+ const ty_ref = try sema.resolveBody(&block, body, zir_index);
break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
}
};
@@ -36357,7 +36360,7 @@ fn semaStructFields(
const decl = mod.declPtr(decl_index);
const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
const zir = mod.namespacePtr(namespace_index).file_scope.zir;
- const zir_index = struct_type.zir_index;
+ const zir_index = struct_type.zir_index.resolve(ip);
const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
@@ -36628,7 +36631,7 @@ fn semaStructFieldInits(
const decl = mod.declPtr(decl_index);
const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
const zir = mod.namespacePtr(namespace_index).file_scope.zir;
- const zir_index = struct_type.zir_index;
+ const zir_index = struct_type.zir_index.resolve(ip);
const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa);
@@ -36777,7 +36780,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
const ip = &mod.intern_pool;
const decl_index = union_type.decl;
const zir = mod.namespacePtr(union_type.namespace).file_scope.zir;
- const extended = zir.instructions.items(.data)[@intFromEnum(union_type.zir_index)].extended;
+ const zir_index = union_type.zir_index.resolve(ip);
+ 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;