| ... | ... | @@ -3524,9 +3524,11 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo |
| 3524 | 3524 | return ty.abiAlignment(zcu); |
| 3525 | 3525 | } |
| 3526 | 3526 | |
| 3527 | | /// Given a container type requiring resolution, ensures that it is up-to-date. |
| 3528 | | /// If not, the type is recreated at a new `InternPool.Index`. |
| 3529 | | /// The new index is returned. This is the same as the old index if the fields were up-to-date. |
| 3527 | /// `ty` is a container type requiring resolution (struct, union, or enum). |
| 3528 | /// If `ty` is outdated, it is recreated at a new `InternPool.Index`, which is returned. |
| 3529 | /// If the type cannot be recreated because it has been lost, `error.AnalysisFail` is returned. |
| 3530 | /// If `ty` is not outdated, that same `InternPool.Index` is returned. |
| 3531 | /// If `ty` has already been replaced by this function, the new index will not be returned again. |
| 3530 | 3532 | pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index { |
| 3531 | 3533 | const zcu = pt.zcu; |
| 3532 | 3534 | const gpa = zcu.gpa; |
| ... | ... | @@ -3536,13 +3538,30 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError |
| 3536 | 3538 | const outdated = zcu.outdated.swapRemove(anal_unit) or |
| 3537 | 3539 | zcu.potentially_outdated.swapRemove(anal_unit); |
| 3538 | 3540 | |
| 3541 | if (outdated) { |
| 3542 | _ = zcu.outdated_ready.swapRemove(anal_unit); |
| 3543 | try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty }); |
| 3544 | } |
| 3545 | |
| 3546 | const ty_key = switch (ip.indexToKey(ty)) { |
| 3547 | .struct_type, .union_type, .enum_type => |key| key, |
| 3548 | else => unreachable, |
| 3549 | }; |
| 3550 | const declared_ty_key = switch (ty_key) { |
| 3551 | .reified => unreachable, // never outdated |
| 3552 | .generated_tag => unreachable, // never outdated |
| 3553 | .declared => |d| d, |
| 3554 | }; |
| 3555 | |
| 3556 | if (declared_ty_key.zir_index.resolve(ip) == null) { |
| 3557 | // The instruction has been lost -- this type is dead. |
| 3558 | return error.AnalysisFail; |
| 3559 | } |
| 3560 | |
| 3539 | 3561 | if (!outdated) return ty; |
| 3540 | 3562 | |
| 3541 | 3563 | // We will recreate the type at a new `InternPool.Index`. |
| 3542 | 3564 | |
| 3543 | | _ = zcu.outdated_ready.swapRemove(anal_unit); |
| 3544 | | try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty }); |
| 3545 | | |
| 3546 | 3565 | // Delete old state which is no longer in use. Technically, this is not necessary: these exports, |
| 3547 | 3566 | // references, etc, will be ignored because the type itself is unreferenced. However, it allows |
| 3548 | 3567 | // reusing the memory which is currently being used to track this state. |
| ... | ... | @@ -3555,9 +3574,9 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError |
| 3555 | 3574 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); |
| 3556 | 3575 | |
| 3557 | 3576 | switch (ip.indexToKey(ty)) { |
| 3558 | | .struct_type => |key| return pt.recreateStructType(ty, key), |
| 3559 | | .union_type => |key| return pt.recreateUnionType(ty, key), |
| 3560 | | .enum_type => |key| return pt.recreateEnumType(ty, key), |
| 3577 | .struct_type => return pt.recreateStructType(ty, declared_ty_key), |
| 3578 | .union_type => return pt.recreateUnionType(ty, declared_ty_key), |
| 3579 | .enum_type => return pt.recreateEnumType(ty, declared_ty_key), |
| 3561 | 3580 | else => unreachable, |
| 3562 | 3581 | } |
| 3563 | 3582 | } |
| ... | ... | @@ -3565,21 +3584,15 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError |
| 3565 | 3584 | fn recreateStructType( |
| 3566 | 3585 | pt: Zcu.PerThread, |
| 3567 | 3586 | old_ty: InternPool.Index, |
| 3568 | | full_key: InternPool.Key.NamespaceType, |
| 3569 | | ) Zcu.SemaError!InternPool.Index { |
| 3587 | key: InternPool.Key.NamespaceType.Declared, |
| 3588 | ) Allocator.Error!InternPool.Index { |
| 3570 | 3589 | const zcu = pt.zcu; |
| 3571 | 3590 | const gpa = zcu.gpa; |
| 3572 | 3591 | const ip = &zcu.intern_pool; |
| 3573 | 3592 | |
| 3574 | | const key = switch (full_key) { |
| 3575 | | .reified => unreachable, // never outdated |
| 3576 | | .generated_tag => unreachable, // not a struct |
| 3577 | | .declared => |d| d, |
| 3578 | | }; |
| 3579 | | |
| 3580 | | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 3593 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3581 | 3594 | const file = zcu.fileByIndex(inst_info.file); |
| 3582 | | if (file.status != .success_zir) return error.AnalysisFail; |
| 3595 | assert(file.status == .success_zir); // otherwise inst tracking failed |
| 3583 | 3596 | const zir = file.zir; |
| 3584 | 3597 | |
| 3585 | 3598 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| ... | ... | @@ -3600,7 +3613,7 @@ fn recreateStructType( |
| 3600 | 3613 | break :blk fields_len; |
| 3601 | 3614 | } else 0; |
| 3602 | 3615 | |
| 3603 | | if (captures_len != key.captures.owned.len) return error.AnalysisFail; |
| 3616 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` |
| 3604 | 3617 | |
| 3605 | 3618 | const struct_obj = ip.loadStructType(old_ty); |
| 3606 | 3619 | |
| ... | ... | @@ -3644,21 +3657,15 @@ fn recreateStructType( |
| 3644 | 3657 | fn recreateUnionType( |
| 3645 | 3658 | pt: Zcu.PerThread, |
| 3646 | 3659 | old_ty: InternPool.Index, |
| 3647 | | full_key: InternPool.Key.NamespaceType, |
| 3648 | | ) Zcu.SemaError!InternPool.Index { |
| 3660 | key: InternPool.Key.NamespaceType.Declared, |
| 3661 | ) Allocator.Error!InternPool.Index { |
| 3649 | 3662 | const zcu = pt.zcu; |
| 3650 | 3663 | const gpa = zcu.gpa; |
| 3651 | 3664 | const ip = &zcu.intern_pool; |
| 3652 | 3665 | |
| 3653 | | const key = switch (full_key) { |
| 3654 | | .reified => unreachable, // never outdated |
| 3655 | | .generated_tag => unreachable, // not a union |
| 3656 | | .declared => |d| d, |
| 3657 | | }; |
| 3658 | | |
| 3659 | | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 3666 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3660 | 3667 | const file = zcu.fileByIndex(inst_info.file); |
| 3661 | | if (file.status != .success_zir) return error.AnalysisFail; |
| 3668 | assert(file.status == .success_zir); // otherwise inst tracking failed |
| 3662 | 3669 | const zir = file.zir; |
| 3663 | 3670 | |
| 3664 | 3671 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| ... | ... | @@ -3681,7 +3688,7 @@ fn recreateUnionType( |
| 3681 | 3688 | break :blk fields_len; |
| 3682 | 3689 | } else 0; |
| 3683 | 3690 | |
| 3684 | | if (captures_len != key.captures.owned.len) return error.AnalysisFail; |
| 3691 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` |
| 3685 | 3692 | |
| 3686 | 3693 | const union_obj = ip.loadUnionType(old_ty); |
| 3687 | 3694 | |
| ... | ... | @@ -3731,23 +3738,19 @@ fn recreateUnionType( |
| 3731 | 3738 | return wip_ty.finish(ip, namespace_index); |
| 3732 | 3739 | } |
| 3733 | 3740 | |
| 3741 | // TODO: is it safe for this to return `SemaError`? enum type resolution is a bit weird... |
| 3734 | 3742 | fn recreateEnumType( |
| 3735 | 3743 | pt: Zcu.PerThread, |
| 3736 | 3744 | old_ty: InternPool.Index, |
| 3737 | | full_key: InternPool.Key.NamespaceType, |
| 3745 | key: InternPool.Key.NamespaceType.Declared, |
| 3738 | 3746 | ) Zcu.SemaError!InternPool.Index { |
| 3739 | 3747 | const zcu = pt.zcu; |
| 3740 | 3748 | const gpa = zcu.gpa; |
| 3741 | 3749 | const ip = &zcu.intern_pool; |
| 3742 | 3750 | |
| 3743 | | const key = switch (full_key) { |
| 3744 | | .reified, .generated_tag => unreachable, // never outdated |
| 3745 | | .declared => |d| d, |
| 3746 | | }; |
| 3747 | | |
| 3748 | | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 3751 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3749 | 3752 | const file = zcu.fileByIndex(inst_info.file); |
| 3750 | | if (file.status != .success_zir) return error.AnalysisFail; |
| 3753 | assert(file.status == .success_zir); // otherwise inst tracking failed |
| 3751 | 3754 | const zir = file.zir; |
| 3752 | 3755 | |
| 3753 | 3756 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| ... | ... | @@ -3787,7 +3790,7 @@ fn recreateEnumType( |
| 3787 | 3790 | break :blk decls_len; |
| 3788 | 3791 | } else 0; |
| 3789 | 3792 | |
| 3790 | | if (captures_len != key.captures.owned.len) return error.AnalysisFail; |
| 3793 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` |
| 3791 | 3794 | |
| 3792 | 3795 | extra_index += captures_len; |
| 3793 | 3796 | extra_index += decls_len; |