mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Sema: delete bootstrap compiler bug workaround
This commit is contained in:
parent
9cf8a7661f
commit
95fbfde9da
1 changed files with 99 additions and 105 deletions
204
src/Sema.zig
204
src/Sema.zig
|
|
@ -7734,123 +7734,117 @@ fn analyzeCall(
|
||||||
} }));
|
} }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This `res2` is here instead of directly breaking from `res` due to a stage1
|
memoize: {
|
||||||
// bug generating invalid LLVM IR.
|
if (!should_memoize) break :memoize;
|
||||||
const res2: Air.Inst.Ref = res2: {
|
if (!is_comptime_call) break :memoize;
|
||||||
memoize: {
|
const memoized_call_index = ip.getIfExists(.{
|
||||||
if (!should_memoize) break :memoize;
|
.memoized_call = .{
|
||||||
if (!is_comptime_call) break :memoize;
|
.func = module_fn_index,
|
||||||
const memoized_call_index = ip.getIfExists(.{
|
.arg_values = memoized_arg_values,
|
||||||
.memoized_call = .{
|
.result = undefined, // ignored by hash+eql
|
||||||
.func = module_fn_index,
|
.branch_count = undefined, // ignored by hash+eql
|
||||||
.arg_values = memoized_arg_values,
|
},
|
||||||
.result = undefined, // ignored by hash+eql
|
}) orelse break :memoize;
|
||||||
.branch_count = undefined, // ignored by hash+eql
|
const memoized_call = ip.indexToKey(memoized_call_index).memoized_call;
|
||||||
},
|
if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) {
|
||||||
}) orelse break :memoize;
|
// Let the call play out se we get the correct source location for the
|
||||||
const memoized_call = ip.indexToKey(memoized_call_index).memoized_call;
|
// "evaluation exceeded X backwards branches" error.
|
||||||
if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) {
|
break :memoize;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
sema.branch_count += memoized_call.branch_count;
|
||||||
|
break :res Air.internedToRef(memoized_call.result);
|
||||||
|
}
|
||||||
|
|
||||||
new_fn_info.return_type = sema.fn_ret_ty.toIntern();
|
new_fn_info.return_type = sema.fn_ret_ty.toIntern();
|
||||||
if (!is_comptime_call and !block.is_typeof) {
|
if (!is_comptime_call and !block.is_typeof) {
|
||||||
const zir_tags = sema.code.instructions.items(.tag);
|
const zir_tags = sema.code.instructions.items(.tag);
|
||||||
for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) {
|
for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) {
|
||||||
.param, .param_comptime => {
|
.param, .param_comptime => {
|
||||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok;
|
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 extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
|
||||||
const param_name = sema.code.nullTerminatedString(extra.data.name);
|
const param_name = sema.code.nullTerminatedString(extra.data.name);
|
||||||
const inst = sema.inst_map.get(param).?;
|
const inst = sema.inst_map.get(param).?;
|
||||||
|
|
||||||
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
||||||
},
|
},
|
||||||
.param_anytype, .param_anytype_comptime => {
|
.param_anytype, .param_anytype_comptime => {
|
||||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;
|
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;
|
||||||
const param_name = inst_data.get(sema.code);
|
const param_name = inst_data.get(sema.code);
|
||||||
const inst = sema.inst_map.get(param).?;
|
const inst = sema.inst_map.get(param).?;
|
||||||
|
|
||||||
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
||||||
},
|
},
|
||||||
else => continue,
|
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);
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (is_comptime_call) {
|
if (is_comptime_call and ensure_result_used) {
|
||||||
const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined);
|
try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src);
|
||||||
const result_interned = result_val.toIntern();
|
}
|
||||||
|
|
||||||
// Transform ad-hoc inferred error set types into concrete error sets.
|
if (is_comptime_call or block.is_typeof) {
|
||||||
const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
|
// 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
|
// We temporarily set `allow_memoize` to `true` to track this comptime call.
|
||||||
// a reference to `comptime_allocs` so is not stable across instances of `Sema`.
|
// It is restored after this call finishes analysis, so that a caller may
|
||||||
// TODO: check whether any external comptime memory was mutated by the
|
// know whether an in-progress call (containing this call) may be memoized.
|
||||||
// comptime function call. If so, then do not memoize the call here.
|
const old_allow_memoize = sema.allow_memoize;
|
||||||
if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) {
|
defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize;
|
||||||
_ = try pt.intern(.{ .memoized_call = .{
|
sema.allow_memoize = true;
|
||||||
.func = module_fn_index,
|
|
||||||
.arg_values = memoized_arg_values,
|
|
||||||
.result = result_transformed,
|
|
||||||
.branch_count = sema.branch_count - old_branch_count,
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = result: {
|
||||||
const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern());
|
sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) {
|
||||||
break :res2 Air.internedToRef(result_transformed);
|
error.ComptimeReturn => break :result inlining.comptime_result,
|
||||||
}
|
else => |e| return e,
|
||||||
|
};
|
||||||
const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern());
|
break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope);
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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: {
|
} else res: {
|
||||||
assert(!func_ty_info.is_generic);
|
assert(!func_ty_info.is_generic);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue