authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-04 13:40:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-04 13:40:51-07:00
logef2fa67ef018a4a49124a40e60941149efd34553
tree5c5c538cf0b1d79e6626637ea5b3192e7cdec868
parentaa0906e9aaaf36bc928b5502bdb34e7a0409b2c0
parent7e64dc42215c93a2d1d6b7fa4f5e07b885788a7d

Merge branch 'g-w1-stage2-evalbranch'

closes #7682

5 files changed, 97 insertions(+), 5 deletions(-)

src/Module.zig+23-4
...@@ -23,6 +23,8 @@ const trace = @import("tracy.zig").trace;...@@ -23,6 +23,8 @@ const trace = @import("tracy.zig").trace;
23const astgen = @import("astgen.zig");23const astgen = @import("astgen.zig");
24const zir_sema = @import("zir_sema.zig");24const zir_sema = @import("zir_sema.zig");
2525
26const default_eval_branch_quota = 1000;
27
26/// General-purpose allocator. Used for both temporary and long-term storage.28/// General-purpose allocator. Used for both temporary and long-term storage.
27gpa: *Allocator,29gpa: *Allocator,
28comp: *Compilation,30comp: *Compilation,
...@@ -765,6 +767,8 @@ pub const Scope = struct {...@@ -765,6 +767,8 @@ pub const Scope = struct {
765 label: ?Label = null,767 label: ?Label = null,
766 inlining: ?*Inlining,768 inlining: ?*Inlining,
767 is_comptime: bool,769 is_comptime: bool,
770 /// Shared to sub-blocks.
771 branch_quota: *u32,
768772
769 pub const InstTable = std.AutoHashMap(*zir.Inst, *Inst);773 pub const InstTable = std.AutoHashMap(*zir.Inst, *Inst);
770774
...@@ -792,8 +796,7 @@ pub const Scope = struct {...@@ -792,8 +796,7 @@ pub const Scope = struct {
792796
793 pub const Shared = struct {797 pub const Shared = struct {
794 caller: ?*Fn,798 caller: ?*Fn,
795 branch_count: u64,799 branch_count: u32,
796 branch_quota: u64,
797 };800 };
798 };801 };
799802
...@@ -1104,6 +1107,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1104,6 +1107,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1104 var inst_table = Scope.Block.InstTable.init(self.gpa);1107 var inst_table = Scope.Block.InstTable.init(self.gpa);
1105 defer inst_table.deinit();1108 defer inst_table.deinit();
11061109
1110 var branch_quota: u32 = default_eval_branch_quota;
1111
1107 var block_scope: Scope.Block = .{1112 var block_scope: Scope.Block = .{
1108 .parent = null,1113 .parent = null,
1109 .inst_table = &inst_table,1114 .inst_table = &inst_table,
...@@ -1113,6 +1118,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1113,6 +1118,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1113 .arena = &decl_arena.allocator,1118 .arena = &decl_arena.allocator,
1114 .inlining = null,1119 .inlining = null,
1115 .is_comptime = false,1120 .is_comptime = false,
1121 .branch_quota = &branch_quota,
1116 };1122 };
1117 defer block_scope.instructions.deinit(self.gpa);1123 defer block_scope.instructions.deinit(self.gpa);
11181124
...@@ -1297,6 +1303,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1297,6 +1303,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1297 var decl_inst_table = Scope.Block.InstTable.init(self.gpa);1303 var decl_inst_table = Scope.Block.InstTable.init(self.gpa);
1298 defer decl_inst_table.deinit();1304 defer decl_inst_table.deinit();
12991305
1306 var branch_quota: u32 = default_eval_branch_quota;
1307
1300 var block_scope: Scope.Block = .{1308 var block_scope: Scope.Block = .{
1301 .parent = null,1309 .parent = null,
1302 .inst_table = &decl_inst_table,1310 .inst_table = &decl_inst_table,
...@@ -1306,6 +1314,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1306,6 +1314,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1306 .arena = &decl_arena.allocator,1314 .arena = &decl_arena.allocator,
1307 .inlining = null,1315 .inlining = null,
1308 .is_comptime = true,1316 .is_comptime = true,
1317 .branch_quota = &branch_quota,
1309 };1318 };
1310 defer block_scope.instructions.deinit(self.gpa);1319 defer block_scope.instructions.deinit(self.gpa);
13111320
...@@ -1367,6 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1367,6 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1367 var var_inst_table = Scope.Block.InstTable.init(self.gpa);1376 var var_inst_table = Scope.Block.InstTable.init(self.gpa);
1368 defer var_inst_table.deinit();1377 defer var_inst_table.deinit();
13691378
1379 var branch_quota_vi: u32 = default_eval_branch_quota;
1370 var inner_block: Scope.Block = .{1380 var inner_block: Scope.Block = .{
1371 .parent = null,1381 .parent = null,
1372 .inst_table = &var_inst_table,1382 .inst_table = &var_inst_table,
...@@ -1376,6 +1386,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1376,6 +1386,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1376 .arena = &gen_scope_arena.allocator,1386 .arena = &gen_scope_arena.allocator,
1377 .inlining = null,1387 .inlining = null,
1378 .is_comptime = true,1388 .is_comptime = true,
1389 .branch_quota = &branch_quota_vi,
1379 };1390 };
1380 defer inner_block.instructions.deinit(self.gpa);1391 defer inner_block.instructions.deinit(self.gpa);
1381 try zir_sema.analyzeBody(self, &inner_block, .{1392 try zir_sema.analyzeBody(self, &inner_block, .{
...@@ -1494,6 +1505,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1494,6 +1505,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1494 var inst_table = Scope.Block.InstTable.init(self.gpa);1505 var inst_table = Scope.Block.InstTable.init(self.gpa);
1495 defer inst_table.deinit();1506 defer inst_table.deinit();
14961507
1508 var branch_quota: u32 = default_eval_branch_quota;
1509
1497 var block_scope: Scope.Block = .{1510 var block_scope: Scope.Block = .{
1498 .parent = null,1511 .parent = null,
1499 .inst_table = &inst_table,1512 .inst_table = &inst_table,
...@@ -1503,6 +1516,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1503,6 +1516,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1503 .arena = &analysis_arena.allocator,1516 .arena = &analysis_arena.allocator,
1504 .inlining = null,1517 .inlining = null,
1505 .is_comptime = true,1518 .is_comptime = true,
1519 .branch_quota = &branch_quota,
1506 };1520 };
1507 defer block_scope.instructions.deinit(self.gpa);1521 defer block_scope.instructions.deinit(self.gpa);
15081522
...@@ -1875,6 +1889,8 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {...@@ -1875,6 +1889,8 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1875 defer decl.typed_value.most_recent.arena.?.* = arena.state;1889 defer decl.typed_value.most_recent.arena.?.* = arena.state;
1876 var inst_table = Scope.Block.InstTable.init(self.gpa);1890 var inst_table = Scope.Block.InstTable.init(self.gpa);
1877 defer inst_table.deinit();1891 defer inst_table.deinit();
1892 var branch_quota: u32 = default_eval_branch_quota;
1893
1878 var inner_block: Scope.Block = .{1894 var inner_block: Scope.Block = .{
1879 .parent = null,1895 .parent = null,
1880 .inst_table = &inst_table,1896 .inst_table = &inst_table,
...@@ -1884,6 +1900,7 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {...@@ -1884,6 +1900,7 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1884 .arena = &arena.allocator,1900 .arena = &arena.allocator,
1885 .inlining = null,1901 .inlining = null,
1886 .is_comptime = false,1902 .is_comptime = false,
1903 .branch_quota = &branch_quota,
1887 };1904 };
1888 defer inner_block.instructions.deinit(self.gpa);1905 defer inner_block.instructions.deinit(self.gpa);
18891906
...@@ -3466,7 +3483,9 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic...@@ -3466,7 +3483,9 @@ pub fn addSafetyCheck(mod: *Module, parent_block: *Scope.Block, ok: *Inst, panic
3466 .arena = parent_block.arena,3483 .arena = parent_block.arena,
3467 .inlining = parent_block.inlining,3484 .inlining = parent_block.inlining,
3468 .is_comptime = parent_block.is_comptime,3485 .is_comptime = parent_block.is_comptime,
3486 .branch_quota = parent_block.branch_quota,
3469 };3487 };
3488
3470 defer fail_block.instructions.deinit(mod.gpa);3489 defer fail_block.instructions.deinit(mod.gpa);
34713490
3472 _ = try mod.safetyPanic(&fail_block, ok.src, panic_id);3491 _ = try mod.safetyPanic(&fail_block, ok.src, panic_id);
...@@ -3532,10 +3551,10 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)...@@ -3532,10 +3551,10 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
3532pub fn emitBackwardBranch(mod: *Module, block: *Scope.Block, src: usize) !void {3551pub fn emitBackwardBranch(mod: *Module, block: *Scope.Block, src: usize) !void {
3533 const shared = block.inlining.?.shared;3552 const shared = block.inlining.?.shared;
3534 shared.branch_count += 1;3553 shared.branch_count += 1;
3535 if (shared.branch_count > shared.branch_quota) {3554 if (shared.branch_count > block.branch_quota.*) {
3536 // TODO show the "called from here" stack3555 // TODO show the "called from here" stack
3537 return mod.fail(&block.base, src, "evaluation exceeded {d} backwards branches", .{3556 return mod.fail(&block.base, src, "evaluation exceeded {d} backwards branches", .{
3538 shared.branch_quota,3557 block.branch_quota.*,
3539 });3558 });
3540 }3559 }
3541}3560}
src/astgen.zig+15
...@@ -2317,6 +2317,19 @@ fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerE...@@ -2317,6 +2317,19 @@ fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerE
2317 return addZIRUnOp(mod, scope, src, .compileerror, target);2317 return addZIRUnOp(mod, scope, src, .compileerror, target);
2318}2318}
23192319
2320fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
2321 try ensureBuiltinParamCount(mod, scope, call, 1);
2322 const tree = scope.tree();
2323 const src = tree.token_locs[call.builtin_token].start;
2324 const params = call.params();
2325 const u32_type = try addZIRInstConst(mod, scope, src, .{
2326 .ty = Type.initTag(.type),
2327 .val = Value.initTag(.u32_type),
2328 });
2329 const quota = try expr(mod, scope, .{ .ty = u32_type }, params[0]);
2330 return addZIRUnOp(mod, scope, src, .set_eval_branch_quota, quota);
2331}
2332
2320fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2333fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
2321 const tree = scope.tree();2334 const tree = scope.tree();
2322 const arena = scope.arena();2335 const arena = scope.arena();
...@@ -2362,6 +2375,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built...@@ -2362,6 +2375,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
2362 return rlWrap(mod, scope, rl, try import(mod, scope, call));2375 return rlWrap(mod, scope, rl, try import(mod, scope, call));
2363 } else if (mem.eql(u8, builtin_name, "@compileError")) {2376 } else if (mem.eql(u8, builtin_name, "@compileError")) {
2364 return compileError(mod, scope, call);2377 return compileError(mod, scope, call);
2378 } else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {
2379 return setEvalBranchQuota(mod, scope, call);
2365 } else {2380 } else {
2366 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});2381 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});
2367 }2382 }
src/zir.zig+5
...@@ -127,6 +127,9 @@ pub const Inst = struct {...@@ -127,6 +127,9 @@ pub const Inst = struct {
127 coerce_to_ptr_elem,127 coerce_to_ptr_elem,
128 /// Emit an error message and fail compilation.128 /// Emit an error message and fail compilation.
129 compileerror,129 compileerror,
130 /// Changes the maximum number of backwards branches that compile-time
131 /// code execution can use before giving up and making a compile error.
132 set_eval_branch_quota,
130 /// Conditional branch. Splits control flow based on a boolean condition value.133 /// Conditional branch. Splits control flow based on a boolean condition value.
131 condbr,134 condbr,
132 /// Special case, has no textual representation.135 /// Special case, has no textual representation.
...@@ -347,6 +350,7 @@ pub const Inst = struct {...@@ -347,6 +350,7 @@ pub const Inst = struct {
347 .anyframe_type,350 .anyframe_type,
348 .bitnot,351 .bitnot,
349 .import,352 .import,
353 .set_eval_branch_quota,
350 => UnOp,354 => UnOp,
351355
352 .add,356 .add,
...@@ -535,6 +539,7 @@ pub const Inst = struct {...@@ -535,6 +539,7 @@ pub const Inst = struct {
535 .switch_range,539 .switch_range,
536 .typeof_peer,540 .typeof_peer,
537 .resolve_inferred_alloc,541 .resolve_inferred_alloc,
542 .set_eval_branch_quota,
538 => false,543 => false,
539544
540 .@"break",545 .@"break",
src/zir_sema.zig+39-1
...@@ -81,6 +81,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -81,6 +81,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
81 .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice),81 .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice),
82 .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?),82 .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?),
83 .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?),83 .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?),
84 .set_eval_branch_quota => return analyzeInstSetEvalBranchQuota(mod, scope, old_inst.castTag(.set_eval_branch_quota).?),
84 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),85 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),
85 .int => {86 .int => {
86 const big_int = old_inst.castTag(.int).?.positionals.int;87 const big_int = old_inst.castTag(.int).?.positionals.int;
...@@ -280,6 +281,24 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {...@@ -280,6 +281,24 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
280 return val.toType(scope.arena());281 return val.toType(scope.arena());
281}282}
282283
284/// Appropriate to call when the coercion has already been done by result
285/// location semantics. Asserts the value fits in the provided `Int` type.
286/// Only supports `Int` types 64 bits or less.
287fn resolveAlreadyCoercedInt(
288 mod: *Module,
289 scope: *Scope,
290 old_inst: *zir.Inst,
291 comptime Int: type,
292) !Int {
293 comptime assert(@typeInfo(Int).Int.bits <= 64);
294 const new_inst = try resolveInst(mod, scope, old_inst);
295 const val = try mod.resolveConstValue(scope, new_inst);
296 switch (@typeInfo(Int).Int.signedness) {
297 .signed => return @intCast(Int, val.toSignedInt()),
298 .unsigned => return @intCast(Int, val.toUnsignedInt()),
299 }
300}
301
283fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {302fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {
284 const new_inst = try resolveInst(mod, scope, old_inst);303 const new_inst = try resolveInst(mod, scope, old_inst);
285 const coerced = try mod.coerce(scope, dest_type, new_inst);304 const coerced = try mod.coerce(scope, dest_type, new_inst);
...@@ -486,6 +505,18 @@ fn analyzeInstStoreToInferredPtr(...@@ -486,6 +505,18 @@ fn analyzeInstStoreToInferredPtr(
486 return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value);505 return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value);
487}506}
488507
508fn analyzeInstSetEvalBranchQuota(
509 mod: *Module,
510 scope: *Scope,
511 inst: *zir.Inst.UnOp,
512) InnerError!*Inst {
513 const b = try mod.requireFunctionBlock(scope, inst.base.src);
514 const quota = try resolveAlreadyCoercedInt(mod, scope, inst.positionals.operand, u32);
515 if (b.branch_quota.* < quota)
516 b.branch_quota.* = quota;
517 return mod.constVoid(scope, inst.base.src);
518}
519
489fn analyzeInstStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {520fn analyzeInstStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
490 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);521 const ptr = try resolveInst(mod, scope, inst.positionals.lhs);
491 const value = try resolveInst(mod, scope, inst.positionals.rhs);522 const value = try resolveInst(mod, scope, inst.positionals.rhs);
...@@ -594,6 +625,7 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError...@@ -594,6 +625,7 @@ fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError
594 .arena = parent_block.arena,625 .arena = parent_block.arena,
595 .inlining = parent_block.inlining,626 .inlining = parent_block.inlining,
596 .is_comptime = parent_block.is_comptime,627 .is_comptime = parent_block.is_comptime,
628 .branch_quota = parent_block.branch_quota,
597 };629 };
598 defer child_block.instructions.deinit(mod.gpa);630 defer child_block.instructions.deinit(mod.gpa);
599631
...@@ -619,6 +651,7 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c...@@ -619,6 +651,7 @@ fn analyzeInstBlockFlat(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_c
619 .label = null,651 .label = null,
620 .inlining = parent_block.inlining,652 .inlining = parent_block.inlining,
621 .is_comptime = parent_block.is_comptime or is_comptime,653 .is_comptime = parent_block.is_comptime or is_comptime,
654 .branch_quota = parent_block.branch_quota,
622 };655 };
623 defer child_block.instructions.deinit(mod.gpa);656 defer child_block.instructions.deinit(mod.gpa);
624657
...@@ -666,6 +699,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt...@@ -666,6 +699,7 @@ fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block, is_compt
666 }),699 }),
667 .inlining = parent_block.inlining,700 .inlining = parent_block.inlining,
668 .is_comptime = is_comptime or parent_block.is_comptime,701 .is_comptime = is_comptime or parent_block.is_comptime,
702 .branch_quota = parent_block.branch_quota,
669 };703 };
670 const merges = &child_block.label.?.merges;704 const merges = &child_block.label.?.merges;
671705
...@@ -867,7 +901,6 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError...@@ -867,7 +901,6 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError
867 // Otherwise we pass on the shared data from the parent scope.901 // Otherwise we pass on the shared data from the parent scope.
868 var shared_inlining = Scope.Block.Inlining.Shared{902 var shared_inlining = Scope.Block.Inlining.Shared{
869 .branch_count = 0,903 .branch_count = 0,
870 .branch_quota = 1000,
871 .caller = b.func,904 .caller = b.func,
872 };905 };
873 // This one is shared among sub-blocks within the same callee, but not906 // This one is shared among sub-blocks within the same callee, but not
...@@ -896,7 +929,9 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError...@@ -896,7 +929,9 @@ fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError
896 .label = null,929 .label = null,
897 .inlining = &inlining,930 .inlining = &inlining,
898 .is_comptime = is_comptime_call,931 .is_comptime = is_comptime_call,
932 .branch_quota = b.branch_quota,
899 };933 };
934
900 const merges = &child_block.inlining.?.merges;935 const merges = &child_block.inlining.?.merges;
901936
902 defer child_block.instructions.deinit(mod.gpa);937 defer child_block.instructions.deinit(mod.gpa);
...@@ -1417,6 +1452,7 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In...@@ -1417,6 +1452,7 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In
1417 .arena = parent_block.arena,1452 .arena = parent_block.arena,
1418 .inlining = parent_block.inlining,1453 .inlining = parent_block.inlining,
1419 .is_comptime = parent_block.is_comptime,1454 .is_comptime = parent_block.is_comptime,
1455 .branch_quota = parent_block.branch_quota,
1420 };1456 };
1421 defer case_block.instructions.deinit(mod.gpa);1457 defer case_block.instructions.deinit(mod.gpa);
14221458
...@@ -1960,6 +1996,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE...@@ -1960,6 +1996,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
1960 .arena = parent_block.arena,1996 .arena = parent_block.arena,
1961 .inlining = parent_block.inlining,1997 .inlining = parent_block.inlining,
1962 .is_comptime = parent_block.is_comptime,1998 .is_comptime = parent_block.is_comptime,
1999 .branch_quota = parent_block.branch_quota,
1963 };2000 };
1964 defer true_block.instructions.deinit(mod.gpa);2001 defer true_block.instructions.deinit(mod.gpa);
1965 try analyzeBody(mod, &true_block, inst.positionals.then_body);2002 try analyzeBody(mod, &true_block, inst.positionals.then_body);
...@@ -1973,6 +2010,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE...@@ -1973,6 +2010,7 @@ fn analyzeInstCondBr(mod: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerE
1973 .arena = parent_block.arena,2010 .arena = parent_block.arena,
1974 .inlining = parent_block.inlining,2011 .inlining = parent_block.inlining,
1975 .is_comptime = parent_block.is_comptime,2012 .is_comptime = parent_block.is_comptime,
2013 .branch_quota = parent_block.branch_quota,
1976 };2014 };
1977 defer false_block.instructions.deinit(mod.gpa);2015 defer false_block.instructions.deinit(mod.gpa);
1978 try analyzeBody(mod, &false_block, inst.positionals.else_body);2016 try analyzeBody(mod, &false_block, inst.positionals.else_body);
test/stage2/cbe.zig+15
...@@ -67,7 +67,22 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -67,7 +67,22 @@ pub fn addCases(ctx: *TestContext) !void {
67 \\}67 \\}
68 , "");68 , "");
69 }69 }
70 {
71 var case = ctx.exeFromCompiledC("@setEvalBranchQuota", .{});
7072
73 case.addCompareOutput(
74 \\export fn main() i32 {
75 \\ @setEvalBranchQuota(1001);
76 \\ const y = rec(1001);
77 \\ return y - 1;
78 \\}
79 \\
80 \\inline fn rec(n: usize) usize {
81 \\ if (n <= 1) return n;
82 \\ return rec(n - 1);
83 \\}
84 , "");
85 }
71 ctx.c("empty start function", linux_x64,86 ctx.c("empty start function", linux_x64,
72 \\export fn _start() noreturn {87 \\export fn _start() noreturn {
73 \\ unreachable;88 \\ unreachable;