| author | |
| committer | |
| log | c2b42383eb058f4c2bd17738cd73382e6a6672eb |
| tree | 064a6184bbb51ac4c6985deab38b0c0e5bc37132 |
| parent | 9c9a5e722b84d12de34d16f53355adbe1f5e11d3 |
| signature |
11 files changed, 246 insertions(+), 98 deletions(-)
lib/std/hash_map.zig+3-3| ... | ... | @@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged( |
| 1526 | 1526 | } |
| 1527 | 1527 | |
| 1528 | 1528 | comptime { |
| 1529 | if (!builtin.strip_debug_info) _ = switch (builtin.zig_backend) { | |
| 1530 | .stage2_llvm => &dbHelper, | |
| 1531 | .stage2_x86_64 => KV, | |
| 1529 | if (!builtin.strip_debug_info) switch (builtin.zig_backend) { | |
| 1530 | .stage2_llvm => _ = &dbHelper, | |
| 1531 | .stage2_x86_64 => _ = @as(KV, undefined), | |
| 1532 | 1532 | else => {}, |
| 1533 | 1533 | }; |
| 1534 | 1534 | } |
src/InternPool.zig+14-2| ... | ... | @@ -3334,11 +3334,17 @@ pub const LoadedStructType = struct { |
| 3334 | 3334 | field_defaults: Index.Slice, |
| 3335 | 3335 | field_aligns: Alignment.Slice, |
| 3336 | 3336 | field_is_comptime_bits: ComptimeBits, |
| 3337 | /// If `layout` is `.@"packed"`, this is `.empty`. | |
| 3337 | 3338 | field_runtime_order: RuntimeOrder.Slice, |
| 3339 | /// If `layout` is `.@"packed"`, this is `.empty`. | |
| 3338 | 3340 | field_offsets: Offsets, |
| 3341 | /// Only valid if `layout` is `.@"packed"`. | |
| 3339 | 3342 | packed_backing_int_type: Index, |
| 3343 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3340 | 3344 | class: TypeClass, |
| 3345 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3341 | 3346 | size: u32, |
| 3347 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3342 | 3348 | alignment: Alignment, |
| 3343 | 3349 | |
| 3344 | 3350 | pub const ComptimeBits = struct { |
| ... | ... | @@ -3516,15 +3522,21 @@ pub const LoadedUnionType = struct { |
| 3516 | 3522 | tag_usage: TagUsage, |
| 3517 | 3523 | /// While `tag_usage` indicates whether the union should logically contain a tag, it may be |
| 3518 | 3524 | /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an |
| 3519 | /// actual runtime tag in the union layout. | |
| 3525 | /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false` | |
| 3526 | /// if `layout` is not `.auto`. | |
| 3520 | 3527 | has_runtime_tag: bool, |
| 3521 | 3528 | /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with |
| 3522 | 3529 | /// the union's "hypothetical" tag type. |
| 3523 | 3530 | enum_tag_type: Index, |
| 3531 | /// Only valid if `layout` is `.@"packed"`. | |
| 3524 | 3532 | packed_backing_int_type: Index, |
| 3533 | /// Not valid if `layout` is `.@"packed"`. | |
| 3525 | 3534 | class: TypeClass, |
| 3535 | /// Not valid if `layout` is `.@"packed"`. | |
| 3526 | 3536 | size: u32, |
| 3537 | /// Not valid if `layout` is `.@"packed"`. | |
| 3527 | 3538 | padding: u32, |
| 3539 | /// Not valid if `layout` is `.@"packed"`. | |
| 3528 | 3540 | alignment: Alignment, |
| 3529 | 3541 | |
| 3530 | 3542 | pub const TagUsage = enum(u2) { |
| ... | ... | @@ -3898,7 +3910,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { |
| 3898 | 3910 | .want_layout = extra.data.bits.want_layout, |
| 3899 | 3911 | .field_types = field_types, |
| 3900 | 3912 | .field_aligns = .empty, |
| 3901 | .has_runtime_tag = undefined, | |
| 3913 | .has_runtime_tag = false, | |
| 3902 | 3914 | .class = undefined, |
| 3903 | 3915 | .size = undefined, |
| 3904 | 3916 | .padding = undefined, |
src/Sema.zig+50-42| ... | ... | @@ -13777,45 +13777,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13777 | 13777 | const many_alloc = try block.addBitCast(many_ty, mutable_alloc); |
| 13778 | 13778 | |
| 13779 | 13779 | // lhs_dest_slice = dest[0..lhs.len] |
| 13780 | const slice_ty_ref = Air.internedToRef(slice_ty.toIntern()); | |
| 13781 | const lhs_len_ref = try pt.intRef(.usize, lhs_len); | |
| 13782 | const lhs_dest_slice = try block.addInst(.{ | |
| 13783 | .tag = .slice, | |
| 13784 | .data = .{ .ty_pl = .{ | |
| 13785 | .ty = slice_ty_ref, | |
| 13786 | .payload = try sema.addExtra(Air.Bin{ | |
| 13787 | .lhs = many_alloc, | |
| 13788 | .rhs = lhs_len_ref, | |
| 13789 | }), | |
| 13790 | } }, | |
| 13791 | }); | |
| 13792 | ||
| 13793 | _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); | |
| 13780 | if (lhs_len > 0) { | |
| 13781 | const lhs_dest_slice = try block.addInst(.{ | |
| 13782 | .tag = .slice, | |
| 13783 | .data = .{ .ty_pl = .{ | |
| 13784 | .ty = .fromType(slice_ty), | |
| 13785 | .payload = try sema.addExtra(Air.Bin{ | |
| 13786 | .lhs = many_alloc, | |
| 13787 | .rhs = try pt.intRef(.usize, lhs_len), | |
| 13788 | }), | |
| 13789 | } }, | |
| 13790 | }); | |
| 13791 | _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); | |
| 13792 | } | |
| 13794 | 13793 | |
| 13795 | 13794 | // rhs_dest_slice = dest[lhs.len..][0..rhs.len] |
| 13796 | const rhs_len_ref = try pt.intRef(.usize, rhs_len); | |
| 13797 | const rhs_dest_offset = try block.addInst(.{ | |
| 13798 | .tag = .ptr_add, | |
| 13799 | .data = .{ .ty_pl = .{ | |
| 13800 | .ty = Air.internedToRef(many_ty.toIntern()), | |
| 13801 | .payload = try sema.addExtra(Air.Bin{ | |
| 13802 | .lhs = many_alloc, | |
| 13803 | .rhs = lhs_len_ref, | |
| 13804 | }), | |
| 13805 | } }, | |
| 13806 | }); | |
| 13807 | const rhs_dest_slice = try block.addInst(.{ | |
| 13808 | .tag = .slice, | |
| 13809 | .data = .{ .ty_pl = .{ | |
| 13810 | .ty = slice_ty_ref, | |
| 13811 | .payload = try sema.addExtra(Air.Bin{ | |
| 13812 | .lhs = rhs_dest_offset, | |
| 13813 | .rhs = rhs_len_ref, | |
| 13814 | }), | |
| 13815 | } }, | |
| 13816 | }); | |
| 13817 | ||
| 13818 | _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); | |
| 13795 | if (rhs_len > 0) { | |
| 13796 | const rhs_dest_offset = try block.addInst(.{ | |
| 13797 | .tag = .ptr_add, | |
| 13798 | .data = .{ .ty_pl = .{ | |
| 13799 | .ty = Air.internedToRef(many_ty.toIntern()), | |
| 13800 | .payload = try sema.addExtra(Air.Bin{ | |
| 13801 | .lhs = many_alloc, | |
| 13802 | .rhs = try pt.intRef(.usize, lhs_len), | |
| 13803 | }), | |
| 13804 | } }, | |
| 13805 | }); | |
| 13806 | const rhs_dest_slice = try block.addInst(.{ | |
| 13807 | .tag = .slice, | |
| 13808 | .data = .{ .ty_pl = .{ | |
| 13809 | .ty = .fromType(slice_ty), | |
| 13810 | .payload = try sema.addExtra(Air.Bin{ | |
| 13811 | .lhs = rhs_dest_offset, | |
| 13812 | .rhs = try pt.intRef(.usize, rhs_len), | |
| 13813 | }), | |
| 13814 | } }, | |
| 13815 | }); | |
| 13816 | _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); | |
| 13817 | } | |
| 13819 | 13818 | |
| 13820 | 13819 | if (res_sent_val) |sent_val| { |
| 13821 | 13820 | const elem_index = try pt.intRef(.usize, result_len); |
| ... | ... | @@ -18829,7 +18828,7 @@ fn finishStructInit( |
| 18829 | 18828 | return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); |
| 18830 | 18829 | }, |
| 18831 | 18830 | .@"packed" => { |
| 18832 | const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8); | |
| 18831 | const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8)); | |
| 18833 | 18832 | var bit_offset: u16 = 0; |
| 18834 | 18833 | for (field_inits) |field_init| { |
| 18835 | 18834 | const field_val = sema.resolveValue(field_init).?; |
| ... | ... | @@ -21113,7 +21112,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21113 | 21112 | else => unreachable, |
| 21114 | 21113 | }; |
| 21115 | 21114 | |
| 21116 | if (!dest_err_ty.isAnyError(zcu) and !dest_err_ty.errorSetHasField(err_name, zcu)) { | |
| 21115 | if (result != .superset and !dest_err_ty.errorSetHasField(err_name, zcu)) { | |
| 21117 | 21116 | return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{ |
| 21118 | 21117 | err_name.fmt(ip), dest_err_ty.fmt(pt), |
| 21119 | 21118 | }); |
| ... | ... | @@ -25186,9 +25185,18 @@ pub fn explainWhyTypeIsNotExtern( |
| 25186 | 25185 | else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}), |
| 25187 | 25186 | }, |
| 25188 | 25187 | .@"enum" => { |
| 25189 | const tag_ty = ty.intTagType(zcu); | |
| 25190 | try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); | |
| 25191 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); | |
| 25188 | const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); | |
| 25189 | switch (enum_obj.int_tag_mode) { | |
| 25190 | .auto => { | |
| 25191 | try sema.errNote(ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{}); | |
| 25192 | try sema.errNote(ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{}); | |
| 25193 | }, | |
| 25194 | .explicit => { | |
| 25195 | const tag_ty: Type = .fromInterned(enum_obj.int_tag_type); | |
| 25196 | try sema.errNote(ty.srcLoc(zcu), msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); | |
| 25197 | try sema.explainWhyTypeIsNotExtern(msg, ty.srcLoc(zcu), tag_ty, position); | |
| 25198 | }, | |
| 25199 | } | |
| 25192 | 25200 | }, |
| 25193 | 25201 | .@"struct" => { |
| 25194 | 25202 | const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); |
src/Value.zig+2-2| ... | ... | @@ -895,7 +895,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { |
| 895 | 895 | // Avoid hitting gpa for accesses to small packed structs |
| 896 | 896 | var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa); |
| 897 | 897 | const sfba = sfba_state.get(); |
| 898 | const buf = try sfba.alloc(u8, (ty.bitSize(zcu) + 7) / 8); | |
| 898 | const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8)); | |
| 899 | 899 | defer sfba.free(buf); |
| 900 | 900 | int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) { |
| 901 | 901 | error.ReinterpretDeclRef => unreachable, // it's an integer |
| ... | ... | @@ -2419,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory |
| 2419 | 2419 | } |
| 2420 | 2420 | for (field_vals, 0..) |*field_val, field_idx| { |
| 2421 | 2421 | if (field_val.* == .none) { |
| 2422 | const default_init = struct_obj.field_inits.get(ip)[field_idx]; | |
| 2422 | const default_init = struct_obj.field_defaults.get(ip)[field_idx]; | |
| 2423 | 2423 | if (default_init == .none) return error.TypeMismatch; |
| 2424 | 2424 | field_val.* = default_init; |
| 2425 | 2425 | } |
src/Zcu.zig+6-1| ... | ... | @@ -3686,6 +3686,11 @@ pub const ImportResult = struct { |
| 3686 | 3686 | pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void { |
| 3687 | 3687 | const gpa = zcu.comp.gpa; |
| 3688 | 3688 | |
| 3689 | if (!dev.env.supports(.incremental)) { | |
| 3690 | // This is the first time `unit` is being analyzed, so there is no stale data to clear. | |
| 3691 | return; | |
| 3692 | } | |
| 3693 | ||
| 3689 | 3694 | // Compile errors |
| 3690 | 3695 | if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { |
| 3691 | 3696 | kv.value.destroy(gpa); |
| ... | ... | @@ -4309,7 +4314,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag |
| 4309 | 4314 | }); |
| 4310 | 4315 | const gop = try units.getOrPut(gpa, other); |
| 4311 | 4316 | if (gop.found_existing) break :queue_paired; |
| 4312 | gop.value_ptr.* = units.values()[unit_idx]; // same reference location | |
| 4317 | gop.value_ptr.* = units.values()[unit_idx - 1]; // same reference location | |
| 4313 | 4318 | } |
| 4314 | 4319 | |
| 4315 | 4320 | refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); |
src/Zcu/PerThread.zig+54-26| ... | ... | @@ -1075,7 +1075,6 @@ pub fn ensureMemoizedStateUpToDate( |
| 1075 | 1075 | const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit); |
| 1076 | 1076 | |
| 1077 | 1077 | if (was_outdated) { |
| 1078 | dev.check(.incremental); | |
| 1079 | 1078 | zcu.resetUnit(unit); |
| 1080 | 1079 | } else { |
| 1081 | 1080 | if (prev_failed) return error.AnalysisFail; |
| ... | ... | @@ -1193,10 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 1193 | 1192 | const was_outdated = zcu.clearOutdatedState(anal_unit); |
| 1194 | 1193 | |
| 1195 | 1194 | if (was_outdated) { |
| 1196 | // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. | |
| 1197 | if (dev.env.supports(.incremental)) { | |
| 1198 | zcu.resetUnit(anal_unit); | |
| 1199 | } | |
| 1195 | zcu.resetUnit(anal_unit); | |
| 1200 | 1196 | } else { |
| 1201 | 1197 | // We can trust the current information about this unit. |
| 1202 | 1198 | if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; |
| ... | ... | @@ -1366,10 +1362,7 @@ pub fn ensureTypeLayoutUpToDate( |
| 1366 | 1362 | }; |
| 1367 | 1363 | |
| 1368 | 1364 | if (was_outdated) { |
| 1369 | // `was_outdated` is true in the initial update, so this isn't a `dev.check`. | |
| 1370 | if (dev.env.supports(.incremental)) { | |
| 1371 | zcu.resetUnit(anal_unit); | |
| 1372 | } | |
| 1365 | zcu.resetUnit(anal_unit); | |
| 1373 | 1366 | // For types, we already know that we have to invalidate all dependees. |
| 1374 | 1367 | // TODO: we actually *could* detect whether everything was the same. should we bother? |
| 1375 | 1368 | try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() }); |
| ... | ... | @@ -1492,10 +1485,7 @@ pub fn ensureStructDefaultsUpToDate( |
| 1492 | 1485 | }; |
| 1493 | 1486 | |
| 1494 | 1487 | if (was_outdated) { |
| 1495 | // `was_outdated` is true in the initial update, so this isn't a `dev.check`. | |
| 1496 | if (dev.env.supports(.incremental)) { | |
| 1497 | zcu.resetUnit(anal_unit); | |
| 1498 | } | |
| 1488 | zcu.resetUnit(anal_unit); | |
| 1499 | 1489 | // For types, we already know that we have to invalidate all dependees. |
| 1500 | 1490 | // TODO: we actually *could* detect whether everything was the same. should we bother? |
| 1501 | 1491 | try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); |
| ... | ... | @@ -1609,7 +1599,6 @@ pub fn ensureNavValUpToDate( |
| 1609 | 1599 | zcu.transitive_failed_analysis.contains(anal_unit); |
| 1610 | 1600 | |
| 1611 | 1601 | if (was_outdated) { |
| 1612 | dev.check(.incremental); | |
| 1613 | 1602 | zcu.resetUnit(anal_unit); |
| 1614 | 1603 | } else { |
| 1615 | 1604 | // We can trust the current information about this unit. |
| ... | ... | @@ -1893,6 +1882,30 @@ fn analyzeNavVal( |
| 1893 | 1882 | } |
| 1894 | 1883 | } |
| 1895 | 1884 | |
| 1885 | // We're about to resolve the value of the Nav. This causes the information about what the value | |
| 1886 | // was last update to be lost; therefore, if the `nav_ty` is currently out of date, it would | |
| 1887 | // incorrectly think it was unchanged when eventually analyzed. To avoid this, we need to detect | |
| 1888 | // that case and invalidate the dependee right now. | |
| 1889 | if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) { | |
| 1890 | assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved` | |
| 1891 | zcu.resetUnit(.wrap(.{ .nav_ty = nav_id })); | |
| 1892 | try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!) | |
| 1893 | if (comp.debugIncremental()) { | |
| 1894 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id })); | |
| 1895 | info.last_update_gen = zcu.generation; | |
| 1896 | info.deps.clearRetainingCapacity(); | |
| 1897 | } | |
| 1898 | const type_changed: bool = switch (old_nav.status) { | |
| 1899 | .unresolved => true, | |
| 1900 | .type_resolved => |old| old.type != nav_ty.toIntern(), | |
| 1901 | .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(), | |
| 1902 | }; | |
| 1903 | if (type_changed) { | |
| 1904 | try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); | |
| 1905 | } else { | |
| 1906 | try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id }); | |
| 1907 | } | |
| 1908 | } | |
| 1896 | 1909 | ip.resolveNavValue(io, nav_id, .{ |
| 1897 | 1910 | .val = nav_val.toIntern(), |
| 1898 | 1911 | .is_const = is_const, |
| ... | ... | @@ -1930,10 +1943,10 @@ fn analyzeNavVal( |
| 1930 | 1943 | try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); |
| 1931 | 1944 | } |
| 1932 | 1945 | |
| 1933 | switch (old_nav.status) { | |
| 1934 | .unresolved, .type_resolved => return .{ .val_changed = true }, | |
| 1935 | .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() }, | |
| 1936 | } | |
| 1946 | return switch (old_nav.status) { | |
| 1947 | .unresolved, .type_resolved => .{ .val_changed = true }, | |
| 1948 | .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() }, | |
| 1949 | }; | |
| 1937 | 1950 | } |
| 1938 | 1951 | |
| 1939 | 1952 | pub fn ensureNavTypeUpToDate( |
| ... | ... | @@ -1973,7 +1986,6 @@ pub fn ensureNavTypeUpToDate( |
| 1973 | 1986 | zcu.transitive_failed_analysis.contains(anal_unit); |
| 1974 | 1987 | |
| 1975 | 1988 | if (was_outdated) { |
| 1976 | dev.check(.incremental); | |
| 1977 | 1989 | zcu.resetUnit(anal_unit); |
| 1978 | 1990 | } else { |
| 1979 | 1991 | // We can trust the current information about this unit. |
| ... | ... | @@ -2107,12 +2119,29 @@ fn analyzeNavType( |
| 2107 | 2119 | |
| 2108 | 2120 | const type_body = zir_decl.type_body orelse { |
| 2109 | 2121 | // There is no type annotation, so we just need to use the declaration's value. |
| 2122 | // If the value had already been re-analyzed, it would have resolved the `nav_ty` unit as | |
| 2123 | // either outdated or up-to-date. So we know that `old_nav` does contain information from | |
| 2124 | // the previous update. As such, after this call, we will be able to determine whether the | |
| 2125 | // type changed. | |
| 2110 | 2126 | try sema.ensureNavResolved(&block, init_src, nav_id, .fully); |
| 2111 | // We don't actually know what the type of this Nav was before it was resolved, so we just | |
| 2112 | // have to assume we were outdated. This isn't too bad, because assuming there was also no | |
| 2113 | // type annotation last update, we should only be re-analyzed if the value changes (it's our | |
| 2114 | // only dependency), or if there was a dependency loop. | |
| 2115 | return .{ .type_changed = true }; | |
| 2127 | const new = ip.getNav(nav_id).status.fully_resolved; | |
| 2128 | const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern"; | |
| 2129 | const changed = switch (old_nav.status) { | |
| 2130 | .unresolved => true, | |
| 2131 | .type_resolved => |r| r.type != ip.typeOf(new.val) or | |
| 2132 | r.alignment != new.alignment or | |
| 2133 | r.@"linksection" != new.@"linksection" or | |
| 2134 | r.@"addrspace" != new.@"addrspace" or | |
| 2135 | r.is_const != new.is_const or | |
| 2136 | r.is_extern_decl != new_is_extern_decl, | |
| 2137 | .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or | |
| 2138 | r.alignment != new.alignment or | |
| 2139 | r.@"linksection" != new.@"linksection" or | |
| 2140 | r.@"addrspace" != new.@"addrspace" or | |
| 2141 | r.is_const != new.is_const or | |
| 2142 | (old_nav.getExtern(ip) != null) != new_is_extern_decl, | |
| 2143 | }; | |
| 2144 | return .{ .type_changed = changed }; | |
| 2116 | 2145 | }; |
| 2117 | 2146 | |
| 2118 | 2147 | block.comptime_reason = .{ .reason = .{ |
| ... | ... | @@ -2210,7 +2239,6 @@ pub fn ensureFuncBodyUpToDate( |
| 2210 | 2239 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); |
| 2211 | 2240 | |
| 2212 | 2241 | if (was_outdated) { |
| 2213 | dev.check(.incremental); | |
| 2214 | 2242 | zcu.resetUnit(anal_unit); |
| 2215 | 2243 | } else { |
| 2216 | 2244 | // We can trust the current information about this function. |
| ... | ... | @@ -2292,7 +2320,7 @@ fn analyzeFuncBody( |
| 2292 | 2320 | |
| 2293 | 2321 | var air = try pt.analyzeFuncBodyInner(func_index, reason); |
| 2294 | 2322 | var air_owned = true; |
| 2295 | errdefer if (air_owned) air.deinit(gpa); | |
| 2323 | defer if (air_owned) air.deinit(gpa); | |
| 2296 | 2324 | |
| 2297 | 2325 | const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or |
| 2298 | 2326 | func.resolvedErrorSetUnordered(ip) != old_resolved_ies; |
src/codegen/c.zig+3-3| ... | ... | @@ -7132,9 +7132,9 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void |
| 7132 | 7132 | var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined; |
| 7133 | 7133 | for (0..big.limbs_len) |limb_index| { |
| 7134 | 7134 | if (limb_index != 0) try w.writeAll(", "); |
| 7135 | const limb_bit_offset: u64 = switch (target.cpu.arch.endian()) { | |
| 7136 | .little => limb_index * big.limb_size.bits(), | |
| 7137 | .big => (big.limbs_len - limb_index - 1) * big.limb_size.bits(), | |
| 7135 | const limb_bit_offset: u16 = switch (target.cpu.arch.endian()) { | |
| 7136 | .little => @intCast(limb_index * big.limb_size.bits()), | |
| 7137 | .big => @intCast((big.limbs_len - limb_index - 1) * big.limb_size.bits()), | |
| 7138 | 7138 | }; |
| 7139 | 7139 | var limb_bigint: std.math.big.int.Mutable = .{ |
| 7140 | 7140 | .limbs = &limb_buf, |
src/codegen/llvm.zig+1-1| ... | ... | @@ -2432,7 +2432,7 @@ pub const Object = struct { |
| 2432 | 2432 | const debug_payload_type = try o.builder.debugUnionType( |
| 2433 | 2433 | payload_name: { |
| 2434 | 2434 | if (layout.tag_size == 0) break :payload_name name; |
| 2435 | break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)}); | |
| 2435 | break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)}); | |
| 2436 | 2436 | }, |
| 2437 | 2437 | file, |
| 2438 | 2438 | scope, |
src/link.zig+4-1| ... | ... | @@ -1557,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1557 | 1557 | .link_func => |codegen_task| nav: { |
| 1558 | 1558 | timer.pause(io); |
| 1559 | 1559 | const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) { |
| 1560 | error.Canceled, error.AlreadyReported => return, | |
| 1560 | error.Canceled, error.AlreadyReported => { | |
| 1561 | comp.link_prog_node.completeOne(); | |
| 1562 | return; | |
| 1563 | }, | |
| 1561 | 1564 | }; |
| 1562 | 1565 | defer mir.deinit(zcu); |
| 1563 | 1566 | timer.@"resume"(io); |
src/link/Dwarf.zig+101-9| ... | ... | @@ -3344,6 +3344,7 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index |
| 3344 | 3344 | } |
| 3345 | 3345 | fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { |
| 3346 | 3346 | const zcu = pt.zcu; |
| 3347 | const ip = &zcu.intern_pool; | |
| 3347 | 3348 | |
| 3348 | 3349 | const val: Value = .fromInterned(value_index); |
| 3349 | 3350 | |
| ... | ... | @@ -3383,20 +3384,109 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde |
| 3383 | 3384 | .debug_loclists = .init(dwarf.gpa), |
| 3384 | 3385 | }; |
| 3385 | 3386 | defer wip_nav.deinit(); |
| 3386 | switch (val.typeOf(zcu).toIntern()) { | |
| 3387 | .type_type => { | |
| 3388 | try wip_nav.abbrevCode(.generated_empty_struct_type); | |
| 3389 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3390 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3387 | ||
| 3388 | switch (ip.indexToKey(value_index)) { | |
| 3389 | // Container types still need to be valid namespaces. | |
| 3390 | .struct_type => { | |
| 3391 | const loaded_struct = ip.loadStructType(value_index); | |
| 3392 | const root_of_file: ?Zcu.File.Index = if (loaded_struct.zir_index.resolveFull(ip)) |r| f: { | |
| 3393 | if (r.inst != .main_struct_inst) break :f null; | |
| 3394 | break :f r.file; | |
| 3395 | } else null; | |
| 3396 | if (root_of_file) |file_index| { | |
| 3397 | assert(loaded_struct.name_nav == .none); | |
| 3398 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index); | |
| 3399 | try wip_nav.abbrevCode(.empty_file); | |
| 3400 | try wip_nav.debug_info.writer.writeUleb128(file_gop.index); | |
| 3401 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | |
| 3402 | } else { | |
| 3403 | try dwarf.emitIncompleteContainerType( | |
| 3404 | &wip_nav, | |
| 3405 | loaded_struct.zir_index, | |
| 3406 | loaded_struct.name, | |
| 3407 | loaded_struct.name_nav, | |
| 3408 | ); | |
| 3409 | } | |
| 3391 | 3410 | }, |
| 3392 | else => |ty| { | |
| 3393 | try wip_nav.abbrevCode(.undefined_comptime_value); | |
| 3394 | try wip_nav.refType(.fromInterned(ty)); | |
| 3411 | .union_type => { | |
| 3412 | const loaded_union = ip.loadUnionType(value_index); | |
| 3413 | try dwarf.emitIncompleteContainerType( | |
| 3414 | &wip_nav, | |
| 3415 | loaded_union.zir_index, | |
| 3416 | loaded_union.name, | |
| 3417 | loaded_union.name_nav, | |
| 3418 | ); | |
| 3419 | }, | |
| 3420 | .enum_type => { | |
| 3421 | const loaded_enum = ip.loadEnumType(value_index); | |
| 3422 | if (loaded_enum.zir_index.unwrap()) |zir_index| { | |
| 3423 | try dwarf.emitIncompleteContainerType( | |
| 3424 | &wip_nav, | |
| 3425 | zir_index, | |
| 3426 | loaded_enum.name, | |
| 3427 | loaded_enum.name_nav, | |
| 3428 | ); | |
| 3429 | } else { | |
| 3430 | try wip_nav.abbrevCode(.generated_empty_struct_type); | |
| 3431 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | |
| 3432 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3433 | } | |
| 3434 | }, | |
| 3435 | .opaque_type => { | |
| 3436 | const loaded_opaque = ip.loadOpaqueType(value_index); | |
| 3437 | try dwarf.emitIncompleteContainerType( | |
| 3438 | &wip_nav, | |
| 3439 | loaded_opaque.zir_index, | |
| 3440 | loaded_opaque.name, | |
| 3441 | loaded_opaque.name_nav, | |
| 3442 | ); | |
| 3443 | }, | |
| 3444 | // Not a container type, so just emit a dummy entry. If `val` happens to be a type, we'll | |
| 3445 | // emit it as if it were an opaque type so that we can name it. | |
| 3446 | else => |val_key| switch (val_key.typeOf()) { | |
| 3447 | .type_type => { | |
| 3448 | try wip_nav.abbrevCode(.generated_empty_struct_type); | |
| 3449 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3450 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3451 | }, | |
| 3452 | else => |ty| { | |
| 3453 | try wip_nav.abbrevCode(.undefined_comptime_value); | |
| 3454 | try wip_nav.refType(.fromInterned(ty)); | |
| 3455 | }, | |
| 3395 | 3456 | }, |
| 3396 | 3457 | } |
| 3397 | 3458 | try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); |
| 3398 | 3459 | try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); |
| 3399 | 3460 | } |
| 3461 | fn emitIncompleteContainerType( | |
| 3462 | dwarf: *Dwarf, | |
| 3463 | wip_nav: *WipNav, | |
| 3464 | zir_index: InternPool.TrackedInst.Index, | |
| 3465 | name: InternPool.NullTerminatedString, | |
| 3466 | name_nav: InternPool.Nav.Index.Optional, | |
| 3467 | ) !void { | |
| 3468 | const zcu = wip_nav.pt.zcu; | |
| 3469 | const ip = &zcu.intern_pool; | |
| 3470 | const file = zir_index.resolveFile(ip); | |
| 3471 | if (name_nav.unwrap()) |nav_index| { | |
| 3472 | const nav = ip.getNav(nav_index); | |
| 3473 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 3474 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 3475 | try wip_nav.declCommon(.{ | |
| 3476 | .decl = .decl_namespace_struct, | |
| 3477 | .generic_decl = .generic_decl_const, | |
| 3478 | .decl_instance = .decl_instance_namespace_struct, | |
| 3479 | }, &nav, file, &decl); | |
| 3480 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3481 | } else { | |
| 3482 | const diw = &wip_nav.debug_info.writer; | |
| 3483 | const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file); | |
| 3484 | try wip_nav.abbrevCode(.empty_struct_type); | |
| 3485 | try diw.writeUleb128(file_gop.index); | |
| 3486 | try wip_nav.strp(name.toSlice(ip)); | |
| 3487 | try diw.writeByte(@intFromBool(true)); | |
| 3488 | } | |
| 3489 | } | |
| 3400 | 3490 | /// Should only be called by the `link.ConstPool` implementation. |
| 3401 | 3491 | /// |
| 3402 | 3492 | /// Emits a DIE for the given comptime-only value (which may be a type). |
| ... | ... | @@ -3418,6 +3508,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3418 | 3508 | val.typeOf(zcu).assertHasLayout(zcu); |
| 3419 | 3509 | } |
| 3420 | 3510 | |
| 3511 | if (value_index == .anyerror_type) return; // handled in `flush` instead | |
| 3512 | ||
| 3421 | 3513 | const value_ip_key = ip.indexToKey(value_index); |
| 3422 | 3514 | switch (value_ip_key) { |
| 3423 | 3515 | .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`) |
| ... | ... | @@ -3746,7 +3838,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 3746 | 3838 | try wip_nav.abbrevCode(.void_type); |
| 3747 | 3839 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); |
| 3748 | 3840 | }, |
| 3749 | .anyerror => return, // delay until flush | |
| 3841 | .anyerror => unreachable, // already did early return above | |
| 3750 | 3842 | .adhoc_inferred_error_set => unreachable, |
| 3751 | 3843 | }, |
| 3752 | 3844 | .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { |
tools/incr-check.zig+8-8| ... | ... | @@ -311,12 +311,12 @@ const Eval = struct { |
| 311 | 311 | .error_bundle => { |
| 312 | 312 | const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 313 | 313 | if (stderr.bufferedLen() > 0) { |
| 314 | const stderr_data = try mr.toOwnedSlice(1); | |
| 315 | 314 | if (eval.allow_stderr) { |
| 316 | std.log.info("error_bundle stderr:\n{s}", .{stderr_data}); | |
| 315 | std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()}); | |
| 317 | 316 | } else { |
| 318 | eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data}); | |
| 317 | eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()}); | |
| 319 | 318 | } |
| 319 | stderr.tossBuffered(); | |
| 320 | 320 | } |
| 321 | 321 | if (result_error_bundle.errorMessageCount() != 0) { |
| 322 | 322 | try eval.checkErrorOutcome(update, result_error_bundle); |
| ... | ... | @@ -327,15 +327,15 @@ const Eval = struct { |
| 327 | 327 | .emit_digest => { |
| 328 | 328 | var r: std.Io.Reader = .fixed(body); |
| 329 | 329 | _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; |
| 330 | ||
| 330 | 331 | if (stderr.bufferedLen() > 0) { |
| 331 | const stderr_data = try mr.toOwnedSlice(1); | |
| 332 | 332 | if (eval.allow_stderr) { |
| 333 | std.log.info("emit_digest stderr:\n{s}", .{stderr_data}); | |
| 333 | std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()}); | |
| 334 | 334 | } else { |
| 335 | eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data}); | |
| 335 | eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()}); | |
| 336 | 336 | } |
| 337 | stderr.tossBuffered(); | |
| 337 | 338 | } |
| 338 | ||
| 339 | 339 | if (eval.target.backend == .sema) { |
| 340 | 340 | try eval.checkSuccessOutcome(update, null, prog_node); |
| 341 | 341 | continue; |
| ... | ... | @@ -369,7 +369,7 @@ const Eval = struct { |
| 369 | 369 | } |
| 370 | 370 | |
| 371 | 371 | waitChild(eval.child, eval); |
| 372 | eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{}); | |
| 372 | eval.fatal("compiler failed to send terminating error_bundle", .{}); | |
| 373 | 373 | } |
| 374 | 374 | |
| 375 | 375 | fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void { |