|
28 | 28 | #include "MoveOnlyBorrowToDestructureUtils.h"
|
29 | 29 | #include "MoveOnlyDiagnostics.h"
|
30 | 30 | #include "MoveOnlyObjectCheckerUtils.h"
|
| 31 | +#include "MoveOnlyTypeUtils.h" |
31 | 32 |
|
32 | 33 | #include "swift/Basic/BlotSetVector.h"
|
33 | 34 | #include "swift/Basic/Defer.h"
|
@@ -544,236 +545,6 @@ void Implementation::checkDestructureUsesOnBoundary() const {
|
544 | 545 | }
|
545 | 546 | }
|
546 | 547 |
|
547 |
| -static StructDecl *getFullyReferenceableStruct(SILType ktypeTy) { |
548 |
| - auto structDecl = ktypeTy.getStructOrBoundGenericStruct(); |
549 |
| - if (!structDecl || structDecl->hasUnreferenceableStorage()) |
550 |
| - return nullptr; |
551 |
| - return structDecl; |
552 |
| -} |
553 |
| - |
554 |
| -namespace { |
555 |
| - |
556 |
| -struct TypeOffsetSizePair { |
557 |
| - SubElementOffset startOffset = 0; |
558 |
| - TypeSubElementCount size = 0; |
559 |
| - |
560 |
| - TypeOffsetSizePair() : startOffset(0), size(0) {} |
561 |
| - TypeOffsetSizePair(SILType baseType, SILFunction *fn) |
562 |
| - : startOffset(0), size(baseType, fn) {} |
563 |
| - TypeOffsetSizePair(SubElementOffset offset, TypeSubElementCount size) |
564 |
| - : startOffset(offset), size(size) {} |
565 |
| - TypeOffsetSizePair(SILValue projection, SILValue base) |
566 |
| - : startOffset(*SubElementOffset::compute(projection, base)), |
567 |
| - size(TypeSubElementCount(projection)) {} |
568 |
| - |
569 |
| - IntRange<unsigned> getRange() const { |
570 |
| - return range(startOffset, getEndOffset()); |
571 |
| - } |
572 |
| - |
573 |
| - SubElementOffset getEndOffset() const { |
574 |
| - return SubElementOffset(startOffset + size); |
575 |
| - } |
576 |
| - |
577 |
| - bool operator==(const TypeOffsetSizePair &other) const { |
578 |
| - return startOffset == other.startOffset && size == other.size; |
579 |
| - } |
580 |
| - |
581 |
| - bool operator!=(const TypeOffsetSizePair &other) const { |
582 |
| - return !(*this == other); |
583 |
| - } |
584 |
| - |
585 |
| - /// Given an ancestor offset \p ancestorOffset and a type called \p |
586 |
| - /// ancestorType, walk one level towards this current type which is assumed to |
587 |
| - /// be a child type of \p ancestorType. |
588 |
| - Optional<std::pair<TypeOffsetSizePair, SILType>> |
589 |
| - walkOneLevelTowardsChild(TypeOffsetSizePair ancestorOffsetSize, |
590 |
| - SILType ancestorType, SILFunction *fn) const { |
591 |
| - assert(ancestorOffsetSize.size >= size && |
592 |
| - "Too large to be a child of ancestorType"); |
593 |
| - assert((ancestorOffsetSize.startOffset <= startOffset && |
594 |
| - startOffset < |
595 |
| - (ancestorOffsetSize.startOffset + ancestorOffsetSize.size)) && |
596 |
| - "Not within the offset range of ancestor"); |
597 |
| - |
598 |
| - if (auto tupleType = ancestorType.getAs<TupleType>()) { |
599 |
| - // Before we do anything, see if we have a single element tuple. If we do, |
600 |
| - // just return that. |
601 |
| - if (tupleType->getNumElements() == 1) { |
602 |
| - return {{ancestorOffsetSize, ancestorType.getTupleElementType(0)}}; |
603 |
| - } |
604 |
| - |
605 |
| - assert(ancestorOffsetSize.size > size && |
606 |
| - "Too large to be a child of ancestorType"); |
607 |
| - |
608 |
| - unsigned childOffset = ancestorOffsetSize.startOffset; |
609 |
| - |
610 |
| - for (auto index : indices(tupleType->getElementTypes())) { |
611 |
| - SILType newType = ancestorType.getTupleElementType(index); |
612 |
| - unsigned newSize = TypeSubElementCount(newType, fn); |
613 |
| - |
614 |
| - // childOffset + size(tupleChild) is the offset of the next tuple |
615 |
| - // element. If our target offset is less than that, then we know that |
616 |
| - // the target type must be a descendent of this tuple element type. |
617 |
| - if (childOffset + newSize > startOffset) { |
618 |
| - return {{{childOffset, newSize}, newType}}; |
619 |
| - } |
620 |
| - |
621 |
| - // Otherwise, add the new size of this field to iterOffset so we visit |
622 |
| - // our sibling type next. |
623 |
| - childOffset += newSize; |
624 |
| - } |
625 |
| - |
626 |
| - // At this point, we know that our type is not a subtype of this |
627 |
| - // type. Some sort of logic error occurred. |
628 |
| - llvm_unreachable("Not a child of this type?!"); |
629 |
| - } |
630 |
| - |
631 |
| - if (auto *structDecl = getFullyReferenceableStruct(ancestorType)) { |
632 |
| - // Before we do anything, see if we have a single element struct. If we |
633 |
| - // do, just return that. |
634 |
| - auto storedProperties = structDecl->getStoredProperties(); |
635 |
| - if (storedProperties.size() == 1) { |
636 |
| - return {{ancestorOffsetSize, |
637 |
| - ancestorType.getFieldType(storedProperties[0], fn)}}; |
638 |
| - } |
639 |
| - |
640 |
| - assert(ancestorOffsetSize.size > size && |
641 |
| - "Too large to be a child of ancestorType"); |
642 |
| - |
643 |
| - unsigned childOffset = ancestorOffsetSize.startOffset; |
644 |
| - for (auto *fieldDecl : storedProperties) { |
645 |
| - SILType newType = ancestorType.getFieldType(fieldDecl, fn); |
646 |
| - unsigned newSize = TypeSubElementCount(newType, fn); |
647 |
| - |
648 |
| - // iterOffset + size(tupleChild) is the offset of the next tuple |
649 |
| - // element. If our target offset is less than that, then we know that |
650 |
| - // the target type must be a child of this tuple element type. |
651 |
| - if (childOffset + newSize > startOffset) { |
652 |
| - return {{{childOffset, newSize}, newType}}; |
653 |
| - } |
654 |
| - |
655 |
| - // Otherwise, add the new size of this field to iterOffset so we visit |
656 |
| - // our sibling type next. |
657 |
| - childOffset += newSize; |
658 |
| - } |
659 |
| - |
660 |
| - // At this point, we know that our type is not a subtype of this |
661 |
| - // type. Some sort of logic error occurred. |
662 |
| - llvm_unreachable("Not a child of this type?!"); |
663 |
| - } |
664 |
| - |
665 |
| - if (auto *enumDecl = ancestorType.getEnumOrBoundGenericEnum()) { |
666 |
| - llvm_unreachable("Cannot find child type of enum!\n"); |
667 |
| - } |
668 |
| - |
669 |
| - llvm_unreachable("Hit a leaf type?! Should have handled it earlier"); |
670 |
| - } |
671 |
| - |
672 |
| - /// Given an ancestor offset \p ancestorOffset and a type called \p |
673 |
| - /// ancestorType, walk one level towards this current type inserting on value, |
674 |
| - /// the relevant projection. |
675 |
| - Optional<std::pair<TypeOffsetSizePair, SILValue>> |
676 |
| - walkOneLevelTowardsChild(SILBuilderWithScope &builder, SILLocation loc, |
677 |
| - TypeOffsetSizePair ancestorOffsetSize, |
678 |
| - SILValue ancestorValue) const { |
679 |
| - auto *fn = ancestorValue->getFunction(); |
680 |
| - SILType ancestorType = ancestorValue->getType(); |
681 |
| - |
682 |
| - assert(ancestorOffsetSize.size >= size && |
683 |
| - "Too large to be a child of ancestorType"); |
684 |
| - assert((ancestorOffsetSize.startOffset <= startOffset && |
685 |
| - startOffset < |
686 |
| - (ancestorOffsetSize.startOffset + ancestorOffsetSize.size)) && |
687 |
| - "Not within the offset range of ancestor"); |
688 |
| - if (auto tupleType = ancestorType.getAs<TupleType>()) { |
689 |
| - // Before we do anything, see if we have a single element tuple. If we do, |
690 |
| - // just return that. |
691 |
| - if (tupleType->getNumElements() == 1) { |
692 |
| - auto *newValue = builder.createTupleExtract(loc, ancestorValue, 0); |
693 |
| - return {{ancestorOffsetSize, newValue}}; |
694 |
| - } |
695 |
| - |
696 |
| - assert(ancestorOffsetSize.size > size && |
697 |
| - "Too large to be a child of ancestorType"); |
698 |
| - |
699 |
| - unsigned childOffset = ancestorOffsetSize.startOffset; |
700 |
| - |
701 |
| - for (auto index : indices(tupleType->getElementTypes())) { |
702 |
| - SILType newType = ancestorType.getTupleElementType(index); |
703 |
| - unsigned newSize = TypeSubElementCount(newType, fn); |
704 |
| - |
705 |
| - // childOffset + size(tupleChild) is the offset of the next tuple |
706 |
| - // element. If our target offset is less than that, then we know that |
707 |
| - // the target type must be a descendent of this tuple element type. |
708 |
| - if (childOffset + newSize > startOffset) { |
709 |
| - auto *newValue = |
710 |
| - builder.createTupleExtract(loc, ancestorValue, index); |
711 |
| - return {{{childOffset, newSize}, newValue}}; |
712 |
| - } |
713 |
| - |
714 |
| - // Otherwise, add the new size of this field to iterOffset so we visit |
715 |
| - // our sibling type next. |
716 |
| - childOffset += newSize; |
717 |
| - } |
718 |
| - |
719 |
| - // At this point, we know that our type is not a subtype of this |
720 |
| - // type. Some sort of logic error occurred. |
721 |
| - llvm_unreachable("Not a child of this type?!"); |
722 |
| - } |
723 |
| - |
724 |
| - if (auto *structDecl = getFullyReferenceableStruct(ancestorType)) { |
725 |
| - // Before we do anything, see if we have a single element struct. If we |
726 |
| - // do, just return that. |
727 |
| - auto storedProperties = structDecl->getStoredProperties(); |
728 |
| - if (storedProperties.size() == 1) { |
729 |
| - auto *newValue = builder.createStructExtract(loc, ancestorValue, |
730 |
| - storedProperties[0]); |
731 |
| - return {{ancestorOffsetSize, newValue}}; |
732 |
| - } |
733 |
| - |
734 |
| - assert(ancestorOffsetSize.size > size && |
735 |
| - "Too large to be a child of ancestorType"); |
736 |
| - |
737 |
| - unsigned childOffset = ancestorOffsetSize.startOffset; |
738 |
| - for (auto *fieldDecl : structDecl->getStoredProperties()) { |
739 |
| - SILType newType = ancestorType.getFieldType(fieldDecl, fn); |
740 |
| - unsigned newSize = TypeSubElementCount(newType, fn); |
741 |
| - |
742 |
| - // iterOffset + size(tupleChild) is the offset of the next tuple |
743 |
| - // element. If our target offset is less than that, then we know that |
744 |
| - // the target type must be a child of this tuple element type. |
745 |
| - if (childOffset + newSize > startOffset) { |
746 |
| - auto *newValue = |
747 |
| - builder.createStructExtract(loc, ancestorValue, fieldDecl); |
748 |
| - return {{{childOffset, newSize}, newValue}}; |
749 |
| - } |
750 |
| - |
751 |
| - // Otherwise, add the new size of this field to iterOffset so we visit |
752 |
| - // our sibling type next. |
753 |
| - childOffset += newSize; |
754 |
| - } |
755 |
| - |
756 |
| - // At this point, we know that our type is not a subtype of this |
757 |
| - // type. Some sort of logic error occurred. |
758 |
| - llvm_unreachable("Not a child of this type?!"); |
759 |
| - } |
760 |
| - |
761 |
| - if (auto *enumDecl = ancestorType.getEnumOrBoundGenericEnum()) { |
762 |
| - llvm_unreachable("Cannot find child type of enum!\n"); |
763 |
| - } |
764 |
| - |
765 |
| - llvm_unreachable("Hit a leaf type?! Should have handled it earlier"); |
766 |
| - } |
767 |
| -}; |
768 |
| - |
769 |
| -llvm::raw_ostream &operator<<(llvm::raw_ostream &os, |
770 |
| - const TypeOffsetSizePair &other) { |
771 |
| - return os << "(startOffset: " << other.startOffset << ", size: " << other.size |
772 |
| - << ")"; |
773 |
| -} |
774 |
| - |
775 |
| -} // anonymous namespace |
776 |
| - |
777 | 548 | #ifndef NDEBUG
|
778 | 549 | static void dumpSmallestTypeAvailable(
|
779 | 550 | SmallVectorImpl<Optional<std::pair<TypeOffsetSizePair, SILType>>>
|
|
0 commit comments