authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-25 17:27:21-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-25 23:32:52-04:00
logab88165326abfd81c5046e8c064bd6603198ed94
tree26de606950aae4029d07f0cfc7612d47914d6c98
parent1dd710947696ed11e35e9fc98b7dab4a1188c0d5

Sema: generic function instantiations inherit branch quota


3 files changed, 12 insertions(+), 5 deletions(-)

src/Module.zig+5
...@@ -1476,6 +1476,10 @@ pub const Fn = struct {...@@ -1476,6 +1476,10 @@ pub const Fn = struct {
1476 lbrace_column: u16,1476 lbrace_column: u16,
1477 rbrace_column: u16,1477 rbrace_column: u16,
14781478
1479 /// When a generic function is instantiated, this value is inherited from the
1480 /// active Sema context. Importantly, this value is also updated when an existing
1481 /// generic function instantiation is found and called.
1482 branch_quota: u32,
1479 state: Analysis,1483 state: Analysis,
1480 is_cold: bool = false,1484 is_cold: bool = false,
1481 is_noinline: bool = false,1485 is_noinline: bool = false,
...@@ -4891,6 +4895,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -4891,6 +4895,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
4891 .func = func,4895 .func = func,
4892 .fn_ret_ty = decl.ty.fnReturnType(),4896 .fn_ret_ty = decl.ty.fnReturnType(),
4893 .owner_func = func,4897 .owner_func = func,
4898 .branch_quota = @maximum(func.branch_quota, Sema.default_branch_quota),
4894 };4899 };
4895 defer sema.deinit();4900 defer sema.deinit();
48964901
src/Sema.zig+7-3
...@@ -38,7 +38,7 @@ func: ?*Module.Fn,...@@ -38,7 +38,7 @@ func: ?*Module.Fn,
38/// generic function which uses a type expression for the return type.38/// generic function which uses a type expression for the return type.
39/// The type will be `void` in the case that `func` is `null`.39/// The type will be `void` in the case that `func` is `null`.
40fn_ret_ty: Type,40fn_ret_ty: Type,
41branch_quota: u32 = 1000,41branch_quota: u32 = default_branch_quota,
42branch_count: u32 = 0,42branch_count: u32 = 0,
43/// Populated when returning `error.ComptimeBreak`. Used to communicate the43/// Populated when returning `error.ComptimeBreak`. Used to communicate the
44/// break instruction up the stack to find the corresponding Block.44/// break instruction up the stack to find the corresponding Block.
...@@ -102,6 +102,8 @@ const Package = @import("Package.zig");...@@ -102,6 +102,8 @@ const Package = @import("Package.zig");
102const crash_report = @import("crash_report.zig");102const crash_report = @import("crash_report.zig");
103const build_options = @import("build_options");103const build_options = @import("build_options");
104104
105pub const default_branch_quota = 1000;
106
105pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref);107pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref);
106108
107/// This is the context needed to semantically analyze ZIR instructions and109/// This is the context needed to semantically analyze ZIR instructions and
...@@ -3752,8 +3754,7 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi...@@ -3752,8 +3754,7 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
3752 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3754 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3753 const src = inst_data.src();3755 const src = inst_data.src();
3754 const quota = @intCast(u32, try sema.resolveInt(block, src, inst_data.operand, Type.u32));3756 const quota = @intCast(u32, try sema.resolveInt(block, src, inst_data.operand, Type.u32));
3755 if (sema.branch_quota < quota)3757 sema.branch_quota = @maximum(sema.branch_quota, quota);
3756 sema.branch_quota = quota;
3757}3758}
37583759
3759fn zirStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {3760fn zirStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
...@@ -5679,6 +5680,8 @@ fn instantiateGenericCall(...@@ -5679,6 +5680,8 @@ fn instantiateGenericCall(
5679 break :callee new_func;5680 break :callee new_func;
5680 } else gop.key_ptr.*;5681 } else gop.key_ptr.*;
56815682
5683 callee.branch_quota = @maximum(callee.branch_quota, sema.branch_quota);
5684
5682 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);5685 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
56835686
5684 // Make a runtime call to the new function, making sure to omit the comptime args.5687 // Make a runtime call to the new function, making sure to omit the comptime args.
...@@ -6773,6 +6776,7 @@ fn funcCommon(...@@ -6773,6 +6776,7 @@ fn funcCommon(
6773 .lbrace_column = @truncate(u16, src_locs.columns),6776 .lbrace_column = @truncate(u16, src_locs.columns),
6774 .rbrace_column = @truncate(u16, src_locs.columns >> 16),6777 .rbrace_column = @truncate(u16, src_locs.columns >> 16),
6775 .param_names = param_names,6778 .param_names = param_names,
6779 .branch_quota = default_branch_quota,
6776 };6780 };
6777 if (maybe_inferred_error_set_node) |node| {6781 if (maybe_inferred_error_set_node) |node| {
6778 new_func.inferred_error_sets.prepend(node);6782 new_func.inferred_error_sets.prepend(node);
test/behavior/eval.zig-2
...@@ -704,8 +704,6 @@ test "call method with comptime pass-by-non-copying-value self parameter" {...@@ -704,8 +704,6 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
704}704}
705705
706test "setting backward branch quota just before a generic fn call" {706test "setting backward branch quota just before a generic fn call" {
707 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
708
709 @setEvalBranchQuota(1001);707 @setEvalBranchQuota(1001);
710 loopNTimes(1001);708 loopNTimes(1001);
711}709}