authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-28 17:43:19-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-28 17:43:19-04:00
log232077dcf90a19316261ac5745a2a947e538c3f5
treec28297faec95ec64d5f68e84a362fef3881bd8c9
parentfe737d7a8f9a801e2db103c085a200a7477cfb08

Sema: create "called from here" notes before reference traces

This allows reference traces to begin at the outermost inline call.

1 files changed, 29 insertions(+), 25 deletions(-)

src/Sema.zig+29-25
......@@ -405,7 +405,9 @@ pub const Block = struct {
405405 /// It is shared among all the blocks in an inline or comptime called
406406 /// function.
407407 pub const Inlining = struct {
408 /// Might be `none`.
408 call_block: *Block,
409 call_src: LazySrcLoc,
410 has_comptime_args: bool,
409411 func: InternPool.Index,
410412 comptime_result: Air.Inst.Ref,
411413 merges: Merges,
......@@ -2390,7 +2392,6 @@ pub fn fail(
23902392}
23912393
23922394fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) CompileError {
2393 _ = block;
23942395 @setCold(true);
23952396 const gpa = sema.gpa;
23962397 const mod = sema.mod;
......@@ -2414,6 +2415,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg)
24142415 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
24152416 try mod.failed_files.ensureUnusedCapacity(gpa, 1);
24162417
2418 var func_index: InternPool.Index = .none;
2419 if (block) |start_block| {
2420 var block_it = start_block;
2421 while (block_it.inlining) |inlining| {
2422 func_index = inlining.func;
2423 block_it = inlining.call_block;
2424 try sema.errNote(block_it, inlining.call_src, err_msg, "called from here", .{});
2425 }
2426 }
2427
24172428 const max_references = blk: {
24182429 if (mod.comp.reference_trace) |num| break :blk num;
24192430 // Do not add multiple traces without explicit request.
......@@ -7268,7 +7279,10 @@ fn analyzeCall(
72687279 // This one is shared among sub-blocks within the same callee, but not
72697280 // shared among the entire inline/comptime call stack.
72707281 var inlining: Block.Inlining = .{
7271 .func = .none,
7282 .call_block = block,
7283 .call_src = call_src,
7284 .has_comptime_args = false,
7285 .func = module_fn_index,
72727286 .comptime_result = undefined,
72737287 .merges = .{
72747288 .src_locs = .{},
......@@ -7352,7 +7366,6 @@ fn analyzeCall(
73527366 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst);
73537367 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
73547368
7355 var has_comptime_args = false;
73567369 var arg_i: u32 = 0;
73577370 for (fn_info.param_body) |inst| {
73587371 const opt_noreturn_ref = try analyzeInlineCallArg(
......@@ -7368,7 +7381,6 @@ fn analyzeCall(
73687381 memoized_arg_values,
73697382 func_ty_info,
73707383 func,
7371 &has_comptime_args,
73727384 );
73737385 if (opt_noreturn_ref) |ref| {
73747386 // Analyzing this argument gave a ref of a noreturn type. Terminate argument analysis here.
......@@ -7380,19 +7392,18 @@ fn analyzeCall(
73807392 // can just use `sema` directly.
73817393 _ = ics.callee();
73827394
7383 if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure)
7384 return error.AnalysisFail;
7395 if (!inlining.has_comptime_args) {
7396 if (module_fn.analysis(ip).state == .sema_failure)
7397 return error.AnalysisFail;
73857398
7386 const recursive_msg = "inline call is recursive";
7387 var head = if (!has_comptime_args) block else null;
7388 while (head) |some| {
7389 const parent_inlining = some.inlining orelse break;
7390 if (parent_inlining.func == module_fn_index) {
7391 return sema.fail(block, call_src, recursive_msg, .{});
7399 var block_it = block;
7400 while (block_it.inlining) |parent_inlining| {
7401 if (!parent_inlining.has_comptime_args and parent_inlining.func == module_fn_index) {
7402 return sema.fail(block, call_src, "inline call is recursive", .{});
7403 }
7404 block_it = parent_inlining.call_block;
73927405 }
7393 head = some.parent;
73947406 }
7395 if (!has_comptime_args) inlining.func = module_fn_index;
73967407
73977408 // In case it is a generic function with an expression for the return type that depends
73987409 // on parameters, we must now do the same for the return type as we just did with
......@@ -7462,12 +7473,6 @@ fn analyzeCall(
74627473 const result = result: {
74637474 sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
74647475 error.ComptimeReturn => break :result inlining.comptime_result,
7465 error.AnalysisFail => {
7466 const err_msg = sema.err orelse return err;
7467 if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;
7468 try sema.errNote(block, call_src, err_msg, "called from here", .{});
7469 return err;
7470 },
74717476 else => |e| return e,
74727477 };
74737478 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
......@@ -7632,13 +7637,12 @@ fn analyzeInlineCallArg(
76327637 memoized_arg_values: []InternPool.Index,
76337638 func_ty_info: InternPool.Key.FuncType,
76347639 func_inst: Air.Inst.Ref,
7635 has_comptime_args: *bool,
76367640) !?Air.Inst.Ref {
76377641 const mod = ics.sema.mod;
76387642 const ip = &mod.intern_pool;
76397643 const zir_tags = ics.callee().code.instructions.items(.tag);
76407644 switch (zir_tags[inst]) {
7641 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
7645 .param_comptime, .param_anytype_comptime => param_block.inlining.?.has_comptime_args = true,
76427646 else => {},
76437647 }
76447648 switch (zir_tags[inst]) {
......@@ -7698,7 +7702,7 @@ fn analyzeInlineCallArg(
76987702 }
76997703
77007704 if (try ics.caller().resolveMaybeUndefVal(casted_arg)) |_| {
7701 has_comptime_args.* = true;
7705 param_block.inlining.?.has_comptime_args = true;
77027706 }
77037707
77047708 arg_i.* += 1;
......@@ -7742,7 +7746,7 @@ fn analyzeInlineCallArg(
77427746 }
77437747
77447748 if (try ics.caller().resolveMaybeUndefVal(uncasted_arg)) |_| {
7745 has_comptime_args.* = true;
7749 param_block.inlining.?.has_comptime_args = true;
77467750 }
77477751
77487752 arg_i.* += 1;