authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-04 13:40:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-04 13:40:01-07:00
log7e64dc42215c93a2d1d6b7fa4f5e07b885788a7d
tree5c5c538cf0b1d79e6626637ea5b3192e7cdec868
parent638f93ebdceb860974aae54b6f8c2c9f52157305

stage2: improvements to `@setEvalBranchQuota`

* extract magic number into a constant * properly use result location casting for the operand * naming convention for ZIR instructions

4 files changed, 34 insertions(+), 13 deletions(-)

src/Module.zig+7-5
...@@ -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,
...@@ -1105,7 +1107,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1105,7 +1107,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1105 var inst_table = Scope.Block.InstTable.init(self.gpa);1107 var inst_table = Scope.Block.InstTable.init(self.gpa);
1106 defer inst_table.deinit();1108 defer inst_table.deinit();
11071109
1108 var branch_quota: u32 = 1000;1110 var branch_quota: u32 = default_eval_branch_quota;
11091111
1110 var block_scope: Scope.Block = .{1112 var block_scope: Scope.Block = .{
1111 .parent = null,1113 .parent = null,
...@@ -1301,7 +1303,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1301,7 +1303,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1301 var decl_inst_table = Scope.Block.InstTable.init(self.gpa);1303 var decl_inst_table = Scope.Block.InstTable.init(self.gpa);
1302 defer decl_inst_table.deinit();1304 defer decl_inst_table.deinit();
13031305
1304 var branch_quota: u32 = 1000;1306 var branch_quota: u32 = default_eval_branch_quota;
13051307
1306 var block_scope: Scope.Block = .{1308 var block_scope: Scope.Block = .{
1307 .parent = null,1309 .parent = null,
...@@ -1374,7 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1374,7 +1376,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1374 var var_inst_table = Scope.Block.InstTable.init(self.gpa);1376 var var_inst_table = Scope.Block.InstTable.init(self.gpa);
1375 defer var_inst_table.deinit();1377 defer var_inst_table.deinit();
13761378
1377 var branch_quota_vi: u32 = 1000;1379 var branch_quota_vi: u32 = default_eval_branch_quota;
1378 var inner_block: Scope.Block = .{1380 var inner_block: Scope.Block = .{
1379 .parent = null,1381 .parent = null,
1380 .inst_table = &var_inst_table,1382 .inst_table = &var_inst_table,
...@@ -1503,7 +1505,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1503,7 +1505,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1503 var inst_table = Scope.Block.InstTable.init(self.gpa);1505 var inst_table = Scope.Block.InstTable.init(self.gpa);
1504 defer inst_table.deinit();1506 defer inst_table.deinit();
15051507
1506 var branch_quota: u32 = 1000;1508 var branch_quota: u32 = default_eval_branch_quota;
15071509
1508 var block_scope: Scope.Block = .{1510 var block_scope: Scope.Block = .{
1509 .parent = null,1511 .parent = null,
...@@ -1887,7 +1889,7 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {...@@ -1887,7 +1889,7 @@ pub fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1887 defer decl.typed_value.most_recent.arena.?.* = arena.state;1889 defer decl.typed_value.most_recent.arena.?.* = arena.state;
1888 var inst_table = Scope.Block.InstTable.init(self.gpa);1890 var inst_table = Scope.Block.InstTable.init(self.gpa);
1889 defer inst_table.deinit();1891 defer inst_table.deinit();
1890 var branch_quota: u32 = 1000;1892 var branch_quota: u32 = default_eval_branch_quota;
18911893
1892 var inner_block: Scope.Block = .{1894 var inner_block: Scope.Block = .{
1893 .parent = null,1895 .parent = null,
src/astgen.zig+2-2
...@@ -2322,12 +2322,12 @@ fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall)...@@ -2322,12 +2322,12 @@ fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall)
2322 const tree = scope.tree();2322 const tree = scope.tree();
2323 const src = tree.token_locs[call.builtin_token].start;2323 const src = tree.token_locs[call.builtin_token].start;
2324 const params = call.params();2324 const params = call.params();
2325 const target = try expr(mod, scope, .none, params[0]);
2326 const u32_type = try addZIRInstConst(mod, scope, src, .{2325 const u32_type = try addZIRInstConst(mod, scope, src, .{
2327 .ty = Type.initTag(.type),2326 .ty = Type.initTag(.type),
2328 .val = Value.initTag(.u32_type),2327 .val = Value.initTag(.u32_type),
2329 });2328 });
2330 return addZIRUnOp(mod, scope, src, .setevalbranchquota, try rlWrap(mod, scope, .{ .ty = u32_type }, target));2329 const quota = try expr(mod, scope, .{ .ty = u32_type }, params[0]);
2330 return addZIRUnOp(mod, scope, src, .set_eval_branch_quota, quota);
2331}2331}
23322332
2333fn 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 {
src/zir.zig+5-4
...@@ -127,8 +127,9 @@ pub const Inst = struct {...@@ -127,8 +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 code execution can use before giving up and making a compile error.130 /// Changes the maximum number of backwards branches that compile-time
131 setevalbranchquota,131 /// code execution can use before giving up and making a compile error.
132 set_eval_branch_quota,
132 /// Conditional branch. Splits control flow based on a boolean condition value.133 /// Conditional branch. Splits control flow based on a boolean condition value.
133 condbr,134 condbr,
134 /// Special case, has no textual representation.135 /// Special case, has no textual representation.
...@@ -349,7 +350,7 @@ pub const Inst = struct {...@@ -349,7 +350,7 @@ pub const Inst = struct {
349 .anyframe_type,350 .anyframe_type,
350 .bitnot,351 .bitnot,
351 .import,352 .import,
352 .setevalbranchquota,353 .set_eval_branch_quota,
353 => UnOp,354 => UnOp,
354355
355 .add,356 .add,
...@@ -538,7 +539,7 @@ pub const Inst = struct {...@@ -538,7 +539,7 @@ pub const Inst = struct {
538 .switch_range,539 .switch_range,
539 .typeof_peer,540 .typeof_peer,
540 .resolve_inferred_alloc,541 .resolve_inferred_alloc,
541 .setevalbranchquota,542 .set_eval_branch_quota,
542 => false,543 => false,
543544
544 .@"break",545 .@"break",
src/zir_sema.zig+20-2
...@@ -81,7 +81,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -81,7 +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 .setevalbranchquota => return analyzeInstSetEvalBranchQuota(mod, scope, old_inst.castTag(.setevalbranchquota).?),84 .set_eval_branch_quota => return analyzeInstSetEvalBranchQuota(mod, scope, old_inst.castTag(.set_eval_branch_quota).?),
85 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),85 .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),
86 .int => {86 .int => {
87 const big_int = old_inst.castTag(.int).?.positionals.int;87 const big_int = old_inst.castTag(.int).?.positionals.int;
...@@ -281,6 +281,24 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {...@@ -281,6 +281,24 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
281 return val.toType(scope.arena());281 return val.toType(scope.arena());
282}282}
283283
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
284fn 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 {
285 const new_inst = try resolveInst(mod, scope, old_inst);303 const new_inst = try resolveInst(mod, scope, old_inst);
286 const coerced = try mod.coerce(scope, dest_type, new_inst);304 const coerced = try mod.coerce(scope, dest_type, new_inst);
...@@ -493,7 +511,7 @@ fn analyzeInstSetEvalBranchQuota(...@@ -493,7 +511,7 @@ fn analyzeInstSetEvalBranchQuota(
493 inst: *zir.Inst.UnOp,511 inst: *zir.Inst.UnOp,
494) InnerError!*Inst {512) InnerError!*Inst {
495 const b = try mod.requireFunctionBlock(scope, inst.base.src);513 const b = try mod.requireFunctionBlock(scope, inst.base.src);
496 const quota = @truncate(u32, try resolveInt(mod, scope, inst.positionals.operand, Type.initTag(.u32)));514 const quota = try resolveAlreadyCoercedInt(mod, scope, inst.positionals.operand, u32);
497 if (b.branch_quota.* < quota)515 if (b.branch_quota.* < quota)
498 b.branch_quota.* = quota;516 b.branch_quota.* = quota;
499 return mod.constVoid(scope, inst.base.src);517 return mod.constVoid(scope, inst.base.src);