diff --git a/docs/SIL.rst b/docs/SIL.rst index b15e735163183..94a6b4fb027d2 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -5191,7 +5191,30 @@ case, the strong reference count will be incremented before any changes to the weak reference count. This operation must be atomic with respect to the final ``strong_release`` on -the operand heap object. It need not be atomic with respect to ``store_weak`` +the operand heap object. It need not be atomic with respect to +``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value`` +operations on the same address. + +strong_copy_weak_value +`````````````````````` +:: + + sil-instruction ::= 'strong_copy_weak_value' sil-operand + + %1 = strong_copy_weak_value %0 : $@sil_weak Optional + // %1 will be a strong @owned value of type $Optional. + // $T must be a reference type + // $@sil_weak Optional must be address-only + +Only valid in opaque values mode. Lowered by AddressLowering to load_weak. + +If the heap object referenced by ``%0`` has not begun deallocation, increments +its strong reference count and produces the value ``Optional.some`` holding the +object. Otherwise, produces the value ``Optional.none``. + +This operation must be atomic with respect to the final ``strong_release`` on +the operand heap object. It need not be atomic with respect to +``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value`` operations on the same address. store_weak @@ -5218,7 +5241,30 @@ currently be initialized. After the evaluation: This operation must be atomic with respect to the final ``strong_release`` on the operand (source) heap object. It need not be atomic with respect to -``store_weak`` or ``load_weak`` operations on the same address. +``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value`` +operations on the same address. + +weak_copy_value +``````````````` +:: + + sil-instruction ::= 'weak_copy_value' sil-operand + + %1 = weak_copy_value %0 : $Optional + // %1 will be an @owned value of type $@sil_weak Optional. + // $T must be a reference type + // $@sil_weak Optional must be address-only + +Only valid in opaque values mode. Lowered by AddressLowering to store_weak. + +If ``%0`` is non-nil, produces the value ``@sil_weak Optional.some`` holding the +object and increments the weak reference count by 1. Otherwise, produces the +value ``Optional.none`` wrapped in a ``@sil_weak`` box. + +This operation must be atomic with respect to the final ``strong_release`` on +the operand (source) heap object. It need not be atomic with respect to +``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value`` +operations on the same address. load_unowned ```````````` @@ -5239,7 +5285,8 @@ positive. Otherwise, traps. This operation must be atomic with respect to the final ``strong_release`` on the operand (source) heap object. It need not be atomic with respect to -``store_unowned`` or ``load_unowned`` operations on the same address. +``store_unowned``/``unowned_copy_value`` or +``load_unowned``/``strong_copy_unowned_value`` operations on the same address. store_unowned ````````````` @@ -5259,8 +5306,30 @@ The storage must be initialized iff ``[init]`` is not specified. This operation must be atomic with respect to the final ``strong_release`` on the operand (source) heap object. It need not be atomic with respect to -``store_unowned`` or ``load_unowned`` operations on the same address. +``store_unowned``/``unowned_copy_value`` or +``load_unowned``/``strong_copy_unowned_value`` operations on the same address. + +unowned_copy_value +`````````````````` +:: + sil-instruction ::= 'unowned_copy_value' sil-operand + + %1 = unowned_copy_value %0 : $T + // %1 will be an @owned value of type $@sil_unowned T. + // $T must be a reference type + // $@sil_unowned T must be address-only + +Only valid in opaque values mode. Lowered by AddressLowering to store_unowned. + +Increments the unowned reference count of the object at ``%0``. + +Wraps the operand in an instance of ``@sil_unowned``. + +This operation must be atomic with respect to the final ``strong_release`` on +the operand (source) heap object. It need not be atomic with respect to +``store_unowned``/``unowned_copy_value`` or +``load_unowned``/``strong_copy_unowned_value`` operations on the same address. fix_lifetime ```````````` diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 40d0b1783d032..f17c67a896ecf 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -1061,20 +1061,49 @@ class SILBuilder { getSILDebugLocation(Loc), ArgumentsSpecification, getModule())); } -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - Load##Name##Inst *createLoad##Name(SILLocation Loc, \ - SILValue src, \ - IsTake_t isTake) { \ - return insert(new (getModule()) \ - Load##Name##Inst(getSILDebugLocation(Loc), src, isTake)); \ - } \ - Store##Name##Inst *createStore##Name(SILLocation Loc, \ - SILValue value, \ - SILValue dest, \ - IsInitialization_t isInit) { \ - return insert(new (getModule()) \ - Store##Name##Inst(getSILDebugLocation(Loc), value, dest, isInit)); \ + UnownedCopyValueInst *createUnownedCopyValue(SILLocation Loc, + SILValue operand) { + assert(!getFunction().getModule().useLoweredAddresses()); + auto type = operand->getType() + .getReferenceStorageType(getFunction().getASTContext(), + ReferenceOwnership::Unowned) + .getObjectType(); + return insert(new (getModule()) UnownedCopyValueInst( + getSILDebugLocation(Loc), operand, type)); + } + + WeakCopyValueInst *createWeakCopyValue(SILLocation Loc, SILValue operand) { + assert(!getFunction().getModule().useLoweredAddresses()); + auto type = operand->getType() + .getReferenceStorageType(getFunction().getASTContext(), + ReferenceOwnership::Weak) + .getObjectType(); + return insert(new (getModule()) WeakCopyValueInst(getSILDebugLocation(Loc), + operand, type)); + } + +#define COPYABLE_STORAGE_HELPER(Name) \ + StrongCopy##Name##ValueInst *createStrongCopy##Name##Value( \ + SILLocation Loc, SILValue operand) { \ + auto type = getFunction().getLoweredType( \ + operand->getType().getASTType().getReferenceStorageReferent()); \ + return insert(new (getModule()) StrongCopy##Name##ValueInst( \ + getSILDebugLocation(Loc), operand, type)); \ } + +#define LOADABLE_STORAGE_HELPER(Name) \ + Load##Name##Inst *createLoad##Name(SILLocation Loc, SILValue src, \ + IsTake_t isTake) { \ + return insert(new (getModule()) Load##Name##Inst(getSILDebugLocation(Loc), \ + src, isTake)); \ + } \ + Store##Name##Inst *createStore##Name(SILLocation Loc, SILValue value, \ + SILValue dest, \ + IsInitialization_t isInit) { \ + return insert(new (getModule()) Store##Name##Inst( \ + getSILDebugLocation(Loc), value, dest, isInit)); \ + } + #define LOADABLE_REF_STORAGE_HELPER(Name) \ Name##ToRefInst *create##Name##ToRef(SILLocation Loc, SILValue op, \ SILType ty) { \ @@ -1085,41 +1114,45 @@ class SILBuilder { SILType ty) { \ return insert(new (getModule()) \ RefTo##Name##Inst(getSILDebugLocation(Loc), op, ty)); \ - } \ - StrongCopy##Name##ValueInst *createStrongCopy##Name##Value( \ - SILLocation Loc, SILValue operand) { \ - auto type = getFunction().getLoweredType( \ - operand->getType().getASTType().getReferenceStorageReferent()); \ - return insert(new (getModule()) StrongCopy##Name##ValueInst( \ - getSILDebugLocation(Loc), operand, type)); \ } -#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - LOADABLE_REF_STORAGE_HELPER(Name) \ - StrongRetain##Name##Inst *createStrongRetain##Name(SILLocation Loc, \ - SILValue Operand, \ - Atomicity atomicity) { \ - return insert(new (getModule()) \ - StrongRetain##Name##Inst(getSILDebugLocation(Loc), Operand, atomicity)); \ - } \ - Name##RetainInst *create##Name##Retain(SILLocation Loc, SILValue Operand, \ - Atomicity atomicity) { \ - return insert(new (getModule()) \ - Name##RetainInst(getSILDebugLocation(Loc), Operand, atomicity)); \ - } \ - Name##ReleaseInst *create##Name##Release(SILLocation Loc, \ - SILValue Operand, \ - Atomicity atomicity) { \ - return insert(new (getModule()) \ - Name##ReleaseInst(getSILDebugLocation(Loc), Operand, atomicity)); \ - } -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") -#define UNCHECKED_REF_STORAGE(Name, ...) \ +#define RETAINABLE_STORAGE_HELPER(Name) \ + StrongRetain##Name##Inst *createStrongRetain##Name( \ + SILLocation Loc, SILValue Operand, Atomicity atomicity) { \ + return insert(new (getModule()) StrongRetain##Name##Inst( \ + getSILDebugLocation(Loc), Operand, atomicity)); \ + } \ + Name##RetainInst *create##Name##Retain(SILLocation Loc, SILValue Operand, \ + Atomicity atomicity) { \ + return insert(new (getModule()) Name##RetainInst(getSILDebugLocation(Loc), \ + Operand, atomicity)); \ + } \ + Name##ReleaseInst *create##Name##Release(SILLocation Loc, SILValue Operand, \ + Atomicity atomicity) { \ + return insert(new (getModule()) Name##ReleaseInst( \ + getSILDebugLocation(Loc), Operand, atomicity)); \ + } + +#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + COPYABLE_STORAGE_HELPER(Name) \ + LOADABLE_REF_STORAGE_HELPER(Name) \ + RETAINABLE_STORAGE_HELPER(Name) +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + COPYABLE_STORAGE_HELPER(Name) \ + LOADABLE_REF_STORAGE_HELPER(Name) \ + LOADABLE_STORAGE_HELPER(Name) \ + RETAINABLE_STORAGE_HELPER(Name) +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + COPYABLE_STORAGE_HELPER(Name) \ + LOADABLE_STORAGE_HELPER(Name) +#define UNCHECKED_REF_STORAGE(Name, ...) \ + COPYABLE_STORAGE_HELPER(Name) \ LOADABLE_REF_STORAGE_HELPER(Name) #include "swift/AST/ReferenceStorage.def" +#undef LOADABLE_STORAGE_HELPER #undef LOADABLE_REF_STORAGE_HELPER +#undef COPYABLE_STORAGE_HELPER +#undef RETAINABLE_STORAGE_HELPER CopyAddrInst *createCopyAddr(SILLocation Loc, SILValue srcAddr, SILValue destAddr, IsTake_t isTake, diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 05ac3044ee277..4a41fa576c1c3 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -1407,7 +1407,34 @@ SILCloner::visitDebugStepInst(DebugStepInst *Inst) { recordClonedInstruction(Inst, getBuilder().createDebugStep(Inst->getLoc())); } -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ +template +void SILCloner::visitUnownedCopyValueInst( + UnownedCopyValueInst *Inst) { + getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); + recordClonedInstruction( + Inst, getBuilder().createUnownedCopyValue( + getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); +} + +template +void SILCloner::visitWeakCopyValueInst(WeakCopyValueInst *Inst) { + getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); + recordClonedInstruction( + Inst, getBuilder().createWeakCopyValue(getOpLocation(Inst->getLoc()), + getOpValue(Inst->getOperand()))); +} + +#define COPYABLE_STORAGE_HELPER(Name, name) \ + template \ + void SILCloner::visitStrongCopy##Name##ValueInst( \ + StrongCopy##Name##ValueInst *Inst) { \ + getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ + recordClonedInstruction(Inst, getBuilder().createStrongCopy##Name##Value( \ + getOpLocation(Inst->getLoc()), \ + getOpValue(Inst->getOperand()))); \ + } + +#define LOADABLE_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitLoad##Name##Inst(Load##Name##Inst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ @@ -1441,17 +1468,8 @@ SILCloner::visitDebugStepInst(DebugStepInst *Inst) { Inst, getBuilder().create##Name##ToRef(getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ getOpType(Inst->getType()))); \ - } \ - template \ - void SILCloner::visitStrongCopy##Name##ValueInst( \ - StrongCopy##Name##ValueInst *Inst) { \ - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ - recordClonedInstruction(Inst, getBuilder().createStrongCopy##Name##Value( \ - getOpLocation(Inst->getLoc()), \ - getOpValue(Inst->getOperand()))); \ } -#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ - LOADABLE_REF_STORAGE_HELPER(Name, name) \ +#define RETAINABLE_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitStrongRetain##Name##Inst( \ StrongRetain##Name##Inst *Inst) { \ @@ -1478,13 +1496,26 @@ SILCloner::visitDebugStepInst(DebugStepInst *Inst) { getOpValue(Inst->getOperand()), \ Inst->getAtomicity())); \ } -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") -#define UNCHECKED_REF_STORAGE(Name, name, ...) \ +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ + COPYABLE_STORAGE_HELPER(Name, name) \ + LOADABLE_STORAGE_HELPER(Name, name) +#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ + COPYABLE_STORAGE_HELPER(Name, name) \ + LOADABLE_REF_STORAGE_HELPER(Name, name) \ + RETAINABLE_STORAGE_HELPER(Name, name) +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ + COPYABLE_STORAGE_HELPER(Name, name) \ + LOADABLE_REF_STORAGE_HELPER(Name, name) \ + LOADABLE_STORAGE_HELPER(Name, name) \ + RETAINABLE_STORAGE_HELPER(Name, name) +#define UNCHECKED_REF_STORAGE(Name, name, ...) \ + COPYABLE_STORAGE_HELPER(Name, name) \ LOADABLE_REF_STORAGE_HELPER(Name, name) #include "swift/AST/ReferenceStorage.def" +#undef LOADABLE_STORAGE_HELPER #undef LOADABLE_REF_STORAGE_HELPER +#undef COPYABLE_STORAGE_HELPER +#undef RETAINABLE_STORAGE_HELPER template void diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 21dd870cf42e1..552d54348b54d 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -8098,6 +8098,40 @@ class ExplicitCopyValueInst : UnaryInstructionBase(DebugLoc, operand, operand->getType()) {} }; +class WeakCopyValueInst + : public UnaryInstructionBase { + friend class SILBuilder; + WeakCopyValueInst(SILDebugLocation DebugLoc, SILValue operand, SILType type) + : UnaryInstructionBase(DebugLoc, operand, type) { + assert(type.getReferenceStorageOwnership() == ReferenceOwnership::Weak); + assert(type.getReferenceStorageReferentType() == operand->getType()); + } +}; + +class UnownedCopyValueInst + : public UnaryInstructionBase { + friend class SILBuilder; + UnownedCopyValueInst(SILDebugLocation DebugLoc, SILValue operand, + SILType type) + : UnaryInstructionBase(DebugLoc, operand, type) { + assert(type.getReferenceStorageOwnership() == ReferenceOwnership::Unowned); + assert(type.getReferenceStorageReferentType() == operand->getType()); + } +}; + +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + class StrongCopy##Name##ValueInst \ + : public UnaryInstructionBase< \ + SILInstructionKind::StrongCopy##Name##ValueInst, \ + SingleValueInstruction> { \ + friend class SILBuilder; \ + StrongCopy##Name##ValueInst(SILDebugLocation DebugLoc, SILValue operand, \ + SILType type) \ + : UnaryInstructionBase(DebugLoc, operand, \ + type.getReferenceStorageReferentType()) {} \ + }; #define UNCHECKED_REF_STORAGE(Name, ...) \ class StrongCopy##Name##ValueInst \ : public UnaryInstructionBase< \ @@ -8108,7 +8142,6 @@ class ExplicitCopyValueInst SILType type) \ : UnaryInstructionBase(DebugLoc, operand, type) {} \ }; - #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ class StrongCopy##Name##ValueInst \ : public UnaryInstructionBase< \ diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def index 65af4ca57e303..a803896eed50d 100644 --- a/include/swift/SIL/SILNodes.def +++ b/include/swift/SIL/SILNodes.def @@ -453,10 +453,12 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction) // alone by OSSA optimizations. SINGLE_VALUE_INST(ExplicitCopyValueInst, explicit_copy_value, SingleValueInstruction, None, DoesNotRelease) -#define UNCHECKED_REF_STORAGE(Name, name, ...) \ - SINGLE_VALUE_INST(StrongCopy##Name##ValueInst, strong_copy_##name##_value, \ + // Produce a @sil_unowned value from the specified value of reference type. + SINGLE_VALUE_INST(UnownedCopyValueInst, unowned_copy_value, SingleValueInstruction, MayHaveSideEffects, DoesNotRelease) -#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ + SINGLE_VALUE_INST(WeakCopyValueInst, weak_copy_value, + SingleValueInstruction, MayHaveSideEffects, DoesNotRelease) +#define REF_STORAGE(Name, name, ...) \ SINGLE_VALUE_INST(StrongCopy##Name##ValueInst, strong_copy_##name##_value, \ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease) #include "swift/AST/ReferenceStorage.def" diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index f4eeb22e9b791..6bec19b3d5c77 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1503,25 +1503,39 @@ class IRGenSILFunction : void visitHasSymbolInst(HasSymbolInst *i); + void visitWeakCopyValueInst(swift::WeakCopyValueInst *i); + void visitUnownedCopyValueInst(swift::UnownedCopyValueInst *i); #define LOADABLE_REF_STORAGE_HELPER(Name) \ void visitRefTo##Name##Inst(RefTo##Name##Inst *i); \ - void visit##Name##ToRefInst(Name##ToRefInst *i); \ + void visit##Name##ToRefInst(Name##ToRefInst *i); +#define COPYABLE_STORAGE_HELPER(Name) \ void visitStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *i); -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - void visitLoad##Name##Inst(Load##Name##Inst *i); \ +#define LOADABLE_STORAGE_HELPER(Name) \ + void visitLoad##Name##Inst(Load##Name##Inst *i); \ void visitStore##Name##Inst(Store##Name##Inst *i); -#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - LOADABLE_REF_STORAGE_HELPER(Name) \ +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + LOADABLE_STORAGE_HELPER(Name) \ + COPYABLE_STORAGE_HELPER(Name) +#define RETAINABLE_STORAGE_HELPER(Name) \ void visitStrongRetain##Name##Inst(StrongRetain##Name##Inst *i); \ void visit##Name##RetainInst(Name##RetainInst *i); \ void visit##Name##ReleaseInst(Name##ReleaseInst *i); -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") -#define UNCHECKED_REF_STORAGE(Name, ...) \ +#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + LOADABLE_REF_STORAGE_HELPER(Name) \ + RETAINABLE_STORAGE_HELPER(Name) +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + LOADABLE_STORAGE_HELPER(Name) \ + COPYABLE_STORAGE_HELPER(Name) \ + LOADABLE_REF_STORAGE_HELPER(Name) \ + RETAINABLE_STORAGE_HELPER(Name) +#define UNCHECKED_REF_STORAGE(Name, ...) \ + COPYABLE_STORAGE_HELPER(Name) \ LOADABLE_REF_STORAGE_HELPER(Name) #include "swift/AST/ReferenceStorage.def" #undef LOADABLE_REF_STORAGE_HELPER +#undef LOADABLE_STORAGE_HELPER +#undef COPYABLE_STORAGE_HELPER +#undef RETAINABLE_STORAGE_HELPER }; } // end anonymous namespace @@ -5338,6 +5352,22 @@ static const ReferenceTypeInfo &getReferentTypeInfo(IRGenFunction &IGF, return cast(IGF.getTypeInfoForLowered(type)); } +void IRGenSILFunction::visitStrongCopyWeakValueInst( + swift::StrongCopyWeakValueInst *i) { + llvm::report_fatal_error( + "strong_copy_weak_value not lowered by AddressLowering!?"); +} + +void IRGenSILFunction::visitWeakCopyValueInst(swift::WeakCopyValueInst *i) { + llvm::report_fatal_error("weak_copy_value not lowered by AddressLowering!?"); +} + +void IRGenSILFunction::visitUnownedCopyValueInst( + swift::UnownedCopyValueInst *i) { + llvm::report_fatal_error( + "unowned_copy_value not lowered by AddressLowering!?"); +} + #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ void IRGenSILFunction::visitLoad##Name##Inst(swift::Load##Name##Inst *i) { \ Address source = getLoweredAddress(i->getOperand()); \ diff --git a/lib/SIL/IR/OperandOwnership.cpp b/lib/SIL/IR/OperandOwnership.cpp index d296b46db0bd0..7fe14a6e059a4 100644 --- a/lib/SIL/IR/OperandOwnership.cpp +++ b/lib/SIL/IR/OperandOwnership.cpp @@ -220,9 +220,9 @@ OPERAND_OWNERSHIP(InstantaneousUse, ClassMethod) OPERAND_OWNERSHIP(InstantaneousUse, SuperMethod) OPERAND_OWNERSHIP(InstantaneousUse, ClassifyBridgeObject) OPERAND_OWNERSHIP(InstantaneousUse, SetDeallocating) -#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value) -#define UNCHECKED_REF_STORAGE(Name, ...) \ +OPERAND_OWNERSHIP(InstantaneousUse, UnownedCopyValue) +OPERAND_OWNERSHIP(InstantaneousUse, WeakCopyValue) +#define REF_STORAGE(Name, ...) \ OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value) #include "swift/AST/ReferenceStorage.def" diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index b1caaa0ce80ef..3aeff49e23af5 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -2141,12 +2141,15 @@ class SILPrinter : public SILInstructionVisitor { *this << getIDAndType(I->getOperand()); } -#define UNCHECKED_REF_STORAGE(Name, ...) \ - void visitStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \ - *this << getIDAndType(I->getOperand()); \ + void visitUnownedCopyValueInst(UnownedCopyValueInst *I) { + *this << getIDAndType(I->getOperand()); + } + + void visitWeakCopyValueInst(WeakCopyValueInst *I) { + *this << getIDAndType(I->getOperand()); } -#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ +#define REF_STORAGE(Name, ...) \ void visitStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \ *this << getIDAndType(I->getOperand()); \ } diff --git a/lib/SIL/IR/ValueOwnership.cpp b/lib/SIL/IR/ValueOwnership.cpp index 34db331c9c427..5cdc0b01c15e8 100644 --- a/lib/SIL/IR/ValueOwnership.cpp +++ b/lib/SIL/IR/ValueOwnership.cpp @@ -49,15 +49,20 @@ class ValueOwnershipKindClassifier return OwnershipKind::OWNERSHIP; \ } -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ +CONSTANT_OWNERSHIP_INST(Owned, UnownedCopyValue) +CONSTANT_OWNERSHIP_INST(Owned, WeakCopyValue) +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + CONSTANT_OWNERSHIP_INST(Owned, StrongCopy##Name##Value) \ CONSTANT_OWNERSHIP_INST(Owned, Load##Name) #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ CONSTANT_OWNERSHIP_INST(Unowned, RefTo##Name) \ CONSTANT_OWNERSHIP_INST(Unowned, Name##ToRef) \ CONSTANT_OWNERSHIP_INST(Owned, StrongCopy##Name##Value) -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + CONSTANT_OWNERSHIP_INST(Owned, Load##Name) \ + CONSTANT_OWNERSHIP_INST(Unowned, RefTo##Name) \ + CONSTANT_OWNERSHIP_INST(Unowned, Name##ToRef) \ + CONSTANT_OWNERSHIP_INST(Owned, StrongCopy##Name##Value) #define UNCHECKED_REF_STORAGE(Name, ...) \ CONSTANT_OWNERSHIP_INST(None, RefTo##Name) \ CONSTANT_OWNERSHIP_INST(Unowned, Name##ToRef) \ diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 5affd663cd93f..6f7d7f0c2afc9 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -3646,8 +3646,12 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B, REFCOUNTING_INSTRUCTION(RetainValue) REFCOUNTING_INSTRUCTION(ReleaseValueAddr) REFCOUNTING_INSTRUCTION(RetainValueAddr) + UNARY_INSTRUCTION(UnownedCopyValue) + UNARY_INSTRUCTION(WeakCopyValue) #define UNCHECKED_REF_STORAGE(Name, ...) \ UNARY_INSTRUCTION(StrongCopy##Name##Value) +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + UNARY_INSTRUCTION(StrongCopy##Name##Value) #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ REFCOUNTING_INSTRUCTION(StrongRetain##Name) \ REFCOUNTING_INSTRUCTION(Name##Retain) \ diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index 72de536f4ae8c..577b0fb3d6448 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -848,10 +848,10 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) #include "swift/AST/ReferenceStorage.def" #undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE -#define UNCHECKED_REF_STORAGE(Name, ...) \ - case SILInstructionKind::StrongCopy##Name##ValueInst: \ + case SILInstructionKind::UnownedCopyValueInst: + case SILInstructionKind::WeakCopyValueInst: return RuntimeEffect::RefCounting; -#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ +#define REF_STORAGE(Name, ...) \ case SILInstructionKind::StrongCopy##Name##ValueInst: \ return RuntimeEffect::RefCounting; #include "swift/AST/ReferenceStorage.def" diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 30b94a169ca3a..1c45435eea961 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -2798,8 +2798,12 @@ class SILVerifier : public SILVerifierBase { requireReferenceStorageCapableValue(I->getOperand(), \ "Operand of ref_to_" #name); \ auto operandType = I->getOperand()->getType().getASTType(); \ + require(!I->getOperand()->getType().isAddressOnly(F), \ + "ref_to_" #name " may not take an address-only operand"); \ auto resultType = \ requireObjectType(Name##StorageType, I, "Result of ref_to_" #name); \ + require(!I->getType().isAddressOnly(F), \ + "ref_to_" #name " must not produce an address-only value"); \ requireSameType(resultType.getReferentType(), operandType, \ "Result of ref_to_" #name " does not have the " \ "operand's type as its referent type"); \ @@ -2807,8 +2811,12 @@ class SILVerifier : public SILVerifierBase { void check##Name##ToRefInst(Name##ToRefInst *I) { \ auto operandType = requireObjectType(Name##StorageType, I->getOperand(), \ "Operand of " #name "_to_ref"); \ + require(!I->getOperand()->getType().isAddressOnly(F), \ + #name "_to_ref may not take an address-only operand"); \ requireReferenceStorageCapableValue(I, "Result of " #name "_to_ref"); \ auto resultType = I->getType().getASTType(); \ + require(!I->getType().isAddressOnly(F), \ + #name "_to_ref may not produce an address-only value"); \ requireSameType(operandType.getReferentType(), resultType, \ "Operand of " #name "_to_ref does not have the " \ "operand's type as its referent type"); \ @@ -2975,6 +2983,27 @@ class SILVerifier : public SILVerifierBase { "'MoveOnly' types can only be copied in Raw SIL?!"); } + void checkUnownedCopyValueInst(UnownedCopyValueInst *I) { + require(!F.getModule().useLoweredAddresses(), + "unowned_copy_value is only valid in opaque values"); + require(I->getType().isAddressOnly(F), + "unowned_copy_value must produce an address-only value"); + } + + void checkWeakCopyValueInst(WeakCopyValueInst *I) { + require(!F.getModule().useLoweredAddresses(), + "weak_copy_value is only valid in opaque values"); + require(I->getType().isAddressOnly(F), + "weak_copy_value must produce an address-only value"); + } + + void checkStrongCopyWeakValueInst(StrongCopyWeakValueInst *I) { + require(!F.getModule().useLoweredAddresses(), + "strong_copy_weak_value is only valid in opaque values"); + require(I->getOperand()->getType().isAddressOnly(F), + "strong_copy_weak_value requires an address-only operand"); + } + void checkExplicitCopyValueInst(ExplicitCopyValueInst *I) { require(F.hasOwnership(), "explicit_copy_* is only valid in OSSA."); require(I->getOperand()->getType().isObject(), diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp index 00eceb9944099..d256963e236d6 100644 --- a/lib/SILGen/SILGenBuilder.cpp +++ b/lib/SILGen/SILGenBuilder.cpp @@ -175,11 +175,24 @@ ManagedValue SILGenBuilder::createCopyValue(SILLocation loc, return SGF.emitManagedRValueWithCleanup(result, lowering); } +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + ManagedValue SILGenBuilder::createStrongCopy##Name##Value( \ + SILLocation loc, ManagedValue originalValue) { \ + assert(!SGF.useLoweredAddresses()); \ + auto ty = originalValue.getType(); \ + assert(ty.isAddressOnly(SGF.F)); \ + auto storageTy = originalValue.getType().castTo(); \ + (void)storageTy; \ + SILValue result = \ + createStrongCopy##Name##Value(loc, originalValue.getValue()); \ + return SGF.emitManagedRValueWithCleanup(result); \ + } #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ ManagedValue SILGenBuilder::createStrongCopy##Name##Value( \ SILLocation loc, ManagedValue originalValue) { \ auto ty = originalValue.getType().castTo(); \ - assert(ty->isLoadable(ResilienceExpansion::Maximal)); \ + assert(ty->isLoadable(ResilienceExpansion::Maximal) || \ + !SGF.useLoweredAddresses()); \ (void)ty; \ SILValue result = \ createStrongCopy##Name##Value(loc, originalValue.getValue()); \ diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h index 66cb0f9188ec0..2891f7cc689e2 100644 --- a/lib/SILGen/SILGenBuilder.h +++ b/lib/SILGen/SILGenBuilder.h @@ -132,6 +132,14 @@ class SILGenBuilder : public SILBuilder { /// values. ManagedValue createExplicitCopyValue(SILLocation Loc, ManagedValue operand); + using SILBuilder::createWeakCopyValue; + + ManagedValue createWeakCopyValue(SILLocation loc, ManagedValue originalValue); + +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + using SILBuilder::createStrongCopy##Name##Value; \ + ManagedValue createStrongCopy##Name##Value(SILLocation loc, \ + ManagedValue originalValue); #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ using SILBuilder::createStrongCopy##Name##Value; \ ManagedValue createStrongCopy##Name##Value(SILLocation loc, \ diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 0ba5fdf907b49..b3ed211e1685f 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -4544,9 +4544,18 @@ ManagedValue SILGenFunction::emitConversionToSemanticRValue( switch (swiftStorageType->getOwnership()) { case ReferenceOwnership::Strong: llvm_unreachable("strong reference storage type should be impossible"); -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - case ReferenceOwnership::Name: \ - /* Address-only storage types are handled with their underlying type. */ \ +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case ReferenceOwnership::Name: \ + if (!useLoweredAddresses()) { \ + auto refTy = src.getType(); \ + auto ty = refTy.getReferenceStorageReferentType(); \ + assert(ty); \ + assert(ty.getOptionalObjectType()); \ + (void)ty; \ + /* Copy the weak value, opening the @sil_weak box. */ \ + return B.createStrongCopy##Name##Value(loc, src); \ + } \ + /* Address-only storage types are handled with their underlying type. */ \ llvm_unreachable("address-only pointers are handled elsewhere"); #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ case ReferenceOwnership::Name: \ @@ -4827,11 +4836,29 @@ SILValue SILGenFunction::emitConversionFromSemanticValue(SILLocation loc, } auto swiftStorageType = storageType.castTo(); + if (!useLoweredAddresses() && storageType.isAddressOnly(F)) { + switch (swiftStorageType->getOwnership()) { + case ReferenceOwnership::Strong: + llvm_unreachable("strong reference storage type should be impossible"); + case ReferenceOwnership::Unmanaged: + llvm_unreachable("unimplemented"); + case ReferenceOwnership::Weak: { + auto value = B.createWeakCopyValue(loc, semanticValue); + B.emitDestroyValueOperation(loc, semanticValue); + return value; + } + case ReferenceOwnership::Unowned: { + auto value = B.createUnownedCopyValue(loc, semanticValue); + B.emitDestroyValueOperation(loc, semanticValue); + return value; + } + } + } switch (swiftStorageType->getOwnership()) { case ReferenceOwnership::Strong: llvm_unreachable("strong reference storage type should be impossible"); -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - case ReferenceOwnership::Name: \ +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case ReferenceOwnership::Name: \ llvm_unreachable("address-only types are never loadable"); #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ case ReferenceOwnership::Name: { \ @@ -4840,16 +4867,16 @@ SILValue SILGenFunction::emitConversionFromSemanticValue(SILLocation loc, B.emitDestroyValueOperation(loc, semanticValue); \ return value; \ } -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - case ReferenceOwnership::Name: { \ - /* For loadable types, place into a box. */ \ - auto type = storageType.castTo(); \ - assert(type->isLoadable(ResilienceExpansion::Maximal)); \ - (void) type; \ - SILValue value = B.createRefTo##Name(loc, semanticValue, storageType); \ - value = B.createCopyValue(loc, value); \ - B.emitDestroyValueOperation(loc, semanticValue); \ - return value; \ +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case ReferenceOwnership::Name: { \ + /* For loadable types, place into a box. */ \ + auto type = storageType.castTo(); \ + assert(type->isLoadable(ResilienceExpansion::Maximal)); \ + (void)type; \ + SILValue value = B.createRefTo##Name(loc, semanticValue, storageType); \ + value = B.createCopyValue(loc, value); \ + B.emitDestroyValueOperation(loc, semanticValue); \ + return value; \ } #define UNCHECKED_REF_STORAGE(Name, ...) \ case ReferenceOwnership::Name: { \ diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp index 3df4f3a620b01..de248485a4bb7 100644 --- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp +++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp @@ -3483,6 +3483,22 @@ class UseRewriter : SILInstructionVisitor { pass.deleter.forceDelete(sei); } + void visitStrongCopyUnownedValueInst(StrongCopyUnownedValueInst *scuvi) { + auto sourceAddr = addrMat.materializeAddress(use->get()); + SILValue value = + builder.createLoadUnowned(scuvi->getLoc(), sourceAddr, IsNotTake); + scuvi->replaceAllUsesWith(value); + pass.deleter.forceDelete(scuvi); + } + + void visitStrongCopyWeakValueInst(StrongCopyWeakValueInst *scwvi) { + auto sourceAddr = addrMat.materializeAddress(use->get()); + SILValue value = + builder.createLoadWeak(scwvi->getLoc(), sourceAddr, IsNotTake); + scwvi->replaceAllUsesWith(value); + pass.deleter.forceDelete(scwvi); + } + // Extract from an opaque struct. void visitStructExtractInst(StructExtractInst *extractInst); @@ -4094,6 +4110,24 @@ class DefRewriter : SILInstructionVisitor { rewriteUnconditionalCheckedCastInst(uncondCheckedCast, pass); } + + void visitUnownedCopyValueInst(UnownedCopyValueInst *uci) { + auto &storage = pass.valueStorageMap.getStorage(uci); + auto destAddr = addrMat.recursivelyMaterializeStorage( + storage, /*intoPhiOperand=*/false); + + builder.createStoreUnowned(uci->getLoc(), uci->getOperand(), destAddr, + IsInitialization); + } + + void visitWeakCopyValueInst(WeakCopyValueInst *wcsvi) { + auto &storage = pass.valueStorageMap.getStorage(wcsvi); + auto destAddr = addrMat.recursivelyMaterializeStorage( + storage, /*intoPhiOperand=*/false); + + builder.createStoreWeak(wcsvi->getLoc(), wcsvi->getOperand(), destAddr, + IsInitialization); + } }; } // end anonymous namespace diff --git a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp index c269fd2955fb5..11de478376585 100644 --- a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp +++ b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp @@ -210,13 +210,11 @@ static bool hasOpaqueArchetype(TypeExpansionContext context, case SILInstructionKind::MarkUnresolvedReferenceBindingInst: case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst: case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst: -#define UNCHECKED_REF_STORAGE(Name, ...) \ - case SILInstructionKind::StrongCopy##Name##ValueInst: -#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::UnownedCopyValueInst: + case SILInstructionKind::WeakCopyValueInst: +#define REF_STORAGE(Name, ...) \ case SILInstructionKind::StrongCopy##Name##ValueInst: #include "swift/AST/ReferenceStorage.def" -#undef UNCHECKED_REF_STORAGE -#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE case SILInstructionKind::UncheckedOwnershipConversionInst: case SILInstructionKind::IsUniqueInst: case SILInstructionKind::IsEscapingClosureInst: diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index 2101fbb93e552..030852d275bf1 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -1122,21 +1122,25 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) { case SILInstructionKind::HopToExecutorInst: case SILInstructionKind::ExtractExecutorInst: case SILInstructionKind::HasSymbolInst: + case SILInstructionKind::UnownedCopyValueInst: + case SILInstructionKind::WeakCopyValueInst: #define COMMON_ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name) \ case SILInstructionKind::Name##ToRefInst: \ case SILInstructionKind::RefTo##Name##Inst: \ case SILInstructionKind::StrongCopy##Name##ValueInst: -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - case SILInstructionKind::Load##Name##Inst: \ - case SILInstructionKind::Store##Name##Inst: +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::Load##Name##Inst: \ + case SILInstructionKind::Store##Name##Inst: \ + case SILInstructionKind::StrongCopy##Name##ValueInst: #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ COMMON_ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name) \ case SILInstructionKind::Name##RetainInst: \ case SILInstructionKind::Name##ReleaseInst: \ case SILInstructionKind::StrongRetain##Name##Inst: -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::Load##Name##Inst: \ + case SILInstructionKind::Store##Name##Inst: \ + ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") #define UNCHECKED_REF_STORAGE(Name, ...) \ COMMON_ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name) #include "swift/AST/ReferenceStorage.def" diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index e97c685ded1ce..419a1063b131f 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -2082,6 +2082,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, (Atomicity)Attr); \ break; + UNARY_INSTRUCTION(UnownedCopyValue) + UNARY_INSTRUCTION(WeakCopyValue) #define UNCHECKED_REF_STORAGE(Name, ...) \ UNARY_INSTRUCTION(StrongCopy##Name##Value) #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ @@ -2089,6 +2091,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, REFCOUNTING_INSTRUCTION(Name##Release) \ REFCOUNTING_INSTRUCTION(StrongRetain##Name) \ UNARY_INSTRUCTION(StrongCopy##Name##Value) +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + UNARY_INSTRUCTION(StrongCopy##Name##Value) #include "swift/AST/ReferenceStorage.def" REFCOUNTING_INSTRUCTION(RetainValue) REFCOUNTING_INSTRUCTION(RetainValueAddr) diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index ac160999ad3b0..5de33709a5961 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 797; // checked_cast_br takes a formal type +const uint16_t SWIFTMODULE_VERSION_MINOR = 800; // added unowned_copy_value /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 629e9fe90990b..cc2602c289f25 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -1442,18 +1442,24 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { ListOfValues); break; } + case SILInstructionKind::UnownedCopyValueInst: + case SILInstructionKind::WeakCopyValueInst: #define UNCHECKED_REF_STORAGE(Name, ...) \ case SILInstructionKind::StrongCopy##Name##ValueInst: -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::StrongCopy##Name##ValueInst: \ case SILInstructionKind::Load##Name##Inst: #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ case SILInstructionKind::Name##RetainInst: \ case SILInstructionKind::Name##ReleaseInst: \ case SILInstructionKind::StrongRetain##Name##Inst: \ case SILInstructionKind::StrongCopy##Name##ValueInst: -#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ - ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") +#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::Load##Name##Inst: \ + case SILInstructionKind::Name##RetainInst: \ + case SILInstructionKind::Name##ReleaseInst: \ + case SILInstructionKind::StrongRetain##Name##Inst: \ + case SILInstructionKind::StrongCopy##Name##ValueInst: #include "swift/AST/ReferenceStorage.def" case SILInstructionKind::RetainValueInst: case SILInstructionKind::DestructureStructInst: diff --git a/test/SIL/Parser/opaque_values_parse.sil b/test/SIL/Parser/opaque_values_parse.sil index 153021a0bbb4f..c196d3fee9f62 100644 --- a/test/SIL/Parser/opaque_values_parse.sil +++ b/test/SIL/Parser/opaque_values_parse.sil @@ -96,3 +96,35 @@ bb0(%0 : $S): return %t : $() } // CHECK-LABEL: } // end sil function 'parse_mutating' + +struct WeakBox { + weak var t: T? +} + +// Test strong_copy_weak_value parsing. + +// CHECK-LABEL: sil [ossa] @test_strong_copy_weak_value : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: strong_copy_weak_value [[WEAK_OPTIONAL]] +// CHECK-LABEL: } // end sil function 'test_strong_copy_weak_value' +sil [ossa] @test_strong_copy_weak_value : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional { +bb0(%instance : @guaranteed $WeakBox): + %weak_optional = struct_extract %instance : $WeakBox, #WeakBox.t + %strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional + return %strong_optional : $Optional +} + +// Test weak_copy_value parsing. + +// CHECK-LABEL: sil [ossa] @test_weak_copy_value_1 : {{.*}} { +// CHECK: bb0([[VALUE:%[^,]+]] : +// CHECK: weak_copy_value [[VALUE]] +// CHECK-LABEL: } // end sil function 'test_weak_copy_value_1' +sil [ossa] @test_weak_copy_value_1 : $@convention(thin) (@owned Optional) -> @out WeakBox { +bb0(%value : @owned $Optional): + %weak_value = weak_copy_value %value : $Optional + destroy_value %value : $Optional + %retval = struct $WeakBox (%weak_value : $@sil_weak Optional) + return %retval : $WeakBox +} diff --git a/test/SIL/Parser/opaque_values_parse_objc.sil b/test/SIL/Parser/opaque_values_parse_objc.sil new file mode 100644 index 0000000000000..3582b7b0df5fa --- /dev/null +++ b/test/SIL/Parser/opaque_values_parse_objc.sil @@ -0,0 +1,22 @@ +// RUN: %target-sil-opt -enable-sil-opaque-values -enable-sil-verify-all -emit-sorted-sil %s | %FileCheck %s + +// REQUIRES: objc_interop + +import Builtin +import Swift + +struct UnownedBox { + unowned var value: T +} + +// CHECK-LABEL: sil [ossa] @test_unowned_copy_value : {{.*}} { +// CHECK: bb0([[VALUE:%[^,]+]] : +// CHECK: unowned_copy_value [[VALUE]] +// CHECK-LABEL: } // end sil function 'test_unowned_copy_value' +sil [ossa] @test_unowned_copy_value : $@convention(thin) (@owned T) -> @out UnownedBox { +bb0(%owned_value : @owned $T): + %unowned_value = unowned_copy_value %owned_value : $T + destroy_value %owned_value : $T + %instance = struct $UnownedBox (%unowned_value : $@sil_unowned T) + return %instance : $UnownedBox +} diff --git a/test/SIL/Serialization/opaque_values_serialize.sil b/test/SIL/Serialization/opaque_values_serialize.sil index 4b7060c97e9ac..104c9aa5038d8 100644 --- a/test/SIL/Serialization/opaque_values_serialize.sil +++ b/test/SIL/Serialization/opaque_values_serialize.sil @@ -82,3 +82,31 @@ bb0(%0 : $S): return %t : $() } // CHECK-LABEL: } // end sil function 'serialize_mutating' + +struct WeakBox { + weak var t: T? +} + +// CHECK-LABEL: sil [ossa] @test_strong_copy_weak_value : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: strong_copy_weak_value [[WEAK_OPTIONAL]] +// CHECK-LABEL: } // end sil function 'test_strong_copy_weak_value' +sil [ossa] @test_strong_copy_weak_value : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional { +bb0(%instance : @guaranteed $WeakBox): + %weak_optional = struct_extract %instance : $WeakBox, #WeakBox.t + %strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional + return %strong_optional : $Optional +} + +// CHECK-LABEL: sil [ossa] @test_weak_copy_value_1 : {{.*}} { +// CHECK: bb0([[VALUE:%[^,]+]] : +// CHECK: weak_copy_value [[VALUE]] +// CHECK-LABEL: } // end sil function 'test_weak_copy_value_1' +sil [ossa] @test_weak_copy_value_1 : $@convention(thin) (@owned Optional) -> @out WeakBox { +bb0(%value : @owned $Optional): + %weak_value = weak_copy_value %value : $Optional + destroy_value %value : $Optional + %retval = struct $WeakBox (%weak_value : $@sil_weak Optional) + return %retval : $WeakBox +} diff --git a/test/SIL/Serialization/opaque_values_serialize_objc.sil b/test/SIL/Serialization/opaque_values_serialize_objc.sil new file mode 100644 index 0000000000000..d18fff44feed4 --- /dev/null +++ b/test/SIL/Serialization/opaque_values_serialize_objc.sil @@ -0,0 +1,30 @@ +// First parse this and then emit a *.sib. Then read in the *.sib, then recreate +// RUN: %empty-directory(%t) +// FIXME: sil-opt -verify is broken +// RUN: %target-sil-opt %s -enable-sil-opaque-values -emit-sib -o %t/tmp.sib -module-name opaqueval +// RUN: %target-sil-opt %t/tmp.sib -enable-sil-opaque-values -verify -o %t/tmp.2.sib -module-name opaqueval +// RUN: %target-sil-opt %t/tmp.2.sib -enable-sil-opaque-values -emit-sorted-sil -verify -module-name opaqueval | %FileCheck %s + +// REQUIRES: objc_interop + +sil_stage raw + +import Builtin +import Swift + +struct UnownedBox { + unowned var value: T +} + +// CHECK-LABEL: sil [ossa] @test_unowned_copy_value : {{.*}} { +// CHECK: bb0([[VALUE:%[^,]+]] : +// CHECK: unowned_copy_value [[VALUE]] +// CHECK-LABEL: } // end sil function 'test_unowned_copy_value' +sil [ossa] @test_unowned_copy_value : $@convention(thin) (@owned T) -> @out UnownedBox { +bb0(%owned_value : @owned $T): + %unowned_value = unowned_copy_value %owned_value : $T + destroy_value %owned_value : $T + %instance = struct $UnownedBox (%unowned_value : $@sil_unowned T) + return %instance : $UnownedBox +} + diff --git a/test/SIL/cloning_opaque_values.sil b/test/SIL/cloning_opaque_values.sil new file mode 100644 index 0000000000000..04f6f35f47ce3 --- /dev/null +++ b/test/SIL/cloning_opaque_values.sil @@ -0,0 +1,52 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -enable-sil-opaque-values -inline %s | %FileCheck %s + +// Check cloning of instructions that are only legal in opaque values mode. + +import Swift + +struct WeakBox { + weak var t: T? +} + +// CHECK-LABEL: sil [ossa] @strong_copy_weak_value_caller : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: [[STRONG_OPTIONAL:%[^,]+]] = strong_copy_weak_value [[WEAK_OPTIONAL]] +// CHECK: return [[STRONG_OPTIONAL]] +// CHECK-LABEL: } // end sil function 'strong_copy_weak_value_caller' +sil [ossa] @strong_copy_weak_value_caller : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional { +bb0(%instance : @guaranteed $WeakBox): + %callee = function_ref @strong_copy_weak_value : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional + %retval = apply %callee(%instance) : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional + return %retval : $Optional +} + +sil [always_inline] [ossa] @strong_copy_weak_value : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional { +bb0(%instance : @guaranteed $WeakBox): + %weak_optional = struct_extract %instance : $WeakBox, #WeakBox.t + %strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional + return %strong_optional : $Optional +} + +// CHECK-LABEL: sil [ossa] @weak_copy_value_caller : {{.*}} { +// CHECK: bb0([[STRONG_OPTIONAL:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = weak_copy_value [[STRONG_OPTIONAL]] +// CHECK: destroy_value [[STRONG_OPTIONAL]] +// CHECK: [[RETVAL:%[^,]+]] = struct $WeakBox ([[WEAK_OPTIONAL]] : +// CHECK: return [[RETVAL]] +// CHECK-LABEL: } // end sil function 'weak_copy_value_caller' +sil [ossa] @weak_copy_value_caller : $@convention(thin) (@owned Optional) -> @out WeakBox { +bb0(%value : @owned $Optional): + %callee = function_ref @weak_copy_value : $@convention(thin) (@owned Optional) -> @out WeakBox + %retval = apply %callee(%value) : $@convention(thin) (@owned Optional) -> @out WeakBox + return %retval : $WeakBox +} + +sil [always_inline] [ossa] @weak_copy_value : $@convention(thin) (@owned Optional) -> @out WeakBox { +bb0(%value : @owned $Optional): + %weak_value = weak_copy_value %value : $Optional + destroy_value %value : $Optional + %retval = struct $WeakBox (%weak_value : $@sil_weak Optional) + return %retval : $WeakBox +} + diff --git a/test/SIL/cloning_opaque_values_objc.sil b/test/SIL/cloning_opaque_values_objc.sil new file mode 100644 index 0000000000000..7c0edbf05474f --- /dev/null +++ b/test/SIL/cloning_opaque_values_objc.sil @@ -0,0 +1,33 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -enable-sil-opaque-values -inline %s | %FileCheck %s + +// Check cloning of instructions that are only legal in opaque values mode. + +// REQUIRES: objc_interop + +import Swift + +struct UnownedBox { + unowned var value: T +} + +// CHECK-LABEL: sil [ossa] @unowned_copy_value_caller : {{.*}} { +// CHECK: bb0([[STRONG:%[^,]+]] : +// CHECK: [[UNOWNED:%[^,]+]] = unowned_copy_value [[STRONG]] +// CHECK: destroy_value [[STRONG]] +// CHECK: [[RETVAL:%[^,]+]] = struct $UnownedBox ([[UNOWNED]] : +// CHECK: return [[RETVAL]] +// CHECK-LABEL: } // end sil function 'unowned_copy_value_caller' +sil [ossa] @unowned_copy_value_caller : $@convention(thin) (@owned T) -> @out UnownedBox { +bb0(%value : @owned $T): + %callee = function_ref @unowned_copy_value : $@convention(thin) (@owned T) -> @out UnownedBox + %retval = apply %callee(%value) : $@convention(thin) (@owned T) -> @out UnownedBox + return %retval : $UnownedBox +} + +sil [always_inline] [ossa] @unowned_copy_value : $@convention(thin) (@owned T) -> @out UnownedBox { +bb0(%owned_value : @owned $T): + %unowned_value = unowned_copy_value %owned_value : $T + destroy_value %owned_value : $T + %instance = struct $UnownedBox (%unowned_value : $@sil_unowned T) + return %instance : $UnownedBox +} diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift index eadee0db3d8d6..b74b970e5049e 100644 --- a/test/SILGen/opaque_values_silgen.swift +++ b/test/SILGen/opaque_values_silgen.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-emit-silgen -enable-sil-opaque-values -Xllvm -sil-full-demangle %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime +// RUN: %target-swift-emit-silgen -enable-sil-opaque-values -Xllvm -sil-full-demangle -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // Test SILGen -enable-sil-opaque-values with tests that depend on the stdlib. @@ -743,3 +743,20 @@ protocol MutatingFooable { func callMutatingFooOnInoutExistential(_ i: inout any MutatingFooable) { i.foo() } + +// CHECK-LABEL: sil {{.*}}[ossa] @$s20opaque_values_silgen7WeakBoxV1txSgvg : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: [[STRONG_OPTIONAL:%[^,]+]] = strong_copy_weak_value [[WEAK_OPTIONAL]] +// CHECK: return [[STRONG_OPTIONAL]] +// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7WeakBoxV1txSgvg' +// CHECK-LABEL: sil {{.*}}[ossa] @$s20opaque_values_silgen7WeakBoxV1tACyxGxSg_tcfC : {{.*}} { +// CHECK: bb0([[STRONG_OPTIONAL:%[^,]+]] : +// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = weak_copy_value [[STRONG_OPTIONAL]] +// CHECK: destroy_value [[STRONG_OPTIONAL]] +// CHECK: [[INSTANCE:%[^,]+]] = struct $WeakBox ([[WEAK_OPTIONAL]] : +// CHECK: return [[INSTANCE]] +// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen7WeakBoxV1tACyxGxSg_tcfC' +struct WeakBox { + weak var t: T? +} diff --git a/test/SILGen/opaque_values_silgen_nonobjc.swift b/test/SILGen/opaque_values_silgen_nonobjc.swift new file mode 100644 index 0000000000000..3bba0ef315665 --- /dev/null +++ b/test/SILGen/opaque_values_silgen_nonobjc.swift @@ -0,0 +1,25 @@ +// RUN: %target-swift-emit-silgen -enable-sil-opaque-values -Xllvm -sil-full-demangle -disable-objc-interop -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime + +// Test SILGen -enable-sil-opaque-values with tests that depend on the stdlib and objc interop. + +// REQUIRES: objc_interop + +// CHECK-LABEL: sil {{.*}}[ossa] @$s28opaque_values_silgen_nonobjc13UnownedVarBoxV5valuexvg : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[UNOWNED_VALUE:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: [[STRONG_VALUE:%[^,]+]] = strong_copy_unowned_value [[UNOWNED_VALUE]] +// CHECK: return [[STRONG_VALUE]] +// CHECK-LABEL: } // end sil function '$s28opaque_values_silgen_nonobjc13UnownedVarBoxV5valuexvg' +// CHECK-LABEL: sil {{.*}}[ossa] @$s28opaque_values_silgen_nonobjc13UnownedVarBoxV5valueACyxGx_tcfC : {{.*}} { +// CHECK: bb0([[STRONG_VALUE:%[^,]+]] : +// CHECK: [[WRAPPED_IN_UNOWNED_TYPE:%[^,]+]] = ref_to_unowned [[STRONG_VALUE]] +// CHECK: [[UNOWNED_VALUE:%[^,]+]] = copy_value [[WRAPPED_IN_UNOWNED_TYPE]] +// CHECK: destroy_value [[STRONG_VALUE]] +// CHECK: [[RETVAL:%[^,]+]] = struct $UnownedVarBox ([[UNOWNED_VALUE]] : $@sil_unowned T) +// CHECK: return [[RETVAL]] +// CHECK-LABEL: } // end sil function '$s28opaque_values_silgen_nonobjc13UnownedVarBoxV5valueACyxGx_tcfC' +struct UnownedVarBox { + unowned var value: T +} + + diff --git a/test/SILGen/opaque_values_silgen_objc.swift b/test/SILGen/opaque_values_silgen_objc.swift new file mode 100644 index 0000000000000..49b02f2d05fdc --- /dev/null +++ b/test/SILGen/opaque_values_silgen_objc.swift @@ -0,0 +1,23 @@ +// RUN: %target-swift-emit-silgen -enable-sil-opaque-values -Xllvm -sil-full-demangle -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime + +// Test SILGen -enable-sil-opaque-values with tests that depend on the stdlib and objc interop. + +// REQUIRES: objc_interop + +// CHECK-LABEL: sil {{.*}}[ossa] @$s25opaque_values_silgen_objc10UnownedBoxV5valuexvg : {{.*}} { +// CHECK: bb0([[INSTANCE:%[^,]+]] : +// CHECK: [[UNOWNED_VALUE:%[^,]+]] = struct_extract [[INSTANCE]] +// CHECK: [[STRONG_VALUE:%[^,]+]] = strong_copy_unowned_value [[UNOWNED_VALUE]] +// CHECK: return [[STRONG_VALUE]] +// CHECK-LABEL: } // end sil function '$s25opaque_values_silgen_objc10UnownedBoxV5valuexvg' +// CHECK-LABEL: sil {{.*}}[ossa] @$s25opaque_values_silgen_objc10UnownedBoxV5valueACyxGx_tcfC : {{.*}} { +// CHECK: bb0([[STRONG_VALUE:%[^,]+]] : +// CHECK: [[UNOWNED_VALUE:%[^,]+]] = unowned_copy_value [[STRONG_VALUE]] +// CHECK: destroy_value [[STRONG_VALUE]] +// CHECK: [[RETVAL:%[^,]+]] = struct $UnownedBox ([[UNOWNED_VALUE]] : $@sil_unowned T) +// CHECK: return [[RETVAL]] +// CHECK-LABEL: } // end sil function '$s25opaque_values_silgen_objc10UnownedBoxV5valueACyxGx_tcfC' +struct UnownedBox { + unowned var value: T +} + diff --git a/test/SILOptimizer/address_lowering.sil b/test/SILOptimizer/address_lowering.sil index efa3d18c273e3..ae4db1dbbf52b 100644 --- a/test/SILOptimizer/address_lowering.sil +++ b/test/SILOptimizer/address_lowering.sil @@ -2720,6 +2720,7 @@ bb0(%instance : @owned $T): %retval = tuple () return %retval : $() } + // CHECK-LABEL: sil [ossa] @test_yield_1_two_values : {{.*}} { // CHECK: tuple_element_addr // CHECK: tuple_element_addr diff --git a/test/SILOptimizer/address_lowering_lib.sil b/test/SILOptimizer/address_lowering_lib.sil index 42938797d21a8..2379d64d29f81 100644 --- a/test/SILOptimizer/address_lowering_lib.sil +++ b/test/SILOptimizer/address_lowering_lib.sil @@ -1,4 +1,4 @@ -// RUN: %target-sil-opt -address-lowering -enable-sil-opaque-values -sil-verify-all %s | %FileCheck %s +// RUN: %target-sil-opt -address-lowering -emit-sorted-sil -enable-sil-opaque-values -sil-verify-all %s | %FileCheck %s // import Builtin import Swift @@ -29,3 +29,34 @@ bb0(%0 : @owned $Error): %ret = tuple () return %ret : $() } + +struct WeakBox { + weak var t: T? +} + +// CHECK-LABEL: sil [ossa] @test_strong_copy_weak_value : {{.*}} { +// CHECK: {{bb[0-9]+}}([[BOX_ADDR:%[^,]+]] : +// CHECK: [[VALUE_ADDR:%[^,]+]] = struct_element_addr [[BOX_ADDR]] : {{.*}}, #WeakBox.t +// CHECK: [[VALUE:%[^,]+]] = load_weak [[VALUE_ADDR]] : $*@sil_weak Optional +// CHECK: return [[VALUE]] : $Optional +// CHECK-LABEL: } // end sil function 'test_strong_copy_weak_value' +sil [ossa] @test_strong_copy_weak_value : $@convention(thin) (@in_guaranteed WeakBox) -> @owned Optional { +bb0(%instance : @guaranteed $WeakBox): + %weak_optional = struct_extract %instance : $WeakBox, #WeakBox.t + %strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional + return %strong_optional : $Optional +} + +// CHECK-LABEL: sil [ossa] @test_weak_copy_value_1 : {{.*}} { +// CHECK: {{bb[0-9]+}}([[RETVAL:%[^,]+]] : $*WeakBox, [[VALUE:%[^,]+]] : +// CHECK: [[VALUE_ADDR:%[^,]+]] = struct_element_addr [[RETVAL]] : {{.*}}, #WeakBox.t +// CHECK: store_weak [[VALUE]] to [init] [[VALUE_ADDR]] +// CHECK: destroy_value [[VALUE]] +// CHECK-LABEL: } // end sil function 'test_weak_copy_value_1' +sil [ossa] @test_weak_copy_value_1 : $@convention(thin) (@owned Optional) -> @out WeakBox { +bb0(%value : @owned $Optional): + %weak_value = weak_copy_value %value : $Optional + destroy_value %value : $Optional + %retval = struct $WeakBox (%weak_value : $@sil_weak Optional) + return %retval : $WeakBox +} diff --git a/test/SILOptimizer/address_lowering_objc.sil b/test/SILOptimizer/address_lowering_objc.sil new file mode 100644 index 0000000000000..6f405554075d8 --- /dev/null +++ b/test/SILOptimizer/address_lowering_objc.sil @@ -0,0 +1,40 @@ +// RUN: %target-sil-opt -address-lowering -enable-sil-opaque-values -emit-sorted-sil -module-name Swift -sil-verify-all %s | %FileCheck %s + +// REQUIRES: objc_interop + +import Builtin + +typealias AnyObject = Builtin.AnyObject + +// The module name must be Swift so that declarations like Error are parsed as the correct loadable type. + +struct UnownedBox { + unowned var value: T +} + +// CHECK-LABEL: sil [ossa] @test_strong_copy_unowned_value : {{.*}} { +// CHECK: bb0([[INSTANCE_ADDR:%[^,]+]] : +// CHECK: [[FIELD_ADDR:%[^,]+]] = struct_element_addr [[INSTANCE_ADDR]] +// CHECK: [[OWNED_VALUE:%[^,]+]] = load_unowned [[FIELD_ADDR]] +// CHECK: return [[OWNED_VALUE]] +// CHECK-LABEL: } // end sil function 'test_strong_copy_unowned_value' +sil [ossa] @test_strong_copy_unowned_value : $@convention(thin) (@in_guaranteed UnownedBox) -> @owned T { +bb0(%instance : @guaranteed $UnownedBox): + %unowned_value = struct_extract %instance : $UnownedBox, #UnownedBox.value + %owned_value = strong_copy_unowned_value %unowned_value : $@sil_unowned T + return %owned_value : $T +} + +// CHECK-LABEL: sil [ossa] @test_unowned_copy_value : {{.*}} { +// CHECK: bb0([[INSTANCE_OUT:%[^,]+]] : {{.*}}, [[OWNED_VALUE:%[^,]+]] : +// CHECK: [[FIELD_ADDR:%[^,]+]] = struct_element_addr [[INSTANCE_OUT]] +// CHECK: store_unowned [[OWNED_VALUE]] to [init] [[FIELD_ADDR]] +// CHECK: destroy_value [[OWNED_VALUE]] +// CHECK-LABEL: } // end sil function 'test_unowned_copy_value' +sil [ossa] @test_unowned_copy_value : $@convention(thin) (@owned T) -> @out UnownedBox { +bb0(%owned_value : @owned $T): + %unowned_value = unowned_copy_value %owned_value : $T + destroy_value %owned_value : $T + %instance = struct $UnownedBox (%unowned_value : $@sil_unowned T) + return %instance : $UnownedBox +}