From 95fbfde9daa165ca74a4d7267720fd32b42af45e Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 19 Aug 2024 07:55:18 +0100 Subject: [PATCH] Sema: delete bootstrap compiler bug workaround --- src/Sema.zig | 204 +++++++++++++++++++++++++-------------------------- 1 file changed, 99 insertions(+), 105 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 8e7e403a52..b0f2623652 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7734,123 +7734,117 @@ fn analyzeCall( } })); } - // This `res2` is here instead of directly breaking from `res` due to a stage1 - // bug generating invalid LLVM IR. - const res2: Air.Inst.Ref = res2: { - memoize: { - if (!should_memoize) break :memoize; - if (!is_comptime_call) break :memoize; - const memoized_call_index = ip.getIfExists(.{ - .memoized_call = .{ - .func = module_fn_index, - .arg_values = memoized_arg_values, - .result = undefined, // ignored by hash+eql - .branch_count = undefined, // ignored by hash+eql - }, - }) orelse break :memoize; - const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; - if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { - // Let the call play out se we get the correct source location for the - // "evaluation exceeded X backwards branches" error. - break :memoize; - } - sema.branch_count += memoized_call.branch_count; - break :res2 Air.internedToRef(memoized_call.result); + memoize: { + if (!should_memoize) break :memoize; + if (!is_comptime_call) break :memoize; + const memoized_call_index = ip.getIfExists(.{ + .memoized_call = .{ + .func = module_fn_index, + .arg_values = memoized_arg_values, + .result = undefined, // ignored by hash+eql + .branch_count = undefined, // ignored by hash+eql + }, + }) orelse break :memoize; + const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; + if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { + // Let the call play out se we get the correct source location for the + // "evaluation exceeded X backwards branches" error. + break :memoize; } + sema.branch_count += memoized_call.branch_count; + break :res Air.internedToRef(memoized_call.result); + } - new_fn_info.return_type = sema.fn_ret_ty.toIntern(); - if (!is_comptime_call and !block.is_typeof) { - const zir_tags = sema.code.instructions.items(.tag); - for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { - .param, .param_comptime => { - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; - const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); - const param_name = sema.code.nullTerminatedString(extra.data.name); - const inst = sema.inst_map.get(param).?; + new_fn_info.return_type = sema.fn_ret_ty.toIntern(); + if (!is_comptime_call and !block.is_typeof) { + const zir_tags = sema.code.instructions.items(.tag); + for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { + .param, .param_comptime => { + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; + const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); + const param_name = sema.code.nullTerminatedString(extra.data.name); + const inst = sema.inst_map.get(param).?; - try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); - }, - .param_anytype, .param_anytype_comptime => { - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; - const param_name = inst_data.get(sema.code); - const inst = sema.inst_map.get(param).?; + try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); + }, + .param_anytype, .param_anytype_comptime => { + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; + const param_name = inst_data.get(sema.code); + const inst = sema.inst_map.get(param).?; - try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); - }, - else => continue, - }; - } - - if (is_comptime_call and ensure_result_used) { - try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); - } - - if (is_comptime_call or block.is_typeof) { - // Save the error trace as our first action in the function - // to match the behavior of runtime function calls. - const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); - sema.error_return_trace_index_on_fn_entry = error_return_trace_index; - child_block.error_return_trace_index = error_return_trace_index; - } - - // We temporarily set `allow_memoize` to `true` to track this comptime call. - // It is restored after this call finishes analysis, so that a caller may - // know whether an in-progress call (containing this call) may be memoized. - const old_allow_memoize = sema.allow_memoize; - defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; - sema.allow_memoize = true; - - // Store the current eval branch count so we can find out how many eval branches - // the comptime call caused. - const old_branch_count = sema.branch_count; - - const result = result: { - sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { - error.ComptimeReturn => break :result inlining.comptime_result, - else => |e| return e, - }; - break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); + try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); + }, + else => continue, }; + } - if (is_comptime_call) { - const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); - const result_interned = result_val.toIntern(); + if (is_comptime_call and ensure_result_used) { + try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); + } - // Transform ad-hoc inferred error set types into concrete error sets. - const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); + if (is_comptime_call or block.is_typeof) { + // Save the error trace as our first action in the function + // to match the behavior of runtime function calls. + const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); + sema.error_return_trace_index_on_fn_entry = error_return_trace_index; + child_block.error_return_trace_index = error_return_trace_index; + } - // If the result can mutate comptime vars, we must not memoize it, as it contains - // a reference to `comptime_allocs` so is not stable across instances of `Sema`. - // TODO: check whether any external comptime memory was mutated by the - // comptime function call. If so, then do not memoize the call here. - if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { - _ = try pt.intern(.{ .memoized_call = .{ - .func = module_fn_index, - .arg_values = memoized_arg_values, - .result = result_transformed, - .branch_count = sema.branch_count - old_branch_count, - } }); - } + // We temporarily set `allow_memoize` to `true` to track this comptime call. + // It is restored after this call finishes analysis, so that a caller may + // know whether an in-progress call (containing this call) may be memoized. + const old_allow_memoize = sema.allow_memoize; + defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; + sema.allow_memoize = true; - break :res2 Air.internedToRef(result_transformed); - } + // Store the current eval branch count so we can find out how many eval branches + // the comptime call caused. + const old_branch_count = sema.branch_count; - if (try sema.resolveValue(result)) |result_val| { - const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); - break :res2 Air.internedToRef(result_transformed); - } - - const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); - if (new_ty != .none) { - // TODO: mutate in place the previous instruction if possible - // rather than adding a bitcast instruction. - break :res2 try block.addBitCast(Type.fromInterned(new_ty), result); - } - - break :res2 result; + const result = result: { + sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { + error.ComptimeReturn => break :result inlining.comptime_result, + else => |e| return e, + }; + break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); }; - break :res res2; + if (is_comptime_call) { + const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); + const result_interned = result_val.toIntern(); + + // Transform ad-hoc inferred error set types into concrete error sets. + const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); + + // If the result can mutate comptime vars, we must not memoize it, as it contains + // a reference to `comptime_allocs` so is not stable across instances of `Sema`. + // TODO: check whether any external comptime memory was mutated by the + // comptime function call. If so, then do not memoize the call here. + if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { + _ = try pt.intern(.{ .memoized_call = .{ + .func = module_fn_index, + .arg_values = memoized_arg_values, + .result = result_transformed, + .branch_count = sema.branch_count - old_branch_count, + } }); + } + + break :res Air.internedToRef(result_transformed); + } + + if (try sema.resolveValue(result)) |result_val| { + const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); + break :res Air.internedToRef(result_transformed); + } + + const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); + if (new_ty != .none) { + // TODO: mutate in place the previous instruction if possible + // rather than adding a bitcast instruction. + break :res try block.addBitCast(Type.fromInterned(new_ty), result); + } + + break :res result; } else res: { assert(!func_ty_info.is_generic);