Commit d717c96877
Changed files (4)
src/Sema/comptime_ptr_access.zig
@@ -228,7 +228,7 @@ fn loadComptimePtrInner(
const base_val: MutableValue = switch (ptr.base_addr) {
.nav => |nav| val: {
- try sema.ensureNavResolved(src, nav, .fully);
+ try sema.ensureNavResolved(block, src, nav, .fully);
const val = ip.getNav(nav).status.fully_resolved.val;
switch (ip.indexToKey(val)) {
.variable => return .runtime_load,
src/Compilation.zig
@@ -3681,32 +3681,27 @@ pub fn addModuleErrorMsg(
const ref = maybe_ref orelse break;
const gop = try seen.getOrPut(gpa, ref.referencer);
if (gop.found_existing) break;
- if (ref_traces.items.len < max_references) skip: {
- const src = ref.src.upgrade(zcu);
- const source = try src.file_scope.getSource(gpa);
- const span = try src.span(gpa);
- const loc = std.zig.findLineColumn(source.bytes, span.main);
- const rt_file_path = try src.file_scope.fullPath(gpa);
- defer gpa.free(rt_file_path);
- const name = switch (ref.referencer.unwrap()) {
+ if (ref_traces.items.len < max_references) {
+ var last_call_src = ref.src;
+ var opt_inline_frame = ref.inline_frame;
+ while (opt_inline_frame.unwrap()) |inline_frame| {
+ const f = inline_frame.ptr(zcu).*;
+ const func_nav = ip.indexToKey(f.callee).func.owner_nav;
+ const func_name = ip.getNav(func_nav).name.toSlice(ip);
+ try addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true);
+ last_call_src = f.call_src;
+ opt_inline_frame = f.parent;
+ }
+ const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) {
.@"comptime" => "comptime",
.nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
.func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
- .memoized_state => break :skip,
+ .memoized_state => null,
};
- try ref_traces.append(gpa, .{
- .decl_name = try eb.addString(name),
- .src_loc = try eb.addSourceLocation(.{
- .src_path = try eb.addString(rt_file_path),
- .span_start = span.start,
- .span_main = span.main,
- .span_end = span.end,
- .line = @intCast(loc.line),
- .column = @intCast(loc.column),
- .source_line = 0,
- }),
- });
+ if (root_name) |n| {
+ try addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false);
+ }
}
referenced_by = ref.referencer;
}
@@ -3786,6 +3781,35 @@ pub fn addModuleErrorMsg(
}
}
+fn addReferenceTraceFrame(
+ zcu: *Zcu,
+ eb: *ErrorBundle.Wip,
+ ref_traces: *std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace),
+ name: []const u8,
+ lazy_src: Zcu.LazySrcLoc,
+ inlined: bool,
+) !void {
+ const gpa = zcu.gpa;
+ const src = lazy_src.upgrade(zcu);
+ const source = try src.file_scope.getSource(gpa);
+ const span = try src.span(gpa);
+ const loc = std.zig.findLineColumn(source.bytes, span.main);
+ const rt_file_path = try src.file_scope.fullPath(gpa);
+ defer gpa.free(rt_file_path);
+ try ref_traces.append(gpa, .{
+ .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),
+ .src_loc = try eb.addSourceLocation(.{
+ .src_path = try eb.addString(rt_file_path),
+ .span_start = span.start,
+ .span_main = span.main,
+ .span_end = span.end,
+ .line = @intCast(loc.line),
+ .column = @intCast(loc.column),
+ .source_line = 0,
+ }),
+ });
+}
+
pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {
const gpa = eb.gpa;
const src_path = try file.fullPath(gpa);
src/Sema.zig
@@ -448,6 +448,21 @@ pub const Block = struct {
func: InternPool.Index,
comptime_result: Air.Inst.Ref,
merges: Merges,
+ /// Populated lazily by `refFrame`.
+ ref_frame: Zcu.InlineReferenceFrame.Index.Optional = .none,
+
+ fn refFrame(inlining: *Inlining, zcu: *Zcu) Allocator.Error!Zcu.InlineReferenceFrame.Index {
+ if (inlining.ref_frame == .none) {
+ inlining.ref_frame = (try zcu.addInlineReferenceFrame(.{
+ .callee = inlining.func,
+ .call_src = inlining.call_src,
+ .parent = if (inlining.call_block.inlining) |parent_inlining| p: {
+ break :p (try parent_inlining.refFrame(zcu)).toOptional();
+ } else .none,
+ })).toOptional();
+ }
+ return inlining.ref_frame.unwrap().?;
+ }
};
pub const Merges = struct {
@@ -4287,7 +4302,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
if (zcu.intern_pool.isFuncBody(val)) {
const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));
if (try ty.fnHasRuntimeBitsSema(pt)) {
- try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = val }));
+ try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = val }));
try zcu.ensureFuncBodyAnalysisQueued(val);
}
}
@@ -6615,7 +6630,7 @@ pub fn analyzeExport(
if (options.linkage == .internal)
return;
- try sema.ensureNavResolved(src, orig_nav_index, .fully);
+ try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
.variable => |v| v.owner_nav,
@@ -6644,7 +6659,7 @@ pub fn analyzeExport(
return sema.fail(block, src, "export target cannot be extern", .{});
}
- try sema.maybeQueueFuncBodyAnalysis(src, exported_nav_index);
+ try sema.maybeQueueFuncBodyAnalysis(block, src, exported_nav_index);
try sema.exports.append(gpa, .{
.opts = options,
@@ -6892,7 +6907,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
.no_embedded_nulls,
);
const nav_index = try sema.lookupIdentifier(block, src, decl_name);
- return sema.analyzeNavRef(src, nav_index);
+ return sema.analyzeNavRef(block, src, nav_index);
}
fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -6988,7 +7003,7 @@ fn lookupInNamespace(
}
for (usingnamespaces.items) |sub_ns_nav| {
- try sema.ensureNavResolved(src, sub_ns_nav, .fully);
+ try sema.ensureNavResolved(block, src, sub_ns_nav, .fully);
const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val);
const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));
try checked_namespaces.put(gpa, sub_ns, {});
@@ -7720,8 +7735,8 @@ fn analyzeCall(
var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{
.call_block = block,
.call_src = call_src,
+ .func = func_val.?.toIntern(),
.has_comptime_args = false, // unused by error reporting
- .func = .none, // unused by error reporting
.comptime_result = .none, // unused by error reporting
.merges = undefined, // unused because we'll never `return`
} else undefined;
@@ -7999,7 +8014,7 @@ fn analyzeCall(
ref_func: {
const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func;
if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func;
- try sema.addReferenceEntry(call_src, .wrap(.{ .func = runtime_func_val.toIntern() }));
+ try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = runtime_func_val.toIntern() }));
try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());
}
@@ -17254,7 +17269,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
.@"comptime" => |index| return Air.internedToRef(index),
.runtime => |index| index,
.nav_val => |nav| return sema.analyzeNavVal(block, src, nav),
- .nav_ref => |nav| return sema.analyzeNavRef(src, nav),
+ .nav_ref => |nav| return sema.analyzeNavRef(block, src, nav),
};
// The comptime case is handled already above. Runtime case below.
@@ -18407,7 +18422,7 @@ fn typeInfoNamespaceDecls(
if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
continue;
}
- try sema.ensureNavResolved(src, nav, .fully);
+ try sema.ensureNavResolved(block, src, nav, .fully);
const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val);
try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);
}
@@ -27932,7 +27947,7 @@ fn namespaceLookupRef(
decl_name: InternPool.NullTerminatedString,
) CompileError!?Air.Inst.Ref {
const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null;
- return try sema.analyzeNavRef(src, nav);
+ return try sema.analyzeNavRef(block, src, nav);
}
fn namespaceLookupVal(
@@ -29095,7 +29110,7 @@ fn coerceExtra(
.@"extern" => |e| e.owner_nav,
else => unreachable,
};
- const inst_as_ptr = try sema.analyzeNavRef(inst_src, fn_nav);
+ const inst_as_ptr = try sema.analyzeNavRef(block, inst_src, fn_nav);
return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
}
@@ -30748,7 +30763,7 @@ fn coerceVarArgParam(
.@"fn" => fn_ptr: {
const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav;
- break :fn_ptr try sema.analyzeNavRef(inst_src, fn_nav);
+ break :fn_ptr try sema.analyzeNavRef(block, inst_src, fn_nav);
},
.array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
.float => float: {
@@ -31758,12 +31773,13 @@ fn analyzeNavVal(
src: LazySrcLoc,
nav_index: InternPool.Nav.Index,
) CompileError!Air.Inst.Ref {
- const ref = try sema.analyzeNavRefInner(src, nav_index, false);
+ const ref = try sema.analyzeNavRefInner(block, src, nav_index, false);
return sema.analyzeLoad(block, src, ref, src);
}
fn addReferenceEntry(
sema: *Sema,
+ opt_block: ?*Block,
src: LazySrcLoc,
referenced_unit: AnalUnit,
) !void {
@@ -31771,10 +31787,12 @@ fn addReferenceEntry(
if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return;
const gop = try sema.references.getOrPut(sema.gpa, referenced_unit);
if (gop.found_existing) return;
- // TODO: we need to figure out how to model inline calls here.
- // They aren't references in the analysis sense, but ought to show up in the reference trace!
- // Would representing inline calls in the reference table cause excessive memory usage?
- try zcu.addUnitReference(sema.owner, referenced_unit, src);
+ try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: {
+ const block = opt_block orelse break :inline_frame .none;
+ const inlining = block.inlining orelse break :inline_frame .none;
+ const frame = try inlining.refFrame(zcu);
+ break :inline_frame frame.toOptional();
+ });
}
pub fn addTypeReferenceEntry(
@@ -31793,7 +31811,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
const pt = sema.pt;
const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
- try sema.addReferenceEntry(src, unit);
+ try sema.addReferenceEntry(null, src, unit);
try sema.declareDependency(.{ .memoized_state = stage });
if (pt.zcu.analysis_in_progress.contains(unit)) {
@@ -31802,7 +31820,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
try pt.ensureMemoizedStateUpToDate(stage);
}
-pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
+pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -31825,7 +31843,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
.type => .{ .nav_ty = nav_index },
.fully => .{ .nav_val = nav_index },
});
- try sema.addReferenceEntry(src, anal_unit);
+ try sema.addReferenceEntry(block, src, anal_unit);
if (zcu.analysis_in_progress.contains(anal_unit)) {
return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
@@ -31855,25 +31873,25 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
} }));
}
-fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref {
- return sema.analyzeNavRefInner(src, nav_index, true);
+fn analyzeNavRef(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref {
+ return sema.analyzeNavRefInner(block, src, nav_index, true);
}
/// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed.
/// If this pointer will be used directly, `is_ref` must be `true`.
/// If this pointer will be immediately loaded (i.e. a `decl_val` instruction), `is_ref` must be `false`.
-fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref {
+fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- try sema.ensureNavResolved(src, orig_nav_index, if (is_ref) .type else .fully);
+ try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully);
const nav_index = nav: {
if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {
// Getting a pointer to this `Nav` might mean we actually get a pointer to something else!
// We need to resolve the value to know for sure.
- if (is_ref) try sema.ensureNavResolved(src, orig_nav_index, .fully);
+ if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
.func => |f| break :nav f.owner_nav,
.@"extern" => |e| break :nav e.owner_nav,
@@ -31897,7 +31915,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N
},
});
if (is_ref) {
- try sema.maybeQueueFuncBodyAnalysis(src, nav_index);
+ try sema.maybeQueueFuncBodyAnalysis(block, src, nav_index);
}
return Air.internedToRef((try pt.intern(.{ .ptr = .{
.ty = ptr_ty.toIntern(),
@@ -31906,7 +31924,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N
} })));
}
-fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {
+fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -31914,16 +31932,16 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPoo
// To avoid forcing too much resolution, let's first resolve the type, and check if it's a function.
// If it is, we can resolve the *value*, and queue analysis as needed.
- try sema.ensureNavResolved(src, nav_index, .type);
+ try sema.ensureNavResolved(block, src, nav_index, .type);
const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip));
if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return;
- try sema.ensureNavResolved(src, nav_index, .fully);
+ try sema.ensureNavResolved(block, src, nav_index, .fully);
const nav_val = zcu.navValue(nav_index);
if (!ip.isFuncBody(nav_val.toIntern())) return;
- try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));
+ try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));
try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
}
@@ -31939,8 +31957,8 @@ fn analyzeRef(
if (try sema.resolveValue(operand)) |val| {
switch (zcu.intern_pool.indexToKey(val.toIntern())) {
- .@"extern" => |e| return sema.analyzeNavRef(src, e.owner_nav),
- .func => |f| return sema.analyzeNavRef(src, f.owner_nav),
+ .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav),
+ .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav),
else => return uavRef(sema, val.toIntern()),
}
}
@@ -35504,7 +35522,7 @@ fn resolveInferredErrorSet(
}
// In this case we are dealing with the actual InferredErrorSet object that
// corresponds to the function, not one created to track an inline/comptime call.
- try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));
+ try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = func_index }));
try pt.ensureFuncBodyUpToDate(func_index);
}
src/Zcu.zig
@@ -215,6 +215,9 @@ all_references: std.ArrayListUnmanaged(Reference) = .empty,
/// Freelist of indices in `all_references`.
free_references: std.ArrayListUnmanaged(u32) = .empty,
+inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame) = .empty,
+free_inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame.Index) = .empty,
+
/// Key is the `AnalUnit` *performing* the reference. This representation allows
/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
/// Value is index into `all_type_reference` of the first reference triggered by the unit.
@@ -583,6 +586,42 @@ pub const Reference = struct {
next: u32,
/// The source location of the reference.
src: LazySrcLoc,
+ /// If not `.none`, this is the index of the `InlineReferenceFrame` which should appear
+ /// between the referencer and `referenced` in the reference trace. These frames represent
+ /// inline calls, which do not create actual references (since they happen in the caller's
+ /// `AnalUnit`), but do show in the reference trace.
+ inline_frame: InlineReferenceFrame.Index.Optional,
+};
+
+pub const InlineReferenceFrame = struct {
+ /// The inline *callee*; that is, the function which was called inline.
+ /// The *caller* is either `parent`, or else the unit causing the original `Reference`.
+ callee: InternPool.Index,
+ /// The source location of the inline call, in the *caller*.
+ call_src: LazySrcLoc,
+ /// If not `.none`, a frame which should appear directly below this one.
+ /// This will be the "parent" inline call; this frame's `callee` is our caller.
+ parent: InlineReferenceFrame.Index.Optional,
+
+ pub const Index = enum(u32) {
+ _,
+ pub fn ptr(idx: Index, zcu: *Zcu) *InlineReferenceFrame {
+ return &zcu.inline_reference_frames.items[@intFromEnum(idx)];
+ }
+ pub fn toOptional(idx: Index) Optional {
+ return @enumFromInt(@intFromEnum(idx));
+ }
+ pub const Optional = enum(u32) {
+ none = std.math.maxInt(u32),
+ _,
+ pub fn unwrap(opt: Optional) ?Index {
+ return switch (opt) {
+ .none => null,
+ _ => @enumFromInt(@intFromEnum(opt)),
+ };
+ }
+ };
+ };
};
pub const TypeReference = struct {
@@ -3440,12 +3479,28 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {
var idx = kv.value;
while (idx != std.math.maxInt(u32)) {
+ const ref = zcu.all_references.items[idx];
zcu.free_references.append(gpa, idx) catch {
// This space will be reused eventually, so we need not propagate this error.
// Just leak it for now, and let GC reclaim it later on.
break :unit_refs;
};
- idx = zcu.all_references.items[idx].next;
+ idx = ref.next;
+
+ var opt_inline_frame = ref.inline_frame;
+ while (opt_inline_frame.unwrap()) |inline_frame| {
+ // The same inline frame could be used multiple times by one unit. We need to
+ // detect this case to avoid adding it to `free_inline_reference_frames` more
+ // than once. We do that by setting `parent` to itself as a marker.
+ if (inline_frame.ptr(zcu).parent == inline_frame.toOptional()) break;
+ zcu.free_inline_reference_frames.append(gpa, inline_frame) catch {
+ // This space will be reused eventually, so we need not propagate this error.
+ // Just leak it for now, and let GC reclaim it later on.
+ break :unit_refs;
+ };
+ opt_inline_frame = inline_frame.ptr(zcu).parent;
+ inline_frame.ptr(zcu).parent = inline_frame.toOptional(); // signal to code above
+ }
}
}
@@ -3480,7 +3535,22 @@ pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void {
}
}
-pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void {
+pub fn addInlineReferenceFrame(zcu: *Zcu, frame: InlineReferenceFrame) Allocator.Error!Zcu.InlineReferenceFrame.Index {
+ const frame_idx: InlineReferenceFrame.Index = zcu.free_inline_reference_frames.pop() orelse idx: {
+ _ = try zcu.inline_reference_frames.addOne(zcu.gpa);
+ break :idx @enumFromInt(zcu.inline_reference_frames.items.len - 1);
+ };
+ frame_idx.ptr(zcu).* = frame;
+ return frame_idx;
+}
+
+pub fn addUnitReference(
+ zcu: *Zcu,
+ src_unit: AnalUnit,
+ referenced_unit: AnalUnit,
+ ref_src: LazySrcLoc,
+ inline_frame: InlineReferenceFrame.Index.Optional,
+) Allocator.Error!void {
const gpa = zcu.gpa;
zcu.clearCachedResolvedReferences();
@@ -3500,6 +3570,7 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit
.referenced = referenced_unit,
.next = if (gop.found_existing) gop.value_ptr.* else std.math.maxInt(u32),
.src = ref_src,
+ .inline_frame = inline_frame,
};
gop.value_ptr.* = @intCast(ref_idx);
@@ -3828,7 +3899,10 @@ pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionT
pub const ResolvedReference = struct {
referencer: AnalUnit,
+ /// If `inline_frame` is not `.none`, this is the *deepest* source location in the chain of
+ /// inline calls. For source locations further up the inline call stack, consult `inline_frame`.
src: LazySrcLoc,
+ inline_frame: InlineReferenceFrame.Index.Optional,
};
/// Returns a mapping from an `AnalUnit` to where it is referenced.
@@ -4037,6 +4111,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
try unit_queue.put(gpa, ref.referenced, .{
.referencer = unit,
.src = ref.src,
+ .inline_frame = ref.inline_frame,
});
}
ref_idx = ref.next;
@@ -4055,6 +4130,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
try type_queue.put(gpa, ref.referenced, .{
.referencer = unit,
.src = ref.src,
+ .inline_frame = .none,
});
}
ref_idx = ref.next;