| author | |
| committer | |
| log | 61919fe63d1eb7134a3c85fe0a4cf279744de3e9 |
| tree | ad8a93f55ed7c4cff101789aedea0b5cc930d0f6 |
| parent | 16d74809d44d6bb8db1a32923ef8db43d956e24d |
| parent | a99ad52b362d966f772f29ad14ae1714218bc033 |
| signature |
incremental: more progress18 files changed, 297 insertions(+), 132 deletions(-)
lib/compiler/aro/aro/Builtins/Builtin.zig+1-1| ... | ... | @@ -5165,7 +5165,7 @@ const dafsa = [_]Node{ |
| 5165 | 5165 | .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 4913 }, |
| 5166 | 5166 | }; |
| 5167 | 5167 | pub const data = blk: { |
| 5168 | @setEvalBranchQuota(3986); | |
| 5168 | @setEvalBranchQuota(30_000); | |
| 5169 | 5169 | break :blk [_]@This(){ |
| 5170 | 5170 | // _Block_object_assign |
| 5171 | 5171 | .{ .tag = @enumFromInt(0), .properties = .{ .param_str = "vv*vC*iC", .header = .blocks, .attributes = .{ .lib_function_without_prefix = true } } }, |
lib/compiler/aro/aro/Parser.zig+2| ... | ... | @@ -4802,6 +4802,7 @@ const CallExpr = union(enum) { |
| 4802 | 4802 | } |
| 4803 | 4803 | |
| 4804 | 4804 | fn shouldPromoteVarArg(self: CallExpr, arg_idx: u32) bool { |
| 4805 | @setEvalBranchQuota(2000); | |
| 4805 | 4806 | return switch (self) { |
| 4806 | 4807 | .standard => true, |
| 4807 | 4808 | .builtin => |builtin| switch (builtin.tag) { |
| ... | ... | @@ -4902,6 +4903,7 @@ const CallExpr = union(enum) { |
| 4902 | 4903 | } |
| 4903 | 4904 | |
| 4904 | 4905 | fn returnType(self: CallExpr, p: *Parser, callable_ty: Type) Type { |
| 4906 | @setEvalBranchQuota(6000); | |
| 4905 | 4907 | return switch (self) { |
| 4906 | 4908 | .standard => callable_ty.returnType(), |
| 4907 | 4909 | .builtin => |builtin| switch (builtin.tag) { |
lib/std/crypto/aes/soft.zig+2| ... | ... | @@ -629,6 +629,8 @@ fn generateSbox(invert: bool) [256]u8 { |
| 629 | 629 | |
| 630 | 630 | // Generate lookup tables. |
| 631 | 631 | fn generateTable(invert: bool) [4][256]u32 { |
| 632 | @setEvalBranchQuota(50000); | |
| 633 | ||
| 632 | 634 | var table: [4][256]u32 = undefined; |
| 633 | 635 | |
| 634 | 636 | for (generateSbox(invert), 0..) |value, index| { |
lib/std/crypto/blake2.zig+2-2| ... | ... | @@ -786,7 +786,7 @@ test "blake2b384 streaming" { |
| 786 | 786 | |
| 787 | 787 | test "comptime blake2b384" { |
| 788 | 788 | comptime { |
| 789 | @setEvalBranchQuota(10000); | |
| 789 | @setEvalBranchQuota(20000); | |
| 790 | 790 | var block = [_]u8{0} ** Blake2b384.block_length; |
| 791 | 791 | var out: [Blake2b384.digest_length]u8 = undefined; |
| 792 | 792 | |
| ... | ... | @@ -878,7 +878,7 @@ test "blake2b512 keyed" { |
| 878 | 878 | |
| 879 | 879 | test "comptime blake2b512" { |
| 880 | 880 | comptime { |
| 881 | @setEvalBranchQuota(10000); | |
| 881 | @setEvalBranchQuota(12000); | |
| 882 | 882 | var block = [_]u8{0} ** Blake2b512.block_length; |
| 883 | 883 | var out: [Blake2b512.digest_length]u8 = undefined; |
| 884 | 884 |
lib/std/crypto/pcurves/p384.zig+1-1| ... | ... | @@ -393,7 +393,7 @@ pub const P384 = struct { |
| 393 | 393 | } |
| 394 | 394 | |
| 395 | 395 | const basePointPc = pc: { |
| 396 | @setEvalBranchQuota(50000); | |
| 396 | @setEvalBranchQuota(70000); | |
| 397 | 397 | break :pc precompute(P384.basePoint, 15); |
| 398 | 398 | }; |
| 399 | 399 |
lib/std/enums.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const testing = std.testing; |
| 6 | 6 | const EnumField = std.builtin.Type.EnumField; |
| 7 | 7 | |
| 8 | 8 | /// Increment this value when adding APIs that add single backwards branches. |
| 9 | const eval_branch_quota_cushion = 5; | |
| 9 | const eval_branch_quota_cushion = 10; | |
| 10 | 10 | |
| 11 | 11 | /// Returns a struct with a field matching each unique named enum element. |
| 12 | 12 | /// If the enum is extern and has multiple names for the same value, only |
lib/std/hash/xxhash.zig+1-1| ... | ... | @@ -890,7 +890,7 @@ test "xxhash32 smhasher" { |
| 890 | 890 | } |
| 891 | 891 | }; |
| 892 | 892 | try Test.do(); |
| 893 | @setEvalBranchQuota(75000); | |
| 893 | @setEvalBranchQuota(85000); | |
| 894 | 894 | comptime try Test.do(); |
| 895 | 895 | } |
| 896 | 896 |
lib/std/math.zig+8-16| ... | ... | @@ -749,31 +749,23 @@ test rotl { |
| 749 | 749 | try testing.expect(rotl(@Vector(1, u32), @Vector(1, u32){1 << 31}, @as(isize, -1))[0] == @as(u32, 1) << 30); |
| 750 | 750 | } |
| 751 | 751 | |
| 752 | /// Returns an unsigned int type that can hold the number of bits in T | |
| 753 | /// - 1. Suitable for 0-based bit indices of T. | |
| 752 | /// Returns an unsigned int type that can hold the number of bits in T - 1. | |
| 753 | /// Suitable for 0-based bit indices of T. | |
| 754 | 754 | pub fn Log2Int(comptime T: type) type { |
| 755 | 755 | // comptime ceil log2 |
| 756 | 756 | if (T == comptime_int) return comptime_int; |
| 757 | comptime var count = 0; | |
| 758 | comptime var s = @typeInfo(T).Int.bits - 1; | |
| 759 | inline while (s != 0) : (s >>= 1) { | |
| 760 | count += 1; | |
| 761 | } | |
| 762 | ||
| 763 | return std.meta.Int(.unsigned, count); | |
| 757 | const bits: u16 = @typeInfo(T).Int.bits; | |
| 758 | const log2_bits = 16 - @clz(bits - 1); | |
| 759 | return std.meta.Int(.unsigned, log2_bits); | |
| 764 | 760 | } |
| 765 | 761 | |
| 766 | 762 | /// Returns an unsigned int type that can hold the number of bits in T. |
| 767 | 763 | pub fn Log2IntCeil(comptime T: type) type { |
| 768 | 764 | // comptime ceil log2 |
| 769 | 765 | if (T == comptime_int) return comptime_int; |
| 770 | comptime var count = 0; | |
| 771 | comptime var s = @typeInfo(T).Int.bits; | |
| 772 | inline while (s != 0) : (s >>= 1) { | |
| 773 | count += 1; | |
| 774 | } | |
| 775 | ||
| 776 | return std.meta.Int(.unsigned, count); | |
| 766 | const bits: u16 = @typeInfo(T).Int.bits; | |
| 767 | const log2_bits = 16 - @clz(bits); | |
| 768 | return std.meta.Int(.unsigned, log2_bits); | |
| 777 | 769 | } |
| 778 | 770 | |
| 779 | 771 | /// Returns the smallest integer type that can hold both from and to. |
lib/std/math/hypot.zig+1| ... | ... | @@ -114,6 +114,7 @@ test "hypot.precise" { |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | test "hypot.special" { |
| 117 | @setEvalBranchQuota(2000); | |
| 117 | 118 | inline for (.{ f16, f32, f64, f128 }) |T| { |
| 118 | 119 | try expect(math.isNan(hypot(nan(T), 0.0))); |
| 119 | 120 | try expect(math.isNan(hypot(0.0, nan(T)))); |
lib/std/math/nextafter.zig+1-1| ... | ... | @@ -144,7 +144,7 @@ test "int" { |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | test "float" { |
| 147 | @setEvalBranchQuota(3000); | |
| 147 | @setEvalBranchQuota(4000); | |
| 148 | 148 | |
| 149 | 149 | // normal -> normal |
| 150 | 150 | try expect(nextAfter(f16, 0x1.234p0, 2.0) == 0x1.238p0); |
lib/std/unicode.zig+1| ... | ... | @@ -535,6 +535,7 @@ fn testUtf16CountCodepoints() !void { |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | 537 | test "utf16 count codepoints" { |
| 538 | @setEvalBranchQuota(2000); | |
| 538 | 539 | try testUtf16CountCodepoints(); |
| 539 | 540 | try comptime testUtf16CountCodepoints(); |
| 540 | 541 | } |
lib/std/zig/AstGen.zig+107-30| ... | ... | @@ -66,6 +66,10 @@ scratch: std.ArrayListUnmanaged(u32) = .{}, |
| 66 | 66 | /// of ZIR. |
| 67 | 67 | /// The key is the ref operand; the value is the ref instruction. |
| 68 | 68 | ref_table: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 69 | /// Any information which should trigger invalidation of incremental compilation | |
| 70 | /// data should be used to update this hasher. The result is the final source | |
| 71 | /// hash of the enclosing declaration/etc. | |
| 72 | src_hasher: std.zig.SrcHasher, | |
| 69 | 73 | |
| 70 | 74 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 71 | 75 | |
| ... | ... | @@ -137,6 +141,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 137 | 141 | .arena = arena.allocator(), |
| 138 | 142 | .tree = &tree, |
| 139 | 143 | .nodes_need_rl = &nodes_need_rl, |
| 144 | .src_hasher = undefined, // `structDeclInner` for the root struct will set this | |
| 140 | 145 | }; |
| 141 | 146 | defer astgen.deinit(gpa); |
| 142 | 147 | |
| ... | ... | @@ -1422,6 +1427,8 @@ fn fnProtoExpr( |
| 1422 | 1427 | .is_extern = false, |
| 1423 | 1428 | .is_noinline = false, |
| 1424 | 1429 | .noalias_bits = noalias_bits, |
| 1430 | ||
| 1431 | .proto_hash = undefined, // ignored for `body_gz == null` | |
| 1425 | 1432 | }); |
| 1426 | 1433 | |
| 1427 | 1434 | _ = try block_scope.addBreak(.break_inline, block_inst, result); |
| ... | ... | @@ -4007,6 +4014,13 @@ fn fnDecl( |
| 4007 | 4014 | const tree = astgen.tree; |
| 4008 | 4015 | const token_tags = tree.tokens.items(.tag); |
| 4009 | 4016 | |
| 4017 | const old_hasher = astgen.src_hasher; | |
| 4018 | defer astgen.src_hasher = old_hasher; | |
| 4019 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 4020 | // We don't add the full source yet, because we also need the prototype hash! | |
| 4021 | // The source slice is added towards the *end* of this function. | |
| 4022 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); | |
| 4023 | ||
| 4010 | 4024 | // missing function name already happened in scanDecls() |
| 4011 | 4025 | const fn_name_token = fn_proto.name_token orelse return error.AnalysisFail; |
| 4012 | 4026 | |
| ... | ... | @@ -4300,11 +4314,21 @@ fn fnDecl( |
| 4300 | 4314 | .is_extern = true, |
| 4301 | 4315 | .is_noinline = is_noinline, |
| 4302 | 4316 | .noalias_bits = noalias_bits, |
| 4317 | .proto_hash = undefined, // ignored for `body_gz == null` | |
| 4303 | 4318 | }); |
| 4304 | 4319 | } else func: { |
| 4305 | 4320 | // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz |
| 4306 | 4321 | fn_gz.instructions_top = ret_gz.instructions.items.len; |
| 4307 | 4322 | |
| 4323 | // Construct the prototype hash. | |
| 4324 | // Leave `astgen.src_hasher` unmodified; this will be used for hashing | |
| 4325 | // the *whole* function declaration, including its body. | |
| 4326 | var proto_hasher = astgen.src_hasher; | |
| 4327 | const proto_node = tree.nodes.items(.data)[decl_node].lhs; | |
| 4328 | proto_hasher.update(tree.getNodeSource(proto_node)); | |
| 4329 | var proto_hash: std.zig.SrcHash = undefined; | |
| 4330 | proto_hasher.final(&proto_hash); | |
| 4331 | ||
| 4308 | 4332 | const prev_fn_block = astgen.fn_block; |
| 4309 | 4333 | const prev_fn_ret_ty = astgen.fn_ret_ty; |
| 4310 | 4334 | defer { |
| ... | ... | @@ -4362,16 +4386,22 @@ fn fnDecl( |
| 4362 | 4386 | .is_extern = false, |
| 4363 | 4387 | .is_noinline = is_noinline, |
| 4364 | 4388 | .noalias_bits = noalias_bits, |
| 4389 | .proto_hash = proto_hash, | |
| 4365 | 4390 | }); |
| 4366 | 4391 | }; |
| 4367 | 4392 | |
| 4393 | // *Now* we can incorporate the full source code into the hasher. | |
| 4394 | astgen.src_hasher.update(tree.getNodeSource(decl_node)); | |
| 4395 | ||
| 4368 | 4396 | // We add this at the end so that its instruction index marks the end range |
| 4369 | 4397 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. |
| 4370 | 4398 | _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst); |
| 4371 | 4399 | |
| 4400 | var hash: std.zig.SrcHash = undefined; | |
| 4401 | astgen.src_hasher.final(&hash); | |
| 4372 | 4402 | try setDeclaration( |
| 4373 | 4403 | decl_inst, |
| 4374 | std.zig.hashSrc(tree.getNodeSource(decl_node)), | |
| 4404 | hash, | |
| 4375 | 4405 | .{ .named = fn_name_token }, |
| 4376 | 4406 | decl_gz.decl_line, |
| 4377 | 4407 | is_pub, |
| ... | ... | @@ -4395,6 +4425,12 @@ fn globalVarDecl( |
| 4395 | 4425 | const tree = astgen.tree; |
| 4396 | 4426 | const token_tags = tree.tokens.items(.tag); |
| 4397 | 4427 | |
| 4428 | const old_hasher = astgen.src_hasher; | |
| 4429 | defer astgen.src_hasher = old_hasher; | |
| 4430 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 4431 | astgen.src_hasher.update(tree.getNodeSource(node)); | |
| 4432 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); | |
| 4433 | ||
| 4398 | 4434 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 4399 | 4435 | // We do this at the beginning so that the instruction index marks the range start |
| 4400 | 4436 | // of the top level declaration. |
| ... | ... | @@ -4534,9 +4570,11 @@ fn globalVarDecl( |
| 4534 | 4570 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node); |
| 4535 | 4571 | } |
| 4536 | 4572 | |
| 4573 | var hash: std.zig.SrcHash = undefined; | |
| 4574 | astgen.src_hasher.final(&hash); | |
| 4537 | 4575 | try setDeclaration( |
| 4538 | 4576 | decl_inst, |
| 4539 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4577 | hash, | |
| 4540 | 4578 | .{ .named = name_token }, |
| 4541 | 4579 | block_scope.decl_line, |
| 4542 | 4580 | is_pub, |
| ... | ... | @@ -4562,6 +4600,12 @@ fn comptimeDecl( |
| 4562 | 4600 | const node_datas = tree.nodes.items(.data); |
| 4563 | 4601 | const body_node = node_datas[node].lhs; |
| 4564 | 4602 | |
| 4603 | const old_hasher = astgen.src_hasher; | |
| 4604 | defer astgen.src_hasher = old_hasher; | |
| 4605 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 4606 | astgen.src_hasher.update(tree.getNodeSource(node)); | |
| 4607 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); | |
| 4608 | ||
| 4565 | 4609 | // Up top so the ZIR instruction index marks the start range of this |
| 4566 | 4610 | // top-level declaration. |
| 4567 | 4611 | const decl_inst = try gz.makeDeclaration(node); |
| ... | ... | @@ -4584,9 +4628,11 @@ fn comptimeDecl( |
| 4584 | 4628 | _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value); |
| 4585 | 4629 | } |
| 4586 | 4630 | |
| 4631 | var hash: std.zig.SrcHash = undefined; | |
| 4632 | astgen.src_hasher.final(&hash); | |
| 4587 | 4633 | try setDeclaration( |
| 4588 | 4634 | decl_inst, |
| 4589 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4635 | hash, | |
| 4590 | 4636 | .@"comptime", |
| 4591 | 4637 | decl_block.decl_line, |
| 4592 | 4638 | false, |
| ... | ... | @@ -4607,6 +4653,12 @@ fn usingnamespaceDecl( |
| 4607 | 4653 | const tree = astgen.tree; |
| 4608 | 4654 | const node_datas = tree.nodes.items(.data); |
| 4609 | 4655 | |
| 4656 | const old_hasher = astgen.src_hasher; | |
| 4657 | defer astgen.src_hasher = old_hasher; | |
| 4658 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 4659 | astgen.src_hasher.update(tree.getNodeSource(node)); | |
| 4660 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); | |
| 4661 | ||
| 4610 | 4662 | const type_expr = node_datas[node].lhs; |
| 4611 | 4663 | const is_pub = blk: { |
| 4612 | 4664 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -4634,9 +4686,11 @@ fn usingnamespaceDecl( |
| 4634 | 4686 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 4635 | 4687 | _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst); |
| 4636 | 4688 | |
| 4689 | var hash: std.zig.SrcHash = undefined; | |
| 4690 | astgen.src_hasher.final(&hash); | |
| 4637 | 4691 | try setDeclaration( |
| 4638 | 4692 | decl_inst, |
| 4639 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4693 | hash, | |
| 4640 | 4694 | .@"usingnamespace", |
| 4641 | 4695 | decl_block.decl_line, |
| 4642 | 4696 | is_pub, |
| ... | ... | @@ -4658,6 +4712,12 @@ fn testDecl( |
| 4658 | 4712 | const node_datas = tree.nodes.items(.data); |
| 4659 | 4713 | const body_node = node_datas[node].rhs; |
| 4660 | 4714 | |
| 4715 | const old_hasher = astgen.src_hasher; | |
| 4716 | defer astgen.src_hasher = old_hasher; | |
| 4717 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 4718 | astgen.src_hasher.update(tree.getNodeSource(node)); | |
| 4719 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); | |
| 4720 | ||
| 4661 | 4721 | // Up top so the ZIR instruction index marks the start range of this |
| 4662 | 4722 | // top-level declaration. |
| 4663 | 4723 | const decl_inst = try gz.makeDeclaration(node); |
| ... | ... | @@ -4819,13 +4879,18 @@ fn testDecl( |
| 4819 | 4879 | .is_extern = false, |
| 4820 | 4880 | .is_noinline = false, |
| 4821 | 4881 | .noalias_bits = 0, |
| 4882 | ||
| 4883 | // Tests don't have a prototype that needs hashing | |
| 4884 | .proto_hash = .{0} ** 16, | |
| 4822 | 4885 | }); |
| 4823 | 4886 | |
| 4824 | 4887 | _ = try decl_block.addBreak(.break_inline, decl_inst, func_inst); |
| 4825 | 4888 | |
| 4889 | var hash: std.zig.SrcHash = undefined; | |
| 4890 | astgen.src_hasher.final(&hash); | |
| 4826 | 4891 | try setDeclaration( |
| 4827 | 4892 | decl_inst, |
| 4828 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4893 | hash, | |
| 4829 | 4894 | test_name, |
| 4830 | 4895 | decl_block.decl_line, |
| 4831 | 4896 | false, |
| ... | ... | @@ -4983,10 +5048,12 @@ fn structDeclInner( |
| 4983 | 5048 | } |
| 4984 | 5049 | }; |
| 4985 | 5050 | |
| 4986 | var fields_hasher = std.zig.SrcHasher.init(.{}); | |
| 4987 | fields_hasher.update(@tagName(layout)); | |
| 5051 | const old_hasher = astgen.src_hasher; | |
| 5052 | defer astgen.src_hasher = old_hasher; | |
| 5053 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5054 | astgen.src_hasher.update(@tagName(layout)); | |
| 4988 | 5055 | if (backing_int_node != 0) { |
| 4989 | fields_hasher.update(tree.getNodeSource(backing_int_node)); | |
| 5056 | astgen.src_hasher.update(tree.getNodeSource(backing_int_node)); | |
| 4990 | 5057 | } |
| 4991 | 5058 | |
| 4992 | 5059 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| ... | ... | @@ -5009,7 +5076,7 @@ fn structDeclInner( |
| 5009 | 5076 | .field => |field| field, |
| 5010 | 5077 | }; |
| 5011 | 5078 | |
| 5012 | fields_hasher.update(tree.getNodeSource(member_node)); | |
| 5079 | astgen.src_hasher.update(tree.getNodeSource(member_node)); | |
| 5013 | 5080 | |
| 5014 | 5081 | if (!is_tuple) { |
| 5015 | 5082 | const field_name = try astgen.identAsString(member.ast.main_token); |
| ... | ... | @@ -5139,7 +5206,7 @@ fn structDeclInner( |
| 5139 | 5206 | } |
| 5140 | 5207 | |
| 5141 | 5208 | var fields_hash: std.zig.SrcHash = undefined; |
| 5142 | fields_hasher.final(&fields_hash); | |
| 5209 | astgen.src_hasher.final(&fields_hash); | |
| 5143 | 5210 | |
| 5144 | 5211 | try gz.setStruct(decl_inst, .{ |
| 5145 | 5212 | .src_node = node, |
| ... | ... | @@ -5240,11 +5307,13 @@ fn unionDeclInner( |
| 5240 | 5307 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 5241 | 5308 | defer wip_members.deinit(); |
| 5242 | 5309 | |
| 5243 | var fields_hasher = std.zig.SrcHasher.init(.{}); | |
| 5244 | fields_hasher.update(@tagName(layout)); | |
| 5245 | fields_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); | |
| 5310 | const old_hasher = astgen.src_hasher; | |
| 5311 | defer astgen.src_hasher = old_hasher; | |
| 5312 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5313 | astgen.src_hasher.update(@tagName(layout)); | |
| 5314 | astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); | |
| 5246 | 5315 | if (arg_node != 0) { |
| 5247 | fields_hasher.update(astgen.tree.getNodeSource(arg_node)); | |
| 5316 | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); | |
| 5248 | 5317 | } |
| 5249 | 5318 | |
| 5250 | 5319 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| ... | ... | @@ -5261,7 +5330,7 @@ fn unionDeclInner( |
| 5261 | 5330 | .decl => continue, |
| 5262 | 5331 | .field => |field| field, |
| 5263 | 5332 | }; |
| 5264 | fields_hasher.update(astgen.tree.getNodeSource(member_node)); | |
| 5333 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); | |
| 5265 | 5334 | member.convertToNonTupleLike(astgen.tree.nodes); |
| 5266 | 5335 | if (member.ast.tuple_like) { |
| 5267 | 5336 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); |
| ... | ... | @@ -5364,7 +5433,7 @@ fn unionDeclInner( |
| 5364 | 5433 | } |
| 5365 | 5434 | |
| 5366 | 5435 | var fields_hash: std.zig.SrcHash = undefined; |
| 5367 | fields_hasher.final(&fields_hash); | |
| 5436 | astgen.src_hasher.final(&fields_hash); | |
| 5368 | 5437 | |
| 5369 | 5438 | if (!block_scope.isEmpty()) { |
| 5370 | 5439 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| ... | ... | @@ -5578,11 +5647,13 @@ fn containerDecl( |
| 5578 | 5647 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); |
| 5579 | 5648 | defer wip_members.deinit(); |
| 5580 | 5649 | |
| 5581 | var fields_hasher = std.zig.SrcHasher.init(.{}); | |
| 5650 | const old_hasher = astgen.src_hasher; | |
| 5651 | defer astgen.src_hasher = old_hasher; | |
| 5652 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5582 | 5653 | if (container_decl.ast.arg != 0) { |
| 5583 | fields_hasher.update(tree.getNodeSource(container_decl.ast.arg)); | |
| 5654 | astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg)); | |
| 5584 | 5655 | } |
| 5585 | fields_hasher.update(&.{@intFromBool(nonexhaustive)}); | |
| 5656 | astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); | |
| 5586 | 5657 | |
| 5587 | 5658 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| 5588 | 5659 | const sfba_allocator = sfba.get(); |
| ... | ... | @@ -5596,7 +5667,7 @@ fn containerDecl( |
| 5596 | 5667 | for (container_decl.ast.members) |member_node| { |
| 5597 | 5668 | if (member_node == counts.nonexhaustive_node) |
| 5598 | 5669 | continue; |
| 5599 | fields_hasher.update(tree.getNodeSource(member_node)); | |
| 5670 | astgen.src_hasher.update(tree.getNodeSource(member_node)); | |
| 5600 | 5671 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5601 | 5672 | .decl => continue, |
| 5602 | 5673 | .field => |field| field, |
| ... | ... | @@ -5676,7 +5747,7 @@ fn containerDecl( |
| 5676 | 5747 | } |
| 5677 | 5748 | |
| 5678 | 5749 | var fields_hash: std.zig.SrcHash = undefined; |
| 5679 | fields_hasher.final(&fields_hash); | |
| 5750 | astgen.src_hasher.final(&fields_hash); | |
| 5680 | 5751 | |
| 5681 | 5752 | const body = block_scope.instructionsSlice(); |
| 5682 | 5753 | const body_len = astgen.countBodyLenAfterFixups(body); |
| ... | ... | @@ -8478,6 +8549,10 @@ fn tunnelThroughClosure( |
| 8478 | 8549 | }); |
| 8479 | 8550 | } |
| 8480 | 8551 | |
| 8552 | // Incorporate the capture index into the source hash, so that changes in | |
| 8553 | // the order of captures cause suitable re-analysis. | |
| 8554 | astgen.src_hasher.update(std.mem.asBytes(&cur_capture_index)); | |
| 8555 | ||
| 8481 | 8556 | // Add an instruction to get the value from the closure. |
| 8482 | 8557 | return gz.addExtendedNodeSmall(.closure_get, inner_ref_node, cur_capture_index); |
| 8483 | 8558 | } |
| ... | ... | @@ -9306,6 +9381,13 @@ fn builtinCall( |
| 9306 | 9381 | }, |
| 9307 | 9382 | |
| 9308 | 9383 | .src => { |
| 9384 | // Incorporate the source location into the source hash, so that | |
| 9385 | // changes in the source location of `@src()` result in re-analysis. | |
| 9386 | astgen.src_hasher.update( | |
| 9387 | std.mem.asBytes(&astgen.source_line) ++ | |
| 9388 | std.mem.asBytes(&astgen.source_column), | |
| 9389 | ); | |
| 9390 | ||
| 9309 | 9391 | const token_starts = tree.tokens.items(.start); |
| 9310 | 9392 | const node_start = token_starts[tree.firstToken(node)]; |
| 9311 | 9393 | astgen.advanceSourceCursor(node_start); |
| ... | ... | @@ -12122,6 +12204,9 @@ const GenZir = struct { |
| 12122 | 12204 | is_test: bool, |
| 12123 | 12205 | is_extern: bool, |
| 12124 | 12206 | is_noinline: bool, |
| 12207 | ||
| 12208 | /// Ignored if `body_gz == null`. | |
| 12209 | proto_hash: std.zig.SrcHash, | |
| 12125 | 12210 | }) !Zir.Inst.Ref { |
| 12126 | 12211 | assert(args.src_node != 0); |
| 12127 | 12212 | const astgen = gz.astgen; |
| ... | ... | @@ -12150,15 +12235,7 @@ const GenZir = struct { |
| 12150 | 12235 | |
| 12151 | 12236 | const columns = args.lbrace_column | (rbrace_column << 16); |
| 12152 | 12237 | |
| 12153 | const proto_hash: std.zig.SrcHash = switch (node_tags[fn_decl]) { | |
| 12154 | .fn_decl => sig_hash: { | |
| 12155 | const proto_node = node_datas[fn_decl].lhs; | |
| 12156 | break :sig_hash std.zig.hashSrc(tree.getNodeSource(proto_node)); | |
| 12157 | }, | |
| 12158 | .test_decl => std.zig.hashSrc(""), // tests don't have a prototype | |
| 12159 | else => unreachable, | |
| 12160 | }; | |
| 12161 | const proto_hash_arr: [4]u32 = @bitCast(proto_hash); | |
| 12238 | const proto_hash_arr: [4]u32 = @bitCast(args.proto_hash); | |
| 12162 | 12239 | |
| 12163 | 12240 | src_locs_and_hash_buffer = .{ |
| 12164 | 12241 | args.lbrace_line, |
src/InternPool.zig+4| ... | ... | @@ -2391,6 +2391,7 @@ pub const Key = union(enum) { |
| 2391 | 2391 | func: Index, |
| 2392 | 2392 | arg_values: []const Index, |
| 2393 | 2393 | result: Index, |
| 2394 | branch_count: u32, | |
| 2394 | 2395 | }; |
| 2395 | 2396 | |
| 2396 | 2397 | pub fn hash32(key: Key, ip: *const InternPool) u32 { |
| ... | ... | @@ -6157,6 +6158,7 @@ pub const MemoizedCall = struct { |
| 6157 | 6158 | func: Index, |
| 6158 | 6159 | args_len: u32, |
| 6159 | 6160 | result: Index, |
| 6161 | branch_count: u32, | |
| 6160 | 6162 | }; |
| 6161 | 6163 | |
| 6162 | 6164 | pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| ... | ... | @@ -6785,6 +6787,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6785 | 6787 | .func = extra.data.func, |
| 6786 | 6788 | .arg_values = @ptrCast(extra_list.view().items(.@"0")[extra.end..][0..extra.data.args_len]), |
| 6787 | 6789 | .result = extra.data.result, |
| 6790 | .branch_count = extra.data.branch_count, | |
| 6788 | 6791 | } }; |
| 6789 | 6792 | }, |
| 6790 | 6793 | }; |
| ... | ... | @@ -7955,6 +7958,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 7955 | 7958 | .func = memoized_call.func, |
| 7956 | 7959 | .args_len = @intCast(memoized_call.arg_values.len), |
| 7957 | 7960 | .result = memoized_call.result, |
| 7961 | .branch_count = memoized_call.branch_count, | |
| 7958 | 7962 | }), |
| 7959 | 7963 | }); |
| 7960 | 7964 | extra.appendSliceAssumeCapacity(.{@ptrCast(memoized_call.arg_values)}); |
src/Sema.zig+110-78| ... | ... | @@ -113,6 +113,11 @@ type_references: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, |
| 113 | 113 | /// `AnalUnit` multiple times. |
| 114 | 114 | dependencies: std.AutoArrayHashMapUnmanaged(InternPool.Dependee, void) = .{}, |
| 115 | 115 | |
| 116 | /// Whether memoization of this call is permitted. Operations with side effects global | |
| 117 | /// to the `Sema`, such as `@setEvalBranchQuota`, set this to `false`. It is observed | |
| 118 | /// by `analyzeCall`. | |
| 119 | allow_memoize: bool = true, | |
| 120 | ||
| 116 | 121 | const MaybeComptimeAlloc = struct { |
| 117 | 122 | /// The runtime index of the `alloc` instruction. |
| 118 | 123 | runtime_index: Value.RuntimeIndex, |
| ... | ... | @@ -5524,6 +5529,7 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 5524 | 5529 | .needed_comptime_reason = "eval branch quota must be comptime-known", |
| 5525 | 5530 | })); |
| 5526 | 5531 | sema.branch_quota = @max(sema.branch_quota, quota); |
| 5532 | sema.allow_memoize = false; | |
| 5527 | 5533 | } |
| 5528 | 5534 | |
| 5529 | 5535 | fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -6416,6 +6422,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 6416 | 6422 | } |
| 6417 | 6423 | |
| 6418 | 6424 | zcu.intern_pool.funcMaxStackAlignment(sema.func_index, alignment); |
| 6425 | sema.allow_memoize = false; | |
| 6419 | 6426 | } |
| 6420 | 6427 | |
| 6421 | 6428 | fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| ... | ... | @@ -6434,6 +6441,7 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) |
| 6434 | 6441 | .cau => return, // does nothing outside a function |
| 6435 | 6442 | }; |
| 6436 | 6443 | ip.funcSetCold(func, is_cold); |
| 6444 | sema.allow_memoize = false; | |
| 6437 | 6445 | } |
| 6438 | 6446 | |
| 6439 | 6447 | fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| ... | ... | @@ -6445,6 +6453,7 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| 6445 | 6453 | .cau => return, // does nothing outside a function |
| 6446 | 6454 | }; |
| 6447 | 6455 | ip.funcSetDisableInstrumentation(func); |
| 6456 | sema.allow_memoize = false; | |
| 6448 | 6457 | } |
| 6449 | 6458 | |
| 6450 | 6459 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| ... | ... | @@ -7589,6 +7598,9 @@ fn analyzeCall( |
| 7589 | 7598 | |
| 7590 | 7599 | const module_fn = zcu.funcInfo(module_fn_index); |
| 7591 | 7600 | |
| 7601 | // The call site definitely depends on the function's signature. | |
| 7602 | try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst }); | |
| 7603 | ||
| 7592 | 7604 | // This is not a function instance, so the function's `Nav` has a |
| 7593 | 7605 | // `Cau` -- we don't need to check `generic_owner`. |
| 7594 | 7606 | const fn_nav = ip.getNav(module_fn.owner_nav); |
| ... | ... | @@ -7725,101 +7737,121 @@ fn analyzeCall( |
| 7725 | 7737 | } })); |
| 7726 | 7738 | } |
| 7727 | 7739 | |
| 7728 | // This `res2` is here instead of directly breaking from `res` due to a stage1 | |
| 7729 | // bug generating invalid LLVM IR. | |
| 7730 | const res2: Air.Inst.Ref = res2: { | |
| 7731 | if (should_memoize and is_comptime_call) { | |
| 7732 | if (zcu.intern_pool.getIfExists(.{ .memoized_call = .{ | |
| 7740 | memoize: { | |
| 7741 | if (!should_memoize) break :memoize; | |
| 7742 | if (!is_comptime_call) break :memoize; | |
| 7743 | const memoized_call_index = ip.getIfExists(.{ | |
| 7744 | .memoized_call = .{ | |
| 7733 | 7745 | .func = module_fn_index, |
| 7734 | 7746 | .arg_values = memoized_arg_values, |
| 7735 | .result = .none, | |
| 7736 | } })) |memoized_call_index| { | |
| 7737 | const memoized_call = zcu.intern_pool.indexToKey(memoized_call_index).memoized_call; | |
| 7738 | break :res2 Air.internedToRef(memoized_call.result); | |
| 7739 | } | |
| 7747 | .result = undefined, // ignored by hash+eql | |
| 7748 | .branch_count = undefined, // ignored by hash+eql | |
| 7749 | }, | |
| 7750 | }) orelse break :memoize; | |
| 7751 | const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; | |
| 7752 | if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { | |
| 7753 | // Let the call play out se we get the correct source location for the | |
| 7754 | // "evaluation exceeded X backwards branches" error. | |
| 7755 | break :memoize; | |
| 7740 | 7756 | } |
| 7757 | sema.branch_count += memoized_call.branch_count; | |
| 7758 | break :res Air.internedToRef(memoized_call.result); | |
| 7759 | } | |
| 7741 | 7760 | |
| 7742 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); | |
| 7743 | if (!is_comptime_call and !block.is_typeof) { | |
| 7744 | const zir_tags = sema.code.instructions.items(.tag); | |
| 7745 | for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { | |
| 7746 | .param, .param_comptime => { | |
| 7747 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; | |
| 7748 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); | |
| 7749 | const param_name = sema.code.nullTerminatedString(extra.data.name); | |
| 7750 | const inst = sema.inst_map.get(param).?; | |
| 7761 | // Since we're doing an inline call, we depend on the source code of the whole | |
| 7762 | // function declaration. | |
| 7763 | try sema.declareDependency(.{ .src_hash = fn_cau.zir_index }); | |
| 7751 | 7764 | |
| 7752 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); | |
| 7753 | }, | |
| 7754 | .param_anytype, .param_anytype_comptime => { | |
| 7755 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; | |
| 7756 | const param_name = inst_data.get(sema.code); | |
| 7757 | const inst = sema.inst_map.get(param).?; | |
| 7765 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); | |
| 7766 | if (!is_comptime_call and !block.is_typeof) { | |
| 7767 | const zir_tags = sema.code.instructions.items(.tag); | |
| 7768 | for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { | |
| 7769 | .param, .param_comptime => { | |
| 7770 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].pl_tok; | |
| 7771 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); | |
| 7772 | const param_name = sema.code.nullTerminatedString(extra.data.name); | |
| 7773 | const inst = sema.inst_map.get(param).?; | |
| 7774 | ||
| 7775 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); | |
| 7776 | }, | |
| 7777 | .param_anytype, .param_anytype_comptime => { | |
| 7778 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok; | |
| 7779 | const param_name = inst_data.get(sema.code); | |
| 7780 | const inst = sema.inst_map.get(param).?; | |
| 7758 | 7781 | |
| 7759 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); | |
| 7760 | }, | |
| 7761 | else => continue, | |
| 7762 | }; | |
| 7763 | } | |
| 7782 | try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name); | |
| 7783 | }, | |
| 7784 | else => continue, | |
| 7785 | }; | |
| 7786 | } | |
| 7764 | 7787 | |
| 7765 | if (is_comptime_call and ensure_result_used) { | |
| 7766 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); | |
| 7767 | } | |
| 7788 | if (is_comptime_call and ensure_result_used) { | |
| 7789 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); | |
| 7790 | } | |
| 7768 | 7791 | |
| 7769 | if (is_comptime_call or block.is_typeof) { | |
| 7770 | // Save the error trace as our first action in the function | |
| 7771 | // to match the behavior of runtime function calls. | |
| 7772 | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); | |
| 7773 | sema.error_return_trace_index_on_fn_entry = error_return_trace_index; | |
| 7774 | child_block.error_return_trace_index = error_return_trace_index; | |
| 7775 | } | |
| 7792 | if (is_comptime_call or block.is_typeof) { | |
| 7793 | // Save the error trace as our first action in the function | |
| 7794 | // to match the behavior of runtime function calls. | |
| 7795 | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); | |
| 7796 | sema.error_return_trace_index_on_fn_entry = error_return_trace_index; | |
| 7797 | child_block.error_return_trace_index = error_return_trace_index; | |
| 7798 | } | |
| 7776 | 7799 | |
| 7777 | const result = result: { | |
| 7778 | sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { | |
| 7779 | error.ComptimeReturn => break :result inlining.comptime_result, | |
| 7780 | else => |e| return e, | |
| 7781 | }; | |
| 7782 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); | |
| 7800 | // We temporarily set `allow_memoize` to `true` to track this comptime call. | |
| 7801 | // It is restored after this call finishes analysis, so that a caller may | |
| 7802 | // know whether an in-progress call (containing this call) may be memoized. | |
| 7803 | const old_allow_memoize = sema.allow_memoize; | |
| 7804 | defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; | |
| 7805 | sema.allow_memoize = true; | |
| 7806 | ||
| 7807 | // Store the current eval branch count so we can find out how many eval branches | |
| 7808 | // the comptime call caused. | |
| 7809 | const old_branch_count = sema.branch_count; | |
| 7810 | ||
| 7811 | const result = result: { | |
| 7812 | sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) { | |
| 7813 | error.ComptimeReturn => break :result inlining.comptime_result, | |
| 7814 | else => |e| return e, | |
| 7783 | 7815 | }; |
| 7816 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); | |
| 7817 | }; | |
| 7784 | 7818 | |
| 7785 | if (is_comptime_call) { | |
| 7786 | const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); | |
| 7787 | const result_interned = result_val.toIntern(); | |
| 7788 | ||
| 7789 | // Transform ad-hoc inferred error set types into concrete error sets. | |
| 7790 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | |
| 7791 | ||
| 7792 | // If the result can mutate comptime vars, we must not memoize it, as it contains | |
| 7793 | // a reference to `comptime_allocs` so is not stable across instances of `Sema`. | |
| 7794 | // TODO: check whether any external comptime memory was mutated by the | |
| 7795 | // comptime function call. If so, then do not memoize the call here. | |
| 7796 | if (should_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { | |
| 7797 | _ = try pt.intern(.{ .memoized_call = .{ | |
| 7798 | .func = module_fn_index, | |
| 7799 | .arg_values = memoized_arg_values, | |
| 7800 | .result = result_transformed, | |
| 7801 | } }); | |
| 7802 | } | |
| 7819 | if (is_comptime_call) { | |
| 7820 | const result_val = try sema.resolveConstValue(block, LazySrcLoc.unneeded, result, undefined); | |
| 7821 | const result_interned = result_val.toIntern(); | |
| 7803 | 7822 | |
| 7804 | break :res2 Air.internedToRef(result_transformed); | |
| 7805 | } | |
| 7823 | // Transform ad-hoc inferred error set types into concrete error sets. | |
| 7824 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | |
| 7806 | 7825 | |
| 7807 | if (try sema.resolveValue(result)) |result_val| { | |
| 7808 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); | |
| 7809 | break :res2 Air.internedToRef(result_transformed); | |
| 7826 | // If the result can mutate comptime vars, we must not memoize it, as it contains | |
| 7827 | // a reference to `comptime_allocs` so is not stable across instances of `Sema`. | |
| 7828 | // TODO: check whether any external comptime memory was mutated by the | |
| 7829 | // comptime function call. If so, then do not memoize the call here. | |
| 7830 | if (should_memoize and sema.allow_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(zcu)) { | |
| 7831 | _ = try pt.intern(.{ .memoized_call = .{ | |
| 7832 | .func = module_fn_index, | |
| 7833 | .arg_values = memoized_arg_values, | |
| 7834 | .result = result_transformed, | |
| 7835 | .branch_count = sema.branch_count - old_branch_count, | |
| 7836 | } }); | |
| 7810 | 7837 | } |
| 7811 | 7838 | |
| 7812 | const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); | |
| 7813 | if (new_ty != .none) { | |
| 7814 | // TODO: mutate in place the previous instruction if possible | |
| 7815 | // rather than adding a bitcast instruction. | |
| 7816 | break :res2 try block.addBitCast(Type.fromInterned(new_ty), result); | |
| 7817 | } | |
| 7839 | break :res Air.internedToRef(result_transformed); | |
| 7840 | } | |
| 7818 | 7841 | |
| 7819 | break :res2 result; | |
| 7820 | }; | |
| 7842 | if (try sema.resolveValue(result)) |result_val| { | |
| 7843 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); | |
| 7844 | break :res Air.internedToRef(result_transformed); | |
| 7845 | } | |
| 7846 | ||
| 7847 | const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern()); | |
| 7848 | if (new_ty != .none) { | |
| 7849 | // TODO: mutate in place the previous instruction if possible | |
| 7850 | // rather than adding a bitcast instruction. | |
| 7851 | break :res try block.addBitCast(Type.fromInterned(new_ty), result); | |
| 7852 | } | |
| 7821 | 7853 | |
| 7822 | break :res res2; | |
| 7854 | break :res result; | |
| 7823 | 7855 | } else res: { |
| 7824 | 7856 | assert(!func_ty_info.is_generic); |
| 7825 | 7857 |
src/register_manager.zig+2| ... | ... | @@ -93,6 +93,8 @@ pub fn RegisterManager( |
| 93 | 93 | comptime set: []const Register, |
| 94 | 94 | reg: Register, |
| 95 | 95 | ) ?std.math.IntFittingRange(0, set.len - 1) { |
| 96 | @setEvalBranchQuota(3000); | |
| 97 | ||
| 96 | 98 | const Id = @TypeOf(reg.id()); |
| 97 | 99 | comptime var min_id: Id = std.math.maxInt(Id); |
| 98 | 100 | comptime var max_id: Id = std.math.minInt(Id); |
test/incremental/delete_comptime_decls+1-1| ... | ... | @@ -31,7 +31,7 @@ pub fn main() void {} |
| 31 | 31 | comptime { |
| 32 | 32 | const x: [*c]u8 = null; |
| 33 | 33 | var runtime_len: usize = undefined; |
| 34 | 		runtime_len = 0; | |
| 34 | runtime_len = 0; | |
| 35 | 35 | const y = x[0..runtime_len]; |
| 36 | 36 | _ = y; |
| 37 | 37 | } |
test/incremental/modify_inline_fn created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | #target=x86_64-linux | |
| 2 | #update=initial version | |
| 3 | #file=main.zig | |
| 4 | const std = @import("std"); | |
| 5 | pub fn main() !void { | |
| 6 | const str = getStr(); | |
| 7 | try std.io.getStdOut().writeAll(str); | |
| 8 | } | |
| 9 | inline fn getStr() []const u8 { | |
| 10 | return "foo\n"; | |
| 11 | } | |
| 12 | #expect_stdout="foo\n" | |
| 13 | #update=change the string | |
| 14 | #file=main.zig | |
| 15 | const std = @import("std"); | |
| 16 | pub fn main() !void { | |
| 17 | const str = getStr(); | |
| 18 | try std.io.getStdOut().writeAll(str); | |
| 19 | } | |
| 20 | inline fn getStr() []const u8 { | |
| 21 | return "bar\n"; | |
| 22 | } | |
| 23 | #expect_stdout="bar\n" |
test/incremental/move_src created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | #target=x86_64-linux | |
| 2 | #update=initial version | |
| 3 | #file=main.zig | |
| 4 | const std = @import("std"); | |
| 5 | pub fn main() !void { | |
| 6 | try std.io.getStdOut().writer().print("{d} {d}\n", .{ foo(), bar() }); | |
| 7 | } | |
| 8 | fn foo() u32 { | |
| 9 | return @src().line; | |
| 10 | } | |
| 11 | fn bar() u32 { | |
| 12 | return 123; | |
| 13 | } | |
| 14 | #expect_stdout="6 123\n" | |
| 15 | ||
| 16 | #update=add newline | |
| 17 | #file=main.zig | |
| 18 | const std = @import("std"); | |
| 19 | pub fn main() !void { | |
| 20 | try std.io.getStdOut().writer().print("{d} {d}\n", .{ foo(), bar() }); | |
| 21 | } | |
| 22 | ||
| 23 | fn foo() u32 { | |
| 24 | return @src().line; | |
| 25 | } | |
| 26 | fn bar() u32 { | |
| 27 | return 123; | |
| 28 | } | |
| 29 | #expect_stdout="7 123\n" |