| ... | ... | @@ -7734,123 +7734,117 @@ fn analyzeCall( |
| 7734 | 7734 | } })); |
| 7735 | 7735 | } |
| 7736 | 7736 | |
| 7737 | | // This `res2` is here instead of directly breaking from `res` due to a stage1 |
| 7738 | | // bug generating invalid LLVM IR. |
| 7739 | | const res2: Air.Inst.Ref = res2: { |
| 7740 | | memoize: { |
| 7741 | | if (!should_memoize) break :memoize; |
| 7742 | | if (!is_comptime_call) break :memoize; |
| 7743 | | const memoized_call_index = ip.getIfExists(.{ |
| 7744 | | .memoized_call = .{ |
| 7745 | | .func = module_fn_index, |
| 7746 | | .arg_values = memoized_arg_values, |
| 7747 | | .result = undefined, // ignored by hash+eql |
| 7748 | | .branch_count = undefined, // ignored by hash+eql |
| 7749 | | }, |
| 7750 | | }) orelse break :memoize; |
| 7751 | | const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; |
| 7752 | | if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { |
| 7753 | | // Let the call play out se we get the correct source location for the |
| 7754 | | // "evaluation exceeded X backwards branches" error. |
| 7755 | | break :memoize; |
| 7756 | | } |
| 7757 | | sema.branch_count += memoized_call.branch_count; |
| 7758 | | break :res2 Air.internedToRef(memoized_call.result); |
| 7737 | memoize: { |
| 7738 | if (!should_memoize) break :memoize; |
| 7739 | if (!is_comptime_call) break :memoize; |
| 7740 | const memoized_call_index = ip.getIfExists(.{ |
| 7741 | .memoized_call = .{ |
| 7742 | .func = module_fn_index, |
| 7743 | .arg_values = memoized_arg_values, |
| 7744 | .result = undefined, // ignored by hash+eql |
| 7745 | .branch_count = undefined, // ignored by hash+eql |
| 7746 | }, |
| 7747 | }) orelse break :memoize; |
| 7748 | const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; |
| 7749 | if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { |
| 7750 | // Let the call play out se we get the correct source location for the |
| 7751 | // "evaluation exceeded X backwards branches" error. |
| 7752 | break :memoize; |
| 7759 | 7753 | } |
| 7754 | sema.branch_count += memoized_call.branch_count; |
| 7755 | break :res Air.internedToRef(memoized_call.result); |
| 7756 | } |
| 7760 | 7757 | |
| 7761 | | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); |
| 7762 | | if (!is_comptime_call and !block.is_typeof) { |
| 7763 | | const zir_tags = sema.code.instructions.items(.tag); |
| 7764 | | for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { |
| 7765 | | .param, .param_comptime => { |
| 7766 | | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; |
| 7767 | | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); |
| 7768 | | const param_name = sema.code.nullTerminatedString(extra.data.name); |
| 7769 | | const inst = sema.inst_map.get(param).?; |
| 7770 | | |
| 7771 | | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); |
| 7772 | | }, |
| 7773 | | .param_anytype, .param_anytype_comptime => { |
| 7774 | | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; |
| 7775 | | const param_name = inst_data.get(sema.code); |
| 7776 | | const inst = sema.inst_map.get(param).?; |
| 7758 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); |
| 7759 | if (!is_comptime_call and !block.is_typeof) { |
| 7760 | const zir_tags = sema.code.instructions.items(.tag); |
| 7761 | for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { |
| 7762 | .param, .param_comptime => { |
| 7763 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; |
| 7764 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); |
| 7765 | const param_name = sema.code.nullTerminatedString(extra.data.name); |
| 7766 | const inst = sema.inst_map.get(param).?; |
| 7767 | |
| 7768 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); |
| 7769 | }, |
| 7770 | .param_anytype, .param_anytype_comptime => { |
| 7771 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; |
| 7772 | const param_name = inst_data.get(sema.code); |
| 7773 | const inst = sema.inst_map.get(param).?; |
| 7777 | 7774 | |
| 7778 | | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); |
| 7779 | | }, |
| 7780 | | else => continue, |
| 7781 | | }; |
| 7782 | | } |
| 7775 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); |
| 7776 | }, |
| 7777 | else => continue, |
| 7778 | }; |
| 7779 | } |
| 7783 | 7780 | |
| 7784 | | if (is_comptime_call and ensure_result_used) { |
| 7785 | | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); |
| 7786 | | } |
| 7781 | if (is_comptime_call and ensure_result_used) { |
| 7782 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); |
| 7783 | } |
| 7787 | 7784 | |
| 7788 | | if (is_comptime_call or block.is_typeof) { |
| 7789 | | // Save the error trace as our first action in the function |
| 7790 | | // to match the behavior of runtime function calls. |
| 7791 | | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); |
| 7792 | | sema.error_return_trace_index_on_fn_entry = error_return_trace_index; |
| 7793 | | child_block.error_return_trace_index = error_return_trace_index; |
| 7794 | | } |
| 7785 | if (is_comptime_call or block.is_typeof) { |
| 7786 | // Save the error trace as our first action in the function |
| 7787 | // to match the behavior of runtime function calls. |
| 7788 | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); |
| 7789 | sema.error_return_trace_index_on_fn_entry = error_return_trace_index; |
| 7790 | child_block.error_return_trace_index = error_return_trace_index; |
| 7791 | } |
| 7795 | 7792 | |
| 7796 | | // We temporarily set `allow_memoize` to `true` to track this comptime call. |
| 7797 | | // It is restored after this call finishes analysis, so that a caller may |
| 7798 | | // know whether an in-progress call (containing this call) may be memoized. |
| 7799 | | const old_allow_memoize = sema.allow_memoize; |
| 7800 | | defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; |
| 7801 | | sema.allow_memoize = true; |
| 7793 | // We temporarily set `allow_memoize` to `true` to track this comptime call. |
| 7794 | // It is restored after this call finishes analysis, so that a caller may |
| 7795 | // know whether an in-progress call (containing this call) may be memoized. |
| 7796 | const old_allow_memoize = sema.allow_memoize; |
| 7797 | defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; |
| 7798 | sema.allow_memoize = true; |
| 7802 | 7799 | |
| 7803 | | // Store the current eval branch count so we can find out how many eval branches |
| 7804 | | // the comptime call caused. |
| 7805 | | const old_branch_count = sema.branch_count; |
| 7800 | // Store the current eval branch count so we can find out how many eval branches |
| 7801 | // the comptime call caused. |
| 7802 | const old_branch_count = sema.branch_count; |
| 7806 | 7803 | |
| 7807 | | const result = result: { |
| 7808 | | sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { |
| 7809 | | error.ComptimeReturn => break :result inlining.comptime_result, |
| 7810 | | else => |e| return e, |
| 7811 | | }; |
| 7812 | | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); |
| 7804 | const result = result: { |
| 7805 | sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { |
| 7806 | error.ComptimeReturn => break :result inlining.comptime_result, |
| 7807 | else => |e| return e, |
| 7813 | 7808 | }; |
| 7809 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); |
| 7810 | }; |
| 7814 | 7811 | |
| 7815 | | if (is_comptime_call) { |
| 7816 | | const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); |
| 7817 | | const result_interned = result_val.toIntern(); |
| 7818 | | |
| 7819 | | // Transform ad-hoc inferred error set types into concrete error sets. |
| 7820 | | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); |
| 7821 | | |
| 7822 | | // If the result can mutate comptime vars, we must not memoize it, as it contains |
| 7823 | | // a reference to `comptime_allocs` so is not stable across instances of `Sema`. |
| 7824 | | // TODO: check whether any external comptime memory was mutated by the |
| 7825 | | // comptime function call. If so, then do not memoize the call here. |
| 7826 | | if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { |
| 7827 | | _ = try pt.intern(.{ .memoized_call = .{ |
| 7828 | | .func = module_fn_index, |
| 7829 | | .arg_values = memoized_arg_values, |
| 7830 | | .result = result_transformed, |
| 7831 | | .branch_count = sema.branch_count - old_branch_count, |
| 7832 | | } }); |
| 7833 | | } |
| 7834 | | |
| 7835 | | break :res2 Air.internedToRef(result_transformed); |
| 7812 | if (is_comptime_call) { |
| 7813 | const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); |
| 7814 | const result_interned = result_val.toIntern(); |
| 7815 | |
| 7816 | // Transform ad-hoc inferred error set types into concrete error sets. |
| 7817 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); |
| 7818 | |
| 7819 | // If the result can mutate comptime vars, we must not memoize it, as it contains |
| 7820 | // a reference to `comptime_allocs` so is not stable across instances of `Sema`. |
| 7821 | // TODO: check whether any external comptime memory was mutated by the |
| 7822 | // comptime function call. If so, then do not memoize the call here. |
| 7823 | if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { |
| 7824 | _ = try pt.intern(.{ .memoized_call = .{ |
| 7825 | .func = module_fn_index, |
| 7826 | .arg_values = memoized_arg_values, |
| 7827 | .result = result_transformed, |
| 7828 | .branch_count = sema.branch_count - old_branch_count, |
| 7829 | } }); |
| 7836 | 7830 | } |
| 7837 | 7831 | |
| 7838 | | if (try sema.resolveValue(result)) |result_val| { |
| 7839 | | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); |
| 7840 | | break :res2 Air.internedToRef(result_transformed); |
| 7841 | | } |
| 7832 | break :res Air.internedToRef(result_transformed); |
| 7833 | } |
| 7842 | 7834 | |
| 7843 | | const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); |
| 7844 | | if (new_ty != .none) { |
| 7845 | | // TODO: mutate in place the previous instruction if possible |
| 7846 | | // rather than adding a bitcast instruction. |
| 7847 | | break :res2 try block.addBitCast(Type.fromInterned(new_ty), result); |
| 7848 | | } |
| 7835 | if (try sema.resolveValue(result)) |result_val| { |
| 7836 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); |
| 7837 | break :res Air.internedToRef(result_transformed); |
| 7838 | } |
| 7849 | 7839 | |
| 7850 | | break :res2 result; |
| 7851 | | }; |
| 7840 | const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); |
| 7841 | if (new_ty != .none) { |
| 7842 | // TODO: mutate in place the previous instruction if possible |
| 7843 | // rather than adding a bitcast instruction. |
| 7844 | break :res try block.addBitCast(Type.fromInterned(new_ty), result); |
| 7845 | } |
| 7852 | 7846 | |
| 7853 | | break :res res2; |
| 7847 | break :res result; |
| 7854 | 7848 | } else res: { |
| 7855 | 7849 | assert(!func_ty_info.is_generic); |
| 7856 | 7850 | |